mirror of
https://github.com/luanti-org/minetestmapper.git
synced 2025-10-05 21:35:22 +02:00
Rewrite DB class to allow backends to fully optimize block fetches
This commit is contained in:
@@ -11,7 +11,6 @@ static inline int64_t stoi64(const std::string &s)
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
static inline std::string i64tos(int64_t i)
|
||||
{
|
||||
std::ostringstream os;
|
||||
@@ -19,6 +18,7 @@ static inline std::string i64tos(int64_t i)
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
DBLevelDB::DBLevelDB(const std::string &mapdir)
|
||||
{
|
||||
leveldb::Options options;
|
||||
@@ -28,6 +28,9 @@ DBLevelDB::DBLevelDB(const std::string &mapdir)
|
||||
throw std::runtime_error(std::string("Failed to open Database: ") + status.ToString());
|
||||
}
|
||||
|
||||
/* LevelDB is a dumb key-value store, so the only optimization we can do
|
||||
* is to cache the block positions that exist in the db.
|
||||
*/
|
||||
loadPosCache();
|
||||
}
|
||||
|
||||
@@ -38,9 +41,21 @@ DBLevelDB::~DBLevelDB()
|
||||
}
|
||||
|
||||
|
||||
std::vector<BlockPos> DBLevelDB::getBlockPos()
|
||||
std::vector<BlockPos> DBLevelDB::getBlockPos(BlockPos min, BlockPos max)
|
||||
{
|
||||
return posCache;
|
||||
std::vector<BlockPos> res;
|
||||
for (const auto &it : posCache) {
|
||||
if (it.first < min.z || it.first >= max.z)
|
||||
continue;
|
||||
for (auto pos2 : it.second) {
|
||||
if (pos2.first < min.x || pos2.first >= max.x)
|
||||
continue;
|
||||
if (pos2.second < min.y || pos2.second >= max.y)
|
||||
continue;
|
||||
res.emplace_back(pos2.first, pos2.second, it.first);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,26 +64,35 @@ void DBLevelDB::loadPosCache()
|
||||
leveldb::Iterator * it = db->NewIterator(leveldb::ReadOptions());
|
||||
for (it->SeekToFirst(); it->Valid(); it->Next()) {
|
||||
int64_t posHash = stoi64(it->key().ToString());
|
||||
posCache.push_back(decodeBlockPos(posHash));
|
||||
BlockPos pos = decodeBlockPos(posHash);
|
||||
|
||||
posCache[pos.z].emplace_back(pos.x, pos.y);
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
|
||||
|
||||
void DBLevelDB::getBlocksOnZ(std::map<int16_t, BlockList> &blocks, int16_t zPos)
|
||||
void DBLevelDB::getBlocksOnXZ(BlockList &blocks, int16_t x, int16_t z,
|
||||
int16_t min_y, int16_t max_y)
|
||||
{
|
||||
std::string datastr;
|
||||
leveldb::Status status;
|
||||
|
||||
for (const auto &it : posCache) {
|
||||
if (it.z != zPos) {
|
||||
auto it = posCache.find(z);
|
||||
if (it == posCache.cend())
|
||||
return;
|
||||
for (auto pos2 : it->second) {
|
||||
if (pos2.first != x)
|
||||
continue;
|
||||
}
|
||||
status = db->Get(leveldb::ReadOptions(), i64tos(encodeBlockPos(it)), &datastr);
|
||||
if (pos2.second < min_y || pos2.second >= max_y)
|
||||
continue;
|
||||
|
||||
BlockPos pos(x, pos2.second, z);
|
||||
status = db->Get(leveldb::ReadOptions(), i64tos(encodeBlockPos(pos)), &datastr);
|
||||
if (status.ok()) {
|
||||
Block b(it, ustring((const unsigned char *) datastr.data(), datastr.size()));
|
||||
blocks[b.first.x].push_back(b);
|
||||
blocks.emplace_back(
|
||||
pos, ustring((unsigned char *) datastr.data(), datastr.size())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user