From: Davin McCall Date: Sun, 5 Jun 2016 18:31:15 +0000 (+0100) Subject: Refactorings. X-Git-Tag: v0.01~11 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ac5bc85246fb308eb17a0d63ed44c7255fce8eca;p=oweals%2Fdinit.git Refactorings. --- diff --git a/src/dinit-log.cc b/src/dinit-log.cc index 64ea5af..8dd08c6 100644 --- a/src/dinit-log.cc +++ b/src/dinit-log.cc @@ -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 { - 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(); } }