From 9b6d699c21a190be0cea7a38effe97f831035723 Mon Sep 17 00:00:00 2001 From: EmelyanenkoK Date: Fri, 8 Dec 2023 14:20:17 +0300 Subject: [PATCH] Cache recent block states and adjust timeouts (#823) * Add parameter --celldb-compress-depth to speed up celldb * Fix collator timeout * Add block_state_cache * Adjust state cache ttl * Don't merge shards when queue is too big * Decrease lt limit if previous block is too old --------- Co-authored-by: SpyCheese --- crypto/vm/db/CellStorage.cpp | 43 +++++++++++--- crypto/vm/db/CellStorage.h | 6 +- crypto/vm/db/DynamicBagOfCellsDb.cpp | 12 +++- crypto/vm/db/DynamicBagOfCellsDb.h | 3 + validator-engine/validator-engine.cpp | 6 ++ validator-engine/validator-engine.hpp | 4 ++ validator/db/celldb.cpp | 82 +++++++++++++++++++++++++-- validator/db/celldb.hpp | 21 ++++++- validator/db/rootdb.cpp | 2 +- validator/db/rootdb.hpp | 7 ++- validator/fabric.h | 4 +- validator/impl/collator-impl.h | 1 + validator/impl/collator.cpp | 16 +++--- validator/impl/fabric.cpp | 5 +- validator/manager-disk.cpp | 2 +- validator/manager-hardfork.cpp | 2 +- validator/manager.cpp | 36 +++++++++++- validator/manager.hpp | 6 ++ validator/validator-options.hpp | 7 +++ validator/validator.h | 2 + 20 files changed, 230 insertions(+), 37 deletions(-) diff --git a/crypto/vm/db/CellStorage.cpp b/crypto/vm/db/CellStorage.cpp index a1b7365b5..acc55898a 100644 --- a/crypto/vm/db/CellStorage.cpp +++ b/crypto/vm/db/CellStorage.cpp @@ -27,16 +27,25 @@ namespace vm { namespace { class RefcntCellStorer { public: - RefcntCellStorer(td::int32 refcnt, const DataCell &cell) : refcnt_(refcnt), cell_(cell) { + RefcntCellStorer(td::int32 refcnt, const td::Ref &cell, bool as_boc) + : refcnt_(refcnt), cell_(cell), as_boc_(as_boc) { } template void store(StorerT &storer) const { using td::store; + if (as_boc_) { + td::int32 tag = -1; + store(tag, storer); + store(refcnt_, storer); + td::BufferSlice data = vm::std_boc_serialize(cell_).move_as_ok(); + storer.store_slice(data); + return; + } store(refcnt_, storer); - store(cell_, storer); - for (unsigned i = 0; i < cell_.size_refs(); i++) { - auto cell = cell_.get_ref(i); + store(*cell_, storer); + for (unsigned i = 0; i < cell_->size_refs(); i++) { + auto cell = cell_->get_ref(i); auto level_mask = cell->get_level_mask(); auto level = level_mask.get_level(); td::uint8 x = static_cast(level_mask.get_mask()); @@ -60,7 +69,8 @@ class RefcntCellStorer { private: td::int32 refcnt_; - const DataCell &cell_; + td::Ref cell_; + bool as_boc_; }; class RefcntCellParser { @@ -69,11 +79,17 @@ class RefcntCellParser { } td::int32 refcnt; Ref cell; + bool stored_boc_; template void parse(ParserT &parser, ExtCellCreator &ext_cell_creator) { using ::td::parse; parse(refcnt, parser); + stored_boc_ = false; + if (refcnt == -1) { + stored_boc_ = true; + parse(refcnt, parser); + } if (!need_data_) { return; } @@ -81,6 +97,12 @@ class RefcntCellParser { TRY_STATUS(parser.get_status()); auto size = parser.get_left_len(); td::Slice data = parser.template fetch_string_raw(size); + if (stored_boc_) { + TRY_RESULT(boc, vm::std_boc_deserialize(data)); + TRY_RESULT(loaded_cell, boc->load_cell()); + cell = std::move(loaded_cell.data_cell); + return td::Status::OK(); + } CellSerializationInfo info; auto cell_data = data; TRY_STATUS(info.init(cell_data, 0 /*ref_byte_size*/)); @@ -122,7 +144,8 @@ class RefcntCellParser { }; } // namespace -CellLoader::CellLoader(std::shared_ptr reader) : reader_(std::move(reader)) { +CellLoader::CellLoader(std::shared_ptr reader, std::function on_load_callback) + : reader_(std::move(reader)), on_load_callback_(std::move(on_load_callback)) { CHECK(reader_); } @@ -145,7 +168,11 @@ td::Result CellLoader::load(td::Slice hash, bool need_da res.refcnt_ = refcnt_cell.refcnt; res.cell_ = std::move(refcnt_cell.cell); + res.stored_boc_ = refcnt_cell.stored_boc_; //CHECK(res.cell_->get_hash() == hash); + if (on_load_callback_) { + on_load_callback_(res); + } return res; } @@ -157,7 +184,7 @@ td::Status CellStorer::erase(td::Slice hash) { return kv_.erase(hash); } -td::Status CellStorer::set(td::int32 refcnt, const DataCell &cell) { - return kv_.set(cell.get_hash().as_slice(), td::serialize(RefcntCellStorer(refcnt, cell))); +td::Status CellStorer::set(td::int32 refcnt, const td::Ref &cell, bool as_boc) { + return kv_.set(cell->get_hash().as_slice(), td::serialize(RefcntCellStorer(refcnt, cell, as_boc))); } } // namespace vm diff --git a/crypto/vm/db/CellStorage.h b/crypto/vm/db/CellStorage.h index b705b5311..3106ee16d 100644 --- a/crypto/vm/db/CellStorage.h +++ b/crypto/vm/db/CellStorage.h @@ -45,19 +45,21 @@ class CellLoader { Ref cell_; td::int32 refcnt_{0}; + bool stored_boc_{false}; }; - CellLoader(std::shared_ptr reader); + CellLoader(std::shared_ptr reader, std::function on_load_callback = {}); td::Result load(td::Slice hash, bool need_data, ExtCellCreator &ext_cell_creator); private: std::shared_ptr reader_; + std::function on_load_callback_; }; class CellStorer { public: CellStorer(KeyValue &kv); td::Status erase(td::Slice hash); - td::Status set(td::int32 refcnt, const DataCell &cell); + td::Status set(td::int32 refcnt, const td::Ref &cell, bool as_boc); private: KeyValue &kv_; diff --git a/crypto/vm/db/DynamicBagOfCellsDb.cpp b/crypto/vm/db/DynamicBagOfCellsDb.cpp index 0d1d099fb..1aa4e0f56 100644 --- a/crypto/vm/db/DynamicBagOfCellsDb.cpp +++ b/crypto/vm/db/DynamicBagOfCellsDb.cpp @@ -210,6 +210,14 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat return td::Status::OK(); } + void set_celldb_compress_depth(td::uint32 value) override { + celldb_compress_depth_ = value; + } + + vm::ExtCellCreator& as_ext_cell_creator() override { + return *this; + } + private: std::unique_ptr loader_; std::vector> to_inc_; @@ -217,6 +225,7 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat CellHashTable hash_table_; std::vector visited_; Stats stats_diff_; + td::uint32 celldb_compress_depth_{0}; static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() { static auto res = td::NamedThreadSafeCounter::get_default().get_counter("DynamicBagOfCellsDb"); @@ -443,7 +452,8 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat guard.dismiss(); } else { auto loaded_cell = info.cell->load_cell().move_as_ok(); - storer.set(info.db_refcnt, *loaded_cell.data_cell); + storer.set(info.db_refcnt, loaded_cell.data_cell, + loaded_cell.data_cell->get_depth() == celldb_compress_depth_ && celldb_compress_depth_ != 0); info.in_db = true; } } diff --git a/crypto/vm/db/DynamicBagOfCellsDb.h b/crypto/vm/db/DynamicBagOfCellsDb.h index 3569208c0..fa2b44d21 100644 --- a/crypto/vm/db/DynamicBagOfCellsDb.h +++ b/crypto/vm/db/DynamicBagOfCellsDb.h @@ -64,6 +64,9 @@ class DynamicBagOfCellsDb { // restart with new loader will also reset stats_diff virtual td::Status set_loader(std::unique_ptr loader) = 0; + virtual void set_celldb_compress_depth(td::uint32 value) = 0; + virtual vm::ExtCellCreator& as_ext_cell_creator() = 0; + static std::unique_ptr create(); class AsyncExecutor { diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index 23cc93473..273274930 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -1363,6 +1363,7 @@ td::Status ValidatorEngine::load_global_config() { if (!session_logs_file_.empty()) { validator_options_.write().set_session_logs_file(session_logs_file_); } + validator_options_.write().set_celldb_compress_depth(celldb_compress_depth_); std::vector h; for (auto &x : conf.validator_->hardforks_) { @@ -3761,6 +3762,11 @@ int main(int argc, char *argv[]) { acts.push_back([&x, at]() { td::actor::send_closure(x, &ValidatorEngine::schedule_shutdown, (double)at); }); return td::Status::OK(); }); + p.add_checked_option('\0', "celldb-compress-depth", "(default: 0)", [&](td::Slice arg) { + TRY_RESULT(value, td::to_integer_safe(arg)); + acts.push_back([&x, value]() { td::actor::send_closure(x, &ValidatorEngine::set_celldb_compress_depth, value); }); + return td::Status::OK(); + }); auto S = p.run(argc, argv); if (S.is_error()) { LOG(ERROR) << "failed to parse options: " << S.move_as_error(); diff --git a/validator-engine/validator-engine.hpp b/validator-engine/validator-engine.hpp index 2d9663513..ebcd60c66 100644 --- a/validator-engine/validator-engine.hpp +++ b/validator-engine/validator-engine.hpp @@ -200,6 +200,7 @@ class ValidatorEngine : public td::actor::Actor { double sync_ttl_ = 0; double archive_ttl_ = 0; double key_proof_ttl_ = 0; + td::uint32 celldb_compress_depth_ = 0; bool read_config_ = false; bool started_keyring_ = false; bool started_ = false; @@ -257,6 +258,9 @@ class ValidatorEngine : public td::actor::Actor { keys_[key.compute_short_id()] = key; } void schedule_shutdown(double at); + void set_celldb_compress_depth(td::uint32 value) { + celldb_compress_depth_ = value; + } void start_up() override; ValidatorEngine() { } diff --git a/validator/db/celldb.cpp b/validator/db/celldb.cpp index 3b2a34f30..6a2b46992 100644 --- a/validator/db/celldb.cpp +++ b/validator/db/celldb.cpp @@ -62,16 +62,29 @@ void CellDbBase::execute_sync(std::function f) { f(); } -CellDbIn::CellDbIn(td::actor::ActorId root_db, td::actor::ActorId parent, std::string path) - : root_db_(root_db), parent_(parent), path_(std::move(path)) { +CellDbIn::CellDbIn(td::actor::ActorId root_db, td::actor::ActorId parent, std::string path, + td::Ref opts) + : root_db_(root_db), parent_(parent), path_(std::move(path)), opts_(opts) { } void CellDbIn::start_up() { + on_load_callback_ = [db = actor_id(this), + compress_depth = opts_->get_celldb_compress_depth()](const vm::CellLoader::LoadResult& res) { + if (res.cell_.is_null()) { + return; + } + bool expected_stored_boc = res.cell_->get_depth() == compress_depth && compress_depth != 0; + if (expected_stored_boc != res.stored_boc_) { + td::actor::send_closure(db, &CellDbIn::migrate_cell, td::Bits256{res.cell_->get_hash().bits()}); + } + }; + CellDbBase::start_up(); cell_db_ = std::make_shared(td::RocksDb::open(path_).move_as_ok()); boc_ = vm::DynamicBagOfCellsDb::create(); - boc_->set_loader(std::make_unique(cell_db_->snapshot())).ensure(); + boc_->set_celldb_compress_depth(opts_->get_celldb_compress_depth()); + boc_->set_loader(std::make_unique(cell_db_->snapshot(), on_load_callback_)).ensure(); td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot()); alarm_timestamp() = td::Timestamp::in(10.0); @@ -129,7 +142,7 @@ void CellDbIn::store_cell(BlockIdExt block_id, td::Ref cell, td::Promi set_block(key_hash, std::move(D)); cell_db_->commit_write_batch().ensure(); - boc_->set_loader(std::make_unique(cell_db_->snapshot())).ensure(); + boc_->set_loader(std::make_unique(cell_db_->snapshot(), on_load_callback_)).ensure(); td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot()); promise.set_result(boc_->load_cell(cell->get_hash().as_slice())); @@ -140,6 +153,9 @@ void CellDbIn::get_cell_db_reader(td::Promise> } void CellDbIn::alarm() { + if (migrate_after_ && migrate_after_.is_in_past()) { + migrate_cells(); + } auto E = get_block(get_empty_key_hash()).move_as_ok(); auto N = get_block(E.next).move_as_ok(); if (N.is_empty()) { @@ -220,7 +236,7 @@ void CellDbIn::gc_cont2(BlockHandle handle) { cell_db_->commit_write_batch().ensure(); alarm_timestamp() = td::Timestamp::now(); - boc_->set_loader(std::make_unique(cell_db_->snapshot())).ensure(); + boc_->set_loader(std::make_unique(cell_db_->snapshot(), on_load_callback_)).ensure(); td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot()); DCHECK(get_block(key_hash).is_error()); @@ -273,6 +289,49 @@ void CellDbIn::set_block(KeyHash key_hash, DbEntry e) { cell_db_->set(td::as_slice(key), e.release()).ensure(); } +void CellDbIn::migrate_cell(td::Bits256 hash) { + cells_to_migrate_.insert(hash); + if (cells_to_migrate_.size() >= 32) { + migrate_cells(); + } else if (!migrate_after_) { + migrate_after_ = td::Timestamp::in(1.0); + } +} + +void CellDbIn::migrate_cells() { + if (cells_to_migrate_.empty()) { + return; + } + vm::CellStorer stor{*cell_db_}; + auto loader = std::make_unique(cell_db_->snapshot()); + boc_->set_loader(std::make_unique(*loader)).ensure(); + cell_db_->begin_write_batch().ensure(); + td::uint32 cnt = 0; + for (const auto& hash : cells_to_migrate_) { + auto R = loader->load(hash.as_slice(), true, boc_->as_ext_cell_creator()); + if (R.is_error()) { + continue; + } + if (R.ok().status == vm::CellLoader::LoadResult::NotFound) { + continue; + } + bool expected_stored_boc = + R.ok().cell_->get_depth() == opts_->get_celldb_compress_depth() && opts_->get_celldb_compress_depth() != 0; + if (expected_stored_boc != R.ok().stored_boc_) { + ++cnt; + stor.set(R.ok().refcnt(), R.ok().cell_, expected_stored_boc).ensure(); + } + } + cells_to_migrate_.clear(); + if (cnt > 0) { + LOG(DEBUG) << "Migrated " << cnt << " cells"; + } + cell_db_->commit_write_batch().ensure(); + boc_->set_loader(std::make_unique(cell_db_->snapshot(), on_load_callback_)).ensure(); + td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot()); + migrate_after_ = td::Timestamp::never(); +} + void CellDb::load_cell(RootHash hash, td::Promise> promise) { if (!started_) { td::actor::send_closure(cell_db_, &CellDbIn::load_cell, hash, std::move(promise)); @@ -300,7 +359,18 @@ void CellDb::get_cell_db_reader(td::Promise> p void CellDb::start_up() { CellDbBase::start_up(); boc_ = vm::DynamicBagOfCellsDb::create(); - cell_db_ = td::actor::create_actor("celldbin", root_db_, actor_id(this), path_); + boc_->set_celldb_compress_depth(opts_->get_celldb_compress_depth()); + cell_db_ = td::actor::create_actor("celldbin", root_db_, actor_id(this), path_, opts_); + on_load_callback_ = [db = cell_db_.get(), + compress_depth = opts_->get_celldb_compress_depth()](const vm::CellLoader::LoadResult& res) { + if (res.cell_.is_null()) { + return; + } + bool expected_stored_boc = res.cell_->get_depth() == compress_depth && compress_depth != 0; + if (expected_stored_boc != res.stored_boc_) { + td::actor::send_closure(db, &CellDbIn::migrate_cell, td::Bits256{res.cell_->get_hash().bits()}); + } + }; } CellDbIn::DbEntry::DbEntry(tl_object_ptr entry) diff --git a/validator/db/celldb.hpp b/validator/db/celldb.hpp index a05e9ddba..6545d5970 100644 --- a/validator/db/celldb.hpp +++ b/validator/db/celldb.hpp @@ -25,6 +25,7 @@ #include "ton/ton-types.h" #include "interfaces/block-handle.h" #include "auto/tl/ton_api.h" +#include "validator.h" namespace ton { @@ -53,7 +54,10 @@ class CellDbIn : public CellDbBase { void store_cell(BlockIdExt block_id, td::Ref cell, td::Promise> promise); void get_cell_db_reader(td::Promise> promise); - CellDbIn(td::actor::ActorId root_db, td::actor::ActorId parent, std::string path); + void migrate_cell(td::Bits256 hash); + + CellDbIn(td::actor::ActorId root_db, td::actor::ActorId parent, std::string path, + td::Ref opts); void start_up() override; void alarm() override; @@ -89,13 +93,20 @@ class CellDbIn : public CellDbBase { void gc_cont2(BlockHandle handle); void skip_gc(); + void migrate_cells(); + td::actor::ActorId root_db_; td::actor::ActorId parent_; std::string path_; + td::Ref opts_; std::unique_ptr boc_; std::shared_ptr cell_db_; + + std::function on_load_callback_; + std::set cells_to_migrate_; + td::Timestamp migrate_after_ = td::Timestamp::never(); }; class CellDb : public CellDbBase { @@ -104,11 +115,12 @@ class CellDb : public CellDbBase { void store_cell(BlockIdExt block_id, td::Ref cell, td::Promise> promise); void update_snapshot(std::unique_ptr snapshot) { started_ = true; - boc_->set_loader(std::make_unique(std::move(snapshot))).ensure(); + boc_->set_loader(std::make_unique(std::move(snapshot), on_load_callback_)).ensure(); } void get_cell_db_reader(td::Promise> promise); - CellDb(td::actor::ActorId root_db, std::string path) : root_db_(root_db), path_(path) { + CellDb(td::actor::ActorId root_db, std::string path, td::Ref opts) + : root_db_(root_db), path_(path), opts_(opts) { } void start_up() override; @@ -116,11 +128,14 @@ class CellDb : public CellDbBase { private: td::actor::ActorId root_db_; std::string path_; + td::Ref opts_; td::actor::ActorOwn cell_db_; std::unique_ptr boc_; bool started_ = false; + + std::function on_load_callback_; }; } // namespace validator diff --git a/validator/db/rootdb.cpp b/validator/db/rootdb.cpp index a7a1becf3..601b07c1e 100644 --- a/validator/db/rootdb.cpp +++ b/validator/db/rootdb.cpp @@ -397,7 +397,7 @@ void RootDb::get_hardforks(td::Promise> promise) { } void RootDb::start_up() { - cell_db_ = td::actor::create_actor("celldb", actor_id(this), root_path_ + "/celldb/"); + cell_db_ = td::actor::create_actor("celldb", actor_id(this), root_path_ + "/celldb/", opts_); state_db_ = td::actor::create_actor("statedb", actor_id(this), root_path_ + "/state/"); static_files_db_ = td::actor::create_actor("staticfilesdb", actor_id(this), root_path_ + "/static/"); archive_db_ = td::actor::create_actor("archive", actor_id(this), root_path_); diff --git a/validator/db/rootdb.hpp b/validator/db/rootdb.hpp index 9b0d52a6b..598defcb4 100644 --- a/validator/db/rootdb.hpp +++ b/validator/db/rootdb.hpp @@ -26,6 +26,7 @@ #include "statedb.hpp" #include "staticfilesdb.hpp" #include "archive-manager.hpp" +#include "validator.h" namespace ton { @@ -34,8 +35,9 @@ namespace validator { class RootDb : public Db { public: enum class Flags : td::uint32 { f_started = 1, f_ready = 2, f_switched = 4, f_archived = 8 }; - RootDb(td::actor::ActorId validator_manager, std::string root_path) - : validator_manager_(validator_manager), root_path_(std::move(root_path)) { + RootDb(td::actor::ActorId validator_manager, std::string root_path, + td::Ref opts) + : validator_manager_(validator_manager), root_path_(std::move(root_path)), opts_(opts) { } void start_up() override; @@ -138,6 +140,7 @@ class RootDb : public Db { td::actor::ActorId validator_manager_; std::string root_path_; + td::Ref opts_; td::actor::ActorOwn cell_db_; td::actor::ActorOwn state_db_; diff --git a/validator/fabric.h b/validator/fabric.h index 58f0647b7..326b17aec 100644 --- a/validator/fabric.h +++ b/validator/fabric.h @@ -20,12 +20,14 @@ #include "interfaces/validator-manager.h" #include "interfaces/db.h" +#include "validator.h" namespace ton { namespace validator { -td::actor::ActorOwn create_db_actor(td::actor::ActorId manager, std::string db_root_); +td::actor::ActorOwn create_db_actor(td::actor::ActorId manager, std::string db_root_, + td::Ref opts); td::actor::ActorOwn create_liteserver_cache_actor(td::actor::ActorId manager, std::string db_root); diff --git a/validator/impl/collator-impl.h b/validator/impl/collator-impl.h index c2088f47b..b30639930 100644 --- a/validator/impl/collator-impl.h +++ b/validator/impl/collator-impl.h @@ -159,6 +159,7 @@ class Collator final : public td::actor::Actor { bool report_version_{false}; bool skip_topmsgdescr_{false}; bool skip_extmsg_{false}; + bool queue_too_big_{false}; bool short_dequeue_records_{false}; td::uint64 overload_history_{0}, underload_history_{0}; td::uint64 block_size_estimate_{}; diff --git a/validator/impl/collator.cpp b/validator/impl/collator.cpp index 2030b345e..2e4dfa1d2 100644 --- a/validator/impl/collator.cpp +++ b/validator/impl/collator.cpp @@ -703,9 +703,7 @@ bool Collator::unpack_last_mc_state() { return fatal_error(limits.move_as_error()); } block_limits_ = limits.move_as_ok(); - if (!is_masterchain()) { - // block_limits_->bytes = {131072 / 3, 524288 / 3, 1048576 / 3}; - // block_limits_->gas = {2000000 / 3, 10000000 / 3, 20000000 / 3}; + if (now_ > prev_now_ + 15 && block_limits_->lt_delta.hard() > 200) { block_limits_->lt_delta = {20, 180, 200}; } LOG(DEBUG) << "block limits: bytes [" << block_limits_->bytes.underload() << ", " << block_limits_->bytes.soft() @@ -1828,9 +1826,6 @@ bool Collator::init_utime() { if (timeout < new_timeout) { double add = new_timeout.at() - timeout.at(); timeout = new_timeout; - queue_cleanup_timeout_ += add; - soft_timeout_ += add; - medium_timeout_ += add; alarm_timestamp() = timeout; } @@ -2259,6 +2254,7 @@ bool Collator::out_msg_queue_cleanup() { if (outq_cleanup_partial_ || total > 8000) { LOG(INFO) << "out_msg_queue too big, skipping importing external messages"; skip_extmsg_ = true; + queue_too_big_ = true; } auto rt = out_msg_queue_->get_root(); if (verbosity >= 2) { @@ -4170,8 +4166,12 @@ bool Collator::check_block_overload() { << " size_estimate=" << block_size_estimate_; auto cl = block_limit_status_->classify(); if (cl <= block::ParamLimits::cl_underload) { - underload_history_ |= 1; - LOG(INFO) << "block is underloaded"; + if (queue_too_big_) { + LOG(INFO) << "block is underloaded, but don't set underload history because out msg queue is big"; + } else { + underload_history_ |= 1; + LOG(INFO) << "block is underloaded"; + } } else if (cl >= block::ParamLimits::cl_soft) { overload_history_ |= 1; LOG(INFO) << "block is overloaded (category " << cl << ")"; diff --git a/validator/impl/fabric.cpp b/validator/impl/fabric.cpp index 0131fff7d..23a03482c 100644 --- a/validator/impl/fabric.cpp +++ b/validator/impl/fabric.cpp @@ -39,8 +39,9 @@ namespace ton { namespace validator { -td::actor::ActorOwn create_db_actor(td::actor::ActorId manager, std::string db_root_) { - return td::actor::create_actor("db", manager, db_root_); +td::actor::ActorOwn create_db_actor(td::actor::ActorId manager, std::string db_root_, + td::Ref opts) { + return td::actor::create_actor("db", manager, db_root_, opts); } td::actor::ActorOwn create_liteserver_cache_actor(td::actor::ActorId manager, diff --git a/validator/manager-disk.cpp b/validator/manager-disk.cpp index 8818c86a2..3717d7b09 100644 --- a/validator/manager-disk.cpp +++ b/validator/manager-disk.cpp @@ -901,7 +901,7 @@ void ValidatorManagerImpl::send_top_shard_block_description(td::Ref R) { R.ensure(); diff --git a/validator/manager-hardfork.cpp b/validator/manager-hardfork.cpp index 80a64d25f..e290f6359 100644 --- a/validator/manager-hardfork.cpp +++ b/validator/manager-hardfork.cpp @@ -549,7 +549,7 @@ void ValidatorManagerImpl::register_block_handle(BlockHandle handle, td::Promise } void ValidatorManagerImpl::start_up() { - db_ = create_db_actor(actor_id(this), db_root_); + db_ = create_db_actor(actor_id(this), db_root_, opts_); } void ValidatorManagerImpl::try_get_static_file(FileHash file_hash, td::Promise promise) { diff --git a/validator/manager.cpp b/validator/manager.cpp index e22616eac..8caed0f69 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -585,6 +585,12 @@ void ValidatorManagerImpl::run_ext_query(td::BufferSlice data, td::Promise> promise) { + auto it0 = block_state_cache_.find(handle->id()); + if (it0 != block_state_cache_.end()) { + it0->second.ttl_ = td::Timestamp::in(30.0); + promise.set_result(it0->second.state_); + return; + } auto it = wait_state_.find(handle->id()); if (it == wait_state_.end()) { auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result> R) { @@ -988,6 +994,9 @@ void ValidatorManagerImpl::get_block_by_seqno_from_db(AccountIdPrefixFull accoun } void ValidatorManagerImpl::finished_wait_state(BlockHandle handle, td::Result> R) { + if (R.is_ok()) { + block_state_cache_[handle->id()] = {R.ok(), td::Timestamp::in(30.0)}; + } auto it = wait_state_.find(handle->id()); if (it != wait_state_.end()) { if (R.is_error()) { @@ -1441,7 +1450,7 @@ void ValidatorManagerImpl::send_block_broadcast(BlockBroadcast broadcast) { } void ValidatorManagerImpl::start_up() { - db_ = create_db_actor(actor_id(this), db_root_); + db_ = create_db_actor(actor_id(this), db_root_, opts_); lite_server_cache_ = create_liteserver_cache_actor(actor_id(this), db_root_); token_manager_ = td::actor::create_actor("tokenmanager"); td::mkdir(db_root_ + "/tmp/").ensure(); @@ -2373,6 +2382,31 @@ void ValidatorManagerImpl::alarm() { for (auto &w : shard_client_waiters_) { w.second.check_timers(); } + for (auto it = block_state_cache_.begin(); it != block_state_cache_.end();) { + bool del = it->second.ttl_.is_in_past(); + if (del) { + auto block_id = it->first; + if (block_id.is_masterchain()) { + if (block_id.seqno() == last_masterchain_seqno_) { + it->second.ttl_ = td::Timestamp::in(30.0); + del = false; + } + } else if (last_masterchain_state_.not_null()) { + auto shard = last_masterchain_state_->get_shard_from_config(block_id.shard_full()); + if (shard.not_null()) { + if (block_id.seqno() == shard->top_block_id().seqno()) { + it->second.ttl_ = td::Timestamp::in(30.0); + del = false; + } + } + } + } + if (del) { + it = block_state_cache_.erase(it); + } else { + ++it; + } + } } alarm_timestamp().relax(check_waiters_at_); if (check_shard_clients_.is_in_past()) { diff --git a/validator/manager.hpp b/validator/manager.hpp index d133f83ba..ccd854235 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -183,6 +183,12 @@ class ValidatorManagerImpl : public ValidatorManager { std::map>> wait_state_; std::map>> wait_block_data_; + struct CachedBlockState { + td::Ref state_; + td::Timestamp ttl_; + }; + std::map block_state_cache_; + struct WaitBlockHandle { std::vector> waiting_; }; diff --git a/validator/validator-options.hpp b/validator/validator-options.hpp index d23d8cc91..3a7e5ba70 100644 --- a/validator/validator-options.hpp +++ b/validator/validator-options.hpp @@ -114,6 +114,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { std::string get_session_logs_file() const override { return session_logs_file_; } + td::uint32 get_celldb_compress_depth() const override { + return celldb_compress_depth_; + } void set_zero_block_id(BlockIdExt block_id) override { zero_block_id_ = block_id; @@ -167,6 +170,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { void set_session_logs_file(std::string f) override { session_logs_file_ = std::move(f); } + void set_celldb_compress_depth(td::uint32 value) override { + celldb_compress_depth_ = value; + } ValidatorManagerOptionsImpl *make_copy() const override { return new ValidatorManagerOptionsImpl(*this); @@ -209,6 +215,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions { BlockSeqno truncate_{0}; BlockSeqno sync_upto_{0}; std::string session_logs_file_; + td::uint32 celldb_compress_depth_{0}; }; } // namespace validator diff --git a/validator/validator.h b/validator/validator.h index 0687b1605..7cdea805c 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -81,6 +81,7 @@ struct ValidatorManagerOptions : public td::CntObject { virtual BlockSeqno get_truncate_seqno() const = 0; virtual BlockSeqno sync_upto() const = 0; virtual std::string get_session_logs_file() const = 0; + virtual td::uint32 get_celldb_compress_depth() const = 0; virtual void set_zero_block_id(BlockIdExt block_id) = 0; virtual void set_init_block_id(BlockIdExt block_id) = 0; @@ -100,6 +101,7 @@ struct ValidatorManagerOptions : public td::CntObject { virtual void truncate_db(BlockSeqno seqno) = 0; virtual void set_sync_upto(BlockSeqno seqno) = 0; virtual void set_session_logs_file(std::string f) = 0; + virtual void set_celldb_compress_depth(td::uint32 value) = 0; static td::Ref create( BlockIdExt zero_block_id, BlockIdExt init_block_id,