From 7ced0e5b81f0e56219652f50d67cc6f06b345a40 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 17 Oct 2016 22:33:21 +0200 Subject: [PATCH] LevelDB as default & automatic migration (#30) * Automatic migration to LevelDB backend (only on Android by default) * Use LevelDB as default backend --- src/game.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++- src/subgame.cpp | 2 +- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 5e6a0a890..3df7ca9cc 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -58,7 +58,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "version.h" #include "minimap.h" #include "mapblock_mesh.h" - +#include "database.h" #include "sound.h" #if USE_SOUND @@ -1500,6 +1500,7 @@ protected: bool initSound(); bool createSingleplayerServer(const std::string map_dir, const SubgameSpec &gamespec, u16 port, std::string *address); + bool autoMigrateSingleplayerWorld(const std::string map_dir); // Client creation bool createClient(const std::string &playername, @@ -2044,6 +2045,8 @@ bool Game::createSingleplayerServer(const std::string map_dir, return false; } + autoMigrateSingleplayerWorld(map_dir); + server = new Server(map_dir, gamespec, simple_singleplayer_mode, bind_addr.isIPv6()); @@ -2052,6 +2055,62 @@ bool Game::createSingleplayerServer(const std::string map_dir, return true; } +bool Game::autoMigrateSingleplayerWorld(const std::string map_dir) +{ + const std::string new_backend = "leveldb"; + +#ifndef __ANDROID__ + infostream << "Auto-migration disabled on this platform..." << std::endl; + return false; +#endif + + // Check if needed for this world + Settings world_mt; + std::string world_mt_path = map_dir + DIR_DELIM + "world.mt"; + if (!world_mt.readConfigFile(world_mt_path.c_str())) { + infostream << "Skipping migration check as world.mt can't be read." << std::endl; + return false; + } + if (!world_mt.exists("backend")) + return false; + std::string old_backend = world_mt.get("backend"); + if (old_backend == new_backend) { + infostream << "Backend matches, not migrating world!" << std::endl; + return false; + } + + // Do migration + showOverlayMessage(wgettext("Migrating world..."), 0, 7.5); + infostream << "Doing auto-migration to " << new_backend << " backend." << std::endl; + Database *old_db = ServerMap::createDatabase(old_backend, map_dir, world_mt), + *new_db = ServerMap::createDatabase(new_backend, map_dir, world_mt); + + std::vector blocks; + old_db->listAllLoadableBlocks(blocks); + new_db->beginSave(); + for (std::vector::const_iterator it = blocks.begin(); it != blocks.end(); ++it) { + std::string data; + old_db->loadBlock(*it, &data); + if (!data.empty()) + new_db->saveBlock(*it, data); + else + errorstream << "Failed to load block " << PP(*it) << ", skipping it." << std::endl; + } + new_db->endSave(); + delete old_db; + delete new_db; + + world_mt.set("backend", new_backend); + world_mt.updateConfigFile(world_mt_path.c_str()); + + // Delete old map data if possible + if (old_backend == "sqlite3") + fs::DeleteSingleFileOrEmptyDirectory(map_dir + DIR_DELIM + "map.sqlite"); + + infostream << "Migration successful!" << std::endl; + return true; +} + bool Game::createClient(const std::string &playername, const std::string &password, std::string *address, u16 port) { diff --git a/src/subgame.cpp b/src/subgame.cpp index 0253191f2..3ae25cd6d 100644 --- a/src/subgame.cpp +++ b/src/subgame.cpp @@ -293,7 +293,7 @@ bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamesp if (!fs::PathExists(worldmt_path)) { std::ostringstream ss(std::ios_base::binary); ss << "gameid = " << gamespec.id - << "\nbackend = sqlite3" + << "\nbackend = leveldb" << "\ncreative_mode = " << g_settings->get("creative_mode") << "\nenable_damage = " << g_settings->get("enable_damage") << "\n";