Refactorings.
authorDavin McCall <davmac@davmac.org>
Sun, 5 Jun 2016 18:31:15 +0000 (19:31 +0100)
committerDavin McCall <davmac@davmac.org>
Sun, 5 Jun 2016 18:31:15 +0000 (19:31 +0100)
src/dinit-log.cc

index 64ea5afdb3f4440051aa27480cf1bb01e6aa2a16..8dd08c64f225b7427cbf973fa9c5ee759ffac4e1 100644 (file)
@@ -10,6 +10,9 @@
 #include "dinit-log.h"
 #include "cpbuffer.h"
 
+// TODO should disarm, not remove, the file descriptor watchers when they are not busy
+//      (and likewise re-arm instead of re-add them when new data arrives).
+
 extern EventLoop_t eventLoop;
 
 LogLevel log_level = LogLevel::WARN;
@@ -20,47 +23,39 @@ static bool log_current_line;  // Whether the current line is being logged
 
 static ServiceSet *service_set = nullptr;  // Reference to service set
 
-
-namespace {
-    class BufferedLogStream;
-}
-
-// TODO just make this the callback, directly.
-static Rearm log_conn_callback(EventLoop_t *loop, BufferedLogStream *w, int revents) noexcept;
-
 namespace {
 class BufferedLogStream : public PosixFdWatcher<NullMutex>
 {
-    public:
-    CPBuffer<4096> log_buffer;
-    
+    private:
+
     // Outgoing:
     bool partway = false;     // if we are partway throught output of a log message
     bool discarded = false;   // if we have discarded a message
 
-    // Incoming:
-    int current_index = 0;    // current/next incoming message index
-       // ^^ TODO is this always just the length of log_buffer?
-
     // A "special message" is not stored in the circular buffer; instead
     // it is delivered from an external buffer not managed by BufferedLogger.
     bool special = false;      // currently outputting special message?
     char *special_buf; // buffer containing special message
     int msg_index;     // index into special message
     
+    public:
+    CPBuffer<4096> log_buffer;
+    
+    // Incoming:
+    int current_index = 0;    // current/next incoming message index
+       // ^^ TODO is this always just the length of log_buffer?
+
     int fd;
 
     void init(int fd)
     {
-        //ev_io_init(&eviocb, log_conn_callback, fd, EV_WRITE);
-        //eviocb.data = this;
         this->fd = fd;
     }
     
-    Rearm gotEvent(EventLoop_t *loop, int fd, int flags) noexcept override
-    {
-        return log_conn_callback(loop, this, flags);
-    }
+    Rearm gotEvent(EventLoop_t *loop, int fd, int flags) noexcept override;
+
+    // Check whether the console can be released.
+    void flushForRelease();
 };
 }
 
@@ -74,8 +69,6 @@ constexpr static int DLOG_CONS = 1; // console
 
 static void release_console()
 {
-    //ev_io_stop(ev_default_loop(EVFLAG_AUTO), & log_stream[DLOG_CONS].eviocb);
-    //log_stream[DLOG_CONS].deregisterWatch(&eventLoop); // now handled elsewhere
     if (! log_to_console) {
         int flags = fcntl(1, F_GETFL, 0);
         fcntl(1, F_SETFL, flags & ~O_NONBLOCK);
@@ -83,20 +76,39 @@ static void release_console()
     }
 }
 
-static Rearm log_conn_callback(EventLoop_t * loop, BufferedLogStream * w, int revents) noexcept
+void BufferedLogStream::flushForRelease()
+{
+    // Try to flush any messages that are currently buffered. (Console is non-blocking
+    // so it will fail gracefully).
+    if (gotEvent(&eventLoop, fd, out_events) == Rearm::REMOVE) {
+        // Console has already been released at this point.
+        deregisterWatch(&eventLoop);
+    }
+    // gotEvent didn't want to disarm, so must be partway through a message; will
+    // release when it's finished.
+}
+
+Rearm BufferedLogStream::gotEvent(EventLoop_t *loop, int fd, int flags) noexcept
 {
-    auto &log_stream = *w;
+    // TODO correct for the case that this is *not* the console log stream.
+    
+    auto &log_stream = *this;
 
-    if (log_stream.special) {
+    if ((! partway) && log_stream.special) {
         char * start = log_stream.special_buf + log_stream.msg_index;
         char * end = std::find(log_stream.special_buf + log_stream.msg_index, (char *)nullptr, '\n');
-        int r = write(w->fd, start, end - start + 1);
+        int r = write(fd, start, end - start + 1);
         if (r >= 0) {
             if (start + r > end) {
                 // All written: go on to next message in queue
                 log_stream.special = false;
                 log_stream.partway = false;
                 log_stream.msg_index = 0;
+                
+                if (!log_to_console) {
+                    release_console();
+                    return Rearm::REMOVE;
+                }
             }
             else {
                 log_stream.msg_index += r;
@@ -133,7 +145,7 @@ static Rearm log_conn_callback(EventLoop_t * loop, BufferedLogStream * w, int re
 
         len = eptr - ptr;
         
-        int r = write(w->fd, ptr, len);
+        int r = write(fd, ptr, len);
 
         if (r >= 0) {
             bool complete = (r == len) && will_complete;
@@ -178,29 +190,15 @@ void enable_console_log(bool enable) noexcept
         int flags = fcntl(1, F_GETFL, 0);
         fcntl(1, F_SETFL, flags | O_NONBLOCK);
         // Activate watcher:
-        //ev_io_init(& log_stream[DLOG_CONS].eviocb, log_conn_callback, 1, EV_WRITE);
         log_stream[DLOG_CONS].init(STDOUT_FILENO);
         if (log_stream[DLOG_CONS].current_index > 0) {
-            //ev_io_start(ev_default_loop(EVFLAG_AUTO), & log_stream[DLOG_CONS].eviocb);
             log_stream[DLOG_CONS].registerWith(&eventLoop, log_stream[DLOG_CONS].fd, out_events);
         }
         log_to_console = true;
     }
     else if (! enable && log_to_console) {
         log_to_console = false;
-        if (! log_stream[DLOG_CONS].partway) {
-            if (log_stream[DLOG_CONS].current_index > 0) {
-                // Try to flush any messages that are currently buffered. (Console is non-blocking
-                // so it will fail gracefully).
-                log_conn_callback(&eventLoop, &log_stream[DLOG_CONS], out_events);
-            }
-            else {
-                release_console();
-                log_stream[DLOG_CONS].deregisterWatch(&eventLoop);
-            }
-        }
-        // (if we're partway through logging a message, we release the console when
-        // finished).
+        log_stream[DLOG_CONS].flushForRelease();
     }
 }