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. 31static 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. 57class 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 virtual 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 virtual 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 virtual void SetStdoutOnly() { 83 log_fd_ = -1; 84 } 85 86 // Enable or disable logging of timestamps. 87 void SetTimestampLogging(bool log_ts_enabled) { 88 log_timestamps_ = log_ts_enabled; 89 } 90 91 // Logs a line, with a vprintf(3)-like interface. This will block on writing 92 // the line to stdout/disk iff the dedicated logging thread is not running. 93 // This will block on adding the line to the queue if doing so would exceed 94 // kMaxQueueSize. 95 // 96 // Args: 97 // priority: If this is numerically greater than the verbosity, the line 98 // will not be logged. 99 // format: see vprintf(3) 100 // args: see vprintf(3) 101 void VLogF(int priority, const char *format, va_list args); 102 103 // Starts the dedicated logging thread. May not be called while multiple 104 // threads are already running. 105 void StartThread(); 106 107 // Stops the dedicated logging thread. May only be called when the logging 108 // thread is the only other thread running. Any queued lines will be logged 109 // before this returns. Waits for the thread to finish before returning. 110 void StopThread(); 111 112 protected: 113 Logger(); 114 115 virtual ~Logger(); 116 117 private: 118 // Args: 119 // line: Must be non-NULL. This function takes ownership of it. 120 void QueueLogLine(string *line); 121 122 // Args: 123 // line: Must be non-NULL. This function takes ownership of it. 124 void WriteAndDeleteLogLine(string *line); 125 126 // Callback for pthread_create(3). 127 static void *StartRoutine(void *ptr); 128 129 // Processes the log queue. 130 void ThreadMain(); 131 132 pthread_t thread_; 133 int verbosity_; 134 int log_fd_; 135 bool thread_running_; 136 bool log_timestamps_; 137 vector<string*> queued_lines_; 138 // This doubles as a mutex for log_fd_ when the logging thread is not running. 139 pthread_mutex_t queued_lines_mutex_; 140 // Lets the logging thread know that the queue is no longer empty. 141 pthread_cond_t queued_lines_cond_; 142 // Lets the threads blocked on the queue having reached kMaxQueueSize know 143 // that the queue has been emptied. 144 pthread_cond_t full_queue_cond_; 145 146 DISALLOW_COPY_AND_ASSIGN(Logger); 147}; 148 149#endif // STRESSAPPTEST_LOGGER_H_ 150