diff options
author | Jude Melton-Houghton <jwmhjwmh@gmail.com> | 2022-09-26 17:03:43 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-26 17:03:43 -0400 |
commit | f4a01f3a5dc0d8fe2f4f6d804d790da91d1bc30c (patch) | |
tree | 089ddc309e22ae8549ec3b86765ee272f57a33df /src/database | |
parent | 03428d9825cfdf2cfaed6ac9410dafccac0d4f3a (diff) | |
download | minetest-f4a01f3a5dc0d8fe2f4f6d804d790da91d1bc30c.tar.xz |
Avoid duplication of mod metadata in memory (#12562)
Co-authored-by: sfan5 <sfan5@live.de>
Diffstat (limited to 'src/database')
-rw-r--r-- | src/database/database-dummy.cpp | 36 | ||||
-rw-r--r-- | src/database/database-dummy.h | 4 | ||||
-rw-r--r-- | src/database/database-files.cpp | 31 | ||||
-rw-r--r-- | src/database/database-files.h | 4 | ||||
-rw-r--r-- | src/database/database-sqlite3.cpp | 75 | ||||
-rw-r--r-- | src/database/database-sqlite3.h | 7 | ||||
-rw-r--r-- | src/database/database.h | 4 |
7 files changed, 153 insertions, 8 deletions
diff --git a/src/database/database-dummy.cpp b/src/database/database-dummy.cpp index a44762d8a..ee88c6684 100644 --- a/src/database/database-dummy.cpp +++ b/src/database/database-dummy.cpp @@ -92,6 +92,32 @@ bool Database_Dummy::getModEntries(const std::string &modname, StringMap *storag return true; } +bool Database_Dummy::getModEntry(const std::string &modname, + const std::string &key, std::string *value) +{ + auto mod_pair = m_mod_meta_database.find(modname); + if (mod_pair == m_mod_meta_database.end()) + return false; + const StringMap &meta = mod_pair->second; + + auto pair = meta.find(key); + if (pair != meta.end()) { + *value = pair->second; + return true; + } + return false; +} + +bool Database_Dummy::hasModEntry(const std::string &modname, const std::string &key) +{ + auto mod_pair = m_mod_meta_database.find(modname); + if (mod_pair == m_mod_meta_database.end()) + return false; + const StringMap &meta = mod_pair->second; + + return meta.find(key) != meta.cend(); +} + bool Database_Dummy::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { @@ -112,6 +138,16 @@ bool Database_Dummy::removeModEntry(const std::string &modname, const std::strin return false; } +bool Database_Dummy::removeModEntries(const std::string &modname) +{ + auto mod_pair = m_mod_meta_database.find(modname); + if (mod_pair != m_mod_meta_database.end() && !mod_pair->second.empty()) { + mod_pair->second.clear(); + return true; + } + return false; +} + void Database_Dummy::listMods(std::vector<std::string> *res) { for (const auto &pair : m_mod_meta_database) { diff --git a/src/database/database-dummy.h b/src/database/database-dummy.h index 44b9e8d68..86c680ef1 100644 --- a/src/database/database-dummy.h +++ b/src/database/database-dummy.h @@ -38,9 +38,13 @@ public: void listPlayers(std::vector<std::string> &res); bool getModEntries(const std::string &modname, StringMap *storage); + bool getModEntry(const std::string &modname, + const std::string &key, std::string *value); + bool hasModEntry(const std::string &modname, const std::string &key); bool setModEntry(const std::string &modname, const std::string &key, const std::string &value); bool removeModEntry(const std::string &modname, const std::string &key); + bool removeModEntries(const std::string &modname); void listMods(std::vector<std::string> *res); void beginSave() {} diff --git a/src/database/database-files.cpp b/src/database/database-files.cpp index 00bc6d765..eff08de12 100644 --- a/src/database/database-files.cpp +++ b/src/database/database-files.cpp @@ -396,6 +396,26 @@ bool ModMetadataDatabaseFiles::getModEntries(const std::string &modname, StringM return true; } +bool ModMetadataDatabaseFiles::getModEntry(const std::string &modname, + const std::string &key, std::string *value) +{ + Json::Value *meta = getOrCreateJson(modname); + if (!meta) + return false; + + if (meta->isMember(key)) { + *value = (*meta)[key].asString(); + return true; + } + return false; +} + +bool ModMetadataDatabaseFiles::hasModEntry(const std::string &modname, const std::string &key) +{ + Json::Value *meta = getOrCreateJson(modname); + return meta && meta->isMember(key); +} + bool ModMetadataDatabaseFiles::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { @@ -424,6 +444,17 @@ bool ModMetadataDatabaseFiles::removeModEntry(const std::string &modname, return false; } +bool ModMetadataDatabaseFiles::removeModEntries(const std::string &modname) +{ + Json::Value *meta = getOrCreateJson(modname); + if (!meta || meta->empty()) + return false; + + meta->clear(); + m_modified.insert(modname); + return true; +} + void ModMetadataDatabaseFiles::beginSave() { } diff --git a/src/database/database-files.h b/src/database/database-files.h index 962e4d7bb..089e071fe 100644 --- a/src/database/database-files.h +++ b/src/database/database-files.h @@ -79,9 +79,13 @@ public: virtual ~ModMetadataDatabaseFiles() = default; virtual bool getModEntries(const std::string &modname, StringMap *storage); + virtual bool getModEntry(const std::string &modname, + const std::string &key, std::string *value); + virtual bool hasModEntry(const std::string &modname, const std::string &key); virtual bool setModEntry(const std::string &modname, const std::string &key, const std::string &value); virtual bool removeModEntry(const std::string &modname, const std::string &key); + virtual bool removeModEntries(const std::string &modname); virtual void listMods(std::vector<std::string> *res); virtual void beginSave(); diff --git a/src/database/database-sqlite3.cpp b/src/database/database-sqlite3.cpp index 5e565be55..0406fadc8 100644 --- a/src/database/database-sqlite3.cpp +++ b/src/database/database-sqlite3.cpp @@ -770,9 +770,12 @@ ModMetadataDatabaseSQLite3::ModMetadataDatabaseSQLite3(const std::string &savedi ModMetadataDatabaseSQLite3::~ModMetadataDatabaseSQLite3() { + FINALIZE_STATEMENT(m_stmt_remove_all) FINALIZE_STATEMENT(m_stmt_remove) FINALIZE_STATEMENT(m_stmt_set) + FINALIZE_STATEMENT(m_stmt_has) FINALIZE_STATEMENT(m_stmt_get) + FINALIZE_STATEMENT(m_stmt_get_all) } void ModMetadataDatabaseSQLite3::createDatabase() @@ -792,31 +795,74 @@ void ModMetadataDatabaseSQLite3::createDatabase() void ModMetadataDatabaseSQLite3::initStatements() { - PREPARE_STATEMENT(get, "SELECT `key`, `value` FROM `entries` WHERE `modname` = ?"); + PREPARE_STATEMENT(get_all, "SELECT `key`, `value` FROM `entries` WHERE `modname` = ?"); + PREPARE_STATEMENT(get, + "SELECT `value` FROM `entries` WHERE `modname` = ? AND `key` = ? LIMIT 1"); + PREPARE_STATEMENT(has, + "SELECT 1 FROM `entries` WHERE `modname` = ? AND `key` = ? LIMIT 1"); PREPARE_STATEMENT(set, "REPLACE INTO `entries` (`modname`, `key`, `value`) VALUES (?, ?, ?)"); PREPARE_STATEMENT(remove, "DELETE FROM `entries` WHERE `modname` = ? AND `key` = ?"); + PREPARE_STATEMENT(remove_all, "DELETE FROM `entries` WHERE `modname` = ?"); } bool ModMetadataDatabaseSQLite3::getModEntries(const std::string &modname, StringMap *storage) { verifyDatabase(); - str_to_sqlite(m_stmt_get, 1, modname); - while (sqlite3_step(m_stmt_get) == SQLITE_ROW) { - const char *key_data = (const char *) sqlite3_column_blob(m_stmt_get, 0); - size_t key_len = sqlite3_column_bytes(m_stmt_get, 0); - const char *value_data = (const char *) sqlite3_column_blob(m_stmt_get, 1); - size_t value_len = sqlite3_column_bytes(m_stmt_get, 1); + str_to_sqlite(m_stmt_get_all, 1, modname); + while (sqlite3_step(m_stmt_get_all) == SQLITE_ROW) { + const char *key_data = (const char *) sqlite3_column_blob(m_stmt_get_all, 0); + size_t key_len = sqlite3_column_bytes(m_stmt_get_all, 0); + const char *value_data = (const char *) sqlite3_column_blob(m_stmt_get_all, 1); + size_t value_len = sqlite3_column_bytes(m_stmt_get_all, 1); (*storage)[std::string(key_data, key_len)] = std::string(value_data, value_len); } sqlite3_vrfy(sqlite3_errcode(m_database), SQLITE_DONE); - sqlite3_reset(m_stmt_get); + sqlite3_reset(m_stmt_get_all); return true; } +bool ModMetadataDatabaseSQLite3::getModEntry(const std::string &modname, + const std::string &key, std::string *value) +{ + verifyDatabase(); + + str_to_sqlite(m_stmt_get, 1, modname); + SQLOK(sqlite3_bind_blob(m_stmt_get, 2, key.data(), key.size(), NULL), + "Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__)); + bool found = sqlite3_step(m_stmt_get) == SQLITE_ROW; + if (found) { + const char *value_data = (const char *) sqlite3_column_blob(m_stmt_get, 0); + size_t value_len = sqlite3_column_bytes(m_stmt_get, 0); + value->assign(value_data, value_len); + sqlite3_step(m_stmt_get); + } + + sqlite3_reset(m_stmt_get); + + return found; +} + +bool ModMetadataDatabaseSQLite3::hasModEntry(const std::string &modname, + const std::string &key) +{ + verifyDatabase(); + + str_to_sqlite(m_stmt_has, 1, modname); + SQLOK(sqlite3_bind_blob(m_stmt_has, 2, key.data(), key.size(), NULL), + "Internal error: failed to bind query at " __FILE__ ":" TOSTRING(__LINE__)); + bool found = sqlite3_step(m_stmt_has) == SQLITE_ROW; + if (found) + sqlite3_step(m_stmt_has); + + sqlite3_reset(m_stmt_has); + + return found; +} + bool ModMetadataDatabaseSQLite3::setModEntry(const std::string &modname, const std::string &key, const std::string &value) { @@ -850,6 +896,19 @@ bool ModMetadataDatabaseSQLite3::removeModEntry(const std::string &modname, return changes > 0; } +bool ModMetadataDatabaseSQLite3::removeModEntries(const std::string &modname) +{ + verifyDatabase(); + + str_to_sqlite(m_stmt_remove_all, 1, modname); + sqlite3_vrfy(sqlite3_step(m_stmt_remove_all), SQLITE_DONE); + int changes = sqlite3_changes(m_database); + + sqlite3_reset(m_stmt_remove_all); + + return changes > 0; +} + void ModMetadataDatabaseSQLite3::listMods(std::vector<std::string> *res) { verifyDatabase(); diff --git a/src/database/database-sqlite3.h b/src/database/database-sqlite3.h index 5e3d7c96c..566f6cebb 100644 --- a/src/database/database-sqlite3.h +++ b/src/database/database-sqlite3.h @@ -240,9 +240,13 @@ public: virtual ~ModMetadataDatabaseSQLite3(); virtual bool getModEntries(const std::string &modname, StringMap *storage); + virtual bool getModEntry(const std::string &modname, + const std::string &key, std::string *value); + virtual bool hasModEntry(const std::string &modname, const std::string &key); virtual bool setModEntry(const std::string &modname, const std::string &key, const std::string &value); virtual bool removeModEntry(const std::string &modname, const std::string &key); + virtual bool removeModEntries(const std::string &modname); virtual void listMods(std::vector<std::string> *res); virtual void beginSave() { Database_SQLite3::beginSave(); } @@ -253,7 +257,10 @@ protected: virtual void initStatements(); private: + sqlite3_stmt *m_stmt_get_all = nullptr; sqlite3_stmt *m_stmt_get = nullptr; + sqlite3_stmt *m_stmt_has = nullptr; sqlite3_stmt *m_stmt_set = nullptr; sqlite3_stmt *m_stmt_remove = nullptr; + sqlite3_stmt *m_stmt_remove_all = nullptr; }; diff --git a/src/database/database.h b/src/database/database.h index fbb5befea..0f22deebc 100644 --- a/src/database/database.h +++ b/src/database/database.h @@ -92,8 +92,12 @@ public: virtual ~ModMetadataDatabase() = default; virtual bool getModEntries(const std::string &modname, StringMap *storage) = 0; + virtual bool hasModEntry(const std::string &modname, const std::string &key) = 0; + virtual bool getModEntry(const std::string &modname, + const std::string &key, std::string *value) = 0; virtual bool setModEntry(const std::string &modname, const std::string &key, const std::string &value) = 0; virtual bool removeModEntry(const std::string &modname, const std::string &key) = 0; + virtual bool removeModEntries(const std::string &modname) = 0; virtual void listMods(std::vector<std::string> *res) = 0; }; |