diff options
Diffstat (limited to 'src/Core/LogManager.cpp')
-rw-r--r-- | src/Core/LogManager.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/Core/LogManager.cpp b/src/Core/LogManager.cpp new file mode 100644 index 0000000..bf9767b --- /dev/null +++ b/src/Core/LogManager.cpp @@ -0,0 +1,146 @@ +/* + * LogManager.cpp + * + * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "LogManager.h" +#include "ConfigEntry.h" + +#include <iostream> + +namespace Mad { +namespace Core { + +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 + cerrLock.lock(); + std::cerr << message << std::endl; + cerrLock.unlock(); + } +} + +void LogManager::ConsoleLogger::logMessage(MessageCategory category _UNUSED_PARAMETER_, MessageLevel, time_t timestamp _UNUSED_PARAMETER_, 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 _UNUSED_PARAMETER_, MessageLevel level _UNUSED_PARAMETER_, time_t timestamp _UNUSED_PARAMETER_, const std::string &message) { + cerrLock.lock(); + std::cerr << message << std::endl; + cerrLock.unlock(); +} + + +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<Logger*>(&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<Logger*>(&consoleLogger)); + + // TODO Debug + consoleLogger.Logger::setLevel(LoggerBase::DEBUG); + + queueLock.lock(); + configured = true; + queueLock.unlock(); + queueCond.notify_one(); +} + +void LogManager::log(MessageCategory category, MessageLevel level, time_t timestamp, const std::string &message) { + if(level == LoggerBase::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, time_t 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<boost::mutex> 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<Logger*>::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<RemoteLogger*>::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(); + } + } +} + +} +} |