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#include "logger.h" 16b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 17b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <pthread.h> 18b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdarg.h> 19b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdio.h> 20b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <unistd.h> 21b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 22b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string> 23b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <vector> 24b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 25b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file must work with autoconf on its public version, 26b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// so these includes are correct. 27b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "sattypes.h" 28b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 29b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 30b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonLogger *Logger::GlobalLogger() { 31b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson static Logger logger; 32b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return &logger; 33b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 34b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 35b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Logger::VLogF(int priority, const char *format, va_list args) { 36b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (priority > verbosity_) { 37b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return; 38b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 39b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buffer[4096]; 40b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int length = vsnprintf(buffer, sizeof buffer, format, args); 41b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (static_cast<size_t>(length) >= sizeof buffer) { 42b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson length = sizeof buffer; 43b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson buffer[sizeof buffer - 1] = '\n'; 44b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 45b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson QueueLogLine(new string(buffer, length)); 46b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 47b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 48b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Logger::StartThread() { 49b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(!thread_running_); 50b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_running_ = true; 51b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_create(&thread_, NULL, &StartRoutine, this)); 52b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 53b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 54b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Logger::StopThread() { 55b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(thread_running_); 56b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_running_ = false; 57b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_)); 58b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool need_cond_signal = queued_lines_.empty(); 59b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson queued_lines_.push_back(NULL); 60b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_unlock(&queued_lines_mutex_)); 61b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (need_cond_signal) { 62b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_signal(&queued_lines_cond_)); 63b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 64b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_join(thread_, NULL)); 65b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 66b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 67b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonLogger::Logger() : verbosity_(20), log_fd_(-1), thread_running_(false) { 68b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_init(&queued_lines_mutex_, NULL)); 69b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_init(&queued_lines_cond_, NULL)); 70b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_init(&full_queue_cond_, NULL)); 71b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 72b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 73b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonLogger::~Logger() { 74b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_destroy(&queued_lines_mutex_)); 75b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_destroy(&queued_lines_cond_)); 76b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_destroy(&full_queue_cond_)); 77b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 78b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 79b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Logger::QueueLogLine(string *line) { 80b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(line != NULL); 81b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_)); 82b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (thread_running_) { 83b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (queued_lines_.size() >= kMaxQueueSize) { 84b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_wait(&full_queue_cond_, 85b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson &queued_lines_mutex_)); 86b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 87b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (queued_lines_.empty()) { 88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_signal(&queued_lines_cond_)); 89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson queued_lines_.push_back(line); 91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WriteAndDeleteLogLine(line); 93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_unlock(&queued_lines_mutex_)); 95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonnamespace { 98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WriteToFile(const string& line, int fd) { 99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(write(fd, line.data(), line.size()) == 100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson static_cast<ssize_t>(line.size())); 101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Logger::WriteAndDeleteLogLine(string *line) { 105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(line != NULL); 106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (log_fd_ >= 0) { 107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WriteToFile(*line, log_fd_); 108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WriteToFile(*line, 1); 110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete line; 111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid *Logger::StartRoutine(void *ptr) { 114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson Logger *self = static_cast<Logger*>(ptr); 115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson self->ThreadMain(); 116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return NULL; 117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Logger::ThreadMain() { 120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson vector<string*> local_queue; 121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_)); 122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (;;) { 124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (queued_lines_.empty()) { 125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_wait(&queued_lines_cond_, 126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson &queued_lines_mutex_)); 127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We move the log lines into a local queue so we can release the lock 131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // while writing them to disk, preventing other threads from blocking on 132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // our writes. 133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson local_queue.swap(queued_lines_); 134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (local_queue.size() >= kMaxQueueSize) { 135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_cond_broadcast(&full_queue_cond_)); 136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Unlock while we process our local queue. 139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_unlock(&queued_lines_mutex_)); 140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (vector<string*>::const_iterator it = local_queue.begin(); 141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson it != local_queue.end(); ++it) { 142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (*it == NULL) { 143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // NULL is guaranteed to be at the end. 144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return; 145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WriteAndDeleteLogLine(*it); 147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson local_queue.clear(); 149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We must hold the lock at the start of each iteration of this for loop. 150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson LOGGER_ASSERT(0 == pthread_mutex_lock(&queued_lines_mutex_)); 151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 153