Force reconnect of the irc bot by creating a file in the cache folder.

This commit is contained in:
lotodore
2012-03-03 14:16:45 +00:00
parent 93236dcc8d
commit 06145f30e9
11 changed files with 142 additions and 87 deletions
+7 -20
View File
@@ -34,6 +34,7 @@ private:
}; };
Thread::Thread() Thread::Thread()
: m_isTerminatedSemaphore(0), m_shouldTerminateSemaphore(0)
{ {
} }
@@ -48,22 +49,14 @@ Thread::Run()
// Create the boost thread object. // Create the boost thread object.
if (!m_threadObj.get()) { 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_threadObj.reset(new boost::thread(ThreadStarter(*this)));
m_threadStartBarrier->wait();
} }
} }
void void
Thread::SignalTermination() Thread::SignalTermination()
{ {
// Unlock the shouldTerminateMutex. m_shouldTerminateSemaphore.post();
if (m_userReqTerminateLock.get()) // cannot signal before calling Run
m_userReqTerminateLock->unlock();
} }
bool bool
@@ -75,19 +68,17 @@ Thread::Join(unsigned msecTimeout)
bool tmpIsTerminated; bool tmpIsTerminated;
if (msecTimeout == THREAD_WAIT_INFINITE) { if (msecTimeout == THREAD_WAIT_INFINITE) {
// Wait infinitely. // Wait infinitely.
boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex); m_isTerminatedSemaphore.wait();
tmpIsTerminated = true; tmpIsTerminated = true;
} else { } else {
// Wait for the termination of the application code. // Wait for the termination of the application code.
boost::defer_lock_t defer; tmpIsTerminated = m_isTerminatedSemaphore.timed_wait(boost::posix_time::microsec_clock::universal_time() + boost::posix_time::millisec(msecTimeout));
boost::timed_mutex::scoped_timed_lock lock(m_isTerminatedMutex, defer);
tmpIsTerminated = lock.timed_lock(boost::posix_time::millisec(msecTimeout));
} }
if (tmpIsTerminated) { if (tmpIsTerminated) {
boost::mutex::scoped_lock lock(m_threadObjMutex); boost::mutex::scoped_lock lock(m_threadObjMutex);
// Wait for "real" termination of the thread. // Wait for "real" termination of the thread.
if (m_threadObj.get()) { if (m_threadObj) {
m_threadObj->join(); m_threadObj->join();
m_threadObj.reset(); m_threadObj.reset();
} }
@@ -105,18 +96,14 @@ Thread::Msleep(unsigned msecs)
void void
Thread::MainWrapper() Thread::MainWrapper()
{ {
boost::timed_mutex::scoped_lock lock(m_isTerminatedMutex);
assert(m_threadStartBarrier.get());
m_threadStartBarrier->wait();
this->Main(); this->Main();
m_isTerminatedSemaphore.post();
} }
bool bool
Thread::ShouldTerminate() const Thread::ShouldTerminate() const
{ {
boost::defer_lock_t defer; return m_shouldTerminateSemaphore.try_wait();
boost::timed_mutex::scoped_try_lock lock(m_shouldTerminateMutex, defer);
return lock.try_lock();
} }
bool bool
+3 -6
View File
@@ -21,7 +21,7 @@
#define _THREAD_H_ #define _THREAD_H_
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/thread/barrier.hpp> #include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#ifndef NANOSECONDS_PER_SECOND #ifndef NANOSECONDS_PER_SECOND
@@ -69,18 +69,15 @@ private:
// Flag specifying whether the application code within the // Flag specifying whether the application code within the
// thread was terminated. // thread was terminated.
mutable boost::timed_mutex m_isTerminatedMutex; mutable boost::interprocess::interprocess_semaphore m_isTerminatedSemaphore;
// Flag specifying whether the thread should be terminated. // Flag specifying whether the thread should be terminated.
mutable boost::timed_mutex m_shouldTerminateMutex; mutable boost::interprocess::interprocess_semaphore m_shouldTerminateSemaphore;
mutable boost::shared_ptr<boost::timed_mutex::scoped_try_lock> m_userReqTerminateLock;
// The boost thread object. // The boost thread object.
boost::shared_ptr<boost::thread> m_threadObj; boost::shared_ptr<boost::thread> m_threadObj;
mutable boost::mutex m_threadObjMutex; mutable boost::mutex m_threadObjMutex;
mutable boost::shared_ptr<boost::barrier> m_threadStartBarrier;
friend class ThreadStarter; friend class ThreadStarter;
}; };
+77 -9
View File
@@ -25,17 +25,21 @@
#include <net/socket_startup.h> #include <net/socket_startup.h>
#include <core/loghelper.h> #include <core/loghelper.h>
#include <boost/filesystem.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#define SERVER_RESTART_IRC_BOT_INTERVAL_SEC 86400 // 1 day #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 std;
using namespace boost::filesystem;
ServerAdminBot::ServerAdminBot() ServerAdminBot::ServerAdminBot(boost::shared_ptr<boost::asio::io_service> ioService)
: m_notifyTimeoutMinutes(0), m_notifyIntervalMinutes(0), m_notifyCounter(0), : 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 void
ServerAdminBot::Init(boost::shared_ptr<ServerLobbyThread> lobbyThread, boost::shared_ptr<IrcThread> ircAdminThread) ServerAdminBot::Init(boost::shared_ptr<ServerLobbyThread> lobbyThread, boost::shared_ptr<IrcThread> ircAdminThread, const std::string &cacheDir)
{ {
m_lobbyThread = lobbyThread; m_lobbyThread = lobbyThread;
m_ircAdminThread = ircAdminThread; m_ircAdminThread = ircAdminThread;
m_cacheDir = cacheDir;
} }
void void
@@ -251,14 +256,45 @@ ServerAdminBot::SignalIrcServerError(int errorCode)
void void
ServerAdminBot::Run() 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(); m_ircAdminThread->Run();
} }
}
void void
ServerAdminBot::Process() ServerAdminBot::ReconnectHandler(const boost::system::error_code& ec)
{
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_ircRestartTimer.elapsed().total_seconds() > SERVER_RESTART_IRC_BOT_INTERVAL_SEC) {
if (m_ircAdminThread) { if (m_ircAdminThread) {
m_ircAdminThread->SignalTermination(); m_ircAdminThread->SignalTermination();
if (m_ircAdminThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) { if (m_ircAdminThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) {
@@ -267,10 +303,31 @@ ServerAdminBot::Process()
m_ircAdminThread = tmpIrcThread; m_ircAdminThread = tmpIrcThread;
} }
} }
m_ircRestartTimer.reset();
m_ircRestartTimer.start();
} }
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); boost::mutex::scoped_lock lock(m_notifyMutex);
if (m_notifyTimeoutMinutes && m_notifyTimer.elapsed().total_seconds() >= m_notifyCounter * m_notifyIntervalMinutes * 60) { if (m_notifyTimeoutMinutes && m_notifyTimer.elapsed().total_seconds() >= m_notifyCounter * m_notifyIntervalMinutes * 60) {
@@ -315,6 +372,12 @@ ServerAdminBot::Process()
m_notifyTimer.reset(); 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) if (m_ircAdminThread)
m_ircAdminThread->SignalTermination(); m_ircAdminThread->SignalTermination();
// Terminated the timers.
m_notifyLoopTimer.cancel();
m_reconnectTimer.cancel();
m_checkFileTimer.cancel();
} }
bool bool
+21 -8
View File
@@ -32,8 +32,8 @@
using namespace std; using namespace std;
ServerLobbyBot::ServerLobbyBot() ServerLobbyBot::ServerLobbyBot(boost::shared_ptr<boost::asio::io_service> ioService)
: m_ircRestartTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::second_timer::auto_start) : m_reconnectTimer(*ioService)
{ {
} }
@@ -94,14 +94,22 @@ ServerLobbyBot::SignalLobbyMessage(unsigned playerId, const std::string &playerN
void void
ServerLobbyBot::Run() 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(); m_ircLobbyThread->Run();
} }
}
void 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) { if (m_ircLobbyThread) {
m_ircLobbyThread->SignalTermination(); m_ircLobbyThread->SignalTermination();
if (m_ircLobbyThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) { if (m_ircLobbyThread->Join(NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC)) {
@@ -110,9 +118,11 @@ ServerLobbyBot::Process()
m_ircLobbyThread = tmpIrcThread; m_ircLobbyThread = tmpIrcThread;
} }
} }
m_reconnectTimer.expires_from_now(
m_ircRestartTimer.reset(); boost::posix_time::seconds(SERVER_RESTART_IRC_BOT_INTERVAL_SEC));
m_ircRestartTimer.start(); m_reconnectTimer.async_wait(
boost::bind(
&ServerLobbyBot::Reconnect, shared_from_this(), boost::asio::placeholders::error));
} }
} }
@@ -121,6 +131,9 @@ ServerLobbyBot::SignalTermination()
{ {
if (m_ircLobbyThread) if (m_ircLobbyThread)
m_ircLobbyThread->SignalTermination(); m_ircLobbyThread->SignalTermination();
// Terminated the reconnect timer.
m_reconnectTimer.cancel();
} }
bool bool
-5
View File
@@ -87,11 +87,6 @@ ServerManager::RunAll()
GetLobbyThread().Run(); GetLobbyThread().Run();
} }
void
ServerManager::Process()
{
}
void void
ServerManager::SignalTerminationAll() ServerManager::SignalTerminationAll()
{ {
+3 -11
View File
@@ -29,8 +29,8 @@ using namespace std;
ServerManagerIrc::ServerManagerIrc(ConfigFile &config, GuiInterface &gui, ServerMode mode, AvatarManager &avatarManager) ServerManagerIrc::ServerManagerIrc(ConfigFile &config, GuiInterface &gui, ServerMode mode, AvatarManager &avatarManager)
: ServerManager(config, gui) : ServerManager(config, gui)
{ {
m_adminBot.reset(new ServerAdminBot); m_adminBot.reset(new ServerAdminBot(m_ioService));
m_lobbyBot.reset(new ServerLobbyBot); m_lobbyBot.reset(new ServerLobbyBot(m_ioService));
m_lobbyThread.reset(new ServerLobbyThread(gui, mode, *m_lobbyBot, config, avatarManager, 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")); myConfig.readConfigString("LobbyIRCChannelPassword"));
} }
m_adminBot->Init(m_lobbyThread, tmpIrcAdminThread); m_adminBot->Init(m_lobbyThread, tmpIrcAdminThread, myConfig.readConfigString("CacheDir"));
m_lobbyBot->Init(m_lobbyThread, tmpIrcLobbyThread); m_lobbyBot->Init(m_lobbyThread, tmpIrcLobbyThread);
ServerManager::Init(serverPort, ipv6, proto, logDir); ServerManager::Init(serverPort, ipv6, proto, logDir);
} }
@@ -81,14 +81,6 @@ ServerManagerIrc::RunAll()
ServerManager::RunAll(); ServerManager::RunAll();
} }
void
ServerManagerIrc::Process()
{
m_adminBot->Process();
m_lobbyBot->Process();
ServerManager::Process();
}
void void
ServerManagerIrc::SignalTerminationAll() ServerManagerIrc::SignalTerminationAll()
{ {
+15 -6
View File
@@ -22,6 +22,7 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <third_party/boost/timers.hpp> #include <third_party/boost/timers.hpp>
#include <string> #include <string>
#include <list> #include <list>
@@ -36,19 +37,23 @@ class ConfigFile;
class AvatarManager; class AvatarManager;
class IrcThread; class IrcThread;
class ServerAdminBot : public IrcCallback class ServerAdminBot : public IrcCallback, public boost::enable_shared_from_this<ServerAdminBot>
{ {
public: public:
ServerAdminBot(); ServerAdminBot(boost::shared_ptr<boost::asio::io_service> ioService);
virtual ~ServerAdminBot(); virtual ~ServerAdminBot();
void Init(boost::shared_ptr<ServerLobbyThread> lobbyThread, boost::shared_ptr<IrcThread> ircAdminThread); void Init(boost::shared_ptr<ServerLobbyThread> lobbyThread, boost::shared_ptr<IrcThread> ircAdminThread, const std::string &cacheDir);
// Main start function. // Main start function.
void Run(); void Run();
// Perform processing. // Reconnect the bot.
void Process(); 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(); void SignalTermination();
bool Join(bool wait); bool Join(bool wait);
@@ -68,6 +73,7 @@ protected:
private: private:
std::string m_ircNick; std::string m_ircNick;
std::string m_cacheDir;
mutable boost::mutex m_notifyMutex; mutable boost::mutex m_notifyMutex;
int m_notifyTimeoutMinutes; int m_notifyTimeoutMinutes;
int m_notifyIntervalMinutes; int m_notifyIntervalMinutes;
@@ -75,8 +81,11 @@ private:
boost::shared_ptr<ServerLobbyThread> m_lobbyThread; boost::shared_ptr<ServerLobbyThread> m_lobbyThread;
boost::shared_ptr<IrcThread> m_ircAdminThread; boost::shared_ptr<IrcThread> m_ircAdminThread;
boost::timers::portable::second_timer m_ircRestartTimer;
boost::timers::portable::second_timer m_notifyTimer; 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 #endif
+7 -6
View File
@@ -21,7 +21,7 @@
#define _SERVERLOBBYBOT_H_ #define _SERVERLOBBYBOT_H_
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <third_party/boost/timers.hpp> #include <boost/enable_shared_from_this.hpp>
#include <string> #include <string>
#include <list> #include <list>
@@ -35,10 +35,10 @@ class ConfigFile;
class AvatarManager; class AvatarManager;
class IrcThread; class IrcThread;
class ServerLobbyBot : public IrcCallback, public ServerIrcBotCallback class ServerLobbyBot : public IrcCallback, public ServerIrcBotCallback, public boost::enable_shared_from_this<ServerLobbyBot>
{ {
public: public:
ServerLobbyBot(); ServerLobbyBot(boost::shared_ptr<boost::asio::io_service> ioService);
virtual ~ServerLobbyBot(); virtual ~ServerLobbyBot();
void Init(boost::shared_ptr<ServerLobbyThread> lobbyThread, boost::shared_ptr<IrcThread> ircLobbyThread); void Init(boost::shared_ptr<ServerLobbyThread> lobbyThread, boost::shared_ptr<IrcThread> ircLobbyThread);
@@ -46,8 +46,8 @@ public:
// Main start function. // Main start function.
void Run(); void Run();
// Perform processing. // Reconnect the bot.
void Process(); void Reconnect(const boost::system::error_code& ec);
void SignalTermination(); void SignalTermination();
bool Join(bool wait); bool Join(bool wait);
@@ -72,7 +72,8 @@ private:
boost::shared_ptr<ServerLobbyThread> m_lobbyThread; boost::shared_ptr<ServerLobbyThread> m_lobbyThread;
boost::shared_ptr<IrcThread> m_ircLobbyThread; boost::shared_ptr<IrcThread> m_ircLobbyThread;
boost::timers::portable::second_timer m_ircRestartTimer;
boost::asio::deadline_timer m_reconnectTimer;
}; };
#endif #endif
-3
View File
@@ -46,9 +46,6 @@ public:
// Main start function. // Main start function.
virtual void RunAll(); virtual void RunAll();
// Let the server manager perform processing.
virtual void Process();
virtual void SignalTerminationAll(); virtual void SignalTerminationAll();
virtual bool JoinAll(bool wait); virtual bool JoinAll(bool wait);
-3
View File
@@ -37,9 +37,6 @@ public:
// Main start function. // Main start function.
virtual void RunAll(); virtual void RunAll();
// Let the server manager perform processing.
virtual void Process();
virtual void SignalTerminationAll(); virtual void SignalTerminationAll();
virtual bool JoinAll(bool wait); virtual bool JoinAll(bool wait);
-1
View File
@@ -343,7 +343,6 @@ bool Session::pollNetworkServerTerminated()
if (!myNetServer) if (!myNetServer)
retVal = true; // already terminated retVal = true; // already terminated
else { else {
myNetServer->Process();
if (myNetServer->JoinAll(false)) if (myNetServer->JoinAll(false))
retVal = true; retVal = true;
} }