diff --git a/CMakeLists.txt b/CMakeLists.txt index d23851b..1413eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ set(mapper_SRCS if(USE_LEVELDB) set(mapper_SRCS ${mapper_SRCS} db-leveldb.cpp) + set(mapper_SRCS ${mapper_SRCS} db-leveldbfm.cpp) endif(USE_LEVELDB) if(USE_REDIS) diff --git a/TileGenerator.cpp b/TileGenerator.cpp index 2406f7d..65016eb 100644 --- a/TileGenerator.cpp +++ b/TileGenerator.cpp @@ -16,6 +16,7 @@ #include "db-sqlite3.h" #if USE_LEVELDB #include "db-leveldb.h" +#include "db-leveldbfm.h" #endif #if USE_REDIS #include "db-redis.h" @@ -294,6 +295,8 @@ void TileGenerator::openDb(const std::string &input) #if USE_LEVELDB else if(m_backend == "leveldb") m_db = new DBLevelDB(input); + else if(m_backend == "leveldbfm") + m_db = new DBLevelDBFM(input); #endif #if USE_REDIS else if(m_backend == "redis") diff --git a/db-leveldb.cpp b/db-leveldb.cpp index 849384a..b99ce09 100644 --- a/db-leveldb.cpp +++ b/db-leveldb.cpp @@ -28,7 +28,8 @@ DBLevelDB::DBLevelDB(const std::string &mapdir) throw std::runtime_error(std::string("Failed to open Database: ") + status.ToString()); } - loadPosCache(); + if(!no_load) + loadPosCache(); } diff --git a/db-leveldb.h b/db-leveldb.h index 8128ee9..500d014 100644 --- a/db-leveldb.h +++ b/db-leveldb.h @@ -6,13 +6,14 @@ class DBLevelDB : public DB { public: - DBLevelDB(const std::string &mapdir); + DBLevelDB(const std::string &mapdir, bool no_load = 0); virtual std::vector getBlockPos(); virtual void getBlocksOnZ(std::map &blocks, int16_t zPos); ~DBLevelDB(); private: void loadPosCache(); +protected: std::vector posCache; leveldb::DB *db; diff --git a/db-leveldbfm.cpp b/db-leveldbfm.cpp new file mode 100644 index 0000000..82b1f2d --- /dev/null +++ b/db-leveldbfm.cpp @@ -0,0 +1,69 @@ +#include +#include "db-leveldbfm.h" +#include "types.h" + +static inline int64_t stoi64(const std::string &s) +{ + std::stringstream tmp(s); + int64_t t; + tmp >> t; + return t; +} + +DBLevelDBFM::DBLevelDBFM(const std::string &mapdir) : DBLevelDB(mapdir, 1) +{ + loadPosCache(); +} + +DBLevelDBFM::~DBLevelDBFM() +{ +} + +std::string getBlockAsString(const BlockPos &pos) { + std::ostringstream os; + os << "a" << pos.x << "," << pos.y << "," << pos.z; + return os.str().c_str(); +} + +BlockPos DBLevelDBFM::getStringAsBlock(const std::string &i) { + std::istringstream is(i); + BlockPos pos; + char c; + if (i[0] == 'a') { + is >> c; // 'a' + is >> pos.x; + is >> c; // ',' + is >> pos.y; + is >> c; // ',' + is >> pos.z; + } else { // old format + return decodeBlockPos(stoi64(i)); + } + return pos; +} + +void DBLevelDBFM::loadPosCache() +{ + leveldb::Iterator * it = db->NewIterator(leveldb::ReadOptions()); + for (it->SeekToFirst(); it->Valid(); it->Next()) { + posCache.push_back(getStringAsBlock(it->key().ToString())); + } + delete it; +} + +void DBLevelDBFM::getBlocksOnZ(std::map &blocks, int16_t zPos) +{ + std::string datastr; + leveldb::Status status; + + for (std::vector::iterator it = posCache.begin(); it != posCache.end(); ++it) { + if (it->z != zPos) { + continue; + } + status = db->Get(leveldb::ReadOptions(), getBlockAsString(*it), &datastr); + if (status.ok()) { + Block b(*it, ustring((const unsigned char *) datastr.data(), datastr.size())); + blocks[b.first.x].push_back(b); + } + } +} diff --git a/db-leveldbfm.h b/db-leveldbfm.h new file mode 100644 index 0000000..015601a --- /dev/null +++ b/db-leveldbfm.h @@ -0,0 +1,18 @@ +#ifndef DB_LEVELDBFM_HEADER +#define DB_LEVELDBFM_HEADER + +#include "db-leveldb.h" +#include + +class DBLevelDBFM : public DBLevelDB { +public: + DBLevelDBFM(const std::string &mapdir); + virtual void getBlocksOnZ(std::map &blocks, int16_t zPos); + ~DBLevelDBFM(); + +protected: + BlockPos getStringAsBlock(const std::string &i); + virtual void loadPosCache(); +}; + +#endif // DB_LEVELDBFM_HEADER diff --git a/mapper.cpp b/mapper.cpp index a661511..46dea59 100644 --- a/mapper.cpp +++ b/mapper.cpp @@ -34,7 +34,7 @@ void usage() " --noshading\n" " --min-y \n" " --max-y \n" - " --backend \n" + " --backend \n" " --geometry x:y+w+h\n" "Color format: '#000000'\n"; std::cout << usage_text;