summaryrefslogtreecommitdiff
path: root/src/database-leveldb.cpp
diff options
context:
space:
mode:
authorIlya Zhuravlev <zhuravlevilya@ya.ru>2012-10-23 01:18:44 +0400
committerSfan5 <sfan5@live.de>2013-09-09 22:50:50 +0200
commit58841ef12f6cba1bb622353c1fcaa0e3c6fb46c9 (patch)
tree6012bbb1905231025dff89aa73782a7c38666839 /src/database-leveldb.cpp
parent71a8769bb5ded4acb3f9e5a8502bb8af277f824d (diff)
downloadminetest-58841ef12f6cba1bb622353c1fcaa0e3c6fb46c9.tar.gz
minetest-58841ef12f6cba1bb622353c1fcaa0e3c6fb46c9.tar.bz2
minetest-58841ef12f6cba1bb622353c1fcaa0e3c6fb46c9.zip
Add dummy and LevelDB database backends
Diffstat (limited to 'src/database-leveldb.cpp')
-rw-r--r--src/database-leveldb.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/database-leveldb.cpp b/src/database-leveldb.cpp
new file mode 100644
index 000000000..34e153988
--- /dev/null
+++ b/src/database-leveldb.cpp
@@ -0,0 +1,163 @@
+#include "config.h"
+
+#if USE_LEVELDB
+/*
+LevelDB databases
+*/
+
+
+#include "map.h"
+#include "mapsector.h"
+#include "mapblock.h"
+#include "main.h"
+#include "filesys.h"
+#include "voxel.h"
+#include "porting.h"
+#include "mapgen.h"
+#include "nodemetadata.h"
+#include "settings.h"
+#include "log.h"
+#include "profiler.h"
+#include "nodedef.h"
+#include "gamedef.h"
+#include "util/directiontables.h"
+#include "rollback_interface.h"
+
+#include "database-leveldb.h"
+#include "leveldb/db.h"
+
+Database_LevelDB::Database_LevelDB(ServerMap *map, std::string savedir)
+{
+ leveldb::Options options;
+ options.create_if_missing = true;
+ leveldb::Status status = leveldb::DB::Open(options, savedir + DIR_DELIM + "map.db", &m_database);
+ assert(status.ok());
+ srvmap = map;
+}
+
+int Database_LevelDB::Initialized(void)
+{
+ return 1;
+}
+
+void Database_LevelDB::beginSave() {}
+void Database_LevelDB::endSave() {}
+
+void Database_LevelDB::saveBlock(MapBlock *block)
+{
+ DSTACK(__FUNCTION_NAME);
+ /*
+ Dummy blocks are not written
+ */
+ if(block->isDummy())
+ {
+ return;
+ }
+
+ // Format used for writing
+ u8 version = SER_FMT_VER_HIGHEST;
+ // Get destination
+ v3s16 p3d = block->getPos();
+
+ /*
+ [0] u8 serialization version
+ [1] data
+ */
+
+ std::ostringstream o(std::ios_base::binary);
+ o.write((char*)&version, 1);
+ // Write basic data
+ block->serialize(o, version, true);
+ // Write block to database
+ std::string tmp = o.str();
+
+ m_database->Put(leveldb::WriteOptions(), i64tos(getBlockAsInteger(p3d)), tmp);
+
+ // We just wrote it to the disk so clear modified flag
+ block->resetModified();
+}
+
+MapBlock* Database_LevelDB::loadBlock(v3s16 blockpos)
+{
+ v2s16 p2d(blockpos.X, blockpos.Z);
+
+ std::string datastr;
+ leveldb::Status s = m_database->Get(leveldb::ReadOptions(), i64tos(getBlockAsInteger(blockpos)), &datastr);
+
+ if(s.ok()) {
+ /*
+ Make sure sector is loaded
+ */
+ MapSector *sector = srvmap->createSector(p2d);
+
+ try {
+ std::istringstream is(datastr, std::ios_base::binary);
+ u8 version = SER_FMT_VER_INVALID;
+ is.read((char*)&version, 1);
+
+ if(is.fail())
+ throw SerializationError("ServerMap::loadBlock(): Failed"
+ " to read MapBlock version");
+
+ MapBlock *block = NULL;
+ bool created_new = false;
+ block = sector->getBlockNoCreateNoEx(blockpos.Y);
+ if(block == NULL)
+ {
+ block = sector->createBlankBlockNoInsert(blockpos.Y);
+ created_new = true;
+ }
+ // Read basic data
+ block->deSerialize(is, version, true);
+ // If it's a new block, insert it to the map
+ if(created_new)
+ sector->insertBlock(block);
+ /*
+ Save blocks loaded in old format in new format
+ */
+
+ //if(version < SER_FMT_VER_HIGHEST || save_after_load)
+ // Only save if asked to; no need to update version
+ //if(save_after_load)
+ // saveBlock(block);
+ // We just loaded it from, so it's up-to-date.
+ block->resetModified();
+
+ }
+ catch(SerializationError &e)
+ {
+ errorstream<<"Invalid block data in database"
+ <<" ("<<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z<<")"
+ <<" (SerializationError): "<<e.what()<<std::endl;
+ // TODO: Block should be marked as invalid in memory so that it is
+ // not touched but the game can run
+
+ if(g_settings->getBool("ignore_world_load_errors")){
+ errorstream<<"Ignoring block load error. Duck and cover! "
+ <<"(ignore_world_load_errors)"<<std::endl;
+ } else {
+ throw SerializationError("Invalid block data in database");
+ //assert(0);
+ }
+ }
+
+ return srvmap->getBlockNoCreateNoEx(blockpos); // should not be using this here
+ }
+ return(NULL);
+}
+
+void Database_LevelDB::listAllLoadableBlocks(core::list<v3s16> &dst)
+{
+ leveldb::Iterator* it = m_database->NewIterator(leveldb::ReadOptions());
+ for (it->SeekToFirst(); it->Valid(); it->Next()) {
+ dst.push_back(getIntegerAsBlock(stoi64(it->key().ToString())));
+ }
+ assert(it->status().ok()); // Check for any errors found during the scan
+ delete it;
+}
+
+Database_LevelDB::~Database_LevelDB()
+{
+ delete m_database;
+}
+#endif