/* * 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 Lesser 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include "LogManager.h" #include "Application.h" #include "ConfigEntry.h" #include "ConfigManager.h" #include namespace Mad { namespace Core { void LogManager::ConsoleLogger::logMessage(MessageCategory /*category*/, MessageLevel level, boost::posix_time::ptime /*timestamp*/, const std::string &message) { if(level != LOG_CRITICAL) {// Critical messages are printed to cerr directly, so don't print them a second time cerrLock.lock(); std::cerr << message << std::endl; cerrLock.unlock(); } } void LogManager::ConsoleLogger::logMessage(MessageCategory /*category*/, MessageLevel /*level*/, boost::posix_time::ptime /*timestamp*/, const std::string &message, const std::string &messageSource) { cerrLock.lock(); std::cerr << message << " from " << messageSource << std::endl; cerrLock.unlock(); } void LogManager::ConsoleLogger::logMessageDirect(MessageCategory /*category*/, MessageLevel /*level*/, boost::posix_time::ptime /*timestamp*/, const std::string &message) { cerrLock.lock(); std::cerr << message << std::endl; cerrLock.unlock(); } LogManager::LogManager(Application *application0) : application(application0), consoleLogger(new ConsoleLogger), configured(false), running(false) { application->getConfigManager()->registerConfigurable(this); } LogManager::~LogManager() { application->getConfigManager()->unregisterConfigurable(this); } 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(boost::static_pointer_cast(consoleLogger)); return true; } } else if(entry[1].empty()) { application->logf(Logger::LOG_WARNING, "Unknown logger '%s'.", entry[0][0].c_str()); return true; } } return false; } void LogManager::configFinished() { if(loggers.empty()) registerLogger(boost::static_pointer_cast(consoleLogger)); // TODO Debug consoleLogger->Logger::setLevel(LoggerBase::LOG_VERBOSE); queueLock.lock(); configured = true; queueLock.unlock(); queueCond.notify_one(); } void LogManager::log(MessageCategory category, MessageLevel level, boost::posix_time::ptime timestamp, const std::string &message) { if(level == LoggerBase::LOG_CRITICAL) consoleLogger->logMessageDirect(category, level, timestamp, message); queueLock.lock(); Message m = {category, level, timestamp, message}; messageQueue.push(m); queueLock.unlock(); queueCond.notify_one(); } void LogManager::log(MessageCategory category, MessageLevel level, boost::posix_time::ptime timestamp, const std::string &message, const std::string &source) { queueLock.lock(); RemoteMessage m = {category, level, timestamp, message, source}; remoteMessageQueue.push(m); queueLock.unlock(); queueCond.notify_one(); } void LogManager::loggerThread() { boost::unique_lock lock(queueLock); running = true; while(running) { while(running && ((messageQueue.empty() && messageQueue.empty()) || !configured)) queueCond.wait(lock); while(!messageQueue.empty()) { Message message = messageQueue.front(); messageQueue.pop(); lock.unlock(); loggerLock.lock(); 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); } loggerLock.unlock(); lock.lock(); } while(!remoteMessageQueue.empty()) { RemoteMessage message = remoteMessageQueue.front(); remoteMessageQueue.pop(); lock.unlock(); remoteLoggerLock.lock(); 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); } remoteLoggerLock.unlock(); lock.lock(); } } } } }