From f9a08ac1c9cc1774b5f808364d9a011965641a3b Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 22 Jun 2014 14:07:23 -0500 Subject: Core/Dependencies: Remove ACE_Singleton dependency from the Log and DelayExecutor classes. Removed an unused function. --- src/server/shared/Logging/Log.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 5fa638e2f40..5f404fcfe70 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -26,14 +26,11 @@ #include #include -#include #define LOGGER_ROOT "root" class Log { - friend class ACE_Singleton; - typedef std::unordered_map LoggerMap; typedef std::unordered_map CachedLoggerContainer; @@ -42,6 +39,12 @@ class Log ~Log(); public: + static Log* instance() + { + static Log* instance = new Log(); + return instance; + } + void LoadFromConfig(); void Close(); bool ShouldLog(std::string const& type, LogLevel level); @@ -127,7 +130,7 @@ inline void Log::outMessage(std::string const& filter, LogLevel level, const cha va_end(ap); } -#define sLog ACE_Singleton::instance() +#define sLog Log::instance() #if PLATFORM != PLATFORM_WINDOWS #define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \ -- cgit v1.2.3 From 0a592dd9dbd34818deee472dd42d700b4746a27e Mon Sep 17 00:00:00 2001 From: leak Date: Tue, 24 Jun 2014 19:13:29 +0200 Subject: Removed ACE dependencies from LogWorker --- src/server/shared/Logging/Log.cpp | 2 +- src/server/shared/Logging/Log.h | 2 +- src/server/shared/Logging/LogWorker.cpp | 17 +++++------------ src/server/shared/Logging/LogWorker.h | 20 +++++--------------- 4 files changed, 12 insertions(+), 29 deletions(-) (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index fd7aa84c0e9..68745046433 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -273,7 +273,7 @@ void Log::write(LogMessage* msg) const msg->text.append("\n"); if (worker) - worker->enqueue(new LogOperation(logger, msg)); + worker->enqueue(*(new LogOperation(logger, msg))); else { logger->write(*msg); diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index c3a47d14e9e..29ebdb3faa1 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -23,7 +23,7 @@ #include "Appender.h" #include "Logger.h" #include "LogWorker.h" - +#include #include #include diff --git a/src/server/shared/Logging/LogWorker.cpp b/src/server/shared/Logging/LogWorker.cpp index b0c82b614f4..cea4262032b 100644 --- a/src/server/shared/Logging/LogWorker.cpp +++ b/src/server/shared/Logging/LogWorker.cpp @@ -17,29 +17,22 @@ #include "LogWorker.h" -LogWorker::LogWorker() - : m_queue(HIGH_WATERMARK, LOW_WATERMARK) -{ - ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 1); -} - LogWorker::~LogWorker() { - m_queue.deactivate(); - wait(); + m_queue.cancel(); } -int LogWorker::enqueue(LogOperation* op) +void LogWorker::enqueue(LogOperation& op) { - return m_queue.enqueue(op); + return m_queue.add(op); } int LogWorker::svc() { while (1) { - LogOperation* request; - if (m_queue.dequeue(request) == -1) + LogOperation* request = nullptr; + if (!m_queue.next(*request)) break; request->call(); diff --git a/src/server/shared/Logging/LogWorker.h b/src/server/shared/Logging/LogWorker.h index 25a57842e08..84d8ba632a8 100644 --- a/src/server/shared/Logging/LogWorker.h +++ b/src/server/shared/Logging/LogWorker.h @@ -19,29 +19,19 @@ #define LOGWORKER_H #include "LogOperation.h" +#include "LockedQueue.h" -#include -#include - -class LogWorker: protected ACE_Task_Base +class LogWorker { public: - LogWorker(); + LogWorker() {}; ~LogWorker(); - typedef ACE_Message_Queue_Ex LogMessageQueueType; - - enum - { - HIGH_WATERMARK = 8 * 1024 * 1024, - LOW_WATERMARK = 8 * 1024 * 1024 - }; - - int enqueue(LogOperation *op); + void enqueue(LogOperation& op); private: virtual int svc(); - LogMessageQueueType m_queue; + LockedQueue m_queue; }; #endif -- cgit v1.2.3 From d8d0b4730e4aece0ffe6a7b89bd74fb2940ea3fb Mon Sep 17 00:00:00 2001 From: leak Date: Tue, 24 Jun 2014 21:09:43 +0200 Subject: Revert "Removed ACE dependencies from LogWorker" This actually needs way more work This reverts commit 0a592dd9dbd34818deee472dd42d700b4746a27e. --- src/server/shared/Logging/Log.cpp | 2 +- src/server/shared/Logging/Log.h | 2 +- src/server/shared/Logging/LogWorker.cpp | 17 ++++++++++++----- src/server/shared/Logging/LogWorker.h | 20 +++++++++++++++----- 4 files changed, 29 insertions(+), 12 deletions(-) (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 68745046433..fd7aa84c0e9 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -273,7 +273,7 @@ void Log::write(LogMessage* msg) const msg->text.append("\n"); if (worker) - worker->enqueue(*(new LogOperation(logger, msg))); + worker->enqueue(new LogOperation(logger, msg)); else { logger->write(*msg); diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 29ebdb3faa1..c3a47d14e9e 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -23,7 +23,7 @@ #include "Appender.h" #include "Logger.h" #include "LogWorker.h" -#include + #include #include diff --git a/src/server/shared/Logging/LogWorker.cpp b/src/server/shared/Logging/LogWorker.cpp index cea4262032b..b0c82b614f4 100644 --- a/src/server/shared/Logging/LogWorker.cpp +++ b/src/server/shared/Logging/LogWorker.cpp @@ -17,22 +17,29 @@ #include "LogWorker.h" +LogWorker::LogWorker() + : m_queue(HIGH_WATERMARK, LOW_WATERMARK) +{ + ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 1); +} + LogWorker::~LogWorker() { - m_queue.cancel(); + m_queue.deactivate(); + wait(); } -void LogWorker::enqueue(LogOperation& op) +int LogWorker::enqueue(LogOperation* op) { - return m_queue.add(op); + return m_queue.enqueue(op); } int LogWorker::svc() { while (1) { - LogOperation* request = nullptr; - if (!m_queue.next(*request)) + LogOperation* request; + if (m_queue.dequeue(request) == -1) break; request->call(); diff --git a/src/server/shared/Logging/LogWorker.h b/src/server/shared/Logging/LogWorker.h index 84d8ba632a8..25a57842e08 100644 --- a/src/server/shared/Logging/LogWorker.h +++ b/src/server/shared/Logging/LogWorker.h @@ -19,19 +19,29 @@ #define LOGWORKER_H #include "LogOperation.h" -#include "LockedQueue.h" -class LogWorker +#include +#include + +class LogWorker: protected ACE_Task_Base { public: - LogWorker() {}; + LogWorker(); ~LogWorker(); - void enqueue(LogOperation& op); + typedef ACE_Message_Queue_Ex LogMessageQueueType; + + enum + { + HIGH_WATERMARK = 8 * 1024 * 1024, + LOW_WATERMARK = 8 * 1024 * 1024 + }; + + int enqueue(LogOperation *op); private: virtual int svc(); - LockedQueue m_queue; + LogMessageQueueType m_queue; }; #endif -- cgit v1.2.3 From eb36acd1522a2e5b8a7d2b4b4a67fc34fc777f03 Mon Sep 17 00:00:00 2001 From: leak Date: Mon, 30 Jun 2014 14:44:52 +0200 Subject: Replaced ACE_Task_Base based LogWorker with ProducerConsumerQueue --- src/server/authserver/Main.cpp | 1 - src/server/shared/Configuration/Config.cpp | 6 +- src/server/shared/Logging/Log.cpp | 2 +- src/server/shared/Logging/Log.h | 1 + src/server/shared/Logging/LogWorker.cpp | 34 ++++--- src/server/shared/Logging/LogWorker.h | 27 +++--- .../shared/Threading/ProducerConsumerQueue.h | 102 +++++++++++++++++++++ 7 files changed, 140 insertions(+), 33 deletions(-) create mode 100644 src/server/shared/Threading/ProducerConsumerQueue.h (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 2427c47a438..3901480c70d 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -67,7 +67,6 @@ using boost::asio::ip::tcp; void SignalHandler(const boost::system::error_code& error, int signalNumber) { - TC_LOG_ERROR("server.authserver", "SIGNAL HANDLER WORKING"); if (!error) { switch (signalNumber) diff --git a/src/server/shared/Configuration/Config.cpp b/src/server/shared/Configuration/Config.cpp index 9e0e57eb198..b6690d02155 100644 --- a/src/server/shared/Configuration/Config.cpp +++ b/src/server/shared/Configuration/Config.cpp @@ -71,7 +71,7 @@ bool ConfigMgr::GetBoolDefault(const char* name, bool def) { try { - std::string val = _config.get(name); + std::string val = _config.get(ptree::path_type(name, '/')); val.erase(std::remove(val.begin(), val.end(), '"'), val.end()); return (val == "true" || val == "TRUE" || val == "yes" || val == "YES" || val == "1"); } @@ -83,12 +83,12 @@ bool ConfigMgr::GetBoolDefault(const char* name, bool def) int ConfigMgr::GetIntDefault(const char* name, int def) { - return _config.get(name, def); + return _config.get(ptree::path_type(name, '/'), def); } float ConfigMgr::GetFloatDefault(const char* name, float def) { - return _config.get(name, def); + return _config.get(ptree::path_type(name, '/'), def); } std::string const& ConfigMgr::GetFilename() diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index fd7aa84c0e9..57d8797e61e 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -273,7 +273,7 @@ void Log::write(LogMessage* msg) const msg->text.append("\n"); if (worker) - worker->enqueue(new LogOperation(logger, msg)); + worker->Enqueue(new LogOperation(logger, msg)); else { logger->write(*msg); diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index c3a47d14e9e..8d2fd33d886 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -23,6 +23,7 @@ #include "Appender.h" #include "Logger.h" #include "LogWorker.h" +#include #include #include diff --git a/src/server/shared/Logging/LogWorker.cpp b/src/server/shared/Logging/LogWorker.cpp index b0c82b614f4..ab0f41bf105 100644 --- a/src/server/shared/Logging/LogWorker.cpp +++ b/src/server/shared/Logging/LogWorker.cpp @@ -16,35 +16,41 @@ */ #include "LogWorker.h" +#include LogWorker::LogWorker() - : m_queue(HIGH_WATERMARK, LOW_WATERMARK) { - ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, 1); + _cancelationToken = false; + _workerThread = std::thread(&LogWorker::WorkerThread, this); } LogWorker::~LogWorker() { - m_queue.deactivate(); - wait(); + _cancelationToken = true; + + _queue.Cancel(); + + _workerThread.join(); } -int LogWorker::enqueue(LogOperation* op) +void LogWorker::Enqueue(LogOperation* op) { - return m_queue.enqueue(op); + return _queue.Push(op); } -int LogWorker::svc() +void LogWorker::WorkerThread() { while (1) { - LogOperation* request; - if (m_queue.dequeue(request) == -1) - break; + LogOperation* operation = nullptr; + + _queue.WaitAndPop(operation); - request->call(); - delete request; - } + if (_cancelationToken) + return; - return 0; + operation->call(); + + delete operation; + } } diff --git a/src/server/shared/Logging/LogWorker.h b/src/server/shared/Logging/LogWorker.h index 25a57842e08..b2680b12c34 100644 --- a/src/server/shared/Logging/LogWorker.h +++ b/src/server/shared/Logging/LogWorker.h @@ -18,30 +18,29 @@ #ifndef LOGWORKER_H #define LOGWORKER_H -#include "LogOperation.h" +#include +#include -#include -#include +#include "LogOperation.h" +#include "ProducerConsumerQueue.h" -class LogWorker: protected ACE_Task_Base +class LogWorker { public: LogWorker(); ~LogWorker(); - typedef ACE_Message_Queue_Ex LogMessageQueueType; + void Enqueue(LogOperation *op); - enum - { - HIGH_WATERMARK = 8 * 1024 * 1024, - LOW_WATERMARK = 8 * 1024 * 1024 - }; + private: + ProducerConsumerQueue _queue; - int enqueue(LogOperation *op); + void WorkerThread(); + std::thread _workerThread; - private: - virtual int svc(); - LogMessageQueueType m_queue; + std::atomic_bool _cancelationToken; }; + + #endif diff --git a/src/server/shared/Threading/ProducerConsumerQueue.h b/src/server/shared/Threading/ProducerConsumerQueue.h new file mode 100644 index 00000000000..961cb9f9c82 --- /dev/null +++ b/src/server/shared/Threading/ProducerConsumerQueue.h @@ -0,0 +1,102 @@ +/* +* Copyright (C) 2008-2014 TrinityCore +* +* 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 2 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 . +*/ + +#ifndef _PCQ_H +#define _PCQ_H + +#include +#include +#include + +template +class ProducerConsumerQueue +{ +private: + std::mutex _queueLock; + std::queue _queue; + std::condition_variable _condition; + +public: + + void Push(const T& value) + { + _queueLock.lock(); + + _queue.push(std::move(value)); + + _queueLock.unlock(); + + _condition.notify_one(); + } + + bool Empty() const + { + std::lock_guard lock(_queueLock); + + return _queue.empty(); + } + + bool Pop(T& value) + { + std::lock_guard lock(_queueLock); + + if (_queue.empty()) + return false; + + value = _queue.front(); + + _queue.pop(); + + return true; + } + + void WaitAndPop(T& value) + { + std::unique_lock lock(_queueLock); + + _condition.wait(lock, [this](){ return !_queue.empty(); }); + + if (_queue.empty()) + return; + + value = _queue.front(); + + _queue.pop(); + } + + void Cancel() + { + _queueLock.lock(); + + while (!_queue.empty()) + { + T& value = _queue.front(); + + delete &value; + + _queue.pop(); + } + + _queueLock.unlock(); + + _condition.notify_all(); + } +}; + +#endif + + -- cgit v1.2.3 From d1594998f80762fa58f64cf123f9bf9cb77036e4 Mon Sep 17 00:00:00 2001 From: leak Date: Tue, 8 Jul 2014 20:55:25 +0200 Subject: Replaced the LogWorker thread with Boost ASIO --- src/server/shared/Database/DatabaseWorker.h | 1 + src/server/shared/Logging/Log.cpp | 17 +++++---- src/server/shared/Logging/Log.h | 16 ++++++-- src/server/shared/Logging/LogWorker.cpp | 56 ---------------------------- src/server/shared/Logging/LogWorker.h | 46 ----------------------- src/server/shared/Networking/AsyncAcceptor.h | 4 +- src/server/worldserver/Main.cpp | 6 +++ 7 files changed, 31 insertions(+), 115 deletions(-) delete mode 100644 src/server/shared/Logging/LogWorker.cpp delete mode 100644 src/server/shared/Logging/LogWorker.h (limited to 'src/server/shared/Logging/Log.h') diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/shared/Database/DatabaseWorker.h index 91aef2c7194..6f452c767f6 100644 --- a/src/server/shared/Database/DatabaseWorker.h +++ b/src/server/shared/Database/DatabaseWorker.h @@ -18,6 +18,7 @@ #ifndef _WORKERTHREAD_H #define _WORKERTHREAD_H +#include #include "ProducerConsumerQueue.h" class MySQLConnection; diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index 57d8797e61e..65cf930a634 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -29,7 +29,7 @@ #include #include -Log::Log() : worker(NULL) +Log::Log() : _ioService(nullptr), _strand(nullptr) { m_logsTimestamp = "_" + GetTimestampStr(); LoadFromConfig(); @@ -37,6 +37,7 @@ Log::Log() : worker(NULL) Log::~Log() { + delete _strand; Close(); } @@ -272,8 +273,13 @@ void Log::write(LogMessage* msg) const Logger const* logger = GetLoggerByType(msg->type); msg->text.append("\n"); - if (worker) - worker->Enqueue(new LogOperation(logger, msg)); + if (_ioService) + { + auto logOperation = std::shared_ptr(new LogOperation(logger, msg)); + + _ioService->post(_strand->wrap([logOperation](){ logOperation->call(); })); + + } else { logger->write(*msg); @@ -375,8 +381,6 @@ void Log::SetRealmId(uint32 id) void Log::Close() { - delete worker; - worker = NULL; loggers.clear(); for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) { @@ -390,9 +394,6 @@ void Log::LoadFromConfig() { Close(); - if (sConfigMgr->GetBoolDefault("Log.Async.Enable", false)) - worker = new LogWorker(); - AppenderId = 0; m_logsDir = sConfigMgr->GetStringDefault("LogsDir", ""); if (!m_logsDir.empty()) diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h index 8d2fd33d886..e739c9eaf4e 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/server/shared/Logging/Log.h @@ -22,8 +22,9 @@ #include "Define.h" #include "Appender.h" #include "Logger.h" -#include "LogWorker.h" #include +#include +#include #include #include @@ -39,9 +40,17 @@ class Log ~Log(); public: - static Log* instance() + + static Log* instance(boost::asio::io_service* ioService = nullptr) { static Log* instance = new Log(); + + if (ioService != nullptr) + { + instance->_ioService = ioService; + instance->_strand = new boost::asio::strand(*ioService); + } + return instance; } @@ -77,7 +86,8 @@ class Log std::string m_logsDir; std::string m_logsTimestamp; - LogWorker* worker; + boost::asio::io_service* _ioService; + boost::asio::strand* _strand; }; inline Logger const* Log::GetLoggerByType(std::string const& type) const diff --git a/src/server/shared/Logging/LogWorker.cpp b/src/server/shared/Logging/LogWorker.cpp deleted file mode 100644 index ab0f41bf105..00000000000 --- a/src/server/shared/Logging/LogWorker.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 2 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 "LogWorker.h" -#include - -LogWorker::LogWorker() -{ - _cancelationToken = false; - _workerThread = std::thread(&LogWorker::WorkerThread, this); -} - -LogWorker::~LogWorker() -{ - _cancelationToken = true; - - _queue.Cancel(); - - _workerThread.join(); -} - -void LogWorker::Enqueue(LogOperation* op) -{ - return _queue.Push(op); -} - -void LogWorker::WorkerThread() -{ - while (1) - { - LogOperation* operation = nullptr; - - _queue.WaitAndPop(operation); - - if (_cancelationToken) - return; - - operation->call(); - - delete operation; - } -} diff --git a/src/server/shared/Logging/LogWorker.h b/src/server/shared/Logging/LogWorker.h deleted file mode 100644 index b2680b12c34..00000000000 --- a/src/server/shared/Logging/LogWorker.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * - * 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 2 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 . - */ - -#ifndef LOGWORKER_H -#define LOGWORKER_H - -#include -#include - -#include "LogOperation.h" -#include "ProducerConsumerQueue.h" - -class LogWorker -{ - public: - LogWorker(); - ~LogWorker(); - - void Enqueue(LogOperation *op); - - private: - ProducerConsumerQueue _queue; - - void WorkerThread(); - std::thread _workerThread; - - std::atomic_bool _cancelationToken; -}; - - - -#endif diff --git a/src/server/shared/Networking/AsyncAcceptor.h b/src/server/shared/Networking/AsyncAcceptor.h index 1b65282527a..789bd9c3a74 100644 --- a/src/server/shared/Networking/AsyncAcceptor.h +++ b/src/server/shared/Networking/AsyncAcceptor.h @@ -37,9 +37,9 @@ public: _socket(ioService), _acceptor(ioService, tcp::endpoint(boost::asio::ip::address::from_string(bindIp), port)) { - AsyncAccept(); + _acceptor.set_option(boost::asio::ip::tcp::no_delay(tcpNoDelay)); - _socket.set_option(boost::asio::ip::tcp::no_delay(tcpNoDelay)); + AsyncAccept(); }; private: diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 15a282b70ea..05ae31e8780 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -145,6 +145,12 @@ extern int main(int argc, char** argv) return 1; } + if (sConfigMgr->GetBoolDefault("Log.Async.Enable", false)) + { + // If logs are supposed to be handled async then we need to pass the io_service into the Log singleton + Log::instance(&_ioService); + } + TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon)", _FULLVERSION); TC_LOG_INFO("server.worldserver", " to stop.\n"); TC_LOG_INFO("server.worldserver", " ______ __"); -- cgit v1.2.3