From 9b43b4641fa11d8b9a03b6fa8df7ae60cab3bbd5 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Wed, 1 Oct 2014 01:33:38 +1000 Subject: [PATCH] Salvaging what I can from the failed experiment, read more I'm salvaging the changes to AccountManager and CharacterManager that don't break the build too badly. This won't build, but it'll be easier to rectify. Also, I've reduced the length of the manager's method names, and renamed sql_utility.*pp to sql_tools.*pp --- server/accounts/account_manager.cpp | 56 ++++++++++++--- server/accounts/account_manager.hpp | 16 +++-- server/characters/character_manager.cpp | 68 +++++++++++++------ server/characters/character_manager.hpp | 19 +++--- .../{sql_utility.cpp => sql_tools.cpp} | 2 +- .../{sql_utility.hpp => sql_tools.hpp} | 0 6 files changed, 113 insertions(+), 48 deletions(-) rename server/server_utilities/{sql_utility.cpp => sql_tools.cpp} (98%) rename server/server_utilities/{sql_utility.hpp => sql_tools.hpp} (100%) diff --git a/server/accounts/account_manager.cpp b/server/accounts/account_manager.cpp index c29bd29..e16ad3c 100644 --- a/server/accounts/account_manager.cpp +++ b/server/accounts/account_manager.cpp @@ -31,12 +31,13 @@ static const char* CREATE_USER_ACCOUNT = "INSERT INTO Accounts (username) VALUES static const char* LOAD_USER_ACCOUNT = "SELECT * FROM Accounts WHERE username = ?;"; static const char* SAVE_USER_ACCOUNT = "UPDATE OR FAIL Accounts SET blacklisted = ?2, whitelisted = ?3, mod = ?4, admin = ?5 WHERE uid = ?1;"; static const char* DELETE_USER_ACCOUNT = "DELETE FROM Accounts WHERE uid = ?;"; +static const char* COUNT_USER_ACCOUNT_RECORDS = "SELECT COUNT(*) FROM Accounts;"; //------------------------- //Define the public methods //------------------------- -int AccountManager::CreateAccount(std::string username, int clientIndex) { +int AccountManager::Create(std::string username, int clientIndex) { //create this user account, failing if it exists, leave this account in memory sqlite3_stmt* statement = nullptr; @@ -60,10 +61,10 @@ int AccountManager::CreateAccount(std::string username, int clientIndex) { sqlite3_finalize(statement); //load this account into memory - return LoadAccount(username, clientIndex); + return Load(username, clientIndex); } -int AccountManager::LoadAccount(std::string username, int clientIndex) { +int AccountManager::Load(std::string username, int clientIndex) { //load this user account, failing if it is in memory, creating it if it doesn't exist sqlite3_stmt* statement = nullptr; @@ -109,13 +110,13 @@ int AccountManager::LoadAccount(std::string username, int clientIndex) { if (ret == SQLITE_DONE) { //create the non-existant account instead - return CreateAccount(username, clientIndex); + return Create(username, clientIndex); } throw(std::runtime_error(std::string() + "Unknown SQL error in LoadAccount: " + sqlite3_errmsg(database) )); } -int AccountManager::SaveAccount(int uid) { +int AccountManager::Save(int uid) { //save this user account from memory, replacing it if it exists in the database //DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID. @@ -158,14 +159,14 @@ int AccountManager::SaveAccount(int uid) { return 0; } -void AccountManager::UnloadAccount(int uid) { +void AccountManager::Unload(int uid) { //save this user account, and then unload it //NOTE: the associated characters are unloaded externally - SaveAccount(uid); + Save(uid); accountMap.erase(uid); } -void AccountManager::DeleteAccount(int uid) { +void AccountManager::Delete(int uid) { //delete a user account from the database, and remove it from memory //NOTE: the associated characters should be deleted externally sqlite3_stmt* statement = nullptr; @@ -194,16 +195,29 @@ void AccountManager::DeleteAccount(int uid) { void AccountManager::UnloadAll() { for (auto& it : accountMap) { - SaveAccount(it.first); + Save(it.first); } accountMap.clear(); } +void AccountManager::UnloadIf(std::function)> fn) { + //replicate std::remove_if, using custom code + for (std::map::iterator it = accountMap.begin(); it != accountMap.end(); /* empty */) { + if (fn(*it)) { + Save(it->first); + it = accountMap.erase(it); + continue; + } + ++it; + } +} + //------------------------- //Define the accessors and mutators //------------------------- -AccountData* AccountManager::GetAccount(int uid) { +AccountData* AccountManager::Get(int uid) { + //TODO: could this load an account first? std::map::iterator it = accountMap.find(uid); if (it == accountMap.end()) { @@ -213,6 +227,28 @@ AccountData* AccountManager::GetAccount(int uid) { return &it->second; } +int AccountManager::GetLoadedCount() { + return accountMap.size(); +} + +int AccountManager::GetTotalCount() { + //a lot just to count something. + sqlite3_stmt* statement = nullptr; + + //prep + if (sqlite3_prepare_v2(database, COUNT_USER_ACCOUNT_RECORDS, -1, &statement, nullptr) != SQLITE_OK) { + throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); + } + + //execute & retrieve the result + sqlite3_step(statement); + int ret = sqlite3_column_int(statement, 0); + + //finish the routine + sqlite3_finalize(statement); + return ret; +} + std::map* AccountManager::GetContainer() { return &accountMap; } diff --git a/server/accounts/account_manager.hpp b/server/accounts/account_manager.hpp index 2e631b5..327eb3a 100644 --- a/server/accounts/account_manager.hpp +++ b/server/accounts/account_manager.hpp @@ -27,21 +27,25 @@ #include "sqlite3/sqlite3.h" +#include #include class AccountManager : public Singleton { public: //public access methods - int CreateAccount(std::string username, int clientIndex); - int LoadAccount(std::string username, int clientIndex); - int SaveAccount(int uid); - void UnloadAccount(int uid); - void DeleteAccount(int uid); + int Create(std::string username, int clientIndex); + int Load(std::string username, int clientIndex); + int Save(int uid); + void Unload(int uid); + void Delete(int uid); void UnloadAll(); + void UnloadIf(std::function)> fn); //accessors and mutators - AccountData* GetAccount(int uid); + AccountData* Get(int uid); + int GetLoadedCount(); + int GetTotalCount(); std::map* GetContainer(); sqlite3* SetDatabase(sqlite3* db); diff --git a/server/characters/character_manager.cpp b/server/characters/character_manager.cpp index 4d2078a..080b0ea 100644 --- a/server/characters/character_manager.cpp +++ b/server/characters/character_manager.cpp @@ -23,6 +23,7 @@ #include "sqlite3/sqlite3.h" +#include #include //------------------------- @@ -33,13 +34,14 @@ static const char* CREATE_CHARACTER = "INSERT INTO Characters (owner, handle, av static const char* LOAD_CHARACTER = "SELECT * FROM Characters WHERE handle = ?;"; static const char* SAVE_CHARACTER = "UPDATE OR FAIL Characters SET roomIndex = ?2, originX = ?3, originY = ?4 WHERE uid = ?1;"; static const char* DELETE_CHARACTER = "DELETE FROM Characters WHERE uid = ?;"; +static const char* COUNT_CHARACTER_RECORDS = "SELECT COUNT(*) FROM Characters;"; //------------------------- //Define the methods //------------------------- //NOTE: default baseStats as a parameter would be good for different beggining states or multiple classes -int CharacterManager::CreateCharacter(int owner, std::string handle, std::string avatar) { +int CharacterManager::Create(int owner, std::string handle, std::string avatar) { //Create the character, failing if it exists sqlite3_stmt* statement = nullptr; @@ -69,10 +71,10 @@ int CharacterManager::CreateCharacter(int owner, std::string handle, std::string sqlite3_finalize(statement); //load this character into memory - return LoadCharacter(owner, handle, avatar); + return Load(owner, handle, avatar); } -int CharacterManager::LoadCharacter(int owner, std::string handle, std::string avatar) { +int CharacterManager::Load(int owner, std::string handle, std::string avatar) { //load the specified character, creating it if it doesn't exist //fail if it is already loaded, or does not belong to this account sqlite3_stmt* statement = nullptr; @@ -132,13 +134,13 @@ int CharacterManager::LoadCharacter(int owner, std::string handle, std::string a if (ret == SQLITE_DONE) { //create the non-existant character instead - return CreateCharacter(owner, handle, avatar); + return Create(owner, handle, avatar); } throw(std::runtime_error(std::string() + "Unknown SQL error in LoadCharacter: " + sqlite3_errmsg(database) )); } -int CharacterManager::SaveCharacter(int uid) { +int CharacterManager::Save(int uid) { //save this character from memory, replacing it if it exists in the database //DOCS: To use this method, change the in-memory copy, and then call this function using that object's UID. @@ -182,13 +184,13 @@ int CharacterManager::SaveCharacter(int uid) { return 0; } -void CharacterManager::UnloadCharacter(int uid) { +void CharacterManager::Unload(int uid) { //save this character, then unload it - SaveCharacter(uid); + Save(uid); characterMap.erase(uid); } -void CharacterManager::DeleteCharacter(int uid) { +void CharacterManager::Delete(int uid) { //delete this character from the database, then remove it from memory sqlite3_stmt* statement = nullptr; @@ -214,30 +216,30 @@ void CharacterManager::DeleteCharacter(int uid) { characterMap.erase(uid); } -void CharacterManager::UnloadCharacterIf(std::function::iterator)> f) { - //save this character, then unload it if the parameter returns true - for (std::map::iterator it = characterMap.begin(); it != characterMap.end(); /* EMPTY */ ) { - if (f(it)) { - SaveCharacter(it->first); +void CharacterManager::UnloadAll() { + for (auto& it : characterMap) { + Save(it.first); + } + characterMap.clear(); +} + +void CharacterManager::UnloadIf(std::function)> fn) { + //replicate std::remove_if, using custom code + for (std::map::iterator it = characterMap.begin(); it != characterMap.end(); /* empty */) { + if (fn(*it)) { + Save(it->first); it = characterMap.erase(it); continue; } - it++; + ++it; } } -void CharacterManager::UnloadAll() { - for (auto& it : characterMap) { - SaveCharacter(it.first); - } - characterMap.clear(); -} - //------------------------- //Define the accessors and mutators //------------------------- -CharacterData* CharacterManager::GetCharacter(int uid) { +CharacterData* CharacterManager::Get(int uid) { std::map::iterator it = characterMap.find(uid); if (it == characterMap.end()) { @@ -247,6 +249,28 @@ CharacterData* CharacterManager::GetCharacter(int uid) { return &it->second; } +int CharacterManager::GetLoadedCount() { + return characterMap.size(); +} + +int CharacterManager::GetTotalCount() { + //a lot just to count something. + sqlite3_stmt* statement = nullptr; + + //prep + if (sqlite3_prepare_v2(database, COUNT_CHARACTER_RECORDS, -1, &statement, nullptr) != SQLITE_OK) { + throw( std::runtime_error(std::string() + "Failed to prepare an SQL statement: " + sqlite3_errmsg(database)) ); + } + + //execute & retrieve the result + sqlite3_step(statement); + int ret = sqlite3_column_int(statement, 0); + + //finish the routine + sqlite3_finalize(statement); + return ret; +} + std::map* CharacterManager::GetContainer() { return &characterMap; } diff --git a/server/characters/character_manager.hpp b/server/characters/character_manager.hpp index 084d595..68b58aa 100644 --- a/server/characters/character_manager.hpp +++ b/server/characters/character_manager.hpp @@ -27,24 +27,25 @@ #include "sqlite3/sqlite3.h" -#include #include +#include class CharacterManager : public Singleton { public: //public access methods - int CreateCharacter(int owner, std::string handle, std::string avatar); - int LoadCharacter(int owner, std::string handle, std::string avatar); - int SaveCharacter(int uid); - void UnloadCharacter(int uid); - void DeleteCharacter(int uid); - - void UnloadCharacterIf(std::function::iterator)> f); + int Create(int owner, std::string handle, std::string avatar); + int Load(int owner, std::string handle, std::string avatar); + int Save(int uid); + void Unload(int uid); + void Delete(int uid); void UnloadAll(); + void UnloadIf(std::function)> fn); //accessors and mutators - CharacterData* GetCharacter(int uid); + CharacterData* Get(int uid); + int GetLoadedCount(); + int GetTotalCount(); std::map* GetContainer(); sqlite3* SetDatabase(sqlite3* db); diff --git a/server/server_utilities/sql_utility.cpp b/server/server_utilities/sql_tools.cpp similarity index 98% rename from server/server_utilities/sql_utility.cpp rename to server/server_utilities/sql_tools.cpp index 5d586d4..19e0ddb 100644 --- a/server/server_utilities/sql_utility.cpp +++ b/server/server_utilities/sql_tools.cpp @@ -19,7 +19,7 @@ * 3. This notice may not be removed or altered from any source * distribution. */ -#include "sql_utility.hpp" +#include "sql_tools.hpp" #include "utility.hpp" diff --git a/server/server_utilities/sql_utility.hpp b/server/server_utilities/sql_tools.hpp similarity index 100% rename from server/server_utilities/sql_utility.hpp rename to server/server_utilities/sql_tools.hpp