From 06145f30e9b3b6135c5af09dbab96374bcb03b90 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sat, 3 Mar 2012 14:16:45 +0000 Subject: [PATCH] Force reconnect of the irc bot by creating a file in the cache folder. --- src/core/common/thread.cpp | 27 ++------ src/core/thread.h | 9 +-- src/net/common/serveradminbot.cpp | 104 +++++++++++++++++++++++----- src/net/common/serverlobbybot.cpp | 29 +++++--- src/net/common/servermanager.cpp | 5 -- src/net/common/servermanagerirc.cpp | 14 +--- src/net/serveradminbot.h | 21 ++++-- src/net/serverlobbybot.h | 13 ++-- src/net/servermanager.h | 3 - src/net/servermanagerirc.h | 3 - src/session.cpp | 1 - 11 files changed, 142 insertions(+), 87 deletions(-) diff --git a/src/core/common/thread.cpp b/src/core/common/thread.cpp index 9a66f72e..552e71cc 100644 --- a/src/core/common/thread.cpp +++ b/src/core/common/thread.cpp @@ -34,6 +34,7 @@ private: }; Thread::Thread() + : m_isTerminatedSemaphore(0), m_shouldTerminateSemaphore(0) { } @@ -48,22 +49,14 @@ Thread::Run() // Create the boost thread object. if (!m_threadObj.get()) { - // Initialise data structures within the context of the thread - // who runs/terminates this thread. - m_userReqTerminateLock.reset(new boost::timed_mutex::scoped_try_lock(m_shouldTerminateMutex)); - m_threadStartBarrier.reset(new boost::barrier(2)); - m_threadObj.reset(new boost::thread(ThreadStarter(*this))); - m_threadStartBarrier->wait(); } } void Thread::SignalTermination() { - // Unlock the shouldTerminateMutex. - if (m_userReqTerminateLock.get()) // cannot signal before calling Run - m_userReqTerminateLock->unlock(); + m_shouldTerminateSemaphore.post(); } bool @@ -75,19 +68,17 @@ Thread::Join(unsigned msecTimeout) bool tmpIsTerminated; if (msecTimeout == THREAD_WAIT_INFINITE) { // Wait infinitely. - boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); + m_isTerminatedSemaphore.wait(); tmpIsTerminated = true; } else { // Wait for the termination of the application code. - boost::defer_lock_t defer; - boost::timed_mutex::scoped_timed_lock lock(m_isTerminatedMutex, defer); - tmpIsTerminated = lock.timed_lock(boost::posix_time::millisec(msecTimeout)); + tmpIsTerminated = m_isTerminatedSemaphore.timed_wait(boost::posix_time::microsec_clock::universal_time() + boost::posix_time::millisec(msecTimeout)); } if (tmpIsTerminated) { boost::mutex::scoped_lock lock(m_threadObjMutex); // Wait for "real" termination of the thread. - if (m_threadObj.get()) { + if (m_threadObj) { m_threadObj->join(); m_threadObj.reset(); } @@ -105,18 +96,14 @@ Thread::Msleep(unsigned msecs) void Thread::MainWrapper() { - boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); - assert(m_threadStartBarrier.get()); - m_threadStartBarrier->wait(); this->Main(); + m_isTerminatedSemaphore.post(); } bool Thread::ShouldTerminate() const { - boost::defer_lock_t defer; - boost::timed_mutex::scoped_try_lock lock(m_shouldTerminateMutex, defer); - return lock.try_lock(); + return m_shouldTerminateSemaphore.try_wait(); } bool diff --git a/src/core/thread.h b/src/core/thread.h index cdf0bb01..27b00e58 100644 --- a/src/core/thread.h +++ b/src/core/thread.h @@ -21,7 +21,7 @@ #define _THREAD_H_ #include -#include +#include #include #ifndef NANOSECONDS_PER_SECOND @@ -69,18 +69,15 @@ private: // Flag specifying whether the application code within the // thread was terminated. - mutable boost::timed_mutex m_isTerminatedMutex; + mutable boost::interprocess::interprocess_semaphore m_isTerminatedSemaphore; // Flag specifying whether the thread should be terminated. - mutable boost::timed_mutex m_shouldTerminateMutex; - mutable boost::shared_ptr m_userReqTerminateLock; + mutable boost::interprocess::interprocess_semaphore m_shouldTerminateSemaphore; // The boost thread object. boost::shared_ptr m_threadObj; mutable boost::mutex m_threadObjMutex; - mutable boost::shared_ptr m_threadStartBarrier; - friend class ThreadStarter; }; diff --git a/src/net/common/serveradminbot.cpp b/src/net/common/serveradminbot.cpp index dbe539c6..26c1241d 100644 --- a/src/net/common/serveradminbot.cpp +++ b/src/net/common/serveradminbot.cpp @@ -25,17 +25,21 @@ #include #include +#include #include #include #define SERVER_RESTART_IRC_BOT_INTERVAL_SEC 86400 // 1 day +#define SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC 1 +#define SERVER_CHECK_IRC_BOT_INTERVAL_SEC 60 using namespace std; +using namespace boost::filesystem; -ServerAdminBot::ServerAdminBot() +ServerAdminBot::ServerAdminBot(boost::shared_ptr ioService) : m_notifyTimeoutMinutes(0), m_notifyIntervalMinutes(0), m_notifyCounter(0), - m_ircRestartTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::second_timer::auto_start), - m_notifyTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::second_timer::manual_start) + m_notifyTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::second_timer::manual_start), + m_reconnectTimer(*ioService), m_notifyLoopTimer(*ioService), m_checkFileTimer(*ioService) { } @@ -44,10 +48,11 @@ ServerAdminBot::~ServerAdminBot() } void -ServerAdminBot::Init(boost::shared_ptr lobbyThread, boost::shared_ptr ircAdminThread) +ServerAdminBot::Init(boost::shared_ptr lobbyThread, boost::shared_ptr ircAdminThread, const std::string &cacheDir) { m_lobbyThread = lobbyThread; m_ircAdminThread = ircAdminThread; + m_cacheDir = cacheDir; } void @@ -251,26 +256,78 @@ ServerAdminBot::SignalIrcServerError(int errorCode) void ServerAdminBot::Run() { - if (m_ircAdminThread) + if (m_ircAdminThread) { + // Initialise the timers. + m_reconnectTimer.expires_from_now( + boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC)); + m_reconnectTimer.async_wait( + boost::bind( + &ServerAdminBot::ReconnectHandler, shared_from_this(), boost::asio::placeholders::error)); + m_notifyLoopTimer.expires_from_now( + boost::posix_time::seconds(SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC)); + m_notifyLoopTimer.async_wait( + boost::bind( + &ServerAdminBot::NotifyLoop, shared_from_this(), boost::asio::placeholders::error)); + m_checkFileTimer.expires_from_now( + boost::posix_time::seconds(SERVER_CHECK_IRC_BOT_INTERVAL_SEC)); + m_checkFileTimer.async_wait( + boost::bind( + &ServerAdminBot::CheckFileHandler, shared_from_this(), boost::asio::placeholders::error)); + m_ircAdminThread->Run(); + } } void -ServerAdminBot::Process() +ServerAdminBot::ReconnectHandler(const boost::system::error_code& ec) { - if (m_ircRestartTimer.elapsed().total_seconds() > SERVER_RESTART_IRC_BOT_INTERVAL_SEC) { - if (m_ircAdminThread) { - m_ircAdminThread->SignalTermination(); - if (m_ircAdminThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) { - boost::shared_ptr tmpIrcThread(new IrcThread(*m_ircAdminThread)); - tmpIrcThread->Run(); - m_ircAdminThread = tmpIrcThread; - } - } - m_ircRestartTimer.reset(); - m_ircRestartTimer.start(); + if (!ec) { + Reconnect(); + + m_reconnectTimer.expires_from_now( + boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC)); + m_reconnectTimer.async_wait( + boost::bind( + &ServerAdminBot::ReconnectHandler, shared_from_this(), boost::asio::placeholders::error)); } - { +} + +void +ServerAdminBot::Reconnect() +{ + if (m_ircAdminThread) { + m_ircAdminThread->SignalTermination(); + if (m_ircAdminThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) { + boost::shared_ptr tmpIrcThread(new IrcThread(*m_ircAdminThread)); + tmpIrcThread->Run(); + m_ircAdminThread = tmpIrcThread; + } + } +} + +void +ServerAdminBot::CheckFileHandler(const boost::system::error_code& ec) +{ + if (!ec) { + // Reconnect the irc bot if a signal file exists. + path cachePath(m_cacheDir); + cachePath /= "SignalAdminReconnect"; + if (exists(cachePath)) { + remove(cachePath); + Reconnect(); + } + m_checkFileTimer.expires_from_now( + boost::posix_time::seconds(SERVER_CHECK_IRC_BOT_INTERVAL_SEC)); + m_checkFileTimer.async_wait( + boost::bind( + &ServerAdminBot::CheckFileHandler, shared_from_this(), boost::asio::placeholders::error)); + } +} + +void +ServerAdminBot::NotifyLoop(const boost::system::error_code& ec) +{ + if (!ec) { boost::mutex::scoped_lock lock(m_notifyMutex); if (m_notifyTimeoutMinutes && m_notifyTimer.elapsed().total_seconds() >= m_notifyCounter * m_notifyIntervalMinutes * 60) { @@ -315,6 +372,12 @@ ServerAdminBot::Process() m_notifyTimer.reset(); } } + m_notifyLoopTimer.expires_from_now( + boost::posix_time::seconds(SERVER_NOTIFY_IRC_BOT_INTERVAL_SEC)); + m_notifyLoopTimer.async_wait( + boost::bind( + &ServerAdminBot::NotifyLoop, shared_from_this(), boost::asio::placeholders::error)); + } } @@ -323,6 +386,11 @@ ServerAdminBot::SignalTermination() { if (m_ircAdminThread) m_ircAdminThread->SignalTermination(); + + // Terminated the timers. + m_notifyLoopTimer.cancel(); + m_reconnectTimer.cancel(); + m_checkFileTimer.cancel(); } bool diff --git a/src/net/common/serverlobbybot.cpp b/src/net/common/serverlobbybot.cpp index d9164d9f..ddf87afb 100644 --- a/src/net/common/serverlobbybot.cpp +++ b/src/net/common/serverlobbybot.cpp @@ -32,8 +32,8 @@ using namespace std; -ServerLobbyBot::ServerLobbyBot() - : m_ircRestartTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::second_timer::auto_start) +ServerLobbyBot::ServerLobbyBot(boost::shared_ptr ioService) + : m_reconnectTimer(*ioService) { } @@ -94,14 +94,22 @@ ServerLobbyBot::SignalLobbyMessage(unsigned playerId, const std::string &playerN void ServerLobbyBot::Run() { - if (m_ircLobbyThread) + if (m_ircLobbyThread) { + // Initialise the reconnect timer. + m_reconnectTimer.expires_from_now( + boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC)); + m_reconnectTimer.async_wait( + boost::bind( + &ServerLobbyBot::Reconnect, shared_from_this(), boost::asio::placeholders::error)); + m_ircLobbyThread->Run(); + } } void -ServerLobbyBot::Process() +ServerLobbyBot::Reconnect(const boost::system::error_code& ec) { - if (m_ircRestartTimer.elapsed().total_seconds() > SERVER_RESTART_IRC_BOT_INTERVAL_SEC) { + if (!ec) { if (m_ircLobbyThread) { m_ircLobbyThread->SignalTermination(); if (m_ircLobbyThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) { @@ -110,9 +118,11 @@ ServerLobbyBot::Process() m_ircLobbyThread = tmpIrcThread; } } - - m_ircRestartTimer.reset(); - m_ircRestartTimer.start(); + m_reconnectTimer.expires_from_now( + boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC)); + m_reconnectTimer.async_wait( + boost::bind( + &ServerLobbyBot::Reconnect, shared_from_this(), boost::asio::placeholders::error)); } } @@ -121,6 +131,9 @@ ServerLobbyBot::SignalTermination() { if (m_ircLobbyThread) m_ircLobbyThread->SignalTermination(); + + // Terminated the reconnect timer. + m_reconnectTimer.cancel(); } bool diff --git a/src/net/common/servermanager.cpp b/src/net/common/servermanager.cpp index d833753f..3c25f8e7 100644 --- a/src/net/common/servermanager.cpp +++ b/src/net/common/servermanager.cpp @@ -87,11 +87,6 @@ ServerManager::RunAll() GetLobbyThread().Run(); } -void -ServerManager::Process() -{ -} - void ServerManager::SignalTerminationAll() { diff --git a/src/net/common/servermanagerirc.cpp b/src/net/common/servermanagerirc.cpp index 502ed0d7..c4a9189b 100644 --- a/src/net/common/servermanagerirc.cpp +++ b/src/net/common/servermanagerirc.cpp @@ -29,8 +29,8 @@ using namespace std; ServerManagerIrc::ServerManagerIrc(ConfigFile &config, GuiInterface &gui, ServerMode mode, AvatarManager &avatarManager) : ServerManager(config, gui) { - m_adminBot.reset(new ServerAdminBot); - m_lobbyBot.reset(new ServerLobbyBot); + m_adminBot.reset(new ServerAdminBot(m_ioService)); + m_lobbyBot.reset(new ServerLobbyBot(m_ioService)); m_lobbyThread.reset(new ServerLobbyThread(gui, mode, *m_lobbyBot, config, avatarManager, m_ioService)); } @@ -68,7 +68,7 @@ ServerManagerIrc::Init(unsigned serverPort, bool ipv6, ServerTransportProtocol p myConfig.readConfigString("LobbyIRCChannelPassword")); } - m_adminBot->Init(m_lobbyThread, tmpIrcAdminThread); + m_adminBot->Init(m_lobbyThread, tmpIrcAdminThread, myConfig.readConfigString("CacheDir")); m_lobbyBot->Init(m_lobbyThread, tmpIrcLobbyThread); ServerManager::Init(serverPort, ipv6, proto, logDir); } @@ -81,14 +81,6 @@ ServerManagerIrc::RunAll() ServerManager::RunAll(); } -void -ServerManagerIrc::Process() -{ - m_adminBot->Process(); - m_lobbyBot->Process(); - ServerManager::Process(); -} - void ServerManagerIrc::SignalTerminationAll() { diff --git a/src/net/serveradminbot.h b/src/net/serveradminbot.h index beaa4752..71347620 100644 --- a/src/net/serveradminbot.h +++ b/src/net/serveradminbot.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -36,19 +37,23 @@ class ConfigFile; class AvatarManager; class IrcThread; -class ServerAdminBot : public IrcCallback +class ServerAdminBot : public IrcCallback, public boost::enable_shared_from_this { public: - ServerAdminBot(); + ServerAdminBot(boost::shared_ptr ioService); virtual ~ServerAdminBot(); - void Init(boost::shared_ptr lobbyThread, boost::shared_ptr ircAdminThread); + void Init(boost::shared_ptr lobbyThread, boost::shared_ptr ircAdminThread, const std::string &cacheDir); // Main start function. void Run(); - // Perform processing. - void Process(); + // Reconnect the bot. + void ReconnectHandler(const boost::system::error_code& ec); + void Reconnect(); + void CheckFileHandler(const boost::system::error_code& ec); + + void NotifyLoop(const boost::system::error_code& ec); void SignalTermination(); bool Join(bool wait); @@ -68,6 +73,7 @@ protected: private: std::string m_ircNick; + std::string m_cacheDir; mutable boost::mutex m_notifyMutex; int m_notifyTimeoutMinutes; int m_notifyIntervalMinutes; @@ -75,8 +81,11 @@ private: boost::shared_ptr m_lobbyThread; boost::shared_ptr m_ircAdminThread; - boost::timers::portable::second_timer m_ircRestartTimer; boost::timers::portable::second_timer m_notifyTimer; + + boost::asio::deadline_timer m_reconnectTimer; + boost::asio::deadline_timer m_notifyLoopTimer; + boost::asio::deadline_timer m_checkFileTimer; }; #endif diff --git a/src/net/serverlobbybot.h b/src/net/serverlobbybot.h index de725111..91edcfd6 100644 --- a/src/net/serverlobbybot.h +++ b/src/net/serverlobbybot.h @@ -21,7 +21,7 @@ #define _SERVERLOBBYBOT_H_ #include -#include +#include #include #include @@ -35,10 +35,10 @@ class ConfigFile; class AvatarManager; class IrcThread; -class ServerLobbyBot : public IrcCallback, public ServerIrcBotCallback +class ServerLobbyBot : public IrcCallback, public ServerIrcBotCallback, public boost::enable_shared_from_this { public: - ServerLobbyBot(); + ServerLobbyBot(boost::shared_ptr ioService); virtual ~ServerLobbyBot(); void Init(boost::shared_ptr lobbyThread, boost::shared_ptr ircLobbyThread); @@ -46,8 +46,8 @@ public: // Main start function. void Run(); - // Perform processing. - void Process(); + // Reconnect the bot. + void Reconnect(const boost::system::error_code& ec); void SignalTermination(); bool Join(bool wait); @@ -72,7 +72,8 @@ private: boost::shared_ptr m_lobbyThread; boost::shared_ptr m_ircLobbyThread; - boost::timers::portable::second_timer m_ircRestartTimer; + + boost::asio::deadline_timer m_reconnectTimer; }; #endif diff --git a/src/net/servermanager.h b/src/net/servermanager.h index d5914ef3..d06d1377 100644 --- a/src/net/servermanager.h +++ b/src/net/servermanager.h @@ -46,9 +46,6 @@ public: // Main start function. virtual void RunAll(); - // Let the server manager perform processing. - virtual void Process(); - virtual void SignalTerminationAll(); virtual bool JoinAll(bool wait); diff --git a/src/net/servermanagerirc.h b/src/net/servermanagerirc.h index 636b27d2..029413dc 100644 --- a/src/net/servermanagerirc.h +++ b/src/net/servermanagerirc.h @@ -37,9 +37,6 @@ public: // Main start function. virtual void RunAll(); - // Let the server manager perform processing. - virtual void Process(); - virtual void SignalTerminationAll(); virtual bool JoinAll(bool wait); diff --git a/src/session.cpp b/src/session.cpp index 82826ab9..30a87ce5 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -343,7 +343,6 @@ bool Session::pollNetworkServerTerminated() if (!myNetServer) retVal = true; // already terminated else { - myNetServer->Process(); if (myNetServer->JoinAll(false)) retVal = true; }