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