From 1314085928af6cc5e3db71c93a49e093fc234ef4 Mon Sep 17 00:00:00 2001 From: H-M-H Date: Thu, 17 Dec 2015 22:04:38 +0100 Subject: [PATCH] restructured sqlconnection reading from and writing to several different servers is now possible TODO: -handle Exceptions properly (try another sqlserver) -if everything fails while writing write the insert to a file --- src/engine/server.h | 4 - src/engine/server/server.cpp | 81 ++-- src/engine/server/server.h | 15 +- src/engine/server/sql_connector.cpp | 42 ++ src/engine/server/sql_connector.h | 39 ++ .../score => engine/server}/sql_server.cpp | 0 .../score => engine/server}/sql_server.h | 9 +- .../server}/sql_string_helpers.h | 4 +- src/engine/shared/config_variables.h | 11 +- src/game/server/score/sql_score.cpp | 459 +++++++++--------- src/game/server/score/sql_score.h | 44 +- 11 files changed, 375 insertions(+), 333 deletions(-) create mode 100644 src/engine/server/sql_connector.cpp create mode 100644 src/engine/server/sql_connector.h rename src/{game/server/score => engine/server}/sql_server.cpp (100%) rename src/{game/server/score => engine/server}/sql_server.h (92%) rename src/{game/server/score => engine/server}/sql_string_helpers.h (96%) diff --git a/src/engine/server.h b/src/engine/server.h index daaf95369..60c844506 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -166,10 +166,6 @@ public: virtual int* GetIdMap(int ClientID) = 0; -#if defined (CONF_SQL) - virtual class CSqlServer *SqlServer() = 0; - virtual class CSqlServer **SqlMasterServers() = 0; -#endif }; class IGameServer : public IInterface diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 918153c96..15efbaa17 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -42,6 +42,11 @@ #include #endif +#ifdef CONF_SQL +CSqlServer** CSqlConnector::ms_ppSqlReadServers = 0; +CSqlServer** CSqlConnector::ms_ppSqlWriteServers = 0; +#endif + static const char *StrLtrim(const char *pStr) { while(*pStr) @@ -302,10 +307,6 @@ CServer::CServer() m_pGameServer = 0; -#if defined (CONF_SQL) - m_pSqlServer = 0; -#endif - m_CurrentGameTick = 0; m_RunServer = 1; @@ -326,8 +327,14 @@ CServer::CServer() m_ServerInfoHighLoad = false; #if defined (CONF_SQL) - for (int i = 0; i < MAX_SQLMASTERS; i++) - m_apMasterSqlServers[i] = 0; + for (int i = 0; i < MAX_SQLSERVERS; i++) + { + m_apSqlReadServers[i] = 0; + m_apSqlWriteServers[i] = 0; + } + + CSqlConnector::SetReadServers(m_apSqlReadServers); + CSqlConnector::SetWriteServers(m_apSqlWriteServers); #endif Init(); @@ -1659,14 +1666,6 @@ int CServer::Run() str_format(aBuf, sizeof(aBuf), "server name is '%s'", g_Config.m_SvName); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); -#if defined (CONF_SQL) - m_pSqlServer = new CSqlServer(g_Config.m_SvSqlDatabase, g_Config.m_SvSqlPrefix, g_Config.m_SvSqlUser, g_Config.m_SvSqlPw, g_Config.m_SvSqlIp, g_Config.m_SvSqlPort); - - // create tables - if(g_Config.m_SvSqlCreateTables) - m_pSqlServer->CreateTables(); -#endif - GameServer()->OnInit(); str_format(aBuf, sizeof(aBuf), "version %s", GameServer()->NetVersion()); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); @@ -1834,12 +1833,14 @@ int CServer::Run() mem_free(m_pCurrentMapData); #if defined (CONF_SQL) - if (m_pSqlServer) - delete m_pSqlServer; + for (int i = 0; i < MAX_SQLSERVERS; i++) + { + if (m_apSqlReadServers[i]) + delete m_apSqlReadServers[i]; - for (int i = 0; i < MAX_SQLMASTERS; i++) - if (m_apMasterSqlServers[i]) - delete m_apMasterSqlServers[i]; + if (m_apSqlWriteServers[i]) + delete m_apSqlWriteServers[i]; + } #endif return 0; @@ -2019,30 +2020,34 @@ void CServer::ConLogout(IConsole::IResult *pResult, void *pUser) #if defined (CONF_SQL) -void CServer::ConAddSqlMaster(IConsole::IResult *pResult, void *pUserData) +void CServer::ConAddSqlServer(IConsole::IResult *pResult, void *pUserData) { CServer *pSelf = (CServer *)pUserData; - if (pResult->NumArguments() != 6) + if (pResult->NumArguments() != 7) { - pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "6 arguments are required"); + pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "7 arguments are required"); return; } - for (int i = 0; i < MAX_SQLMASTERS; i++) - { - if (!pSelf->m_apMasterSqlServers[i]) - { - pSelf->m_apMasterSqlServers[i] = new CSqlServer(pResult->GetString(0), pResult->GetString(1), pResult->GetString(2), pResult->GetString(3), pResult->GetString(4), pResult->GetInteger(5)); + bool ReadOnly = !pResult->GetInteger(0); - if(g_Config.m_SvSqlMastersCreateTables) + CSqlServer** apSqlServers = ReadOnly ? pSelf->m_apSqlReadServers : pSelf->m_apSqlWriteServers; + + for (int i = 0; i < MAX_SQLSERVERS; i++) + { + if (!apSqlServers[i]) + { + apSqlServers[i] = new CSqlServer(pResult->GetString(1), pResult->GetString(2), pResult->GetString(3), pResult->GetString(4), pResult->GetString(5), pResult->GetInteger(6)); + + if(g_Config.m_SvSqlCreateTables == 3 || (g_Config.m_SvSqlCreateTables == 1 && ReadOnly) || (g_Config.m_SvSqlCreateTables == 2 && !ReadOnly)) { - void *TablesThread = thread_init(CreateTablesThread, pSelf->m_apMasterSqlServers[i]); + void *TablesThread = thread_init(CreateTablesThread, apSqlServers[i]); thread_detach(TablesThread); } char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "Added new sqlmasterserver: %d: DB: '%s' Prefix: '%s' User: '%s' Pass: '%s' IP: '%s' Port: %d", i, pSelf->m_apMasterSqlServers[i]->GetDatabase(), pSelf->m_apMasterSqlServers[i]->GetPrefix(), pSelf->m_apMasterSqlServers[i]->GetUser(), pSelf->m_apMasterSqlServers[i]->GetPass(), pSelf->m_apMasterSqlServers[i]->GetIP(), pSelf->m_apMasterSqlServers[i]->GetPort()); + str_format(aBuf, sizeof(aBuf), "Added new Sql%sServer: %d: DB: '%s' Prefix: '%s' User: '%s' Pass: '%s' IP: '%s' Port: %d", ReadOnly ? "Read" : "Write", i, apSqlServers[i]->GetDatabase(), apSqlServers[i]->GetPrefix(), apSqlServers[i]->GetUser(), apSqlServers[i]->GetPass(), apSqlServers[i]->GetIP(), apSqlServers[i]->GetPort()); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); return; } @@ -2050,15 +2055,19 @@ void CServer::ConAddSqlMaster(IConsole::IResult *pResult, void *pUserData) pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", "failed to add new sqlmaster: limit of sqlmasters reached"); } -void CServer::ConDumpSqlMaster(IConsole::IResult *pResult, void *pUserData) +void CServer::ConDumpSqlServers(IConsole::IResult *pResult, void *pUserData) { CServer *pSelf = (CServer *)pUserData; - for (int i = 0; i < MAX_SQLMASTERS; i++) - if (pSelf->m_apMasterSqlServers[i]) + bool ReadOnly = !pResult->GetInteger(0); + + CSqlServer** apSqlServers = ReadOnly ? pSelf->m_apSqlReadServers : pSelf->m_apSqlWriteServers; + + for (int i = 0; i < MAX_SQLSERVERS; i++) + if (apSqlServers[i]) { char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "SQL-Master %d: DB: '%s' Prefix: '%s' User: '%s' Pass: '%s' IP: '%s' Port: %d", i, pSelf->m_apMasterSqlServers[i]->GetDatabase(), pSelf->m_apMasterSqlServers[i]->GetPrefix(), pSelf->m_apMasterSqlServers[i]->GetUser(), pSelf->m_apMasterSqlServers[i]->GetPass(), pSelf->m_apMasterSqlServers[i]->GetIP(), pSelf->m_apMasterSqlServers[i]->GetPort()); + str_format(aBuf, sizeof(aBuf), "SQL-%s %d: DB: '%s' Prefix: '%s' User: '%s' Pass: '%s' IP: '%s' Port: %d", ReadOnly ? "Read" : "Write", i, apSqlServers[i]->GetDatabase(), apSqlServers[i]->GetPrefix(), apSqlServers[i]->GetUser(), apSqlServers[i]->GetPass(), apSqlServers[i]->GetIP(), apSqlServers[i]->GetPort()); pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); } } @@ -2201,8 +2210,8 @@ void CServer::RegisterCommands() #if defined (CONF_SQL) - Console()->Register("add_sqlmaster", "sssssi", CFGFLAG_SERVER, ConAddSqlMaster, this, "add a sqlmasterserver "); - Console()->Register("dump_sqlmaster", "", CFGFLAG_SERVER, ConDumpSqlMaster, this, "dumps all sqlmasterservers"); + Console()->Register("add_sqlserver", "isssssi", CFGFLAG_SERVER, ConAddSqlServer, this, "add a sqlserver "); + Console()->Register("dump_sqlservers", "i", CFGFLAG_SERVER, ConDumpSqlServers, this, "dumps all sqlservers readservers = 0, writeservers = 1"); #endif diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 9b477f1cd..751f6377c 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -18,7 +18,8 @@ #include #if defined (CONF_SQL) - #include + #include "sql_connector.h" + #include "sql_server.h" #endif class CSnapIDPool @@ -81,8 +82,8 @@ class CServer : public IServer class IStorage *m_pStorage; #if defined (CONF_SQL) - CSqlServer* m_pSqlServer; - CSqlServer* m_apMasterSqlServers[MAX_SQLMASTERS]; + CSqlServer* m_apSqlReadServers[MAX_SQLSERVERS]; + CSqlServer* m_apSqlWriteServers[MAX_SQLSERVERS];; #endif public: @@ -281,8 +282,8 @@ public: #if defined (CONF_SQL) // console commands for sqlmasters - static void ConAddSqlMaster(IConsole::IResult *pResult, void *pUserData); - static void ConDumpSqlMaster(IConsole::IResult *pResult, void *pUserData); + static void ConAddSqlServer(IConsole::IResult *pResult, void *pUserData); + static void ConDumpSqlServers(IConsole::IResult *pResult, void *pUserData); static void CreateTablesThread(void *pData); #endif @@ -316,10 +317,6 @@ public: virtual int* GetIdMap(int ClientID); -#if defined (CONF_SQL) - CSqlServer *SqlServer() { return m_pSqlServer; } - CSqlServer **SqlMasterServers() { return m_apMasterSqlServers; } -#endif }; #endif diff --git a/src/engine/server/sql_connector.cpp b/src/engine/server/sql_connector.cpp new file mode 100644 index 000000000..00772ad66 --- /dev/null +++ b/src/engine/server/sql_connector.cpp @@ -0,0 +1,42 @@ +#if defined(CONF_SQL) + +#include + +#include "sql_connector.h" + +CSqlConnector::CSqlConnector() : +m_pSqlServer(0), +m_NumReadRetries(0), +m_NumWriteRetries(0) +{} + +bool CSqlConnector::ConnectSqlServer(bool ReadOnly) +{ + ReadOnly ? ++m_NumReadRetries : ++m_NumWriteRetries; + + bool passedOldServer = !m_pSqlServer; + + for (int i = 0; i < MAX_SQLSERVERS && SqlServer(i, ReadOnly); i++) + { + + if (!passedOldServer) + { + if (m_pSqlServer == SqlServer(i, ReadOnly)) + passedOldServer = true; + continue; + } + + if (SqlServer(i, ReadOnly) && SqlServer(i, ReadOnly)->Connect()) + { + m_pSqlServer = SqlServer(i, ReadOnly); + return true; + } + if (SqlServer()) + dbg_msg("SQL", "Warning: Unable to connect to Sql%sServer %d ('%s'), trying next...", ReadOnly ? "read" : "write", i, SqlServer()->GetIP()); + } + dbg_msg("SQL", "ERROR: No Sql%sServers available", ReadOnly ? "Read" : "Write"); + m_pSqlServer = 0; + return false; +} + +#endif diff --git a/src/engine/server/sql_connector.h b/src/engine/server/sql_connector.h new file mode 100644 index 000000000..a51785ed7 --- /dev/null +++ b/src/engine/server/sql_connector.h @@ -0,0 +1,39 @@ +#ifndef ENGINE_SERVER_SQL_CONNECTOR_H +#define ENGINE_SERVER_SQL_CONNECTOR_H + +#include "sql_server.h" + +enum +{ + MAX_SQLSERVERS=15 +}; + +// implementation to provide sqlservers +class CSqlConnector +{ +public: + CSqlConnector(); + + CSqlServer* SqlServer(int i, bool ReadOnly = true) { return ReadOnly ? ms_ppSqlReadServers[i] : ms_ppSqlWriteServers[i]; } + + // always returns the last connected sql-server + CSqlServer* SqlServer() { return m_pSqlServer; } + + static void SetReadServers(CSqlServer** ppReadServers) { ms_ppSqlReadServers = ppReadServers; } + static void SetWriteServers(CSqlServer** ppWriteServers) { ms_ppSqlWriteServers = ppWriteServers; } + + bool ConnectSqlServer(bool ReadOnly = true); + + bool MaxTriesReached(bool ReadOnly = true) { return ReadOnly ? m_NumReadRetries : m_NumWriteRetries >= MAX_SQLSERVERS; } + +private: + + CSqlServer *m_pSqlServer; + static CSqlServer **ms_ppSqlReadServers; + static CSqlServer **ms_ppSqlWriteServers; + + int m_NumReadRetries; + int m_NumWriteRetries; +}; + +#endif diff --git a/src/game/server/score/sql_server.cpp b/src/engine/server/sql_server.cpp similarity index 100% rename from src/game/server/score/sql_server.cpp rename to src/engine/server/sql_server.cpp diff --git a/src/game/server/score/sql_server.h b/src/engine/server/sql_server.h similarity index 92% rename from src/game/server/score/sql_server.h rename to src/engine/server/sql_server.h index 65fd114e2..e505efc33 100644 --- a/src/game/server/score/sql_server.h +++ b/src/engine/server/sql_server.h @@ -1,5 +1,5 @@ -#ifndef GAME_SERVER_SQL_SERVER_H -#define GAME_SERVER_SQL_SERVER_H +#ifndef ENGINE_SERVER_SQL_SERVER_H +#define ENGINE_SERVER_SQL_SERVER_H #include @@ -7,11 +7,6 @@ #include #include -enum -{ - MAX_SQLMASTERS=10 -}; - class CSqlServer { public: diff --git a/src/game/server/score/sql_string_helpers.h b/src/engine/server/sql_string_helpers.h similarity index 96% rename from src/game/server/score/sql_string_helpers.h rename to src/engine/server/sql_string_helpers.h index 8e12bd631..c84ce6e68 100644 --- a/src/game/server/score/sql_string_helpers.h +++ b/src/engine/server/sql_string_helpers.h @@ -1,5 +1,5 @@ -#ifndef GAME_SERVER_SQL_STRING_HELPERS_H -#define GAME_SERVER_SQL_STRING_HELPERS_H +#ifndef ENGINE_SERVER_SQL_STRING_HELPERS_H +#define ENGINE_SERVER_SQL_STRING_HELPERS_H #include diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index 758d7d063..5e4155f58 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -217,19 +217,10 @@ MACRO_CONFIG_STR(SvScoreFolder, sv_score_folder, 32, "records", CFGFLAG_SERVER, #if defined(CONF_SQL) MACRO_CONFIG_INT(SvUseSQL, sv_use_sql, 0, 0, 1, CFGFLAG_SERVER, "Enables SQL DB instead of record file") -MACRO_CONFIG_STR(SvSqlUser, sv_sql_user, 32, "nameless", CFGFLAG_SERVER, "SQL User") -MACRO_CONFIG_STR(SvSqlPw, sv_sql_pw, 32, "tee", CFGFLAG_SERVER, "SQL Password") -MACRO_CONFIG_STR(SvSqlIp, sv_sql_ip, 32, "127.0.0.1", CFGFLAG_SERVER, "SQL Database IP") -MACRO_CONFIG_INT(SvSqlPort, sv_sql_port, 3306, 0, 65535, CFGFLAG_SERVER, "SQL Database port") -MACRO_CONFIG_INT(SvSqlCreateTables, sv_sql_create_tables, 1, 0, 1, CFGFLAG_SERVER, "Try to create the SQL tables when starting") -MACRO_CONFIG_STR(SvSqlDatabase, sv_sql_database, 16, "teeworlds", CFGFLAG_SERVER, "SQL Database name") +MACRO_CONFIG_INT(SvSqlCreateTables, sv_sql_create_tables, 0, 0, 3, CFGFLAG_SERVER, "Try to create the SQL tables when starting (O = never, 1 = readserver, 2 = write server, 3 = both)") MACRO_CONFIG_STR(SvSqlServerName, sv_sql_servername, 5, "UNK", CFGFLAG_SERVER, "SQL Server name that is inserted into record table") -MACRO_CONFIG_STR(SvSqlPrefix, sv_sql_prefix, 16, "record", CFGFLAG_SERVER, "SQL Database table prefix") MACRO_CONFIG_INT(SvSaveGames, sv_savegames, 1, 0, 1, CFGFLAG_SERVER, "Enables savegames (/save and /load)") MACRO_CONFIG_INT(SvSaveGamesDelay, sv_savegames_delay, 60, 0, 10000, CFGFLAG_SERVER, "Delay in seconds for loading a savegame") - -MACRO_CONFIG_INT(SvUseSQLMasters, sv_use_sqlmasters, 0, 0, 1, CFGFLAG_SERVER, "Redirects all writes to the specified masterservers") -MACRO_CONFIG_INT(SvSqlMastersCreateTables, sv_sqlmasters_create_tables, 0, 0, 1, CFGFLAG_SERVER, "Try to create the SQL tables when starting") #endif MACRO_CONFIG_INT(SvDDRaceRules, sv_ddrace_rules, 1, 0, 1, CFGFLAG_SERVER, "Whether the default mod rules are displayed or not") diff --git a/src/game/server/score/sql_score.cpp b/src/game/server/score/sql_score.cpp index 7b6543792..507e2daa4 100644 --- a/src/game/server/score/sql_score.cpp +++ b/src/game/server/score/sql_score.cpp @@ -8,21 +8,20 @@ #include #include "sql_score.h" -#include "sql_string_helpers.h" +#include #include "../entities/character.h" #include "../gamemodes/DDRace.h" #include "../save.h" -CGameContext *CSqlData::ms_pGameServer = 0; -IServer *CSqlData::ms_pServer = 0; -CPlayerData *CSqlData::ms_pPlayerData = 0; -const char *CSqlData::ms_pMap = 0; -CSqlServer *CSqlData::ms_pSqlServer = 0; -CSqlServer **CSqlData::ms_pMasterSqlServers = 0; +CGameContext* CSqlData::ms_pGameServer = 0; +IServer* CSqlData::ms_pServer = 0; +CPlayerData* CSqlData::ms_pPlayerData = 0; +const char* CSqlData::ms_pMap = 0; -CSqlScore::CSqlScore(CGameContext *pGameServer) : m_pGameServer(pGameServer), - m_pServer(pGameServer->Server()) +CSqlScore::CSqlScore(CGameContext *pGameServer) : +m_pGameServer(pGameServer), +m_pServer(pGameServer->Server()) { str_copy(m_aMap, g_Config.m_SvMap, sizeof(m_aMap)); ClearString(m_aMap); @@ -31,28 +30,26 @@ CSqlScore::CSqlScore(CGameContext *pGameServer) : m_pGameServer(pGameServer), CSqlData::ms_pServer = m_pServer; CSqlData::ms_pPlayerData = PlayerData(0); CSqlData::ms_pMap = m_aMap; - CSqlData::ms_pSqlServer = SqlServer(); - CSqlData::ms_pMasterSqlServers = SqlMasterServers(); Init(); } -// create tables... should be done only once void CSqlScore::Init() { + CSqlConnector Connector; // create connection - if(SqlServer()->Connect()) + if(Connector.ConnectSqlServer()) { try { char aBuf[1024]; // get the best time - str_format(aBuf, sizeof(aBuf), "SELECT Time FROM %s_race WHERE Map='%s' ORDER BY `Time` ASC LIMIT 0, 1;", SqlServer()->GetPrefix(), m_aMap); - SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "SELECT Time FROM %s_race WHERE Map='%s' ORDER BY `Time` ASC LIMIT 0, 1;", Connector.SqlServer()->GetPrefix(), m_aMap); + Connector.SqlServer()->executeSqlQuery(aBuf); - if(SqlServer()->GetResults()->next()) + if(Connector.SqlServer()->GetResults()->next()) { - ((CGameControllerDDRace*)GameServer()->m_pController)->m_CurrentRecord = (float)SqlServer()->GetResults()->getDouble("Time"); + ((CGameControllerDDRace*)GameServer()->m_pController)->m_CurrentRecord = (float)Connector.SqlServer()->GetResults()->getDouble("Time"); dbg_msg("SQL", "Getting best time on server done"); } @@ -66,7 +63,7 @@ void CSqlScore::Init() } // disconnect from database - SqlServer()->Disconnect(); + Connector.SqlServer()->Disconnect(); } } @@ -75,8 +72,10 @@ void CSqlScore::LoadScoreThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { @@ -85,12 +84,12 @@ void CSqlScore::LoadScoreThread(void *pUser) char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "SELECT * FROM %s_race WHERE Map='%s' AND Name='%s' ORDER BY time ASC LIMIT 1;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName); - pData->SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->next()) + str_format(aBuf, sizeof(aBuf), "SELECT * FROM %s_race WHERE Map='%s' AND Name='%s' ORDER BY time ASC LIMIT 1;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName); + connector.SqlServer()->executeSqlQuery(aBuf); + if(connector.SqlServer()->GetResults()->next()) { // get the best time - float time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); + float time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); pData->PlayerData(pData->m_ClientID)->m_BestTime = time; pData->PlayerData(pData->m_ClientID)->m_CurrentTime = time; if(pData->GameServer()->m_apPlayers[pData->m_ClientID]) @@ -102,7 +101,7 @@ void CSqlScore::LoadScoreThread(void *pUser) for(int i = 0; i < NUM_CHECKPOINTS; i++) { str_format(aColumn, sizeof(aColumn), "cp%d", i+1); - pData->PlayerData(pData->m_ClientID)->m_aBestCpTime[i] = (float)pData->SqlServer()->GetResults()->getDouble(aColumn); + pData->PlayerData(pData->m_ClientID)->m_aBestCpTime[i] = (float)connector.SqlServer()->GetResults()->getDouble(aColumn); } } } @@ -118,7 +117,7 @@ void CSqlScore::LoadScoreThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; } @@ -137,19 +136,15 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) { CSqlTeamScoreData *pData = (CSqlTeamScoreData *)pUser; - for (int skipCount = 0; skipCount < MAX_SQLMASTERS; skipCount++) + CSqlConnector connector; + + for (int retries = 0; retries < MAX_SQLSERVERS; retries++) { // Connect to database - pData->ConnectSqlServer(g_Config.m_SvUseSQLMasters, skipCount); + connector.ConnectSqlServer(true); - if (pData->ActiveMasterID() == -1) - { - dbg_msg("SQL", "ERROR: Could not connect to ANY SQLMASTER-Server"); - return; - } - - if(pData->SqlServer()) + if(connector.SqlServer()) { try { @@ -162,10 +157,10 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) ClearString(pData->m_aNames[i]); } - str_format(aBuf, sizeof(aBuf), "SELECT Name, l.ID, Time FROM ((SELECT ID FROM %s_teamrace WHERE Map = '%s' AND Name = '%s') as l) LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY ID;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aNames[0], pData->SqlServer()->GetPrefix()); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "SELECT Name, l.ID, Time FROM ((SELECT ID FROM %s_teamrace WHERE Map = '%s' AND Name = '%s') as l) LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY ID;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aNames[0], connector.SqlServer()->GetPrefix()); + connector.SqlServer()->executeSqlQuery(aBuf); - if (pData->SqlServer()->GetResults()->rowsCount() > 0) + if (connector.SqlServer()->GetResults()->rowsCount() > 0) { char aID[17]; char aID2[17]; @@ -173,14 +168,14 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) unsigned int Count = 0; bool ValidNames = true; - pData->SqlServer()->GetResults()->first(); - float Time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); - strcpy(aID, pData->SqlServer()->GetResults()->getString("ID").c_str()); + connector.SqlServer()->GetResults()->first(); + float Time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); + strcpy(aID, connector.SqlServer()->GetResults()->getString("ID").c_str()); do { - strcpy(aID2, pData->SqlServer()->GetResults()->getString("ID").c_str()); - strcpy(aName, pData->SqlServer()->GetResults()->getString("Name").c_str()); + strcpy(aID2, connector.SqlServer()->GetResults()->getString("ID").c_str()); + strcpy(aName, connector.SqlServer()->GetResults()->getString("Name").c_str()); ClearString(aName); if (str_comp(aID, aID2) != 0) { @@ -193,7 +188,7 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) break; } - Time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); + Time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); ValidNames = true; Count = 0; strcpy(aID, aID2); @@ -213,7 +208,7 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) break; } } - } while (pData->SqlServer()->GetResults()->next()); + } while (connector.SqlServer()->GetResults()->next()); if (ValidNames && Count == pData->m_Size) { @@ -226,20 +221,20 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) if (aUpdateID[0]) { - str_format(aBuf, sizeof(aBuf), "UPDATE %s_teamrace SET Time='%.2f' WHERE ID = '%s';", pData->SqlServer()->GetPrefix(), pData->m_Time, aUpdateID); + str_format(aBuf, sizeof(aBuf), "UPDATE %s_teamrace SET Time='%.2f' WHERE ID = '%s';", connector.SqlServer()->GetPrefix(), pData->m_Time, aUpdateID); dbg_msg("SQL", aBuf); - pData->SqlServer()->executeSql(aBuf); + connector.SqlServer()->executeSql(aBuf); } else { - pData->SqlServer()->executeSql("SET @id = UUID();"); + connector.SqlServer()->executeSql("SET @id = UUID();"); for(unsigned int i = 0; i < pData->m_Size; i++) { // if no entry found... create a new one - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_teamrace(Map, Name, Timestamp, Time, ID) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', @id);", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aNames[i], pData->m_Time); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_teamrace(Map, Name, Timestamp, Time, ID) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', @id);", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aNames[i], pData->m_Time); dbg_msg("SQL", aBuf); - pData->SqlServer()->executeSql(aBuf); + connector.SqlServer()->executeSql(aBuf); } } @@ -255,7 +250,7 @@ void CSqlScore::SaveTeamScoreThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); // no errors and everything updated --> break fallback loop break; @@ -281,8 +276,10 @@ void CSqlScore::MapVoteThread(void *pUser) { CSqlMapData *pData = (CSqlMapData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { char originalMap[128]; strcpy(originalMap,pData->m_aMap); @@ -294,8 +291,8 @@ void CSqlScore::MapVoteThread(void *pUser) try { char aBuf[768]; - str_format(aBuf, sizeof(aBuf), "SELECT Map, Server FROM %s_maps WHERE Map LIKE '%s' COLLATE utf8_general_ci ORDER BY CASE WHEN Map = '%s' THEN 0 ELSE 1 END, CASE WHEN Map LIKE '%s%%' THEN 0 ELSE 1 END, LENGTH(Map), Map LIMIT 1;", pData->SqlServer()->GetPrefix(), pData->m_aMap, clearMap, clearMap); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "SELECT Map, Server FROM %s_maps WHERE Map LIKE '%s' COLLATE utf8_general_ci ORDER BY CASE WHEN Map = '%s' THEN 0 ELSE 1 END, CASE WHEN Map LIKE '%s%%' THEN 0 ELSE 1 END, LENGTH(Map), Map LIMIT 1;", connector.SqlServer()->GetPrefix(), pData->m_aMap, clearMap, clearMap); + connector.SqlServer()->executeSqlQuery(aBuf); CPlayer *pPlayer = pData->GameServer()->m_apPlayers[pData->m_ClientID]; @@ -307,7 +304,7 @@ void CSqlScore::MapVoteThread(void *pUser) Timeleft = pPlayer->m_LastVoteCall + pData->Server()->TickSpeed()*g_Config.m_SvVoteDelay - Now; - if(pData->SqlServer()->GetResults()->rowsCount() != 1) + if(connector.SqlServer()->GetResults()->rowsCount() != 1) { str_format(aBuf, sizeof(aBuf), "No map like \"%s\" found. Try adding a '%%' at the start if you don't know the first character. Example: /map %%castle for \"Out of Castle\"", originalMap); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); @@ -326,11 +323,11 @@ void CSqlScore::MapVoteThread(void *pUser) } else { - pData->SqlServer()->GetResults()->next(); + connector.SqlServer()->GetResults()->next(); char aMap[128]; - strcpy(aMap, pData->SqlServer()->GetResults()->getString("Map").c_str()); + strcpy(aMap, connector.SqlServer()->GetResults()->getString("Map").c_str()); char aServer[32]; - strcpy(aServer, pData->SqlServer()->GetResults()->getString("Server").c_str()); + strcpy(aServer, connector.SqlServer()->GetResults()->getString("Server").c_str()); for(char *p = aServer; *p; p++) *p = tolower(*p); @@ -355,7 +352,7 @@ void CSqlScore::MapVoteThread(void *pUser) dbg_msg("SQL", "ERROR: Could not update time"); } - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; } @@ -374,8 +371,10 @@ void CSqlScore::MapInfoThread(void *pUser) { CSqlMapData *pData = (CSqlMapData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { char originalMap[128]; strcpy(originalMap,pData->m_aMap); @@ -387,29 +386,29 @@ void CSqlScore::MapInfoThread(void *pUser) try { char aBuf[1024]; - str_format(aBuf, sizeof(aBuf), "SELECT l.Map, l.Server, Mapper, Points, Stars, (select count(Name) from %s_race where Map = l.Map) as Finishes, (select count(distinct Name) from %s_race where Map = l.Map) as Finishers, (select round(avg(Time)) from record_race where Map = l.Map) as Average, UNIX_TIMESTAMP(l.Timestamp) as Stamp, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(l.Timestamp) as Ago FROM (SELECT * FROM %s_maps WHERE Map LIKE '%s' COLLATE utf8_general_ci ORDER BY CASE WHEN Map = '%s' THEN 0 ELSE 1 END, CASE WHEN Map LIKE '%s%%' THEN 0 ELSE 1 END, LENGTH(Map), Map LIMIT 1) as l;", pData->SqlServer()->GetPrefix(), pData->SqlServer()->GetPrefix(), pData->SqlServer()->GetPrefix(), pData->m_aMap, clearMap, clearMap); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "SELECT l.Map, l.Server, Mapper, Points, Stars, (select count(Name) from %s_race where Map = l.Map) as Finishes, (select count(distinct Name) from %s_race where Map = l.Map) as Finishers, (select round(avg(Time)) from record_race where Map = l.Map) as Average, UNIX_TIMESTAMP(l.Timestamp) as Stamp, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(l.Timestamp) as Ago FROM (SELECT * FROM %s_maps WHERE Map LIKE '%s' COLLATE utf8_general_ci ORDER BY CASE WHEN Map = '%s' THEN 0 ELSE 1 END, CASE WHEN Map LIKE '%s%%' THEN 0 ELSE 1 END, LENGTH(Map), Map LIMIT 1) as l;", connector.SqlServer()->GetPrefix(), connector.SqlServer()->GetPrefix(), connector.SqlServer()->GetPrefix(), pData->m_aMap, clearMap, clearMap); + connector.SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->rowsCount() != 1) + if(connector.SqlServer()->GetResults()->rowsCount() != 1) { str_format(aBuf, sizeof(aBuf), "No map like \"%s\" found.", originalMap); } else { - pData->SqlServer()->GetResults()->next(); - int points = (int)pData->SqlServer()->GetResults()->getInt("Points"); - int stars = (int)pData->SqlServer()->GetResults()->getInt("Stars"); - int finishes = (int)pData->SqlServer()->GetResults()->getInt("Finishes"); - int finishers = (int)pData->SqlServer()->GetResults()->getInt("Finishers"); - int average = (int)pData->SqlServer()->GetResults()->getInt("Average"); + connector.SqlServer()->GetResults()->next(); + int points = (int)connector.SqlServer()->GetResults()->getInt("Points"); + int stars = (int)connector.SqlServer()->GetResults()->getInt("Stars"); + int finishes = (int)connector.SqlServer()->GetResults()->getInt("Finishes"); + int finishers = (int)connector.SqlServer()->GetResults()->getInt("Finishers"); + int average = (int)connector.SqlServer()->GetResults()->getInt("Average"); char aMap[128]; - strcpy(aMap, pData->SqlServer()->GetResults()->getString("Map").c_str()); + strcpy(aMap, connector.SqlServer()->GetResults()->getString("Map").c_str()); char aServer[32]; - strcpy(aServer, pData->SqlServer()->GetResults()->getString("Server").c_str()); + strcpy(aServer, connector.SqlServer()->GetResults()->getString("Server").c_str()); char aMapper[128]; - strcpy(aMapper, pData->SqlServer()->GetResults()->getString("Mapper").c_str()); - int stamp = (int)pData->SqlServer()->GetResults()->getInt("Stamp"); - int ago = (int)pData->SqlServer()->GetResults()->getInt("Ago"); + strcpy(aMapper, connector.SqlServer()->GetResults()->getString("Mapper").c_str()); + int stamp = (int)connector.SqlServer()->GetResults()->getInt("Stamp"); + int ago = (int)connector.SqlServer()->GetResults()->getInt("Ago"); char pAgoString[40] = "\0"; char pReleasedString[60] = "\0"; @@ -450,7 +449,7 @@ void CSqlScore::MapInfoThread(void *pUser) dbg_msg("SQL", "ERROR: Could not update time"); } - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; } @@ -459,19 +458,10 @@ void CSqlScore::SaveScoreThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; - for (int skipCount = 0; skipCount < MAX_SQLMASTERS; skipCount++) - { + CSqlConnector connector; // Connect to database - pData->ConnectSqlServer(g_Config.m_SvUseSQLMasters, skipCount); - - if (pData->ActiveMasterID() == -1) - { - dbg_msg("SQL", "ERROR: Could not connect to ANY SQLMASTER-Server"); - return; - } - - if(pData->SqlServer()) + while (!connector.MaxTriesReached(false) && connector.ConnectSqlServer(false)) { try { @@ -480,32 +470,32 @@ void CSqlScore::SaveScoreThread(void *pUser) // check strings ClearString(pData->m_aName); - str_format(aBuf, sizeof(aBuf), "SELECT * FROM %s_race WHERE Map='%s' AND Name='%s' ORDER BY time ASC LIMIT 1;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName); - pData->SqlServer()->executeSqlQuery(aBuf); - if(!pData->SqlServer()->GetResults()->next()) + str_format(aBuf, sizeof(aBuf), "SELECT * FROM %s_race WHERE Map='%s' AND Name='%s' ORDER BY time ASC LIMIT 1;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName); + connector.SqlServer()->executeSqlQuery(aBuf); + if(!connector.SqlServer()->GetResults()->next()) { - str_format(aBuf, sizeof(aBuf), "SELECT Points FROM %s_maps WHERE Map ='%s'", pData->SqlServer()->GetPrefix(), pData->MapName()); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "SELECT Points FROM %s_maps WHERE Map ='%s'", connector.SqlServer()->GetPrefix(), pData->MapName()); + connector.SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->rowsCount() == 1) + if(connector.SqlServer()->GetResults()->rowsCount() == 1) { - pData->SqlServer()->GetResults()->next(); - int points = (int)pData->SqlServer()->GetResults()->getInt("Points"); + connector.SqlServer()->GetResults()->next(); + int points = (int)connector.SqlServer()->GetResults()->getInt("Points"); if (points == 1) str_format(aBuf, sizeof(aBuf), "You earned %d point for finishing this map!", points); else str_format(aBuf, sizeof(aBuf), "You earned %d points for finishing this map!", points); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); - str_format(aBuf, sizeof(aBuf), "INSERT INTO %s_points(Name, Points) VALUES ('%s', '%d') ON duplicate key UPDATE Name=VALUES(Name), Points=Points+VALUES(Points);", pData->SqlServer()->GetPrefix(), pData->m_aName, points); - pData->SqlServer()->executeSql(aBuf); + str_format(aBuf, sizeof(aBuf), "INSERT INTO %s_points(Name, Points) VALUES ('%s', '%d') ON duplicate key UPDATE Name=VALUES(Name), Points=Points+VALUES(Points);", connector.SqlServer()->GetPrefix(), pData->m_aName, points); + connector.SqlServer()->executeSql(aBuf); } } // if no entry found... create a new one - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f');", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName, pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24]); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_race(Map, Name, Timestamp, Time, Server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10, cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25) VALUES ('%s', '%s', CURRENT_TIMESTAMP(), '%.2f', '%s', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f', '%.2f');", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName, pData->m_Time, g_Config.m_SvSqlServerName, pData->m_aCpCurrent[0], pData->m_aCpCurrent[1], pData->m_aCpCurrent[2], pData->m_aCpCurrent[3], pData->m_aCpCurrent[4], pData->m_aCpCurrent[5], pData->m_aCpCurrent[6], pData->m_aCpCurrent[7], pData->m_aCpCurrent[8], pData->m_aCpCurrent[9], pData->m_aCpCurrent[10], pData->m_aCpCurrent[11], pData->m_aCpCurrent[12], pData->m_aCpCurrent[13], pData->m_aCpCurrent[14], pData->m_aCpCurrent[15], pData->m_aCpCurrent[16], pData->m_aCpCurrent[17], pData->m_aCpCurrent[18], pData->m_aCpCurrent[19], pData->m_aCpCurrent[20], pData->m_aCpCurrent[21], pData->m_aCpCurrent[22], pData->m_aCpCurrent[23], pData->m_aCpCurrent[24]); dbg_msg("SQL", aBuf); - pData->SqlServer()->executeSql(aBuf); + connector.SqlServer()->executeSql(aBuf); dbg_msg("SQL", "Updating time done"); } @@ -518,14 +508,11 @@ void CSqlScore::SaveScoreThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); // no errors and everything updated --> break fallback loop break; } - else - dbg_msg("SQL", "ERROR: Could not connect to SQL-Server"); - } delete pData; } @@ -568,8 +555,10 @@ void CSqlScore::ShowTeamRankThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { @@ -583,14 +572,14 @@ void CSqlScore::ShowTeamRankThread(void *pUser) char aNames[2300]; aNames[0] = '\0'; - pData->SqlServer()->executeSql("SET @prev := NULL;"); - pData->SqlServer()->executeSql("SET @rank := 1;"); - pData->SqlServer()->executeSql("SET @pos := 0;"); - str_format(aBuf, sizeof(aBuf), "SELECT Rank, Name, Time FROM (SELECT Rank, l2.ID FROM ((SELECT ID, (@pos := @pos+1) pos, (@rank := IF(@prev = Time,@rank,@pos)) rank, (@prev := Time) Time FROM (SELECT ID, Time FROM %s_teamrace WHERE Map = '%s' GROUP BY ID ORDER BY Time) as ll) as l2) LEFT JOIN %s_teamrace as r2 ON l2.ID = r2.ID WHERE Map = '%s' AND Name = '%s' ORDER BY Rank LIMIT 1) as l LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY Name;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName, pData->SqlServer()->GetPrefix()); + connector.SqlServer()->executeSql("SET @prev := NULL;"); + connector.SqlServer()->executeSql("SET @rank := 1;"); + connector.SqlServer()->executeSql("SET @pos := 0;"); + str_format(aBuf, sizeof(aBuf), "SELECT Rank, Name, Time FROM (SELECT Rank, l2.ID FROM ((SELECT ID, (@pos := @pos+1) pos, (@rank := IF(@prev = Time,@rank,@pos)) rank, (@prev := Time) Time FROM (SELECT ID, Time FROM %s_teamrace WHERE Map = '%s' GROUP BY ID ORDER BY Time) as ll) as l2) LEFT JOIN %s_teamrace as r2 ON l2.ID = r2.ID WHERE Map = '%s' AND Name = '%s' ORDER BY Rank LIMIT 1) as l LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY Name;", connector.SqlServer()->GetPrefix(), pData->MapName(), connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName, connector.SqlServer()->GetPrefix()); - pData->SqlServer()->executeSqlQuery(aBuf); + connector.SqlServer()->executeSqlQuery(aBuf); - int Rows = pData->SqlServer()->GetResults()->rowsCount(); + int Rows = connector.SqlServer()->GetResults()->rowsCount(); if(Rows < 1) { @@ -599,15 +588,15 @@ void CSqlScore::ShowTeamRankThread(void *pUser) } else { - pData->SqlServer()->GetResults()->first(); + connector.SqlServer()->GetResults()->first(); - float Time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); - int Rank = (int)pData->SqlServer()->GetResults()->getInt("Rank"); + float Time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); + int Rank = (int)connector.SqlServer()->GetResults()->getInt("Rank"); for(int Row = 0; Row < Rows; Row++) { - strcat(aNames, pData->SqlServer()->GetResults()->getString("Name").c_str()); - pData->SqlServer()->GetResults()->next(); + strcat(aNames, connector.SqlServer()->GetResults()->getString("Name").c_str()); + connector.SqlServer()->GetResults()->next(); if (Row < Rows - 2) strcat(aNames, ", "); @@ -615,7 +604,7 @@ void CSqlScore::ShowTeamRankThread(void *pUser) strcat(aNames, " & "); } - pData->SqlServer()->GetResults()->first(); + connector.SqlServer()->GetResults()->first(); if(g_Config.m_SvHideScore) str_format(aBuf, sizeof(aBuf), "Your team time: %02d:%05.02f", (int)(Time/60), Time-((int)Time/60*60)); @@ -636,7 +625,7 @@ void CSqlScore::ShowTeamRankThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -646,25 +635,27 @@ void CSqlScore::ShowTeamTop5Thread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { // check sort methode char aBuf[512]; - pData->SqlServer()->executeSql("SET @prev := NULL;"); - pData->SqlServer()->executeSql("SET @previd := NULL;"); - pData->SqlServer()->executeSql("SET @rank := 1;"); - pData->SqlServer()->executeSql("SET @pos := 0;"); - str_format(aBuf, sizeof(aBuf), "SELECT ID, Name, Time, rank FROM (SELECT r.ID, Name, rank, l.Time FROM ((SELECT ID, rank, Time FROM (SELECT ID, (@pos := IF(@previd = ID,@pos,@pos+1)) pos, (@previd := ID), (@rank := IF(@prev = Time,@rank,@pos)) rank, (@prev := Time) Time FROM (SELECT ID, MIN(Time) as Time FROM %s_teamrace WHERE Map = '%s' GROUP BY ID ORDER BY `Time` ASC) as all_top_times) as a LIMIT %d, 5) as l) LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY Time ASC, r.ID, Name ASC) as a;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_Num-1, pData->SqlServer()->GetPrefix(), pData->MapName()); - pData->SqlServer()->executeSqlQuery(aBuf); + connector.SqlServer()->executeSql("SET @prev := NULL;"); + connector.SqlServer()->executeSql("SET @previd := NULL;"); + connector.SqlServer()->executeSql("SET @rank := 1;"); + connector.SqlServer()->executeSql("SET @pos := 0;"); + str_format(aBuf, sizeof(aBuf), "SELECT ID, Name, Time, rank FROM (SELECT r.ID, Name, rank, l.Time FROM ((SELECT ID, rank, Time FROM (SELECT ID, (@pos := IF(@previd = ID,@pos,@pos+1)) pos, (@previd := ID), (@rank := IF(@prev = Time,@rank,@pos)) rank, (@prev := Time) Time FROM (SELECT ID, MIN(Time) as Time FROM %s_teamrace WHERE Map = '%s' GROUP BY ID ORDER BY `Time` ASC) as all_top_times) as a LIMIT %d, 5) as l) LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY Time ASC, r.ID, Name ASC) as a;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_Num-1, connector.SqlServer()->GetPrefix(), pData->MapName()); + connector.SqlServer()->executeSqlQuery(aBuf); // show teamtop5 pData->GameServer()->SendChatTarget(pData->m_ClientID, "------- Team Top 5 -------"); - int Rows = pData->SqlServer()->GetResults()->rowsCount(); + int Rows = connector.SqlServer()->GetResults()->rowsCount(); if (Rows >= 1) { char aID[17]; @@ -678,33 +669,33 @@ void CSqlScore::ShowTeamTop5Thread(void *pUser) aNames[0] = '\0'; aCuts[0] = -1; - pData->SqlServer()->GetResults()->first(); - strcpy(aID, pData->SqlServer()->GetResults()->getString("ID").c_str()); + connector.SqlServer()->GetResults()->first(); + strcpy(aID, connector.SqlServer()->GetResults()->getString("ID").c_str()); for(int Row = 0; Row < Rows; Row++) { - strcpy(aID2, pData->SqlServer()->GetResults()->getString("ID").c_str()); + strcpy(aID2, connector.SqlServer()->GetResults()->getString("ID").c_str()); if (str_comp(aID, aID2) != 0) { strcpy(aID, aID2); aCuts[CutPos++] = Row - 1; } - pData->SqlServer()->GetResults()->next(); + connector.SqlServer()->GetResults()->next(); } aCuts[CutPos] = Rows - 1; CutPos = 0; - pData->SqlServer()->GetResults()->first(); + connector.SqlServer()->GetResults()->first(); for(int Row = 0; Row < Rows; Row++) { - strcat(aNames, pData->SqlServer()->GetResults()->getString("Name").c_str()); + strcat(aNames, connector.SqlServer()->GetResults()->getString("Name").c_str()); if (Row < aCuts[CutPos] - 1) strcat(aNames, ", "); else if (Row < aCuts[CutPos]) strcat(aNames, " & "); - Time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); - Rank = (float)pData->SqlServer()->GetResults()->getInt("rank"); + Time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); + Rank = (float)connector.SqlServer()->GetResults()->getInt("rank"); if (Row == aCuts[CutPos]) { @@ -714,7 +705,7 @@ void CSqlScore::ShowTeamTop5Thread(void *pUser) aNames[0] = '\0'; } - pData->SqlServer()->GetResults()->next(); + connector.SqlServer()->GetResults()->next(); } } @@ -731,7 +722,7 @@ void CSqlScore::ShowTeamTop5Thread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -741,8 +732,10 @@ void CSqlScore::ShowRankThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { @@ -754,28 +747,28 @@ void CSqlScore::ShowRankThread(void *pUser) // check sort methode char aBuf[600]; - pData->SqlServer()->executeSql("SET @prev := NULL;"); - pData->SqlServer()->executeSql("SET @rank := 1;"); - pData->SqlServer()->executeSql("SET @pos := 0;"); - str_format(aBuf, sizeof(aBuf), "SELECT Rank, Name, Time FROM (SELECT Name, (@pos := @pos+1) pos, (@rank := IF(@prev = Time,@rank, @pos)) rank, (@prev := Time) Time FROM (SELECT Name, min(Time) as Time FROM %s_race WHERE Map = '%s' GROUP BY Name ORDER BY `Time` ASC) as a) as b WHERE Name = '%s';", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName); + connector.SqlServer()->executeSql("SET @prev := NULL;"); + connector.SqlServer()->executeSql("SET @rank := 1;"); + connector.SqlServer()->executeSql("SET @pos := 0;"); + str_format(aBuf, sizeof(aBuf), "SELECT Rank, Name, Time FROM (SELECT Name, (@pos := @pos+1) pos, (@rank := IF(@prev = Time,@rank, @pos)) rank, (@prev := Time) Time FROM (SELECT Name, min(Time) as Time FROM %s_race WHERE Map = '%s' GROUP BY Name ORDER BY `Time` ASC) as a) as b WHERE Name = '%s';", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName); - pData->SqlServer()->executeSqlQuery(aBuf); + connector.SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->rowsCount() != 1) + if(connector.SqlServer()->GetResults()->rowsCount() != 1) { str_format(aBuf, sizeof(aBuf), "%s is not ranked", originalName); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); } else { - pData->SqlServer()->GetResults()->next(); + connector.SqlServer()->GetResults()->next(); - float Time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); - int Rank = (int)pData->SqlServer()->GetResults()->getInt("Rank"); + float Time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); + int Rank = (int)connector.SqlServer()->GetResults()->getInt("Rank"); if(g_Config.m_SvHideScore) str_format(aBuf, sizeof(aBuf), "Your time: %02d:%05.2f", (int)(Time/60), Time-((int)Time/60*60)); else - str_format(aBuf, sizeof(aBuf), "%d. %s Time: %02d:%05.2f, requested by %s", Rank, pData->SqlServer()->GetResults()->getString("Name").c_str(), (int)(Time/60), Time-((int)Time/60*60), pData->m_aRequestingPlayer); + str_format(aBuf, sizeof(aBuf), "%d. %s Time: %02d:%05.2f, requested by %s", Rank, connector.SqlServer()->GetResults()->getString("Name").c_str(), (int)(Time/60), Time-((int)Time/60*60), pData->m_aRequestingPlayer); pData->GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, pData->m_ClientID); } @@ -791,7 +784,7 @@ void CSqlScore::ShowRankThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -825,29 +818,31 @@ void CSqlScore::ShowTop5Thread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { // check sort methode char aBuf[512]; - pData->SqlServer()->executeSql("SET @prev := NULL;"); - pData->SqlServer()->executeSql("SET @rank := 1;"); - pData->SqlServer()->executeSql("SET @pos := 0;"); - str_format(aBuf, sizeof(aBuf), "SELECT Name, Time, rank FROM (SELECT Name, (@pos := @pos+1) pos, (@rank := IF(@prev = Time,@rank, @pos)) rank, (@prev := Time) Time FROM (SELECT Name, min(Time) as Time FROM %s_race WHERE Map = '%s' GROUP BY Name ORDER BY `Time` ASC) as a) as b LIMIT %d, 5;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_Num-1); - pData->SqlServer()->executeSqlQuery(aBuf); + connector.SqlServer()->executeSql("SET @prev := NULL;"); + connector.SqlServer()->executeSql("SET @rank := 1;"); + connector.SqlServer()->executeSql("SET @pos := 0;"); + str_format(aBuf, sizeof(aBuf), "SELECT Name, Time, rank FROM (SELECT Name, (@pos := @pos+1) pos, (@rank := IF(@prev = Time,@rank, @pos)) rank, (@prev := Time) Time FROM (SELECT Name, min(Time) as Time FROM %s_race WHERE Map = '%s' GROUP BY Name ORDER BY `Time` ASC) as a) as b LIMIT %d, 5;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_Num-1); + connector.SqlServer()->executeSqlQuery(aBuf); // show top5 pData->GameServer()->SendChatTarget(pData->m_ClientID, "----------- Top 5 -----------"); int Rank = 0; float Time = 0; - while(pData->SqlServer()->GetResults()->next()) + while(connector.SqlServer()->GetResults()->next()) { - Time = (float)pData->SqlServer()->GetResults()->getDouble("Time"); - Rank = (float)pData->SqlServer()->GetResults()->getInt("rank"); - str_format(aBuf, sizeof(aBuf), "%d. %s Time: %02d:%05.2f", Rank, pData->SqlServer()->GetResults()->getString("Name").c_str(), (int)(Time/60), Time-((int)Time/60*60)); + Time = (float)connector.SqlServer()->GetResults()->getDouble("Time"); + Rank = (float)connector.SqlServer()->GetResults()->getInt("rank"); + str_format(aBuf, sizeof(aBuf), "%d. %s Time: %02d:%05.2f", Rank, connector.SqlServer()->GetResults()->getString("Name").c_str(), (int)(Time/60), Time-((int)Time/60*60)); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); //Rank++; } @@ -864,7 +859,7 @@ void CSqlScore::ShowTop5Thread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; } @@ -873,8 +868,10 @@ void CSqlScore::ShowTimesThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { @@ -885,32 +882,32 @@ void CSqlScore::ShowTimesThread(void *pUser) char aBuf[512]; if(pData->m_Search) // last 5 times of a player - str_format(aBuf, sizeof(aBuf), "SELECT Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago, UNIX_TIMESTAMP(Timestamp) as Stamp FROM %s_race WHERE Map = '%s' AND Name = '%s' ORDER BY Ago ASC LIMIT %d, 5;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName, pData->m_Num-1); + str_format(aBuf, sizeof(aBuf), "SELECT Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago, UNIX_TIMESTAMP(Timestamp) as Stamp FROM %s_race WHERE Map = '%s' AND Name = '%s' ORDER BY Ago ASC LIMIT %d, 5;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_aName, pData->m_Num-1); else// last 5 times of server - str_format(aBuf, sizeof(aBuf), "SELECT Name, Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago, UNIX_TIMESTAMP(Timestamp) as Stamp FROM %s_race WHERE Map = '%s' ORDER BY Ago ASC LIMIT %d, 5;", pData->SqlServer()->GetPrefix(), pData->MapName(), pData->m_Num-1); + str_format(aBuf, sizeof(aBuf), "SELECT Name, Time, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago, UNIX_TIMESTAMP(Timestamp) as Stamp FROM %s_race WHERE Map = '%s' ORDER BY Ago ASC LIMIT %d, 5;", connector.SqlServer()->GetPrefix(), pData->MapName(), pData->m_Num-1); - pData->SqlServer()->executeSqlQuery(aBuf); + connector.SqlServer()->executeSqlQuery(aBuf); // show top5 - if(pData->SqlServer()->GetResults()->rowsCount() == 0) + if(connector.SqlServer()->GetResults()->rowsCount() == 0) { pData->GameServer()->SendChatTarget(pData->m_ClientID, "There are no times in the specified range"); goto end; } - str_format(aBuf, sizeof(aBuf), "------------ Last Times No %d - %d ------------",pData->m_Num,pData->m_Num + pData->SqlServer()->GetResults()->rowsCount() - 1); + str_format(aBuf, sizeof(aBuf), "------------ Last Times No %d - %d ------------",pData->m_Num,pData->m_Num + connector.SqlServer()->GetResults()->rowsCount() - 1); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); float pTime = 0; int pSince = 0; int pStamp = 0; - while(pData->SqlServer()->GetResults()->next()) + while(connector.SqlServer()->GetResults()->next()) { char pAgoString[40] = "\0"; - pSince = (int)pData->SqlServer()->GetResults()->getInt("Ago"); - pStamp = (int)pData->SqlServer()->GetResults()->getInt("Stamp"); - pTime = (float)pData->SqlServer()->GetResults()->getDouble("Time"); + pSince = (int)connector.SqlServer()->GetResults()->getInt("Ago"); + pStamp = (int)connector.SqlServer()->GetResults()->getInt("Stamp"); + pTime = (float)connector.SqlServer()->GetResults()->getDouble("Time"); agoTimeToString(pSince,pAgoString); @@ -924,9 +921,9 @@ void CSqlScore::ShowTimesThread(void *pUser) else // last 5 times of the server { if(pStamp == 0) // stamp is 00:00:00 cause it's an old entry from old times where there where no stamps yet - str_format(aBuf, sizeof(aBuf), "%s, %02d:%05.02f s, don't know when", pData->SqlServer()->GetResults()->getString("Name").c_str(), (int)(pTime/60), pTime-((int)pTime/60*60)); + str_format(aBuf, sizeof(aBuf), "%s, %02d:%05.02f s, don't know when", connector.SqlServer()->GetResults()->getString("Name").c_str(), (int)(pTime/60), pTime-((int)pTime/60*60)); else - str_format(aBuf, sizeof(aBuf), "%s, %s ago, %02d:%05.02f s", pData->SqlServer()->GetResults()->getString("Name").c_str(), pAgoString, (int)(pTime/60), pTime-((int)pTime/60*60)); + str_format(aBuf, sizeof(aBuf), "%s, %s ago, %02d:%05.02f s", connector.SqlServer()->GetResults()->getString("Name").c_str(), pAgoString, (int)(pTime/60), pTime-((int)pTime/60*60)); } pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); } @@ -943,7 +940,7 @@ void CSqlScore::ShowTimesThread(void *pUser) } end: // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; } @@ -995,8 +992,10 @@ void CSqlScore::ShowPointsThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { @@ -1005,25 +1004,25 @@ void CSqlScore::ShowPointsThread(void *pUser) strcpy(originalName,pData->m_aName); ClearString(pData->m_aName); - pData->SqlServer()->executeSql("SET @prev := NULL;"); - pData->SqlServer()->executeSql("SET @rank := 1;"); - pData->SqlServer()->executeSql("SET @pos := 0;"); + connector.SqlServer()->executeSql("SET @prev := NULL;"); + connector.SqlServer()->executeSql("SET @rank := 1;"); + connector.SqlServer()->executeSql("SET @pos := 0;"); char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "select Rank, Name, Points from (select (@pos := @pos+1) pos, (@rank := IF(@prev = Points,@rank,@pos)) Rank, Points, Name from (select (@prev := Points) Points, Name from %s_points order by Points desc) as ll) as l where Name = '%s';", pData->SqlServer()->GetPrefix(), pData->m_aName); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "select Rank, Name, Points from (select (@pos := @pos+1) pos, (@rank := IF(@prev = Points,@rank,@pos)) Rank, Points, Name from (select (@prev := Points) Points, Name from %s_points order by Points desc) as ll) as l where Name = '%s';", connector.SqlServer()->GetPrefix(), pData->m_aName); + connector.SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->rowsCount() != 1) + if(connector.SqlServer()->GetResults()->rowsCount() != 1) { str_format(aBuf, sizeof(aBuf), "%s has not collected any points so far", originalName); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); } else { - pData->SqlServer()->GetResults()->next(); - int count = (int)pData->SqlServer()->GetResults()->getInt("Points"); - int rank = (int)pData->SqlServer()->GetResults()->getInt("rank"); - str_format(aBuf, sizeof(aBuf), "%d. %s Points: %d, requested by %s", rank, pData->SqlServer()->GetResults()->getString("Name").c_str(), count, pData->m_aRequestingPlayer); + connector.SqlServer()->GetResults()->next(); + int count = (int)connector.SqlServer()->GetResults()->getInt("Points"); + int rank = (int)connector.SqlServer()->GetResults()->getInt("rank"); + str_format(aBuf, sizeof(aBuf), "%d. %s Points: %d, requested by %s", rank, connector.SqlServer()->GetResults()->getString("Name").c_str(), count, pData->m_aRequestingPlayer); pData->GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf, pData->m_ClientID); } @@ -1038,7 +1037,7 @@ void CSqlScore::ShowPointsThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -1060,25 +1059,27 @@ void CSqlScore::ShowTopPointsThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { char aBuf[512]; - pData->SqlServer()->executeSql("SET @prev := NULL;"); - pData->SqlServer()->executeSql("SET @rank := 1;"); - pData->SqlServer()->executeSql("SET @pos := 0;"); - str_format(aBuf, sizeof(aBuf), "select Rank, Name, Points from (select (@pos := @pos+1) pos, (@rank := IF(@prev = Points,@rank,@pos)) Rank, Points, Name from (select (@prev := Points) Points, Name from %s_points order by Points desc) as ll) as l LIMIT %d, 5;", pData->SqlServer()->GetPrefix(), pData->m_Num-1); + connector.SqlServer()->executeSql("SET @prev := NULL;"); + connector.SqlServer()->executeSql("SET @rank := 1;"); + connector.SqlServer()->executeSql("SET @pos := 0;"); + str_format(aBuf, sizeof(aBuf), "select Rank, Name, Points from (select (@pos := @pos+1) pos, (@rank := IF(@prev = Points,@rank,@pos)) Rank, Points, Name from (select (@prev := Points) Points, Name from %s_points order by Points desc) as ll) as l LIMIT %d, 5;", connector.SqlServer()->GetPrefix(), pData->m_Num-1); - pData->SqlServer()->executeSqlQuery(aBuf); + connector.SqlServer()->executeSqlQuery(aBuf); // show top points pData->GameServer()->SendChatTarget(pData->m_ClientID, "-------- Top Points --------"); - while(pData->SqlServer()->GetResults()->next()) + while(connector.SqlServer()->GetResults()->next()) { - str_format(aBuf, sizeof(aBuf), "%d. %s Points: %d", pData->SqlServer()->GetResults()->getInt("rank"), pData->SqlServer()->GetResults()->getString("Name").c_str(), pData->SqlServer()->GetResults()->getInt("Points")); + str_format(aBuf, sizeof(aBuf), "%d. %s Points: %d", connector.SqlServer()->GetResults()->getInt("rank"), connector.SqlServer()->GetResults()->getString("Name").c_str(), connector.SqlServer()->GetResults()->getInt("Points")); pData->GameServer()->SendChatTarget(pData->m_ClientID, aBuf); } pData->GameServer()->SendChatTarget(pData->m_ClientID, "-------------------------------"); @@ -1094,7 +1095,7 @@ void CSqlScore::ShowTopPointsThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -1114,27 +1115,29 @@ void CSqlScore::RandomMapThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { char aBuf[512]; if(pData->m_Num) - str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" and Stars = \"%d\" order by RAND() limit 1;", pData->SqlServer()->GetPrefix(), g_Config.m_SvServerType, pData->m_Num); + str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" and Stars = \"%d\" order by RAND() limit 1;", connector.SqlServer()->GetPrefix(), g_Config.m_SvServerType, pData->m_Num); else - str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" order by RAND() limit 1;", pData->SqlServer()->GetPrefix(), g_Config.m_SvServerType); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" order by RAND() limit 1;", connector.SqlServer()->GetPrefix(), g_Config.m_SvServerType); + connector.SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->rowsCount() != 1) + if(connector.SqlServer()->GetResults()->rowsCount() != 1) { pData->GameServer()->SendChatTarget(pData->m_ClientID, "No maps found on this server!"); } else { - pData->SqlServer()->GetResults()->next(); + connector.SqlServer()->GetResults()->next(); char aMap[128]; - strcpy(aMap, pData->SqlServer()->GetResults()->getString("Map").c_str()); + strcpy(aMap, connector.SqlServer()->GetResults()->getString("Map").c_str()); str_format(aBuf, sizeof(aBuf), "change_map \"%s\"", aMap); pData->GameServer()->Console()->ExecuteLine(aBuf); @@ -1151,7 +1154,7 @@ void CSqlScore::RandomMapThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -1161,8 +1164,10 @@ void CSqlScore::RandomUnfinishedMapThread(void *pUser) { CSqlScoreData *pData = (CSqlScoreData *)pUser; + CSqlConnector connector; + // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { @@ -1172,20 +1177,20 @@ void CSqlScore::RandomUnfinishedMapThread(void *pUser) char aBuf[512]; if(pData->m_Num) - str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" and Stars = \"%d\" and not exists (select * from %s_race where Name = \"%s\" and %s_race.Map = %s_maps.Map) order by RAND() limit 1;", pData->SqlServer()->GetPrefix(), g_Config.m_SvServerType, pData->m_Num, pData->SqlServer()->GetPrefix(), pData->m_aName, pData->SqlServer()->GetPrefix(), pData->SqlServer()->GetPrefix()); + str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" and Stars = \"%d\" and not exists (select * from %s_race where Name = \"%s\" and %s_race.Map = %s_maps.Map) order by RAND() limit 1;", connector.SqlServer()->GetPrefix(), g_Config.m_SvServerType, pData->m_Num, connector.SqlServer()->GetPrefix(), pData->m_aName, connector.SqlServer()->GetPrefix(), connector.SqlServer()->GetPrefix()); else - str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" and not exists (select * from %s_race where Name = \"%s\" and %s_race.Map = %s_maps.Map) order by RAND() limit 1;", pData->SqlServer()->GetPrefix(), g_Config.m_SvServerType, pData->SqlServer()->GetPrefix(), pData->m_aName, pData->SqlServer()->GetPrefix(), pData->SqlServer()->GetPrefix()); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "select * from %s_maps where Server = \"%s\" and not exists (select * from %s_race where Name = \"%s\" and %s_race.Map = %s_maps.Map) order by RAND() limit 1;", connector.SqlServer()->GetPrefix(), g_Config.m_SvServerType, connector.SqlServer()->GetPrefix(), pData->m_aName, connector.SqlServer()->GetPrefix(), connector.SqlServer()->GetPrefix()); + connector.SqlServer()->executeSqlQuery(aBuf); - if(pData->SqlServer()->GetResults()->rowsCount() != 1) + if(connector.SqlServer()->GetResults()->rowsCount() != 1) { pData->GameServer()->SendChatTarget(pData->m_ClientID, "You have no unfinished maps on this server!"); } else { - pData->SqlServer()->GetResults()->next(); + connector.SqlServer()->GetResults()->next(); char aMap[128]; - strcpy(aMap, pData->SqlServer()->GetResults()->getString("Map").c_str()); + strcpy(aMap, connector.SqlServer()->GetResults()->getString("Map").c_str()); str_format(aBuf, sizeof(aBuf), "change_map \"%s\"", aMap); pData->GameServer()->Console()->ExecuteLine(aBuf); @@ -1202,7 +1207,7 @@ void CSqlScore::RandomUnfinishedMapThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } delete pData; @@ -1259,6 +1264,8 @@ void CSqlScore::SaveTeamThread(void *pUser) CSaveTeam* SavedTeam = 0; CSqlTeamSave *pData = (CSqlTeamSave *)pUser; + CSqlConnector connector; + char TeamString[65536]; int Team = pData->m_Team; char OriginalCode[32]; @@ -1299,20 +1306,20 @@ void CSqlScore::SaveTeamThread(void *pUser) pData->GameServer()->SendChatTarget(pData->m_ClientID, "You have to be in a Team (from 1-63)"); // Connect to database - if(!Num && pData->SqlServer()->Connect()) + if(!Num && connector.ConnectSqlServer()) { try { char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "select Savegame from %s_saves where Code = '%s' and Map = '%s';", pData->SqlServer()->GetPrefix(), pData->m_Code, Map); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "select Savegame from %s_saves where Code = '%s' and Map = '%s';", connector.SqlServer()->GetPrefix(), pData->m_Code, Map); + connector.SqlServer()->executeSqlQuery(aBuf); - if (pData->SqlServer()->GetResults()->rowsCount() == 0) + if (connector.SqlServer()->GetResults()->rowsCount() == 0) { char aBuf[65536]; - str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_saves(Savegame, Map, Code, Timestamp, Server) VALUES ('%s', '%s', '%s', CURRENT_TIMESTAMP(), '%s')", pData->SqlServer()->GetPrefix(), TeamString, Map, pData->m_Code, pData->m_Server); + str_format(aBuf, sizeof(aBuf), "INSERT IGNORE INTO %s_saves(Savegame, Map, Code, Timestamp, Server) VALUES ('%s', '%s', '%s', CURRENT_TIMESTAMP(), '%s')", connector.SqlServer()->GetPrefix(), TeamString, Map, pData->m_Code, pData->m_Server); dbg_msg("SQL", aBuf); - pData->SqlServer()->executeSql(aBuf); + connector.SqlServer()->executeSql(aBuf); char aBuf2[256]; str_format(aBuf2, sizeof(aBuf2), "Team successfully saved. Use '/load %s' to continue", OriginalCode); @@ -1335,7 +1342,7 @@ void CSqlScore::SaveTeamThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } else if(!Num) { @@ -1365,6 +1372,8 @@ void CSqlScore::LoadTeamThread(void *pUser) CSaveTeam* SavedTeam; CSqlTeamLoad *pData = (CSqlTeamLoad *)pUser; + CSqlConnector connector; + SavedTeam = new CSaveTeam(pData->GameServer()->m_pController); ClearString(pData->m_Code, sizeof(pData->m_Code)); @@ -1374,19 +1383,19 @@ void CSqlScore::LoadTeamThread(void *pUser) int Num; // Connect to database - if(pData->SqlServer()->Connect()) + if(connector.ConnectSqlServer()) { try { char aBuf[768]; - str_format(aBuf, sizeof(aBuf), "select Savegame, Server, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago from %s_saves where Code = '%s' and Map = '%s';", pData->SqlServer()->GetPrefix(), pData->m_Code, Map); - pData->SqlServer()->executeSqlQuery(aBuf); + str_format(aBuf, sizeof(aBuf), "select Savegame, Server, UNIX_TIMESTAMP(CURRENT_TIMESTAMP)-UNIX_TIMESTAMP(Timestamp) as Ago from %s_saves where Code = '%s' and Map = '%s';", connector.SqlServer()->GetPrefix(), pData->m_Code, Map); + connector.SqlServer()->executeSqlQuery(aBuf); - if (pData->SqlServer()->GetResults()->rowsCount() > 0) + if (connector.SqlServer()->GetResults()->rowsCount() > 0) { - pData->SqlServer()->GetResults()->first(); + connector.SqlServer()->GetResults()->first(); char ServerName[5]; - str_copy(ServerName, pData->SqlServer()->GetResults()->getString("Server").c_str(), sizeof(ServerName)); + str_copy(ServerName, connector.SqlServer()->GetResults()->getString("Server").c_str(), sizeof(ServerName)); if(str_comp(ServerName, g_Config.m_SvSqlServerName)) { str_format(aBuf, sizeof(aBuf), "You have to be on the '%s' server to load this savegame", ServerName); @@ -1394,8 +1403,8 @@ void CSqlScore::LoadTeamThread(void *pUser) goto end; } - pData->SqlServer()->GetResults()->getInt("Ago"); - int since = (int)pData->SqlServer()->GetResults()->getInt("Ago"); + connector.SqlServer()->GetResults()->getInt("Ago"); + int since = (int)connector.SqlServer()->GetResults()->getInt("Ago"); if(since < g_Config.m_SvSaveGamesDelay) { @@ -1404,7 +1413,7 @@ void CSqlScore::LoadTeamThread(void *pUser) goto end; } - Num = SavedTeam->LoadString(pData->SqlServer()->GetResults()->getString("Savegame").c_str()); + Num = SavedTeam->LoadString(connector.SqlServer()->GetResults()->getString("Savegame").c_str()); if(Num) pData->GameServer()->SendChatTarget(pData->m_ClientID, "Unable to load savegame: data corrupted"); @@ -1456,8 +1465,8 @@ void CSqlScore::LoadTeamThread(void *pUser) { pData->GameServer()->SendChatTeam(n, "Loading successfully done"); char aBuf[512]; - str_format(aBuf, sizeof(aBuf), "DELETE from %s_saves where Code='%s' and Map='%s';", pData->SqlServer()->GetPrefix(), pData->m_Code, Map); - pData->SqlServer()->executeSql(aBuf); + str_format(aBuf, sizeof(aBuf), "DELETE from %s_saves where Code='%s' and Map='%s';", connector.SqlServer()->GetPrefix(), pData->m_Code, Map); + connector.SqlServer()->executeSql(aBuf); } } } @@ -1476,7 +1485,7 @@ void CSqlScore::LoadTeamThread(void *pUser) } // disconnect from database - pData->SqlServer()->Disconnect(); + connector.SqlServer()->Disconnect(); } else { diff --git a/src/game/server/score/sql_score.h b/src/game/server/score/sql_score.h index e4afed014..286cc3834 100644 --- a/src/game/server/score/sql_score.h +++ b/src/game/server/score/sql_score.h @@ -5,23 +5,20 @@ #define GAME_SERVER_SQLSCORE_H #include +#include -#include "sql_server.h" #include "../score.h" class CSqlScore: public IScore { CGameContext *GameServer() { return m_pGameServer; } IServer *Server() { return m_pServer; } - inline CSqlServer *SqlServer() { return m_pServer->SqlServer(); } - inline CSqlServer *SqlMasterServer(int i) { return m_pServer->SqlMasterServers()[i]; } - inline CSqlServer **SqlMasterServers() { return m_pServer->SqlMasterServers(); } - - void Init(); CGameContext *m_pGameServer; IServer *m_pServer; + void Init(); + char m_aMap[64]; static void MapInfoThread(void *pUser); @@ -68,51 +65,18 @@ public: virtual void LoadTeam(const char* Code, int ClientID); }; -// generic implementation to provide sqlserver, gameserver and server +// generic implementation to provide gameserver and server struct CSqlData { - CSqlData() : m_pSqlServer(ms_pSqlServer), m_ActiveMaster(-1) {} - CGameContext* GameServer() { return ms_pGameServer; } IServer* Server() { return ms_pServer; } CPlayerData* PlayerData(int ID) { return &ms_pPlayerData[ID]; } const char* MapName() { return ms_pMap; } - CSqlServer* SqlMasterServer(int i) { return ms_pMasterSqlServers[i]; } - CSqlServer* SqlServer() { return m_pSqlServer; } - int ActiveMasterID() { return m_ActiveMaster; } - - void ConnectSqlServer(bool useMasters = false, int skipCount = 0) - { - if (useMasters) - { - m_pSqlServer = 0; - for (int i = skipCount; i < MAX_SQLMASTERS; i++) - { - if (SqlMasterServer(i) && SqlMasterServer(i)->Connect()) - { - m_pSqlServer = SqlMasterServer(i); - m_ActiveMaster = 0; - return; - } - if (SqlMasterServer(i)) - dbg_msg("SQL", "Warning: Unable to connect to sqlmaster %d ('%s'), trying next...", i, SqlMasterServer(i)->GetIP()); - } - dbg_msg("SQL", "ERROR: No sqlmasterservers available"); - m_ActiveMaster = -1; - } - else if (!SqlServer()->Connect()) - m_pSqlServer = 0; - } static CGameContext *ms_pGameServer; static IServer *ms_pServer; static CPlayerData *ms_pPlayerData; static const char *ms_pMap; - static CSqlServer *ms_pSqlServer; - static CSqlServer **ms_pMasterSqlServers; - - CSqlServer *m_pSqlServer; - int m_ActiveMaster; }; struct CSqlMapData : CSqlData