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