Store server statistics data in a log file and reload it when the server is restarted.
This commit is contained in:
+5
-1
@@ -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
|
||||
|
||||
@@ -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 &
|
||||
|
||||
@@ -28,14 +28,23 @@
|
||||
#include <core/loghelper.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#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<NetPacket> 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<ServerGameThread> 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<SessionData> s)
|
||||
}
|
||||
|
||||
void
|
||||
ServerLobbyThread::BroadcastStatisticsUpdate()
|
||||
ServerLobbyThread::UpdateStatisticsNumberOfPlayers()
|
||||
{
|
||||
boost::shared_ptr<NetPacket> 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<NetPacket> packet(new NetPacketStatisticsChanged);
|
||||
NetPacketStatisticsChanged::Data statData;
|
||||
statData.stats = stats;
|
||||
try {
|
||||
static_cast<NetPacketStatisticsChanged *>(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()
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<ConnectData> data);
|
||||
void ReAddSession(SessionWrapper session, int reason);
|
||||
@@ -123,7 +123,11 @@ protected:
|
||||
void SendError(boost::shared_ptr<SessionData> s, int errorCode);
|
||||
void SendJoinGameFailed(boost::shared_ptr<SessionData> s, int reason);
|
||||
void SendGameList(boost::shared_ptr<SessionData> 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
|
||||
|
||||
+2
-1
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user