1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Divorce map database locking from env lock (#15151)

This commit is contained in:
sfan5 2024-09-11 19:17:08 +02:00
parent 526a2f7b8c
commit 588a0f83e9
6 changed files with 197 additions and 90 deletions

View file

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "filesys.h"
#include "log.h"
#include "servermap.h"
#include "database/database.h"
#include "mapblock.h"
#include "mapgen/mg_biome.h"
#include "mapgen/mg_ore.h"
@ -185,10 +186,22 @@ SchematicManager *EmergeManager::getWritableSchematicManager()
return schemmgr;
}
void EmergeManager::initMap(MapDatabaseAccessor *holder)
{
FATAL_ERROR_IF(m_db, "Map database already initialized.");
assert(holder->dbase);
m_db = holder;
}
void EmergeManager::resetMap()
{
FATAL_ERROR_IF(m_threads_active, "Threads are still active.");
m_db = nullptr;
}
void EmergeManager::initMapgens(MapgenParams *params)
{
FATAL_ERROR_IF(!m_mapgens.empty(), "Mapgen already initialised.");
FATAL_ERROR_IF(!m_mapgens.empty(), "Mapgen already initialized.");
mgparams = params;
@ -466,7 +479,7 @@ void EmergeThread::signal()
}
bool EmergeThread::pushBlock(const v3s16 &pos)
bool EmergeThread::pushBlock(v3s16 pos)
{
m_block_queue.push(pos);
return true;
@ -491,7 +504,7 @@ void EmergeThread::cancelPendingItems()
}
void EmergeThread::runCompletionCallbacks(const v3s16 &pos, EmergeAction action,
void EmergeThread::runCompletionCallbacks(v3s16 pos, EmergeAction action,
const EmergeCallbackList &callbacks)
{
m_emerge->reportCompletedEmerge(action);
@ -524,21 +537,36 @@ bool EmergeThread::popBlockEmerge(v3s16 *pos, BlockEmergeData *bedata)
}
EmergeAction EmergeThread::getBlockOrStartGen(
const v3s16 &pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata)
EmergeAction EmergeThread::getBlockOrStartGen(const v3s16 pos, bool allow_gen,
const std::string *from_db, MapBlock **block, BlockMakeData *bmdata)
{
MutexAutoLock envlock(m_server->m_env_mutex);
auto block_ok = [] (MapBlock *b) {
return b && b->isGenerated();
};
// 1). Attempt to fetch block from memory
*block = m_map->getBlockNoCreateNoEx(pos);
if (*block) {
if ((*block)->isGenerated())
if (block_ok(*block)) {
// if we just read it from the db but the block exists that means
// someone else was faster. don't touch it to prevent data loss.
if (from_db)
verbosestream << "getBlockOrStartGen: block loading raced" << std::endl;
return EMERGE_FROM_MEMORY;
}
} else {
// 2). Attempt to load block from disk if it was not in the memory
*block = m_map->loadBlock(pos);
if (*block && (*block)->isGenerated())
if (!from_db) {
// 2). We should attempt loading it
return EMERGE_FROM_DISK;
}
// 2). Second invocation, we have the data
if (!from_db->empty()) {
*block = m_map->loadBlock(*from_db, pos);
if (block_ok(*block))
return EMERGE_FROM_DISK;
}
}
// 3). Attempt to start generation
@ -643,7 +671,8 @@ void *EmergeThread::run()
BEGIN_DEBUG_EXCEPTION_HANDLER
v3s16 pos;
std::map<v3s16, MapBlock *> modified_blocks;
std::map<v3s16, MapBlock*> modified_blocks;
std::string databuf;
m_map = &m_server->m_env->getServerMap();
m_emerge = m_server->getEmergeManager();
@ -669,13 +698,30 @@ void *EmergeThread::run()
continue;
}
g_profiler->add(m_name + ": processed [#]", 1);
if (blockpos_over_max_limit(pos))
continue;
bool allow_gen = bedata.flags & BLOCK_EMERGE_ALLOW_GEN;
EMERGE_DBG_OUT("pos=" << pos << " allow_gen=" << allow_gen);
action = getBlockOrStartGen(pos, allow_gen, &block, &bmdata);
action = getBlockOrStartGen(pos, allow_gen, nullptr, &block, &bmdata);
/* Try to load it */
if (action == EMERGE_FROM_DISK) {
auto &m_db = *m_emerge->m_db;
{
ScopeProfiler sp(g_profiler, "EmergeThread: load block - async (sum)");
MutexAutoLock dblock(m_db.mutex);
m_db.loadBlock(pos, databuf);
}
// actually load it, then decide again
action = getBlockOrStartGen(pos, allow_gen, &databuf, &block, &bmdata);
databuf.clear();
}
/* Generate it */
if (action == EMERGE_GENERATED) {
bool error = false;
m_trans_liquid = &bmdata.transforming_liquid;