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:
parent
526a2f7b8c
commit
588a0f83e9
6 changed files with 197 additions and 90 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue