/* * LogManager.cpp * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "LogManager.h" #include "ConfigEntry.h" #include "ThreadManager.h" #include namespace Mad { namespace Common { LogManager LogManager::logManager; void LogManager::ConsoleLogger::logMessage(MessageCategory category _UNUSED_PARAMETER_, MessageLevel level, time_t timestamp _UNUSED_PARAMETER_, const std::string &message) { if(level != CRITICAL) {// Critical messages are printed to cerr directly, so don't print them a second time gl_lock_lock(cerrLock); std::cerr << message << std::endl; gl_lock_unlock(cerrLock); } } void LogManager::ConsoleLogger::logMessage(MessageCategory category _UNUSED_PARAMETER_, MessageLevel, time_t timestamp _UNUSED_PARAMETER_, const std::string &message, const std::string &messageSource) { gl_lock_lock(cerrLock); std::cerr << message << " from " << messageSource << std::endl; gl_lock_unlock(cerrLock); } void LogManager::ConsoleLogger::logMessageDirect(MessageCategory category _UNUSED_PARAMETER_, MessageLevel level _UNUSED_PARAMETER_, time_t timestamp _UNUSED_PARAMETER_, const std::string &message) { gl_lock_lock(cerrLock); std::cerr << message << std::endl; gl_lock_unlock(cerrLock); } bool LogManager::handleConfigEntry(const ConfigEntry &entry, bool handled) { if(handled) return false; if(entry[0].getKey().matches("Logger")) { if(entry[0][0].matches("Console")) { if(entry[1].empty()) { registerLogger(static_cast(&consoleLogger)); return true; } } else if(entry[1].empty()) { Logger::logf(Logger::WARNING, "Unknown logger '%s'.", entry[0][0].c_str()); return true; } } return false; } void LogManager::configFinished() { if(loggers.empty()) registerLogger(static_cast(&consoleLogger)); gl_lock_lock(lock); configured = true; gl_cond_signal(queueCond); gl_lock_unlock(lock); } void LogManager::log(MessageCategory category, MessageLevel level, time_t timestamp, const std::string &message) { if(level == LoggerBase::CRITICAL) consoleLogger.logMessageDirect(category, level, timestamp, message); gl_lock_lock(lock); Message m = {category, level, timestamp, message}; messageQueue.push(m); gl_cond_signal(queueCond); gl_lock_unlock(lock); } void LogManager::log(MessageCategory category, MessageLevel level, time_t timestamp, const std::string &message, const std::string &source) { gl_lock_lock(lock); RemoteMessage m = {category, level, timestamp, message, source}; remoteMessageQueue.push(m); gl_cond_signal(queueCond); gl_lock_unlock(lock); } void LogManager::loggerThread() { gl_lock_lock(lock); running = true; while(running) { while(running && ((messageQueue.empty() && messageQueue.empty()) || !configured)) gl_cond_wait(queueCond, lock); while(!messageQueue.empty()) { Message message = messageQueue.front(); messageQueue.pop(); gl_lock_unlock(lock); gl_lock_lock(loggerLock); for(std::set::iterator logger = loggers.begin(); logger != loggers.end(); ++logger) { if((*logger)->getLevel() >= message.level && (*logger)->isCategorySet(message.category)) (*logger)->logMessage(message.category, message.level, message.timestamp, message.message); } gl_lock_unlock(loggerLock); gl_lock_lock(lock); } while(!remoteMessageQueue.empty()) { RemoteMessage message = remoteMessageQueue.front(); remoteMessageQueue.pop(); gl_lock_unlock(lock); gl_lock_lock(remoteLoggerLock); for(std::set::iterator logger = remoteLoggers.begin(); logger != remoteLoggers.end(); ++logger) { if((*logger)->getLevel() >= message.level && (*logger)->isCategorySet(message.category)) (*logger)->logMessage(message.category, message.level, message.timestamp, message.message, message.source); } gl_lock_unlock(remoteLoggerLock); gl_lock_lock(lock); } } gl_lock_unlock(lock); } } }