1 // Copyright 2009 Google Inc. All Rights Reserved. 2 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 7 // http://www.apache.org/licenses/LICENSE-2.0 8 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef STRESSAPPTEST_LOGGER_H_ 16 #define STRESSAPPTEST_LOGGER_H_ 17 18 #include <pthread.h> 19 #include <stdarg.h> 20 21 #include <string> 22 #include <vector> 23 24 // This file must work with autoconf on its public version, 25 // so these includes are correct. 26 #include "sattypes.h" 27 28 // Attempts to log additional lines will block when the queue reaches this size. 29 // Due to how the logging thread works, up to twice this many log lines may be 30 // outstanding at any point. 31 static const size_t kMaxQueueSize = 250; 32 33 34 // This is only for use by the Logger class, do not use it elsewhere! 35 // 36 // All Logger assertions should use this macro instead of sat_assert(). 37 // 38 // This is like sat_assert() from sattypes.h, but whereas sat_assert() tries to 39 // log the assertion after printing it to stderr, this only prints it to stderr. 40 // Logging from within the wrong part of the logger would trigger a deadlock, 41 // and even in places where it wouldn't there's a very good chance that the 42 // logger is in no condition to handle new log lines. 43 #define LOGGER_ASSERT(x) \ 44 {\ 45 if (!(x)) {\ 46 fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\ 47 exit(1);\ 48 }\ 49 } 50 51 52 // This class handles logging in SAT. It is a singleton accessed via 53 // GlobalLogger(). 54 // 55 // By default log lines are written in the calling thread. Call StartThread() 56 // to launch a dedicated thread for the writes. 57 class Logger { 58 public: 59 // Returns a pointer to the single global Logger instance. Will not return 60 // NULL. 61 static Logger *GlobalLogger(); 62 63 // Lines with a priority numerically greater than this will not be logged. 64 // May not be called while multiple threads are running. 65 void SetVerbosity(int verbosity) { 66 verbosity_ = verbosity; 67 } 68 69 // Sets a file to log to, in addition to stdout. May not be called while 70 // multiple threads are running. 71 // 72 // Args: 73 // log_fd: The file descriptor to write to. Will not be closed by this 74 // object. 75 void SetLogFd(int log_fd) { 76 LOGGER_ASSERT(log_fd >= 0); 77 log_fd_ = log_fd; 78 } 79 80 // Set output to be written to stdout only. This is the default mode. May 81 // not be called while multiple threads are running. 82 void SetStdoutOnly() { 83 log_fd_ = -1; 84 } 85 86 // Logs a line, with a vprintf(3)-like interface. This will block on writing 87 // the line to stdout/disk iff the dedicated logging thread is not running. 88 // This will block on adding the line to the queue if doing so would exceed 89 // kMaxQueueSize. 90 // 91 // Args: 92 // priority: If this is numerically greater than the verbosity, the line 93 // will not be logged. 94 // format: see vprintf(3) 95 // args: see vprintf(3) 96 void VLogF(int priority, const char *format, va_list args); 97 98 // Starts the dedicated logging thread. May not be called while multiple 99 // threads are already running. 100 void StartThread(); 101 102 // Stops the dedicated logging thread. May only be called when the logging 103 // thread is the only other thread running. Any queued lines will be logged 104 // before this returns. Waits for the thread to finish before returning. 105 void StopThread(); 106 107 private: 108 Logger(); 109 110 ~Logger(); 111 112 // Args: 113 // line: Must be non-NULL. This function takes ownership of it. 114 void QueueLogLine(string *line); 115 116 // Args: 117 // line: Must be non-NULL. This function takes ownership of it. 118 void WriteAndDeleteLogLine(string *line); 119 120 // Callback for pthread_create(3). 121 static void *StartRoutine(void *ptr); 122 123 // Processes the log queue. 124 void ThreadMain(); 125 126 pthread_t thread_; 127 int verbosity_; 128 int log_fd_; 129 bool thread_running_; 130 vector<string*> queued_lines_; 131 // This doubles as a mutex for log_fd_ when the logging thread is not running. 132 pthread_mutex_t queued_lines_mutex_; 133 // Lets the logging thread know that the queue is no longer empty. 134 pthread_cond_t queued_lines_cond_; 135 // Lets the threads blocked on the queue having reached kMaxQueueSize know 136 // that the queue has been emptied. 137 pthread_cond_t full_queue_cond_; 138 139 DISALLOW_COPY_AND_ASSIGN(Logger); 140 }; 141 142 #endif // STRESSAPPTEST_LOGGER_H_ 143