Skip to content

Commit

Permalink
abm_world cached storage
Browse files Browse the repository at this point in the history
  • Loading branch information
proller committed Feb 11, 2024
1 parent 9b2e681 commit 95e722d
Show file tree
Hide file tree
Showing 14 changed files with 260 additions and 79 deletions.
4 changes: 2 additions & 2 deletions src/database/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ v3s16 MapDatabase::getIntegerAsBlock(s64 i)
return pos;
}

std::string MapDatabase::getBlockAsString(const v3bpos_t &pos) const {
std::string MapDatabase::getBlockAsString(const v3bpos_t &pos) {
std::ostringstream os;
os << "a" << pos.X << "," << pos.Y << "," << pos.Z;
return os.str().c_str();
}

v3bpos_t MapDatabase::getStringAsBlock(const std::string &i) const {
v3bpos_t MapDatabase::getStringAsBlock(const std::string &i) {
std::istringstream is(i);
v3bpos_t pos;
char c;
Expand Down
4 changes: 2 additions & 2 deletions src/database/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ class MapDatabase : public Database
static s64 getBlockAsInteger(const v3s16 &pos);
static v3s16 getIntegerAsBlock(s64 i);

std::string getBlockAsString(const v3pos_t &pos) const;
v3pos_t getStringAsBlock(const std::string &i) const;
static std::string getBlockAsString(const v3pos_t &pos);
static v3pos_t getStringAsBlock(const std::string &i);

virtual void listAllLoadableBlocks(std::vector<v3s16> &dst) = 0;
};
Expand Down
13 changes: 12 additions & 1 deletion src/fm_abm.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include <cstddef>
#include <sstream>
#include <string>
#include <strstream>
#include "irr_v3d.h"
#include "map.h"
#include "profiler.h"
Expand Down Expand Up @@ -185,7 +188,8 @@ void ABMHandler::apply(MapBlock *block, bool activate)
std::lock_guard<std::mutex> lock(block->abm_triggers_mutex);

if (!block->abm_triggers)
block->abm_triggers = std::make_unique<MapBlock::abm_triggers_type>();
block->abm_triggers =
std::make_unique<MapBlock::abm_triggers_type>();

block->abm_triggers->emplace_back(
abm_trigger_one{i, p, c, active_object_count,
Expand Down Expand Up @@ -334,6 +338,13 @@ size_t MapBlock::abmTriggersRun(ServerEnvironment *m_env, u32 time, bool activat
}
if (abm_triggers->empty())
abm_triggers.reset();

if (triggers_count) {
std::stringstream key;
key << "a" << getPos().X << "," << getPos().Y << "," << getPos().Z;
m_env->blocks_with_abm.put(key.str(), std::to_string(time));
}

return triggers_count;
}

Expand Down
46 changes: 36 additions & 10 deletions src/fm_server.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include "database/database.h"
#include "emerge.h"
#include "irrTypes.h"
#include "irr_v3d.h"
Expand Down Expand Up @@ -327,6 +329,8 @@ class AbmWorldThread : public thread_pool
return nullptr;
}

int16_t abm_world_load_all = -1; // -1 : auto; 0 : disable; 1 : force
g_settings->getS16NoEx("abm_world_load_all", abm_world_load_all);
u64 abm_world_throttle = m_server->isSingleplayer() ? 10 : 0;
g_settings->getU64NoEx("abm_world_throttle", abm_world_throttle);
u64 abm_world_max_clients = m_server->isSingleplayer() ? 1 : 0;
Expand All @@ -345,24 +349,44 @@ class AbmWorldThread : public thread_pool

if (!can_work()) {
tracestream << "Abm world wait" << '\n';

std::this_thread::sleep_for(std::chrono::seconds(10));
sleep(10);
continue;
}

std::vector<v3pos_t> loadable_blocks;
std::vector<v3bpos_t> loadable_blocks;

auto time_start = porting::getTimeMs();

if (abm_world_load_all <= 0) {
#if USE_LEVELDB
if (const auto it = m_server->getEnv()
.blocks_with_abm.database.new_iterator();
it) {
for (it->SeekToFirst(); it->Valid(); it->Next()) {
const auto key = it->key().ToString();
if (key.starts_with("a")) {
const v3bpos_t pos = MapDatabase::getStringAsBlock(key);
loadable_blocks.emplace_back(pos);
}
}
}
#endif
}

TimeTaker bll("Block list load", nullptr);
// Load whole world firts time, fill blocks_with_abm
if (abm_world_load_all && loadable_blocks.empty()) {
actionstream << "Abm world full load" << '\n';
m_server->getEnv().getServerMap().listAllLoadableBlocks(loadable_blocks);
}

m_server->getEnv().getServerMap().listAllLoadableBlocks(loadable_blocks);
const auto loadable_blocks_size = loadable_blocks.size();
infostream << "Abm world blocks " << loadable_blocks_size << " per "
<< bll.getTimerTime() << " from " << abm_world_last
<< " max_clients " << abm_world_max_clients << " throttle "
<< abm_world_throttle << '\n';
<< (porting::getTimeMs() - time_start) / 1000 << " from "
<< abm_world_last << " max_clients " << abm_world_max_clients
<< " throttle " << abm_world_throttle << '\n';
size_t cur_n = 0, processed = 0, triggers_total = 0;

auto time_start = porting::getTimeMs();
time_start = porting::getTimeMs();

const auto printstat = [&]() {
auto time = porting::getTimeMs();
Expand Down Expand Up @@ -442,7 +466,7 @@ class AbmWorldThread : public thread_pool
printstat();
abm_world_last = 0;

std::this_thread::sleep_for(std::chrono::seconds(60));
sleep(60);
}
END_DEBUG_EXCEPTION_HANDLER
return nullptr;
Expand Down Expand Up @@ -554,6 +578,7 @@ void Server::maintenance_start()
m_env->getServerMap().m_map_loading_enabled = false;
// fmtodo: m_env->getServerMap().dbase->close();
m_env->m_key_value_storage.clear();
m_env->blocks_with_abm.close();
stat.close();
actionstream << "Server: Starting maintenance: bases closed now." << std::endl;
};
Expand All @@ -562,6 +587,7 @@ void Server::maintenance_end()
{
// fmtodo:m_env->getServerMap().dbase->open();
stat.open();
m_env->blocks_with_abm.open();
m_env->getServerMap().m_map_saving_enabled = true;
m_env->getServerMap().m_map_loading_enabled = true;
m_emerge->startThreads();
Expand Down
2 changes: 2 additions & 0 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1339,6 +1339,8 @@ int Server::save(float dtime, float dedicated_server_step, bool breakable) {
m_env->saveMeta();

stat.save();
m_env->blocks_with_abm.save();

}
save_break:;

Expand Down
3 changes: 3 additions & 0 deletions src/server/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
set(server_SRCS

${CMAKE_CURRENT_SOURCE_DIR}/fm_key_value_cached.cpp

${CMAKE_CURRENT_SOURCE_DIR}/activeobjectmgr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/luaentity_sao.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mods.cpp
Expand Down
79 changes: 79 additions & 0 deletions src/server/fm_key_value_cached.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
This file is part of Freeminer.
Freeminer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Freeminer 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Freeminer. If not, see <http://www.gnu.org/licenses/>.
*/

//#include <ctime>

//#include "stat.h"
//#include "gettime.h"
//#include "log.h"

#include "fm_key_value_cached.h"

KeyValueCached::KeyValueCached(const std::string &savedir, const std::string &name) :
database(savedir, name){};

KeyValueCached::~KeyValueCached()
{
save();
};

void KeyValueCached::save()
{
std::lock_guard<std::mutex> lock(mutex);
for (const auto &ir : stats) {
//errorstream<<"stat saving: "<<ir.first<< " = "<< ir.second<<std::endl;
if (ir.second.empty()) {
database.del(ir.first);
} else {
database.put(ir.first, ir.second);
}
}
}

void KeyValueCached::unload()
{
save();
std::lock_guard<std::mutex> lock(mutex);
stats.clear();
}

void KeyValueCached::open()
{
database.open();
}

void KeyValueCached::close()
{
unload();
database.close();
}

const std::string & KeyValueCached::get(const std::string &key)
{
std::lock_guard<std::mutex> lock(mutex);
if (!stats.contains(key))
database.get(key, stats[key]);
//errorstream<<"stat get: "<<key<<" = "<< stats[key]<<std::endl;
return stats[key];
}

const std::string & KeyValueCached::put(const std::string &key, const std::string &value)
{
//errorstream<<"stat one: "<<key<< " = "<< value<<std::endl;
std::lock_guard<std::mutex> lock(mutex);
return stats[key] = value;
}
25 changes: 25 additions & 0 deletions src/server/fm_key_value_cached.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <unordered_map>
#include "key_value_storage.h"

class KeyValueCached
{
public:
KeyValueStorage database;
std::unordered_map<std::string, std::string> stats;

KeyValueCached(const std::string &savedir, const std::string &name);
~KeyValueCached();

void save();
void unload();
void open();
void close();

const std::string &get(const std::string &key);
const std::string &put(const std::string &key, const std::string &value);

private:
std::mutex mutex;
};
1 change: 1 addition & 0 deletions src/serverenvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map,

m_abmhandler(this),
m_circuit(script_iface, map, server->ndef(), path_world),
blocks_with_abm(path_world, "abm_world"),

m_map(map),
m_script(script_iface),
Expand Down
2 changes: 2 additions & 0 deletions src/serverenvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h"
#include "irr_v3d.h"
#include "map.h"
#include "server/fm_key_value_cached.h"
#include "settings.h"
#include "server/activeobjectmgr.h"
#include "threading/concurrent_set.h"
Expand Down Expand Up @@ -493,6 +494,7 @@ class ServerEnvironment final : public Environment
u32 m_active_block_analyzed_last = 0;
std::mutex m_max_lag_estimate_mutex;
public:
KeyValueCached blocks_with_abm;
size_t abm_world_last = 0;
//end of freeminer

Expand Down
44 changes: 26 additions & 18 deletions src/stat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,70 +19,78 @@

#include "stat.h"
#include "gettime.h"
//#include "log.h"


Stat::Stat(std::string savedir) :
database(savedir, "stat") {
Stat::Stat(const std::string &savedir) : database(savedir, "stat")
{
update_time();
};

Stat::~Stat() {
Stat::~Stat()
{
save();
};

void Stat::save() {
void Stat::save()
{
std::lock_guard<std::mutex> lock(mutex);
for(const auto & ir : stats) {
for (const auto &ir : stats) {
//errorstream<<"stat saving: "<<ir.first<< " = "<< ir.second<<std::endl;
if (ir.second)
database.put(ir.first, ir.second);
}
update_time();
}

void Stat::unload() {
void Stat::unload()
{
save();
std::lock_guard<std::mutex> lock(mutex);
stats.clear();
}

void Stat::open() {
void Stat::open()
{
database.open();
}

void Stat::close() {
void Stat::close()
{
unload();
database.close();
}

stat_value Stat::get(const std::string & key) {
const Stat::stat_value &Stat::get(const std::string &key)
{
std::lock_guard<std::mutex> lock(mutex);
if (!stats.count(key))
database.get(key, stats[key]);
//errorstream<<"stat get: "<<key<<" = "<< stats[key]<<std::endl;
return stats[key];
}

stat_value Stat::write_one(const std::string & key, const stat_value & value) {
const Stat::stat_value &Stat::write_one(const std::string &key, const stat_value &value)
{
//errorstream<<"stat one: "<<key<< " = "<< value<<std::endl;
get(key);
std::lock_guard<std::mutex> lock(mutex);
return stats[key] += value;
}

stat_value Stat::add(const std::string & key, const std::string & player, stat_value value) {
const Stat::stat_value &Stat::add(
const std::string &key, const std::string &player, stat_value value)
{
//errorstream<<"stat adding: "<<key<< " player="<<player<<" = "<< value<<std::endl;
stat_value ret = write_one("total|" + key, value);
write_one("day|"+ key + "|" + day , value);
write_one("week|"+ key + "|" + week, value);
write_one("month|"+ key + "|" + month, value);
write_one("day|" + key + "|" + day, value);
write_one("week|" + key + "|" + week, value);
write_one("month|" + key + "|" + month, value);
if (!player.empty())
ret = write_one("player|" + key + "|" + player, value);
ret = write_one("player|" + key + "|" + player, value);
return ret;
}

void Stat::update_time() {
void Stat::update_time()
{
//auto t = time(NULL);
const auto tm = mt_localtime(); //localtime_safe(&t);
char cs[20];
Expand Down
Loading

0 comments on commit 95e722d

Please sign in to comment.