From d905359251c161ffd3392621ced026b04edc2abe Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 11 Nov 2007 15:58:35 +0000 Subject: [PATCH] Store server statistics data in a log file and reload it when the server is restarted. --- src/game_defs.h | 6 +- src/net/common/serveracceptthread.cpp | 4 +- src/net/common/serverlobbythread.cpp | 129 +++++++++++++++++++++----- src/net/serveracceptthread.h | 2 +- src/net/serverlobbythread.h | 15 ++- src/session.cpp | 3 +- 6 files changed, 127 insertions(+), 32 deletions(-) diff --git a/src/game_defs.h b/src/game_defs.h index 518441ff..91d59020 100644 --- a/src/game_defs.h +++ b/src/game_defs.h @@ -69,10 +69,14 @@ enum Button { struct ServerStats { - ServerStats() : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverStarted(0) {} + ServerStats() + : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverStarted(0), + maxGamesRunning(0), maxPlayersLoggedIn(0) {} unsigned numberOfPlayersOnServer; unsigned totalPlayersEverLoggedIn; unsigned totalGamesEverStarted; + unsigned maxGamesRunning; + unsigned maxPlayersLoggedIn; }; #endif diff --git a/src/net/common/serveracceptthread.cpp b/src/net/common/serveracceptthread.cpp index 4b806599..c1ef66ed 100644 --- a/src/net/common/serveracceptthread.cpp +++ b/src/net/common/serveracceptthread.cpp @@ -44,7 +44,7 @@ ServerAcceptThread::~ServerAcceptThread() } void -ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd) +ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const string &pwd, const string &logDir) { if (IsRunning()) { @@ -60,7 +60,7 @@ ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::s context.SetAddrFamily(socket_has_dual_stack() ? AF_INET6 : (ipv6 ? AF_INET6 : AF_INET)); context.SetServerPort(serverPort); - GetLobbyThread().Init(pwd); + GetLobbyThread().Init(pwd, logDir); } ServerCallback & diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index f3cebc6c..5ca89e9d 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -28,14 +28,23 @@ #include #include +#include #include +#include #define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. #define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day +#define SERVER_SAVE_STATISTICS_INTERVAL_SEC 60 #define SERVER_INIT_SESSION_TIMEOUT_SEC 20 #define SERVER_COMPUTER_PLAYER_NAME "Computer" +#define SERVER_STATISTICS_FILE_NAME "server_statistics.log" +#define SERVER_STATISTICS_STR_TOTAL_PLAYERS "TotalNumPlayersLoggedIn" +#define SERVER_STATISTICS_STR_TOTAL_GAMES "TotalNumGamesStarted" +#define SERVER_STATISTICS_STR_MAX_GAMES "MaxGamesRunning" +#define SERVER_STATISTICS_STR_MAX_PLAYERS "MaxPlayersLoggedIn" + using namespace std; @@ -60,7 +69,7 @@ private: ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager) : m_gui(gui), m_avatarManager(avatarManager), m_playerConfig(playerConfig), m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1), - m_totalPlayersLoggedIn(0), m_totalGamesStarted(0) + m_statDataChanged(false) { m_senderCallback.reset(new ServerSenderCallback(*this)); m_sender.reset(new SenderThread(GetSenderCallback())); @@ -73,9 +82,20 @@ ServerLobbyThread::~ServerLobbyThread() } void -ServerLobbyThread::Init(const string &pwd) +ServerLobbyThread::Init(const string &pwd, const string &logDir) { m_password = pwd; + // Read previous server statistics. + if (!logDir.empty()) + { + boost::filesystem::path logPath(logDir); + if (!logDir.empty()) + { + logPath /= SERVER_STATISTICS_FILE_NAME; + m_statisticsFileName = logPath.directory_string(); + ReadStatisticsFile(); + } + } } void @@ -129,7 +149,7 @@ ServerLobbyThread::CloseSession(SessionWrapper session) m_gameSessionManager.RemoveSession(session.sessionData->GetId()); // Update stats (if needed). - BroadcastStatisticsUpdate(); + UpdateStatisticsNumberOfPlayers(); } void @@ -177,6 +197,14 @@ ServerLobbyThread::NotifyStartingGame(unsigned gameId) boost::shared_ptr packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_STARTED); m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); + + { + boost::mutex::scoped_lock lock(m_statMutex); + ++m_statData.totalGamesEverStarted; + if (m_statData.totalGamesEverStarted > m_statData.maxGamesRunning) + m_statData.maxGamesRunning = m_statData.totalGamesEverStarted; + m_statDataChanged = true; + } } void @@ -262,6 +290,8 @@ ServerLobbyThread::Main() RemoveGameLoop(); // Cleanup cache. CleanupAvatarCache(); + // Save statistics if needed. + SaveStatisticsFile(); } } catch (const PokerTHException &e) { @@ -632,10 +662,10 @@ ServerLobbyThread::EstablishSession(SessionWrapper session) { boost::mutex::scoped_lock lock(m_statMutex); - ++m_totalPlayersLoggedIn; + ++m_statData.totalPlayersEverLoggedIn; + m_statDataChanged = true; } - - BroadcastStatisticsUpdate(); + UpdateStatisticsNumberOfPlayers(); } void @@ -753,12 +783,6 @@ ServerLobbyThread::InternalAddGame(boost::shared_ptr game) // Notify all players. m_sessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established); m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game); - - { - boost::mutex::scoped_lock lock(m_statMutex); - ++m_totalGamesStarted; - } - BroadcastStatisticsUpdate(); } void @@ -891,23 +915,32 @@ ServerLobbyThread::SendGameList(boost::shared_ptr s) } void -ServerLobbyThread::BroadcastStatisticsUpdate() +ServerLobbyThread::UpdateStatisticsNumberOfPlayers() { - boost::shared_ptr packet(new NetPacketStatisticsChanged); - NetPacketStatisticsChanged::Data statData; + ServerStats stats; unsigned curNumberOfPlayersOnServer = m_sessionManager.GetRawSessionCount() + m_gameSessionManager.GetRawSessionCount(); { boost::mutex::scoped_lock lock(m_statMutex); - if (curNumberOfPlayersOnServer != m_lastStatData.numberOfPlayersOnServer) - m_lastStatData.numberOfPlayersOnServer = statData.stats.numberOfPlayersOnServer = curNumberOfPlayersOnServer; - if (m_totalPlayersLoggedIn != m_lastStatData.totalPlayersEverLoggedIn) - m_lastStatData.totalPlayersEverLoggedIn = statData.stats.totalPlayersEverLoggedIn = m_totalPlayersLoggedIn; - if (m_totalGamesStarted != m_lastStatData.totalGamesEverStarted) - m_lastStatData.totalGamesEverStarted = statData.stats.totalGamesEverStarted = m_totalGamesStarted; + if (curNumberOfPlayersOnServer != m_statData.numberOfPlayersOnServer) + { + m_statData.numberOfPlayersOnServer = stats.numberOfPlayersOnServer = curNumberOfPlayersOnServer; + if (curNumberOfPlayersOnServer > m_statData.maxPlayersLoggedIn) + m_statData.maxPlayersLoggedIn = curNumberOfPlayersOnServer; + m_statDataChanged = true; + } } + // Do not send other stats than number of players for now. + BroadcastStatisticsUpdate(stats); +} - if (curNumberOfPlayersOnServer) +void +ServerLobbyThread::BroadcastStatisticsUpdate(const ServerStats &stats) +{ + if (stats.numberOfPlayersOnServer) { + boost::shared_ptr packet(new NetPacketStatisticsChanged); + NetPacketStatisticsChanged::Data statData; + statData.stats = stats; try { static_cast(packet.get())->SetData(statData); @@ -921,6 +954,58 @@ ServerLobbyThread::BroadcastStatisticsUpdate() } } +void +ServerLobbyThread::ReadStatisticsFile() +{ + ifstream i(m_statisticsFileName.c_str(), ios_base::in); + + if (!i.fail() && !i.eof()) + { + boost::mutex::scoped_lock lock(m_statMutex); + do + { + string statisticsType; + unsigned statisticsValue; + i >> statisticsType; + i >> statisticsValue; + if (statisticsType == SERVER_STATISTICS_STR_TOTAL_PLAYERS) + m_statData.totalPlayersEverLoggedIn = statisticsValue; + else if (statisticsType == SERVER_STATISTICS_STR_TOTAL_GAMES) + m_statData.totalGamesEverStarted = statisticsValue; + else if (statisticsType == SERVER_STATISTICS_STR_MAX_PLAYERS) + m_statData.maxPlayersLoggedIn = statisticsValue; + else if (statisticsType == SERVER_STATISTICS_STR_MAX_GAMES) + m_statData.maxGamesRunning = statisticsValue; + } while (!i.fail() && !i.eof()); + m_statDataChanged = false; + } +} + +void +ServerLobbyThread::SaveStatisticsFile() +{ + if (m_saveStatisticsTimer.elapsed().total_seconds() > SERVER_SAVE_STATISTICS_INTERVAL_SEC) + { + { + boost::mutex::scoped_lock lock(m_statMutex); + if (m_statDataChanged) + { + ofstream o(m_statisticsFileName.c_str(), ios_base::out | ios_base::trunc); + if (!o.fail()) + { + o << SERVER_STATISTICS_STR_TOTAL_PLAYERS " " << m_statData.totalPlayersEverLoggedIn << endl; + o << SERVER_STATISTICS_STR_TOTAL_GAMES " " << m_statData.totalGamesEverStarted << endl; + o << SERVER_STATISTICS_STR_MAX_PLAYERS " " << m_statData.maxPlayersLoggedIn << endl; + o << SERVER_STATISTICS_STR_MAX_GAMES " " << m_statData.maxGamesRunning << endl; + m_statDataChanged = false; + } + } + } + m_saveStatisticsTimer.reset(); + m_saveStatisticsTimer.start(); + } +} + ServerCallback & ServerLobbyThread::GetCallback() { diff --git a/src/net/serveracceptthread.h b/src/net/serveracceptthread.h index 84b2bf20..c6b80fd0 100644 --- a/src/net/serveracceptthread.h +++ b/src/net/serveracceptthread.h @@ -42,7 +42,7 @@ public: virtual ~ServerAcceptThread(); // Set the parameters. - void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd); + void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const std::string &logDir); ServerCallback &GetCallback(); GuiInterface &GetGui(); diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 2dd91263..a2bdbf47 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -49,7 +49,7 @@ public: ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager); virtual ~ServerLobbyThread(); - void Init(const std::string &pwd); + void Init(const std::string &pwd, const std::string &logDir); void AddConnection(boost::shared_ptr data); void ReAddSession(SessionWrapper session, int reason); @@ -123,7 +123,11 @@ protected: void SendError(boost::shared_ptr s, int errorCode); void SendJoinGameFailed(boost::shared_ptr s, int reason); void SendGameList(boost::shared_ptr s); - void BroadcastStatisticsUpdate(); + void UpdateStatisticsNumberOfPlayers(); + void BroadcastStatisticsUpdate(const ServerStats &stats); + + void ReadStatisticsFile(); + void SaveStatisticsFile(); SenderThread &GetSender(); ReceiverHelper &GetReceiver(); @@ -167,6 +171,7 @@ private: AvatarManager &m_avatarManager; std::string m_password; + std::string m_statisticsFileName; ConfigFile *m_playerConfig; u_int32_t m_curGameId; @@ -175,12 +180,12 @@ private: mutable boost::mutex m_curUniquePlayerIdMutex; - ServerStats m_lastStatData; - unsigned m_totalPlayersLoggedIn; - unsigned m_totalGamesStarted; + ServerStats m_statData; + bool m_statDataChanged; mutable boost::mutex m_statMutex; boost::timers::portable::microsec_timer m_cacheCleanupTimer; + boost::timers::portable::microsec_timer m_saveStatisticsTimer; }; #endif diff --git a/src/session.cpp b/src/session.cpp index 1a46ca78..ab2d2cc8 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -261,7 +261,8 @@ void Session::startNetworkServer() myConfig->readConfigInt("ServerPort"), myConfig->readConfigInt("ServerUseIpv6") == 1, myConfig->readConfigInt("ServerUseSctp") == 1, - myConfig->readConfigString("ServerPassword")); + myConfig->readConfigString("ServerPassword"), + myConfig->readConfigString("LogDir")); myNetServer->Run(); }