LevelDB as default & automatic migration (#30)

* Automatic migration to LevelDB backend (only on Android by default)

* Use LevelDB as default backend
This commit is contained in:
sfan5 2016-10-17 22:33:21 +02:00 committed by Maksim Gamarnik
parent b33e6dbcad
commit 7ced0e5b81
2 changed files with 61 additions and 2 deletions

View File

@ -58,7 +58,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "version.h" #include "version.h"
#include "minimap.h" #include "minimap.h"
#include "mapblock_mesh.h" #include "mapblock_mesh.h"
#include "database.h"
#include "sound.h" #include "sound.h"
#if USE_SOUND #if USE_SOUND
@ -1500,6 +1500,7 @@ protected:
bool initSound(); bool initSound();
bool createSingleplayerServer(const std::string map_dir, bool createSingleplayerServer(const std::string map_dir,
const SubgameSpec &gamespec, u16 port, std::string *address); const SubgameSpec &gamespec, u16 port, std::string *address);
bool autoMigrateSingleplayerWorld(const std::string map_dir);
// Client creation // Client creation
bool createClient(const std::string &playername, bool createClient(const std::string &playername,
@ -2044,6 +2045,8 @@ bool Game::createSingleplayerServer(const std::string map_dir,
return false; return false;
} }
autoMigrateSingleplayerWorld(map_dir);
server = new Server(map_dir, gamespec, simple_singleplayer_mode, server = new Server(map_dir, gamespec, simple_singleplayer_mode,
bind_addr.isIPv6()); bind_addr.isIPv6());
@ -2052,6 +2055,62 @@ bool Game::createSingleplayerServer(const std::string map_dir,
return true; 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<v3s16> blocks;
old_db->listAllLoadableBlocks(blocks);
new_db->beginSave();
for (std::vector<v3s16>::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, bool Game::createClient(const std::string &playername,
const std::string &password, std::string *address, u16 port) const std::string &password, std::string *address, u16 port)
{ {

View File

@ -293,7 +293,7 @@ bool loadGameConfAndInitWorld(const std::string &path, const SubgameSpec &gamesp
if (!fs::PathExists(worldmt_path)) { if (!fs::PathExists(worldmt_path)) {
std::ostringstream ss(std::ios_base::binary); std::ostringstream ss(std::ios_base::binary);
ss << "gameid = " << gamespec.id ss << "gameid = " << gamespec.id
<< "\nbackend = sqlite3" << "\nbackend = leveldb"
<< "\ncreative_mode = " << g_settings->get("creative_mode") << "\ncreative_mode = " << g_settings->get("creative_mode")
<< "\nenable_damage = " << g_settings->get("enable_damage") << "\nenable_damage = " << g_settings->get("enable_damage")
<< "\n"; << "\n";