예제 #1
0
        /// <summary>Returns the JournalMessage.</summary>
        public void Dispose()
        {
            Clear();

            if (s_cachedMessage == null ||
                (this._data.Count > s_cachedMessage._data.Count)) // Prefer caching longer _data
            {
                s_cachedMessage = this;
            }
        }
예제 #2
0
        internal static JournalMessage Get(bool isEnabled)
        {
            JournalMessage message = s_cachedMessage;

            if (message == null)
            {
                message = new JournalMessage();
            }
            else
            {
                s_cachedMessage = null;
            }

            message._isEnabled = isEnabled;

            return(message);
        }
예제 #3
0
 /// <summary>Obtain a cleared JournalMessage. The Message must be Disposed to return it.</summary>
 public static JournalMessage GetMessage()
 {
     return(JournalMessage.Get(IsSupported));
 }
예제 #4
0
        /// <summary>
        /// Submit a log entry to the journal.
        /// </summary>
        public static unsafe LogResult Log(LogFlags flags, JournalMessage message)
        {
            Socket socket = GetJournalSocket();

            if (socket == null)
            {
                if (s_isSupported.Value)
                {
                    return(LogResult.NotAvailable);
                }
                else
                {
                    return(LogResult.NotSupported);
                }
            }

            if (message.IsEmpty)
            {
                return(LogResult.Success);
            }

            int priority = (int)flags & 0xf;

            if (priority != 0)
            {
                message.Append(JournalFieldName.Priority, priority - 1);
            }
            if (((flags & LogFlags.DontAppendSyslogIdentifier) == LogFlags.None) &&
                SyslogIdentifier != null)
            {
                message.Append(JournalFieldName.SyslogIdentifier, SyslogIdentifier);
            }

            List <ArraySegment <byte> > data = message.GetData();
            int dataLength = data.Count;

            if (dataLength > MaxIovs)
            {
                // We should handle this the same way as EMSGSIZE, which we don't handle atm.
                ErrorWhileLogging("size exceeded");
                return(LogResult.Size);
            }
            Span <IOVector> iovs    = stackalloc IOVector[dataLength];
            Span <GCHandle> handles = stackalloc GCHandle[dataLength];

            for (int i = 0; i < data.Count; i++)
            {
                handles[i]     = GCHandle.Alloc(data[i].Array, GCHandleType.Pinned);
                iovs[i].Base   = handles[i].AddrOfPinnedObject();
                iovs[i].Length = new IntPtr(data[i].Count);
            }
            int sendmsgFlags = 0;

            if ((flags & LogFlags.DropWhenBusy) != 0)
            {
                sendmsgFlags |= MSG_DONTWAIT;
            }
            LogResult result = LogResult.Success;

            fixed(IOVector *pIovs = &MemoryMarshal.GetReference(iovs))
            {
                bool loop;

                do
                {
                    loop = false;
                    msghdr msg;
                    msg.msg_iov    = pIovs;
                    msg.msg_iovlen = (SizeT)dataLength;
                    int rv = sendmsg(socket.Handle.ToInt32(), &msg, sendmsgFlags).ToInt32();
                    if (rv < 0)
                    {
                        int errno = Marshal.GetLastWin32Error();
                        if (errno == EINTR)
                        {
                            loop = true;
                        }
                        else if (errno == EAGAIN)
                        {
                            result = LogResult.Busy;
                        }
                        else
                        {
                            result = LogResult.UnknownError;
                            ErrorWhileLogging($"errno={errno}");
                        }
                    }
                } while (loop);
            }

            for (int i = 0; i < handles.Length; i++)
            {
                handles[i].Free();
            }
            return(result);
        }