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