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