diff --git a/src/main.cpp b/src/main.cpp index e06a3c421..2800dcd6d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,9 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (C) 2010-2013 celeron55, Perttu Ahola +#include +#include + #include "irrlichttypes_bloated.h" #include "irrlicht.h" // createDevice #include "irrlicht_changes/printing.h" @@ -405,6 +408,22 @@ static void print_help(const OptionList &allowed_options) { std::cout << _("Allowed options:") << std::endl; print_allowed_options(allowed_options); + std::cout << std::endl; + + std::pair> the_list[] = { + {"map", ServerMap::getDatabaseBackends()}, + {"players", ServerEnvironment::getPlayerDatabaseBackends()}, + {"auth", ServerEnvironment::getAuthDatabaseBackends()}, + {"mod storage", Server::getModStorageDatabaseBackends()}, + }; + + std::cout << "Supported database backends:"; + for (auto &e : the_list) { + SORT_AND_UNIQUE(e.second); + std::cout << "\n " << padStringRight(e.first, 16) + << ": " << str_join(e.second, ", "); + } + std::cout << std::endl; } static void print_allowed_options(const OptionList &allowed_options) diff --git a/src/server.cpp b/src/server.cpp index 3cf02a59e..139dc0e19 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -4289,15 +4289,28 @@ ModStorageDatabase *Server::openModStorageDatabase(const std::string &world_path std::string backend = world_mt.exists("mod_storage_backend") ? world_mt.get("mod_storage_backend") : "files"; - if (backend == "files") + if (backend == "files") { warningstream << "/!\\ You are using the old mod storage files backend. " - << "This backend is deprecated and may be removed in a future release /!\\" - << std::endl << "Switching to SQLite3 is advised, " - << "please read https://docs.luanti.org/for-server-hosts/database-backends." << std::endl; + "This backend is deprecated and may be removed in a future release /!\\" + "\nSwitching to SQLite3 is advised, " + "please read https://docs.luanti.org/for-server-hosts/database-backends." << std::endl; + } return openModStorageDatabase(backend, world_path, world_mt); } +std::vector Server::getModStorageDatabaseBackends() +{ + std::vector ret; + ret.emplace_back("sqlite3"); +#if USE_POSTGRESQL + ret.emplace_back("postgresql"); +#endif + ret.emplace_back("files"); + ret.emplace_back("dummy"); + return ret; +} + ModStorageDatabase *Server::openModStorageDatabase(const std::string &backend, const std::string &world_path, const Settings &world_mt) { diff --git a/src/server.h b/src/server.h index 177af002f..24818c6b0 100644 --- a/src/server.h +++ b/src/server.h @@ -435,6 +435,8 @@ public: // map key = binary sha1, map value = file path std::unordered_map getMediaList(); + static std::vector getModStorageDatabaseBackends(); + static ModStorageDatabase *openModStorageDatabase(const std::string &world_path); static ModStorageDatabase *openModStorageDatabase(const std::string &backend, diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index a9f072583..c7ce34069 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1828,6 +1828,21 @@ void ServerEnvironment::processActiveObjectRemove(ServerActiveObject *obj) m_script->removeObjectReference(obj); } +std::vector ServerEnvironment::getPlayerDatabaseBackends() +{ + std::vector ret; + ret.emplace_back("sqlite3"); + ret.emplace_back("dummy"); +#if USE_POSTGRESQL + ret.emplace_back("postgresql"); +#endif +#if USE_LEVELDB + ret.emplace_back("leveldb"); +#endif + ret.emplace_back("files"); + return ret; +} + PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name, const std::string &savedir, const Settings &conf) { @@ -1944,6 +1959,21 @@ bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params, return true; } +std::vector ServerEnvironment::getAuthDatabaseBackends() +{ + std::vector ret; + ret.emplace_back("sqlite3"); + ret.emplace_back("dummy"); +#if USE_POSTGRESQL + ret.emplace_back("postgresql"); +#endif + ret.emplace_back("files"); +#if USE_LEVELDB + ret.emplace_back("leveldb"); +#endif + return ret; +} + AuthDatabase *ServerEnvironment::openAuthDatabase( const std::string &name, const std::string &savedir, const Settings &conf) { diff --git a/src/serverenvironment.h b/src/serverenvironment.h index 973a8b00f..92205bd57 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -278,12 +278,15 @@ public: const std::vector getPlayers() const { return m_players; } u32 getPlayerCount() const { return m_players.size(); } + static std::vector getPlayerDatabaseBackends(); static bool migratePlayersDatabase(const GameParams &game_params, const Settings &cmd_args); AuthDatabase *getAuthDatabase() { return m_auth_database; } + static std::vector getAuthDatabaseBackends(); static bool migrateAuthDatabase(const GameParams &game_params, const Settings &cmd_args); + private: /** diff --git a/src/servermap.cpp b/src/servermap.cpp index f94a58d0d..bdd90523f 100644 --- a/src/servermap.cpp +++ b/src/servermap.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-2.1-or-later // Copyright (C) 2010-2024 celeron55, Perttu Ahola +#include + #include "map.h" #include "mapsector.h" #include "filesys.h" @@ -568,36 +570,62 @@ void ServerMap::listAllLoadedBlocks(std::vector &dst) } } +std::vector ServerMap::getDatabaseBackends() +{ + std::vector ret; + ret.emplace_back("sqlite3"); + ret.emplace_back("dummy"); +#if USE_LEVELDB + ret.emplace_back("leveldb"); +#endif +#if USE_REDIS + ret.emplace_back("redis"); +#endif +#if USE_POSTGRESQL + ret.emplace_back("postgresql"); +#endif + return ret; +} + MapDatabase *ServerMap::createDatabase( const std::string &name, const std::string &savedir, Settings &conf) { + // Hopefully this way we don't forget to keep them in sync. + auto valid = getDatabaseBackends(); + if (!CONTAINS(valid, name)) { + auto err = std::string("Database backend \"") + name + "\" unknown or not supported"; + errorstream << err << std::endl; + throw BaseException(err); + } + MapDatabase *db = nullptr; - verbosestream << "Creating map database with backend \"" << name << "\"" << std::endl; + infostream << "Creating map database with backend \"" << name << "\"" << std::endl; if (name == "sqlite3") db = new MapDatabaseSQLite3(savedir); - if (name == "dummy") + else if (name == "dummy") db = new Database_Dummy(); - #if USE_LEVELDB - if (name == "leveldb") +#if USE_LEVELDB + else if (name == "leveldb") db = new Database_LevelDB(savedir); - #endif - #if USE_REDIS - if (name == "redis") +#endif +#if USE_REDIS + else if (name == "redis") db = new Database_Redis(conf); - #endif - #if USE_POSTGRESQL - if (name == "postgresql") { +#endif +#if USE_POSTGRESQL + else if (name == "postgresql") { std::string connect_string; conf.getNoEx("pgsql_connection", connect_string); db = new MapDatabasePostgreSQL(connect_string); } - #endif +#endif + + // Constructor can't return null, only throw + sanity_check(db); - if (!db) - throw BaseException(std::string("Database backend ") + name + " not supported."); // Do this to get feedback about errors asap db->verifyDatabase(); assert(db->initialized()); diff --git a/src/servermap.h b/src/servermap.h index c4bdff92d..861d64dbe 100644 --- a/src/servermap.h +++ b/src/servermap.h @@ -101,6 +101,7 @@ public: /* Database functions */ + static std::vector getDatabaseBackends(); static MapDatabase *createDatabase(const std::string &name, const std::string &savedir, Settings &conf); // Call these before and after saving of blocks