aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/database/CMakeLists.txt1
-rw-r--r--src/database/database-lmdb.cpp226
-rw-r--r--src/database/database-lmdb.h64
-rw-r--r--src/map.cpp3
5 files changed, 296 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c068be575..d051fad68 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -531,6 +531,7 @@ if(BUILD_CLIENT)
${LUA_BIT_LIBRARY}
${FREETYPE_LIBRARY}
${PLATFORM_LIBS}
+ /usr/lib/x86_64-linux-gnu/liblmdb.a
)
if(NOT USE_LUAJIT)
set_target_properties(${PROJECT_NAME} PROPERTIES
@@ -600,6 +601,7 @@ if(BUILD_SERVER)
${LUA_BIT_LIBRARY}
${GMP_LIBRARY}
${PLATFORM_LIBS}
+ /usr/lib/x86_64-linux-gnu/liblmdb.a
)
set_target_properties(${PROJECT_NAME}server PROPERTIES
COMPILE_DEFINITIONS "SERVER")
diff --git a/src/database/CMakeLists.txt b/src/database/CMakeLists.txt
index e9d157c29..991d0c565 100644
--- a/src/database/CMakeLists.txt
+++ b/src/database/CMakeLists.txt
@@ -6,5 +6,6 @@ set(database_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/database-postgresql.cpp
${CMAKE_CURRENT_SOURCE_DIR}/database-redis.cpp
${CMAKE_CURRENT_SOURCE_DIR}/database-sqlite3.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/database-lmdb.cpp
PARENT_SCOPE
)
diff --git a/src/database/database-lmdb.cpp b/src/database/database-lmdb.cpp
new file mode 100644
index 000000000..f36eecb57
--- /dev/null
+++ b/src/database/database-lmdb.cpp
@@ -0,0 +1,226 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/*
+LMDB database class
+*/
+
+#include "database-lmdb.h"
+#include "remoteplayer.h"
+
+#include <fcntl.h>
+//#include <sys/time.h>
+
+//static uint64_t microtime(void) {
+// struct timeval tv;
+// struct timezone tz = {0};
+//
+// gettimeofday(&tv, &tz);
+// return (tv.tv_sec * 1000000) + tv.tv_usec;
+//}
+
+Database_LMDB::Database_LMDB(const std::string &savedir)
+{
+ mdb_env_create(&env);
+ mdb_env_set_mapsize(env, 0x10000000000);
+ mdb_strerror(mdb_env_open(env, (savedir+"/map.mdb").c_str(), MDB_NOSUBDIR | MDB_NORDAHEAD | MDB_NOMETASYNC, S_IRUSR | S_IWUSR));
+ mdb_txn_begin(env, NULL, MDB_RDONLY, &rdtxn);
+ mdb_txn_begin(env, NULL, 0, &wrtxn);
+ mdb_dbi_open(wrtxn, NULL, MDB_INTEGERKEY, &dbi);
+ mdb_txn_commit(wrtxn);
+}
+
+Database_LMDB::~Database_LMDB()
+{
+ mdb_txn_abort(rdtxn);
+ mdb_dbi_close(env, dbi);
+ mdb_env_close(env);
+}
+
+bool Database_LMDB::saveBlock(const v3s16 &pos, const std::string &data)
+{
+ struct MDB_val key, val;
+ s64 k = getBlockAsInteger(pos);
+ key.mv_size = sizeof(k);
+ key.mv_data = &k;
+ val.mv_size = data.size();
+ val.mv_data = (void*)data.c_str();
+
+ int retval = mdb_cursor_put(wrcursor, &key, &val, 0);
+ if (retval != 0)
+ return false;
+
+ return true;
+}
+
+void Database_LMDB::loadBlock(const v3s16 &pos, std::string *block)
+{
+// uint64_t start_time = microtime();
+ s64 k = getBlockAsInteger(pos);
+
+ MDB_val key, val;
+ key.mv_size = sizeof(k);
+ key.mv_data = &k;
+
+ int notfound = mdb_get(rdtxn, dbi, &key, &val);
+// printf("loadBlock: took %luus\n", microtime() - start_time);
+
+ if (notfound)
+ *block = "";
+ else
+ *block = std::string((const char *)val.mv_data, val.mv_size);
+
+ return;
+}
+
+bool Database_LMDB::deleteBlock(const v3s16 &pos)
+{
+ mdb_txn_reset(rdtxn);
+ int retval = mdb_txn_begin(env, NULL, 0, &wrtxn);
+ if (retval != 0)
+ return false;
+// printf("txn_begin: %s\n", mdb_strerror(retval));
+
+ s64 k = getBlockAsInteger(pos);
+ MDB_val key;
+ key.mv_size = sizeof(k);
+ key.mv_data = &k;
+ mdb_del(wrtxn, dbi, &key, NULL);
+
+ retval = mdb_txn_commit(wrtxn);
+ if (retval != 0)
+ return false;
+// printf("txn_commit: %s\n", mdb_strerror(retval));
+ mdb_txn_renew(rdtxn);
+
+ return true;
+}
+
+void Database_LMDB::listAllLoadableBlocks(std::vector<v3s16> &dst)
+{
+// dst.reserve(m_database.size());
+// for (std::map<s64, std::string>::const_iterator x = m_database.begin();
+// x != m_database.end(); ++x) {
+// dst.push_back(getIntegerAsBlock(x->first));
+// }
+
+ mdb_txn_reset(rdtxn);
+ MDB_txn *txn;
+ mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
+ MDB_cursor *cursor;
+
+ mdb_cursor_open(txn, dbi, &cursor);
+ MDB_val key, val;
+ if (mdb_cursor_get(cursor, &key, &val, MDB_FIRST) != 0)
+ return;
+
+ dst.push_back(getIntegerAsBlock((s64)key.mv_data));
+
+ while (mdb_cursor_get(cursor, &key, &val, MDB_NEXT) == 0)
+ dst.push_back(getIntegerAsBlock(*((s64*)key.mv_data)));
+
+ mdb_cursor_close(cursor);
+ mdb_txn_abort(txn);
+ mdb_txn_renew(rdtxn);
+}
+
+//static uint64_t start_time;
+
+void Database_LMDB::beginSave()
+{
+// start_time = microtime();
+ mdb_txn_reset(rdtxn);
+ mdb_txn_begin(env, NULL, 0, &wrtxn);
+// if (retval != 0)
+// printf("txn_begin: %s\n", mdb_strerror(retval));
+
+ mdb_cursor_open(wrtxn, dbi, &wrcursor);
+// if (retval != 0)
+// printf("cursor_open: %s\n", mdb_strerror(retval));
+}
+
+void Database_LMDB::endSave()
+{
+ mdb_txn_commit(wrtxn);
+// if (retval != 0)
+// printf("txn_commit: %s\n", mdb_strerror(retval));
+ mdb_txn_renew(rdtxn);
+// printf("Write complete, time: %luus\n", microtime() - start_time);
+}
+
+//void Database_LMDB::savePlayer(RemotePlayer *player)
+//{
+// m_player_database.insert(player->getName());
+//}
+//
+//bool Database_LMDB::loadPlayer(RemotePlayer *player, PlayerSAO *sao)
+//{
+// return m_player_database.find(player->getName()) != m_player_database.end();
+//}
+//
+//bool Database_LMDB::removePlayer(const std::string &name)
+//{
+// m_player_database.erase(name);
+// return true;
+//}
+//
+//void Database_LMDB::listPlayers(std::vector<std::string> &res)
+//{
+// for (const auto &player : m_player_database) {
+// res.emplace_back(player);
+// }
+//}
+//
+//bool Database_LMDB::getModEntries(const std::string &modname, StringMap *storage)
+//{
+// const auto mod_pair = m_mod_meta_database.find(modname);
+// if (mod_pair != m_mod_meta_database.cend()) {
+// for (const auto &pair : mod_pair->second) {
+// (*storage)[pair.first] = pair.second;
+// }
+// }
+// return true;
+//}
+//
+//bool Database_LMDB::setModEntry(const std::string &modname,
+// const std::string &key, const std::string &value)
+//{
+// auto mod_pair = m_mod_meta_database.find(modname);
+// if (mod_pair == m_mod_meta_database.end()) {
+// m_mod_meta_database[modname] = StringMap({{key, value}});
+// } else {
+// mod_pair->second[key] = value;
+// }
+// return true;
+//}
+//
+//bool Database_LMDB::removeModEntry(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 mod_pair->second.erase(key) > 0;
+// return false;
+//}
+//
+//void Database_LMDB::listMods(std::vector<std::string> *res)
+//{
+// for (const auto &pair : m_mod_meta_database) {
+// res->push_back(pair.first);
+// }
+//}
diff --git a/src/database/database-lmdb.h b/src/database/database-lmdb.h
new file mode 100644
index 000000000..12efc651c
--- /dev/null
+++ b/src/database/database-lmdb.h
@@ -0,0 +1,64 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include <lmdb.h>
+
+#include <map>
+#include <string>
+#include "database.h"
+#include "irrlichttypes.h"
+
+class Database_LMDB : public MapDatabase//, public PlayerDatabase, public ModMetadataDatabase
+{
+public:
+ Database_LMDB(const std::string &savedir);
+ ~Database_LMDB();
+
+ bool saveBlock(const v3s16 &pos, const std::string &data);
+ void loadBlock(const v3s16 &pos, std::string *block);
+ bool deleteBlock(const v3s16 &pos);
+ void listAllLoadableBlocks(std::vector<v3s16> &dst);
+
+// void savePlayer(RemotePlayer *player);
+// bool loadPlayer(RemotePlayer *player, PlayerSAO *sao);
+// bool removePlayer(const std::string &name);
+// void listPlayers(std::vector<std::string> &res);
+//
+// bool getModEntries(const std::string &modname, StringMap *storage);
+// bool setModEntry(const std::string &modname,
+// const std::string &key, const std::string &value);
+// bool removeModEntry(const std::string &modname, const std::string &key);
+// void listMods(std::vector<std::string> *res);
+//
+ void beginSave();
+ void endSave();
+
+//private:
+// std::map<s64, std::string> m_database;
+// std::set<std::string> m_player_database;
+// std::unordered_map<std::string, StringMap> m_mod_meta_database;
+
+ MDB_env *env;
+ MDB_txn *rdtxn;
+ MDB_txn *wrtxn;
+ MDB_dbi dbi;
+ MDB_cursor *wrcursor;
+};
diff --git a/src/map.cpp b/src/map.cpp
index 58443a000..d5a4fccdc 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -44,6 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "database/database.h"
#include "database/database-dummy.h"
#include "database/database-sqlite3.h"
+#include "database/database-lmdb.h"
#include "script/scripting_server.h"
#include <deque>
#include <queue>
@@ -1699,6 +1700,8 @@ MapDatabase *ServerMap::createDatabase(
return new MapDatabaseSQLite3(savedir);
if (name == "dummy")
return new Database_Dummy();
+ if (name == "lmdb")
+ return new Database_LMDB(savedir);
#if USE_LEVELDB
if (name == "leveldb")
return new Database_LevelDB(savedir);