From 88e3d219588052a8ab222ab4f6f2b27c9c29c1b2 Mon Sep 17 00:00:00 2001 From: Guillaume Melquiond Date: Sun, 16 Sep 2007 11:10:06 +0000 Subject: Added global accounting of beings. --- ChangeLog | 7 +++++ src/Makefile.am | 1 + src/account-server/main-account.cpp | 43 ++++++++++++++++++++++++---- src/account-server/serverhandler.cpp | 53 +++++++++++++++++++++++++++++++++++ src/account-server/serverhandler.hpp | 6 ++++ src/game-server/accountconnection.cpp | 46 +++++++++++++++++++++++++++++- src/game-server/accountconnection.hpp | 7 ++++- src/game-server/main-game.cpp | 1 + 8 files changed, 156 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index c2b0daa2..22f48f60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,13 @@ * src/chat-server/chathandler.hpp: Fixed missing header. * src/account-server/serverhandler.cpp: Moved map/server data into connection local storage. + * src/game-server/accountconnection.cpp, src/game-server/main-game.cpp, + src/game-server/accountconnection.hpp: Added statistic sender to + game server. + * src/account-server/serverhandler.cpp, + src/account-server/serverhandler.hpp, src/Makefile.am, + src/account-server/main-account.cpp: Added statistic receiver and + dumper to account server. 2007-09-10 Eugenio Favalli diff --git a/src/Makefile.am b/src/Makefile.am index f63ef660..7f2dcba7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,6 +60,7 @@ tmwserv_account_SOURCES = \ utils/processorutils.cpp \ utils/stringfilter.h \ utils/stringfilter.cpp \ + utils/timer.cpp \ utils/tokencollector.hpp \ utils/tokencollector.cpp \ utils/tokendispenser.hpp \ diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp index 1aacf2fb..68cb134b 100644 --- a/src/account-server/main-account.cpp +++ b/src/account-server/main-account.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -44,13 +45,15 @@ #include "utils/logger.h" #include "utils/processorutils.hpp" #include "utils/stringfilter.h" +#include "utils/timer.h" // Default options that automake should be able to override. #define DEFAULT_LOG_FILE "tmwserv-account.log" +#define DEFAULT_STATS_FILE "tmwserv.stats" #define DEFAULT_CONFIG_FILE "tmwserv.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" -bool running = true; /**< Determines if server keeps running */ +static bool running = true; /**< Determines if server keeps running */ Configuration config; /**< XML config reader */ @@ -75,7 +78,7 @@ ChatChannelManager *chatChannelManager; GuildManager *guildManager; /** Callback used when SIGQUIT signal is received. */ -void closeGracefully(int) +static void closeGracefully(int) { running = false; } @@ -83,7 +86,7 @@ void closeGracefully(int) /** * Initializes the server. */ -void initialize() +static void initialize() { // Reset to default segmentation fault handling for debugging purposes @@ -185,7 +188,7 @@ void initialize() /** * Deinitializes the server. */ -void deinitialize() +static void deinitialize() { delete stringFilter; // Write configuration file @@ -211,11 +214,35 @@ void deinitialize() PHYSFS_deinit(); } +/** + * Dumps statistics. + */ +static void dumpStatistics() +{ +#if defined STATS_FILE + std::string path = STATS_FILE; +#else + +#if (defined __USE_UNIX98 || defined __FreeBSD__) + std::string path = getenv("HOME"); + path += "/."; + path += DEFAULT_STATS_FILE; +#else // Win32, ... + std::string path = DEFAULT_STATS_FILE; +#endif + +#endif + + std::ofstream os(path.c_str()); + os << "\n"; + serverHandler->dumpStatistics(os); + os << "\n"; +} /** * Show command line arguments */ -void printHelp() +static void printHelp() { std::cout << "tmwserv" << std::endl << std::endl << "Options: " << std::endl @@ -228,7 +255,7 @@ void printHelp() /** * Parse the command line arguments */ -void parseOptions(int argc, char *argv[]) +static void parseOptions(int argc, char *argv[]) { const char *optstring = "h"; @@ -293,10 +320,14 @@ int main(int argc, char *argv[]) return 3; } + // Dump statistics every 10 seconds. + utils::Timer statTimer(10000); + while (running) { accountHandler->process(50); chatHandler->process(50); serverHandler->process(50); + if (statTimer.poll()) dumpStatistics(); } LOG_INFO("Received: Quit signal, closing down..."); diff --git a/src/account-server/serverhandler.cpp b/src/account-server/serverhandler.cpp index 87f99c81..39e63c6e 100644 --- a/src/account-server/serverhandler.cpp +++ b/src/account-server/serverhandler.cpp @@ -249,6 +249,32 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) storage->banCharacter(id, duration); } break; + case GAMSG_STATISTICS: + { + while (msg.getUnreadLength()) + { + int mapId = msg.readShort(); + ServerStatistics::iterator i = server->maps.find(mapId); + if (i == server->maps.end()) + { + LOG_ERROR("Server " << server->address << ':' + << server->port << " should not be sending stati" + "stics for map " << mapId << '.'); + // Skip remaining data. + break; + } + MapStatistics &m = i->second; + m.nbThings = msg.readShort(); + m.nbMonsters = msg.readShort(); + int nb = msg.readShort(); + m.players.resize(nb); + for (int j = 0; j < nb; ++j) + { + m.players[j] = msg.readLong(); + } + } + } break; + #if 0 case GAMSG_GUILD_CREATE: { @@ -424,6 +450,33 @@ void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg) comp->send(result); } +void ServerHandler::dumpStatistics(std::ostream &os) const +{ + for (NetComputers::const_iterator i = clients.begin(), + i_end = clients.end(); i != i_end; ++i) + { + GameServer *server = static_cast< GameServer * >(*i); + if (!server->port) continue; + os << "address << "\" port=\"" + << server->port << "\">\n"; + + for (ServerStatistics::const_iterator j = server->maps.begin(), + j_end = server->maps.end(); j != j_end; ++j) + { + MapStatistics const &m = j->second; + os << "first << "\" nb_things=\"" << m.nbThings + << "\" nb_monsters=\"" << m.nbMonsters << "\">\n"; + for (std::vector< int >::const_iterator k = m.players.begin(), + k_end = m.players.end(); k != k_end; ++k) + { + os << "\n"; + } + os << "\n"; + } + os << "\n"; + } +} + #if 0 void ServerHandler::enterChannel(const std::string &name, CharacterData *player) diff --git a/src/account-server/serverhandler.hpp b/src/account-server/serverhandler.hpp index febc663e..76151569 100644 --- a/src/account-server/serverhandler.hpp +++ b/src/account-server/serverhandler.hpp @@ -24,6 +24,7 @@ #ifndef _TMWSERV_SERVERHANDLER_H_ #define _TMWSERV_SERVERHANDLER_H_ +#include #include #include "net/connectionhandler.hpp" @@ -68,6 +69,11 @@ class ServerHandler: public ConnectionHandler */ void enterChannel(const std::string &guildName, Character *player); + /** + * Dumps per-server statistics into given stream + */ + void dumpStatistics(std::ostream &) const; + protected: /** * Processes server messages. diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index 9a2084df..4219b33d 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -21,9 +21,10 @@ * $Id$ */ +#include "game-server/accountconnection.hpp" + #include "configuration.h" #include "defines.h" -#include "game-server/accountconnection.hpp" #include "game-server/character.hpp" #include "game-server/gamehandler.hpp" #include "game-server/map.hpp" @@ -260,6 +261,49 @@ void AccountConnection::banCharacter(Character *ch, int duration) send(msg); } +void AccountConnection::sendStatistics() +{ + MessageOut msg(GAMSG_STATISTICS); + MapManager::Maps const &maps = MapManager::getMaps(); + for (MapManager::Maps::const_iterator i = maps.begin(), + i_end = maps.end(); i != i_end; ++i) + { + MapComposite *m = i->second; + if (!m->isActive()) continue; + msg.writeShort(i->first); + int nbThings = 0, nbMonsters = 0; + typedef std::vector< Thing * > Things; + Things const &things = m->getEverything(); + std::vector< int > players; + for (Things::const_iterator j = things.begin(), + j_end = things.end(); j != j_end; ++j) + { + Thing *t = *j; + switch (t->getType()) + { + case OBJECT_CHARACTER: + players.push_back + (static_cast< Character * >(t)->getDatabaseID()); + break; + case OBJECT_MONSTER: + ++nbMonsters; + break; + default: + ++nbThings; + } + } + msg.writeShort(nbThings); + msg.writeShort(nbMonsters); + msg.writeShort(players.size()); + for (std::vector< int >::const_iterator j = players.begin(), + j_end = players.end(); j != j_end; ++j) + { + msg.writeLong(*j); + } + } + send(msg); +} + #if 0 void AccountConnection::playerCreateGuild(int id, const std::string &guildName) { diff --git a/src/game-server/accountconnection.hpp b/src/game-server/accountconnection.hpp index b591df16..59652dd5 100644 --- a/src/game-server/accountconnection.hpp +++ b/src/game-server/accountconnection.hpp @@ -64,7 +64,12 @@ class AccountConnection : public Connection /** * Sends ban message. */ - void banCharacter(Character *, int); + void banCharacter(Character *, int); + + /** + * Gathers statistics and sends them. + */ + void sendStatistics(); #if 0 /** diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 0325f28c..db8fee45 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -301,6 +301,7 @@ int main(int argc, char *argv[]) // Print world time at 10 second intervals to show we're alive if (worldTime % 100 == 0) { LOG_INFO("World time: " << worldTime); + accountHandler->sendStatistics(); } // Handle all messages that are in the message queues -- cgit v1.2.3-70-g09d2