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