| 59 | } |
| 60 | |
| 61 | void AsyncLogger::Write(bool force_flush, |
| 62 | time_t timestamp, |
| 63 | const char* message, |
| 64 | size_t message_len) { |
| 65 | { |
| 66 | MutexLock l(lock_); |
| 67 | DCHECK_EQ(state_, RUNNING); |
| 68 | while (BufferFull(*active_buf_)) { |
| 69 | app_threads_blocked_count_for_tests_++; |
| 70 | free_buffer_cond_.Wait(); |
| 71 | } |
| 72 | active_buf_->add(Msg(timestamp, string(message, message_len)), |
| 73 | force_flush); |
| 74 | wake_flusher_cond_.Signal(); |
| 75 | } |
| 76 | |
| 77 | // In most cases, we take the 'force_flush' argument to mean that we'll let the logger |
| 78 | // thread do the flushing for us, but not block the application. However, for the |
| 79 | // special case of a FATAL log message, we really want to make sure that our message |
| 80 | // hits the log before we continue, or else it's likely that the application will exit |
| 81 | // while it's still in our buffer. |
| 82 | // |
| 83 | // NOTE: even if the application doesn't wrap the FATAL-level logger, log messages at |
| 84 | // FATAL are also written to all other log files with lower levels. So, a FATAL message |
| 85 | // will force a synchronous flush of all lower-level logs before exiting. |
| 86 | // |
| 87 | // Unfortunately, the underlying log level isn't passed through to this interface, so we |
| 88 | // have to use this hack: messages from FATAL errors start with the character 'F'. |
| 89 | if (message_len > 0 && message[0] == 'F') { |
| 90 | Flush(); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | void AsyncLogger::Flush() { |
| 95 | MutexLock l(lock_); |