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 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