mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-15 04:32:21 +00:00
commit
3a595ce849
25 changed files with 329 additions and 56 deletions
|
@ -27,16 +27,25 @@ namespace vm {
|
||||||
namespace {
|
namespace {
|
||||||
class RefcntCellStorer {
|
class RefcntCellStorer {
|
||||||
public:
|
public:
|
||||||
RefcntCellStorer(td::int32 refcnt, const DataCell &cell) : refcnt_(refcnt), cell_(cell) {
|
RefcntCellStorer(td::int32 refcnt, const td::Ref<DataCell> &cell, bool as_boc)
|
||||||
|
: refcnt_(refcnt), cell_(cell), as_boc_(as_boc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
using td::store;
|
using td::store;
|
||||||
|
if (as_boc_) {
|
||||||
|
td::int32 tag = -1;
|
||||||
|
store(tag, storer);
|
||||||
store(refcnt_, storer);
|
store(refcnt_, storer);
|
||||||
store(cell_, storer);
|
td::BufferSlice data = vm::std_boc_serialize(cell_).move_as_ok();
|
||||||
for (unsigned i = 0; i < cell_.size_refs(); i++) {
|
storer.store_slice(data);
|
||||||
auto cell = cell_.get_ref(i);
|
return;
|
||||||
|
}
|
||||||
|
store(refcnt_, storer);
|
||||||
|
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_mask = cell->get_level_mask();
|
||||||
auto level = level_mask.get_level();
|
auto level = level_mask.get_level();
|
||||||
td::uint8 x = static_cast<td::uint8>(level_mask.get_mask());
|
td::uint8 x = static_cast<td::uint8>(level_mask.get_mask());
|
||||||
|
@ -60,7 +69,8 @@ class RefcntCellStorer {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
td::int32 refcnt_;
|
td::int32 refcnt_;
|
||||||
const DataCell &cell_;
|
td::Ref<DataCell> cell_;
|
||||||
|
bool as_boc_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RefcntCellParser {
|
class RefcntCellParser {
|
||||||
|
@ -69,11 +79,17 @@ class RefcntCellParser {
|
||||||
}
|
}
|
||||||
td::int32 refcnt;
|
td::int32 refcnt;
|
||||||
Ref<DataCell> cell;
|
Ref<DataCell> cell;
|
||||||
|
bool stored_boc_;
|
||||||
|
|
||||||
template <class ParserT>
|
template <class ParserT>
|
||||||
void parse(ParserT &parser, ExtCellCreator &ext_cell_creator) {
|
void parse(ParserT &parser, ExtCellCreator &ext_cell_creator) {
|
||||||
using ::td::parse;
|
using ::td::parse;
|
||||||
parse(refcnt, parser);
|
parse(refcnt, parser);
|
||||||
|
stored_boc_ = false;
|
||||||
|
if (refcnt == -1) {
|
||||||
|
stored_boc_ = true;
|
||||||
|
parse(refcnt, parser);
|
||||||
|
}
|
||||||
if (!need_data_) {
|
if (!need_data_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -81,6 +97,12 @@ class RefcntCellParser {
|
||||||
TRY_STATUS(parser.get_status());
|
TRY_STATUS(parser.get_status());
|
||||||
auto size = parser.get_left_len();
|
auto size = parser.get_left_len();
|
||||||
td::Slice data = parser.template fetch_string_raw<td::Slice>(size);
|
td::Slice data = parser.template fetch_string_raw<td::Slice>(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;
|
CellSerializationInfo info;
|
||||||
auto cell_data = data;
|
auto cell_data = data;
|
||||||
TRY_STATUS(info.init(cell_data, 0 /*ref_byte_size*/));
|
TRY_STATUS(info.init(cell_data, 0 /*ref_byte_size*/));
|
||||||
|
@ -122,7 +144,8 @@ class RefcntCellParser {
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CellLoader::CellLoader(std::shared_ptr<KeyValueReader> reader) : reader_(std::move(reader)) {
|
CellLoader::CellLoader(std::shared_ptr<KeyValueReader> reader, std::function<void(const LoadResult &)> on_load_callback)
|
||||||
|
: reader_(std::move(reader)), on_load_callback_(std::move(on_load_callback)) {
|
||||||
CHECK(reader_);
|
CHECK(reader_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +168,11 @@ td::Result<CellLoader::LoadResult> CellLoader::load(td::Slice hash, bool need_da
|
||||||
|
|
||||||
res.refcnt_ = refcnt_cell.refcnt;
|
res.refcnt_ = refcnt_cell.refcnt;
|
||||||
res.cell_ = std::move(refcnt_cell.cell);
|
res.cell_ = std::move(refcnt_cell.cell);
|
||||||
|
res.stored_boc_ = refcnt_cell.stored_boc_;
|
||||||
//CHECK(res.cell_->get_hash() == hash);
|
//CHECK(res.cell_->get_hash() == hash);
|
||||||
|
if (on_load_callback_) {
|
||||||
|
on_load_callback_(res);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +184,7 @@ td::Status CellStorer::erase(td::Slice hash) {
|
||||||
return kv_.erase(hash);
|
return kv_.erase(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Status CellStorer::set(td::int32 refcnt, const DataCell &cell) {
|
td::Status CellStorer::set(td::int32 refcnt, const td::Ref<DataCell> &cell, bool as_boc) {
|
||||||
return kv_.set(cell.get_hash().as_slice(), td::serialize(RefcntCellStorer(refcnt, cell)));
|
return kv_.set(cell->get_hash().as_slice(), td::serialize(RefcntCellStorer(refcnt, cell, as_boc)));
|
||||||
}
|
}
|
||||||
} // namespace vm
|
} // namespace vm
|
||||||
|
|
|
@ -45,19 +45,21 @@ class CellLoader {
|
||||||
|
|
||||||
Ref<DataCell> cell_;
|
Ref<DataCell> cell_;
|
||||||
td::int32 refcnt_{0};
|
td::int32 refcnt_{0};
|
||||||
|
bool stored_boc_{false};
|
||||||
};
|
};
|
||||||
CellLoader(std::shared_ptr<KeyValueReader> reader);
|
CellLoader(std::shared_ptr<KeyValueReader> reader, std::function<void(const LoadResult &)> on_load_callback = {});
|
||||||
td::Result<LoadResult> load(td::Slice hash, bool need_data, ExtCellCreator &ext_cell_creator);
|
td::Result<LoadResult> load(td::Slice hash, bool need_data, ExtCellCreator &ext_cell_creator);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<KeyValueReader> reader_;
|
std::shared_ptr<KeyValueReader> reader_;
|
||||||
|
std::function<void(const LoadResult &)> on_load_callback_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CellStorer {
|
class CellStorer {
|
||||||
public:
|
public:
|
||||||
CellStorer(KeyValue &kv);
|
CellStorer(KeyValue &kv);
|
||||||
td::Status erase(td::Slice hash);
|
td::Status erase(td::Slice hash);
|
||||||
td::Status set(td::int32 refcnt, const DataCell &cell);
|
td::Status set(td::int32 refcnt, const td::Ref<DataCell> &cell, bool as_boc);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KeyValue &kv_;
|
KeyValue &kv_;
|
||||||
|
|
|
@ -210,6 +210,14 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
|
||||||
return td::Status::OK();
|
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:
|
private:
|
||||||
std::unique_ptr<CellLoader> loader_;
|
std::unique_ptr<CellLoader> loader_;
|
||||||
std::vector<Ref<Cell>> to_inc_;
|
std::vector<Ref<Cell>> to_inc_;
|
||||||
|
@ -217,6 +225,7 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
|
||||||
CellHashTable<CellInfo> hash_table_;
|
CellHashTable<CellInfo> hash_table_;
|
||||||
std::vector<CellInfo *> visited_;
|
std::vector<CellInfo *> visited_;
|
||||||
Stats stats_diff_;
|
Stats stats_diff_;
|
||||||
|
td::uint32 celldb_compress_depth_{0};
|
||||||
|
|
||||||
static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() {
|
static td::NamedThreadSafeCounter::CounterRef get_thread_safe_counter() {
|
||||||
static auto res = td::NamedThreadSafeCounter::get_default().get_counter("DynamicBagOfCellsDb");
|
static auto res = td::NamedThreadSafeCounter::get_default().get_counter("DynamicBagOfCellsDb");
|
||||||
|
@ -443,7 +452,8 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
|
||||||
guard.dismiss();
|
guard.dismiss();
|
||||||
} else {
|
} else {
|
||||||
auto loaded_cell = info.cell->load_cell().move_as_ok();
|
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;
|
info.in_db = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ class DynamicBagOfCellsDb {
|
||||||
// restart with new loader will also reset stats_diff
|
// restart with new loader will also reset stats_diff
|
||||||
virtual td::Status set_loader(std::unique_ptr<CellLoader> loader) = 0;
|
virtual td::Status set_loader(std::unique_ptr<CellLoader> loader) = 0;
|
||||||
|
|
||||||
|
virtual void set_celldb_compress_depth(td::uint32 value) = 0;
|
||||||
|
virtual vm::ExtCellCreator& as_ext_cell_creator() = 0;
|
||||||
|
|
||||||
static std::unique_ptr<DynamicBagOfCellsDb> create();
|
static std::unique_ptr<DynamicBagOfCellsDb> create();
|
||||||
|
|
||||||
class AsyncExecutor {
|
class AsyncExecutor {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "vm/cellslice.h"
|
#include "vm/cellslice.h"
|
||||||
#include "vm/stack.hpp"
|
#include "vm/stack.hpp"
|
||||||
#include "common/bitstring.h"
|
#include "common/bitstring.h"
|
||||||
|
#include "td/utils/Random.h"
|
||||||
|
|
||||||
#include "td/utils/bits.h"
|
#include "td/utils/bits.h"
|
||||||
|
|
||||||
|
@ -2007,7 +2008,7 @@ bool DictionaryFixed::combine_with(DictionaryFixed& dict2) {
|
||||||
|
|
||||||
bool DictionaryFixed::dict_check_for_each(Ref<Cell> dict, td::BitPtr key_buffer, int n, int total_key_len,
|
bool DictionaryFixed::dict_check_for_each(Ref<Cell> dict, td::BitPtr key_buffer, int n, int total_key_len,
|
||||||
const DictionaryFixed::foreach_func_t& foreach_func,
|
const DictionaryFixed::foreach_func_t& foreach_func,
|
||||||
bool invert_first) const {
|
bool invert_first, bool shuffle) const {
|
||||||
if (dict.is_null()) {
|
if (dict.is_null()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2026,26 +2027,29 @@ bool DictionaryFixed::dict_check_for_each(Ref<Cell> dict, td::BitPtr key_buffer,
|
||||||
key_buffer += l + 1;
|
key_buffer += l + 1;
|
||||||
if (l) {
|
if (l) {
|
||||||
invert_first = false;
|
invert_first = false;
|
||||||
} else if (invert_first) {
|
}
|
||||||
|
bool invert = shuffle ? td::Random::fast(0, 1) == 1: invert_first;
|
||||||
|
if (invert) {
|
||||||
std::swap(c1, c2);
|
std::swap(c1, c2);
|
||||||
}
|
}
|
||||||
key_buffer[-1] = invert_first;
|
key_buffer[-1] = invert;
|
||||||
// recursive check_foreach applied to both children
|
// recursive check_foreach applied to both children
|
||||||
if (!dict_check_for_each(std::move(c1), key_buffer, n - l - 1, total_key_len, foreach_func)) {
|
if (!dict_check_for_each(std::move(c1), key_buffer, n - l - 1, total_key_len, foreach_func, false, shuffle)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
key_buffer[-1] = !invert_first;
|
key_buffer[-1] = !invert;
|
||||||
return dict_check_for_each(std::move(c2), key_buffer, n - l - 1, total_key_len, foreach_func);
|
return dict_check_for_each(std::move(c2), key_buffer, n - l - 1, total_key_len, foreach_func, false, shuffle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DictionaryFixed::check_for_each(const foreach_func_t& foreach_func, bool invert_first) {
|
bool DictionaryFixed::check_for_each(const foreach_func_t& foreach_func, bool invert_first, bool shuffle) {
|
||||||
force_validate();
|
force_validate();
|
||||||
if (is_empty()) {
|
if (is_empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int key_len = get_key_bits();
|
int key_len = get_key_bits();
|
||||||
unsigned char key_buffer[max_key_bytes];
|
unsigned char key_buffer[max_key_bytes];
|
||||||
return dict_check_for_each(get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, foreach_func, invert_first);
|
return dict_check_for_each(get_root_cell(), td::BitPtr{key_buffer}, key_len, key_len, foreach_func, invert_first,
|
||||||
|
shuffle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool set_bit(td::BitPtr ptr, bool value = true) {
|
static inline bool set_bit(td::BitPtr ptr, bool value = true) {
|
||||||
|
|
|
@ -223,7 +223,7 @@ class DictionaryFixed : public DictionaryBase {
|
||||||
int get_common_prefix(td::BitPtr buffer, unsigned buffer_len);
|
int get_common_prefix(td::BitPtr buffer, unsigned buffer_len);
|
||||||
bool cut_prefix_subdict(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix = false);
|
bool cut_prefix_subdict(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix = false);
|
||||||
Ref<vm::Cell> extract_prefix_subdict_root(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix = false);
|
Ref<vm::Cell> extract_prefix_subdict_root(td::ConstBitPtr prefix, int prefix_len, bool remove_prefix = false);
|
||||||
bool check_for_each(const foreach_func_t& foreach_func, bool invert_first = false);
|
bool check_for_each(const foreach_func_t& foreach_func, bool invert_first = false, bool shuffle = false);
|
||||||
int filter(filter_func_t check);
|
int filter(filter_func_t check);
|
||||||
bool combine_with(DictionaryFixed& dict2, const combine_func_t& combine_func, int mode = 0);
|
bool combine_with(DictionaryFixed& dict2, const combine_func_t& combine_func, int mode = 0);
|
||||||
bool combine_with(DictionaryFixed& dict2, const simple_combine_func_t& simple_combine_func, int mode = 0);
|
bool combine_with(DictionaryFixed& dict2, const simple_combine_func_t& simple_combine_func, int mode = 0);
|
||||||
|
@ -292,7 +292,7 @@ class DictionaryFixed : public DictionaryBase {
|
||||||
std::pair<Ref<Cell>, bool> extract_prefix_subdict_internal(Ref<Cell> dict, td::ConstBitPtr prefix, int prefix_len,
|
std::pair<Ref<Cell>, bool> extract_prefix_subdict_internal(Ref<Cell> dict, td::ConstBitPtr prefix, int prefix_len,
|
||||||
bool remove_prefix = false) const;
|
bool remove_prefix = false) const;
|
||||||
bool dict_check_for_each(Ref<Cell> dict, td::BitPtr key_buffer, int n, int total_key_len,
|
bool dict_check_for_each(Ref<Cell> dict, td::BitPtr key_buffer, int n, int total_key_len,
|
||||||
const foreach_func_t& foreach_func, bool invert_first = false) const;
|
const foreach_func_t& foreach_func, bool invert_first = false, bool shuffle = false) const;
|
||||||
std::pair<Ref<Cell>, int> dict_filter(Ref<Cell> dict, td::BitPtr key, int n, const filter_func_t& check_leaf,
|
std::pair<Ref<Cell>, int> dict_filter(Ref<Cell> dict, td::BitPtr key, int n, const filter_func_t& check_leaf,
|
||||||
int& skip_rest) const;
|
int& skip_rest) const;
|
||||||
Ref<Cell> dict_combine_with(Ref<Cell> dict1, Ref<Cell> dict2, td::BitPtr key_buffer, int n, int total_key_len,
|
Ref<Cell> dict_combine_with(Ref<Cell> dict1, Ref<Cell> dict2, td::BitPtr key_buffer, int n, int total_key_len,
|
||||||
|
|
|
@ -110,6 +110,7 @@ class Timestamp {
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator==(Timestamp a, Timestamp b);
|
friend bool operator==(Timestamp a, Timestamp b);
|
||||||
|
friend Timestamp &operator+=(Timestamp &a, double b);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double at_{0};
|
double at_{0};
|
||||||
|
@ -122,6 +123,11 @@ inline bool operator<(const Timestamp &a, const Timestamp &b) {
|
||||||
return a.at() < b.at();
|
return a.at() < b.at();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Timestamp &operator+=(Timestamp &a, double b) {
|
||||||
|
a.at_ += b;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(const Timestamp ×tamp, StorerT &storer) {
|
void store(const Timestamp ×tamp, StorerT &storer) {
|
||||||
storer.store_binary(timestamp.at() - Time::now() + Clocks::system());
|
storer.store_binary(timestamp.at() - Time::now() + Clocks::system());
|
||||||
|
|
|
@ -1363,6 +1363,7 @@ td::Status ValidatorEngine::load_global_config() {
|
||||||
if (!session_logs_file_.empty()) {
|
if (!session_logs_file_.empty()) {
|
||||||
validator_options_.write().set_session_logs_file(session_logs_file_);
|
validator_options_.write().set_session_logs_file(session_logs_file_);
|
||||||
}
|
}
|
||||||
|
validator_options_.write().set_celldb_compress_depth(celldb_compress_depth_);
|
||||||
|
|
||||||
std::vector<ton::BlockIdExt> h;
|
std::vector<ton::BlockIdExt> h;
|
||||||
for (auto &x : conf.validator_->hardforks_) {
|
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); });
|
acts.push_back([&x, at]() { td::actor::send_closure(x, &ValidatorEngine::schedule_shutdown, (double)at); });
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
});
|
});
|
||||||
|
p.add_checked_option('\0', "celldb-compress-depth", "(default: 0)", [&](td::Slice arg) {
|
||||||
|
TRY_RESULT(value, td::to_integer_safe<td::uint32>(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);
|
auto S = p.run(argc, argv);
|
||||||
if (S.is_error()) {
|
if (S.is_error()) {
|
||||||
LOG(ERROR) << "failed to parse options: " << S.move_as_error();
|
LOG(ERROR) << "failed to parse options: " << S.move_as_error();
|
||||||
|
|
|
@ -200,6 +200,7 @@ class ValidatorEngine : public td::actor::Actor {
|
||||||
double sync_ttl_ = 0;
|
double sync_ttl_ = 0;
|
||||||
double archive_ttl_ = 0;
|
double archive_ttl_ = 0;
|
||||||
double key_proof_ttl_ = 0;
|
double key_proof_ttl_ = 0;
|
||||||
|
td::uint32 celldb_compress_depth_ = 0;
|
||||||
bool read_config_ = false;
|
bool read_config_ = false;
|
||||||
bool started_keyring_ = false;
|
bool started_keyring_ = false;
|
||||||
bool started_ = false;
|
bool started_ = false;
|
||||||
|
@ -257,6 +258,9 @@ class ValidatorEngine : public td::actor::Actor {
|
||||||
keys_[key.compute_short_id()] = key;
|
keys_[key.compute_short_id()] = key;
|
||||||
}
|
}
|
||||||
void schedule_shutdown(double at);
|
void schedule_shutdown(double at);
|
||||||
|
void set_celldb_compress_depth(td::uint32 value) {
|
||||||
|
celldb_compress_depth_ = value;
|
||||||
|
}
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
ValidatorEngine() {
|
ValidatorEngine() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,16 +62,29 @@ void CellDbBase::execute_sync(std::function<void()> f) {
|
||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
|
|
||||||
CellDbIn::CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path)
|
CellDbIn::CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path,
|
||||||
: root_db_(root_db), parent_(parent), path_(std::move(path)) {
|
td::Ref<ValidatorManagerOptions> opts)
|
||||||
|
: root_db_(root_db), parent_(parent), path_(std::move(path)), opts_(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellDbIn::start_up() {
|
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();
|
CellDbBase::start_up();
|
||||||
cell_db_ = std::make_shared<td::RocksDb>(td::RocksDb::open(path_).move_as_ok());
|
cell_db_ = std::make_shared<td::RocksDb>(td::RocksDb::open(path_).move_as_ok());
|
||||||
|
|
||||||
boc_ = vm::DynamicBagOfCellsDb::create();
|
boc_ = vm::DynamicBagOfCellsDb::create();
|
||||||
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot())).ensure();
|
boc_->set_celldb_compress_depth(opts_->get_celldb_compress_depth());
|
||||||
|
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot(), on_load_callback_)).ensure();
|
||||||
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
||||||
|
|
||||||
alarm_timestamp() = td::Timestamp::in(10.0);
|
alarm_timestamp() = td::Timestamp::in(10.0);
|
||||||
|
@ -129,7 +142,7 @@ void CellDbIn::store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promi
|
||||||
set_block(key_hash, std::move(D));
|
set_block(key_hash, std::move(D));
|
||||||
cell_db_->commit_write_batch().ensure();
|
cell_db_->commit_write_batch().ensure();
|
||||||
|
|
||||||
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot())).ensure();
|
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot(), on_load_callback_)).ensure();
|
||||||
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
||||||
|
|
||||||
promise.set_result(boc_->load_cell(cell->get_hash().as_slice()));
|
promise.set_result(boc_->load_cell(cell->get_hash().as_slice()));
|
||||||
|
@ -140,6 +153,9 @@ void CellDbIn::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>>
|
||||||
}
|
}
|
||||||
|
|
||||||
void CellDbIn::alarm() {
|
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 E = get_block(get_empty_key_hash()).move_as_ok();
|
||||||
auto N = get_block(E.next).move_as_ok();
|
auto N = get_block(E.next).move_as_ok();
|
||||||
if (N.is_empty()) {
|
if (N.is_empty()) {
|
||||||
|
@ -220,7 +236,7 @@ void CellDbIn::gc_cont2(BlockHandle handle) {
|
||||||
cell_db_->commit_write_batch().ensure();
|
cell_db_->commit_write_batch().ensure();
|
||||||
alarm_timestamp() = td::Timestamp::now();
|
alarm_timestamp() = td::Timestamp::now();
|
||||||
|
|
||||||
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot())).ensure();
|
boc_->set_loader(std::make_unique<vm::CellLoader>(cell_db_->snapshot(), on_load_callback_)).ensure();
|
||||||
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
td::actor::send_closure(parent_, &CellDb::update_snapshot, cell_db_->snapshot());
|
||||||
|
|
||||||
DCHECK(get_block(key_hash).is_error());
|
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();
|
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<vm::CellLoader>(cell_db_->snapshot());
|
||||||
|
boc_->set_loader(std::make_unique<vm::CellLoader>(*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<vm::CellLoader>(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<td::Ref<vm::DataCell>> promise) {
|
void CellDb::load_cell(RootHash hash, td::Promise<td::Ref<vm::DataCell>> promise) {
|
||||||
if (!started_) {
|
if (!started_) {
|
||||||
td::actor::send_closure(cell_db_, &CellDbIn::load_cell, hash, std::move(promise));
|
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<std::shared_ptr<vm::CellDbReader>> p
|
||||||
void CellDb::start_up() {
|
void CellDb::start_up() {
|
||||||
CellDbBase::start_up();
|
CellDbBase::start_up();
|
||||||
boc_ = vm::DynamicBagOfCellsDb::create();
|
boc_ = vm::DynamicBagOfCellsDb::create();
|
||||||
cell_db_ = td::actor::create_actor<CellDbIn>("celldbin", root_db_, actor_id(this), path_);
|
boc_->set_celldb_compress_depth(opts_->get_celldb_compress_depth());
|
||||||
|
cell_db_ = td::actor::create_actor<CellDbIn>("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<ton_api::db_celldb_value> entry)
|
CellDbIn::DbEntry::DbEntry(tl_object_ptr<ton_api::db_celldb_value> entry)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "ton/ton-types.h"
|
#include "ton/ton-types.h"
|
||||||
#include "interfaces/block-handle.h"
|
#include "interfaces/block-handle.h"
|
||||||
#include "auto/tl/ton_api.h"
|
#include "auto/tl/ton_api.h"
|
||||||
|
#include "validator.h"
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
|
@ -53,7 +54,10 @@ class CellDbIn : public CellDbBase {
|
||||||
void store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promise<td::Ref<vm::DataCell>> promise);
|
void store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promise<td::Ref<vm::DataCell>> promise);
|
||||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise);
|
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise);
|
||||||
|
|
||||||
CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path);
|
void migrate_cell(td::Bits256 hash);
|
||||||
|
|
||||||
|
CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path,
|
||||||
|
td::Ref<ValidatorManagerOptions> opts);
|
||||||
|
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
void alarm() override;
|
void alarm() override;
|
||||||
|
@ -89,13 +93,20 @@ class CellDbIn : public CellDbBase {
|
||||||
void gc_cont2(BlockHandle handle);
|
void gc_cont2(BlockHandle handle);
|
||||||
void skip_gc();
|
void skip_gc();
|
||||||
|
|
||||||
|
void migrate_cells();
|
||||||
|
|
||||||
td::actor::ActorId<RootDb> root_db_;
|
td::actor::ActorId<RootDb> root_db_;
|
||||||
td::actor::ActorId<CellDb> parent_;
|
td::actor::ActorId<CellDb> parent_;
|
||||||
|
|
||||||
std::string path_;
|
std::string path_;
|
||||||
|
td::Ref<ValidatorManagerOptions> opts_;
|
||||||
|
|
||||||
std::unique_ptr<vm::DynamicBagOfCellsDb> boc_;
|
std::unique_ptr<vm::DynamicBagOfCellsDb> boc_;
|
||||||
std::shared_ptr<vm::KeyValue> cell_db_;
|
std::shared_ptr<vm::KeyValue> cell_db_;
|
||||||
|
|
||||||
|
std::function<void(const vm::CellLoader::LoadResult&)> on_load_callback_;
|
||||||
|
std::set<td::Bits256> cells_to_migrate_;
|
||||||
|
td::Timestamp migrate_after_ = td::Timestamp::never();
|
||||||
};
|
};
|
||||||
|
|
||||||
class CellDb : public CellDbBase {
|
class CellDb : public CellDbBase {
|
||||||
|
@ -104,11 +115,12 @@ class CellDb : public CellDbBase {
|
||||||
void store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promise<td::Ref<vm::DataCell>> promise);
|
void store_cell(BlockIdExt block_id, td::Ref<vm::Cell> cell, td::Promise<td::Ref<vm::DataCell>> promise);
|
||||||
void update_snapshot(std::unique_ptr<td::KeyValueReader> snapshot) {
|
void update_snapshot(std::unique_ptr<td::KeyValueReader> snapshot) {
|
||||||
started_ = true;
|
started_ = true;
|
||||||
boc_->set_loader(std::make_unique<vm::CellLoader>(std::move(snapshot))).ensure();
|
boc_->set_loader(std::make_unique<vm::CellLoader>(std::move(snapshot), on_load_callback_)).ensure();
|
||||||
}
|
}
|
||||||
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise);
|
void get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>> promise);
|
||||||
|
|
||||||
CellDb(td::actor::ActorId<RootDb> root_db, std::string path) : root_db_(root_db), path_(path) {
|
CellDb(td::actor::ActorId<RootDb> root_db, std::string path, td::Ref<ValidatorManagerOptions> opts)
|
||||||
|
: root_db_(root_db), path_(path), opts_(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
|
@ -116,11 +128,14 @@ class CellDb : public CellDbBase {
|
||||||
private:
|
private:
|
||||||
td::actor::ActorId<RootDb> root_db_;
|
td::actor::ActorId<RootDb> root_db_;
|
||||||
std::string path_;
|
std::string path_;
|
||||||
|
td::Ref<ValidatorManagerOptions> opts_;
|
||||||
|
|
||||||
td::actor::ActorOwn<CellDbIn> cell_db_;
|
td::actor::ActorOwn<CellDbIn> cell_db_;
|
||||||
|
|
||||||
std::unique_ptr<vm::DynamicBagOfCellsDb> boc_;
|
std::unique_ptr<vm::DynamicBagOfCellsDb> boc_;
|
||||||
bool started_ = false;
|
bool started_ = false;
|
||||||
|
|
||||||
|
std::function<void(const vm::CellLoader::LoadResult&)> on_load_callback_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -397,7 +397,7 @@ void RootDb::get_hardforks(td::Promise<std::vector<BlockIdExt>> promise) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootDb::start_up() {
|
void RootDb::start_up() {
|
||||||
cell_db_ = td::actor::create_actor<CellDb>("celldb", actor_id(this), root_path_ + "/celldb/");
|
cell_db_ = td::actor::create_actor<CellDb>("celldb", actor_id(this), root_path_ + "/celldb/", opts_);
|
||||||
state_db_ = td::actor::create_actor<StateDb>("statedb", actor_id(this), root_path_ + "/state/");
|
state_db_ = td::actor::create_actor<StateDb>("statedb", actor_id(this), root_path_ + "/state/");
|
||||||
static_files_db_ = td::actor::create_actor<StaticFilesDb>("staticfilesdb", actor_id(this), root_path_ + "/static/");
|
static_files_db_ = td::actor::create_actor<StaticFilesDb>("staticfilesdb", actor_id(this), root_path_ + "/static/");
|
||||||
archive_db_ = td::actor::create_actor<ArchiveManager>("archive", actor_id(this), root_path_);
|
archive_db_ = td::actor::create_actor<ArchiveManager>("archive", actor_id(this), root_path_);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "statedb.hpp"
|
#include "statedb.hpp"
|
||||||
#include "staticfilesdb.hpp"
|
#include "staticfilesdb.hpp"
|
||||||
#include "archive-manager.hpp"
|
#include "archive-manager.hpp"
|
||||||
|
#include "validator.h"
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
|
@ -34,8 +35,9 @@ namespace validator {
|
||||||
class RootDb : public Db {
|
class RootDb : public Db {
|
||||||
public:
|
public:
|
||||||
enum class Flags : td::uint32 { f_started = 1, f_ready = 2, f_switched = 4, f_archived = 8 };
|
enum class Flags : td::uint32 { f_started = 1, f_ready = 2, f_switched = 4, f_archived = 8 };
|
||||||
RootDb(td::actor::ActorId<ValidatorManager> validator_manager, std::string root_path)
|
RootDb(td::actor::ActorId<ValidatorManager> validator_manager, std::string root_path,
|
||||||
: validator_manager_(validator_manager), root_path_(std::move(root_path)) {
|
td::Ref<ValidatorManagerOptions> opts)
|
||||||
|
: validator_manager_(validator_manager), root_path_(std::move(root_path)), opts_(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
|
@ -138,6 +140,7 @@ class RootDb : public Db {
|
||||||
td::actor::ActorId<ValidatorManager> validator_manager_;
|
td::actor::ActorId<ValidatorManager> validator_manager_;
|
||||||
|
|
||||||
std::string root_path_;
|
std::string root_path_;
|
||||||
|
td::Ref<ValidatorManagerOptions> opts_;
|
||||||
|
|
||||||
td::actor::ActorOwn<CellDb> cell_db_;
|
td::actor::ActorOwn<CellDb> cell_db_;
|
||||||
td::actor::ActorOwn<StateDb> state_db_;
|
td::actor::ActorOwn<StateDb> state_db_;
|
||||||
|
|
|
@ -20,12 +20,14 @@
|
||||||
|
|
||||||
#include "interfaces/validator-manager.h"
|
#include "interfaces/validator-manager.h"
|
||||||
#include "interfaces/db.h"
|
#include "interfaces/db.h"
|
||||||
|
#include "validator.h"
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
namespace validator {
|
namespace validator {
|
||||||
|
|
||||||
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_);
|
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_,
|
||||||
|
td::Ref<ValidatorManagerOptions> opts);
|
||||||
td::actor::ActorOwn<LiteServerCache> create_liteserver_cache_actor(td::actor::ActorId<ValidatorManager> manager,
|
td::actor::ActorOwn<LiteServerCache> create_liteserver_cache_actor(td::actor::ActorId<ValidatorManager> manager,
|
||||||
std::string db_root);
|
std::string db_root);
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,7 @@ class Collator final : public td::actor::Actor {
|
||||||
bool report_version_{false};
|
bool report_version_{false};
|
||||||
bool skip_topmsgdescr_{false};
|
bool skip_topmsgdescr_{false};
|
||||||
bool skip_extmsg_{false};
|
bool skip_extmsg_{false};
|
||||||
|
bool queue_too_big_{false};
|
||||||
bool short_dequeue_records_{false};
|
bool short_dequeue_records_{false};
|
||||||
td::uint64 overload_history_{0}, underload_history_{0};
|
td::uint64 overload_history_{0}, underload_history_{0};
|
||||||
td::uint64 block_size_estimate_{};
|
td::uint64 block_size_estimate_{};
|
||||||
|
|
|
@ -703,6 +703,9 @@ bool Collator::unpack_last_mc_state() {
|
||||||
return fatal_error(limits.move_as_error());
|
return fatal_error(limits.move_as_error());
|
||||||
}
|
}
|
||||||
block_limits_ = limits.move_as_ok();
|
block_limits_ = limits.move_as_ok();
|
||||||
|
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()
|
LOG(DEBUG) << "block limits: bytes [" << block_limits_->bytes.underload() << ", " << block_limits_->bytes.soft()
|
||||||
<< ", " << block_limits_->bytes.hard() << "]";
|
<< ", " << block_limits_->bytes.hard() << "]";
|
||||||
LOG(DEBUG) << "block limits: gas [" << block_limits_->gas.underload() << ", " << block_limits_->gas.soft() << ", "
|
LOG(DEBUG) << "block limits: gas [" << block_limits_->gas.underload() << ", " << block_limits_->gas.soft() << ", "
|
||||||
|
@ -1818,6 +1821,14 @@ bool Collator::init_utime() {
|
||||||
CHECK(config_);
|
CHECK(config_);
|
||||||
// consider unixtime and lt from previous block(s) of the same shardchain
|
// consider unixtime and lt from previous block(s) of the same shardchain
|
||||||
prev_now_ = prev_state_utime_;
|
prev_now_ = prev_state_utime_;
|
||||||
|
// Extend collator timeout if previous block is too old
|
||||||
|
td::Timestamp new_timeout = td::Timestamp::in(std::min(30.0, (td::Clocks::system() - (double)prev_now_) / 2));
|
||||||
|
if (timeout < new_timeout) {
|
||||||
|
double add = new_timeout.at() - timeout.at();
|
||||||
|
timeout = new_timeout;
|
||||||
|
alarm_timestamp() = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
auto prev = std::max<td::uint32>(config_->utime, prev_now_);
|
auto prev = std::max<td::uint32>(config_->utime, prev_now_);
|
||||||
now_ = std::max<td::uint32>(prev + 1, (unsigned)std::time(nullptr));
|
now_ = std::max<td::uint32>(prev + 1, (unsigned)std::time(nullptr));
|
||||||
if (now_ > now_upper_limit_) {
|
if (now_ > now_upper_limit_) {
|
||||||
|
@ -2170,18 +2181,30 @@ bool Collator::out_msg_queue_cleanup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = out_msg_queue_->filter([&](vm::CellSlice& cs, td::ConstBitPtr key, int n) -> int {
|
auto queue_root = out_msg_queue_->get_root_cell();
|
||||||
|
if (queue_root.is_null()) {
|
||||||
|
LOG(DEBUG) << "out_msg_queue is empty";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto old_out_msg_queue = std::make_unique<vm::AugmentedDictionary>(queue_root, 352, block::tlb::aug_OutMsgQueue);
|
||||||
|
|
||||||
|
int deleted = 0;
|
||||||
|
int total = 0;
|
||||||
|
bool fail = false;
|
||||||
|
old_out_msg_queue->check_for_each([&](Ref<vm::CellSlice> value, td::ConstBitPtr key, int n) -> bool {
|
||||||
|
++total;
|
||||||
assert(n == 352);
|
assert(n == 352);
|
||||||
|
vm::CellSlice& cs = value.write();
|
||||||
// LOG(DEBUG) << "key is " << key.to_hex(n);
|
// LOG(DEBUG) << "key is " << key.to_hex(n);
|
||||||
if (queue_cleanup_timeout_.is_in_past(td::Timestamp::now())) {
|
if (queue_cleanup_timeout_.is_in_past(td::Timestamp::now())) {
|
||||||
LOG(WARNING) << "cleaning up outbound queue takes too long, ending";
|
LOG(WARNING) << "cleaning up outbound queue takes too long, ending";
|
||||||
outq_cleanup_partial_ = true;
|
outq_cleanup_partial_ = true;
|
||||||
return (1 << 30) + 1; // retain all remaining outbound queue entries including this one without processing
|
return false; // retain all remaining outbound queue entries including this one without processing
|
||||||
}
|
}
|
||||||
if (block_full_) {
|
if (block_full_) {
|
||||||
LOG(WARNING) << "BLOCK FULL while cleaning up outbound queue, cleanup completed only partially";
|
LOG(WARNING) << "BLOCK FULL while cleaning up outbound queue, cleanup completed only partially";
|
||||||
outq_cleanup_partial_ = true;
|
outq_cleanup_partial_ = true;
|
||||||
return (1 << 30) + 1; // retain all remaining outbound queue entries including this one without processing
|
return false; // retain all remaining outbound queue entries including this one without processing
|
||||||
}
|
}
|
||||||
block::EnqueuedMsgDescr enq_msg_descr;
|
block::EnqueuedMsgDescr enq_msg_descr;
|
||||||
unsigned long long created_lt;
|
unsigned long long created_lt;
|
||||||
|
@ -2190,7 +2213,8 @@ bool Collator::out_msg_queue_cleanup() {
|
||||||
&& enq_msg_descr.check_key(key) // check key
|
&& enq_msg_descr.check_key(key) // check key
|
||||||
&& enq_msg_descr.lt_ == created_lt)) {
|
&& enq_msg_descr.lt_ == created_lt)) {
|
||||||
LOG(ERROR) << "cannot unpack EnqueuedMsg with key " << key.to_hex(n);
|
LOG(ERROR) << "cannot unpack EnqueuedMsg with key " << key.to_hex(n);
|
||||||
return -1;
|
fail = true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
LOG(DEBUG) << "scanning outbound message with (lt,hash)=(" << enq_msg_descr.lt_ << ","
|
LOG(DEBUG) << "scanning outbound message with (lt,hash)=(" << enq_msg_descr.lt_ << ","
|
||||||
<< enq_msg_descr.hash_.to_hex() << ") enqueued_lt=" << enq_msg_descr.enqueued_lt_;
|
<< enq_msg_descr.hash_.to_hex() << ") enqueued_lt=" << enq_msg_descr.enqueued_lt_;
|
||||||
|
@ -2208,22 +2232,30 @@ bool Collator::out_msg_queue_cleanup() {
|
||||||
if (delivered) {
|
if (delivered) {
|
||||||
LOG(DEBUG) << "outbound message with (lt,hash)=(" << enq_msg_descr.lt_ << "," << enq_msg_descr.hash_.to_hex()
|
LOG(DEBUG) << "outbound message with (lt,hash)=(" << enq_msg_descr.lt_ << "," << enq_msg_descr.hash_.to_hex()
|
||||||
<< ") enqueued_lt=" << enq_msg_descr.enqueued_lt_ << " has been already delivered, dequeueing";
|
<< ") enqueued_lt=" << enq_msg_descr.enqueued_lt_ << " has been already delivered, dequeueing";
|
||||||
|
++deleted;
|
||||||
|
out_msg_queue_->lookup_delete_with_extra(key, n);
|
||||||
if (!dequeue_message(std::move(enq_msg_descr.msg_env_), deliver_lt)) {
|
if (!dequeue_message(std::move(enq_msg_descr.msg_env_), deliver_lt)) {
|
||||||
fatal_error(PSTRING() << "cannot dequeue outbound message with (lt,hash)=(" << enq_msg_descr.lt_ << ","
|
fatal_error(PSTRING() << "cannot dequeue outbound message with (lt,hash)=(" << enq_msg_descr.lt_ << ","
|
||||||
<< enq_msg_descr.hash_.to_hex() << ") by inserting a msg_export_deq record");
|
<< enq_msg_descr.hash_.to_hex() << ") by inserting a msg_export_deq record");
|
||||||
return -1;
|
fail = true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
register_out_msg_queue_op();
|
register_out_msg_queue_op();
|
||||||
if (!block_limit_status_->fits(block::ParamLimits::cl_normal)) {
|
if (!block_limit_status_->fits(block::ParamLimits::cl_normal)) {
|
||||||
block_full_ = true;
|
block_full_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !delivered;
|
return true;
|
||||||
});
|
}, false, true /* random order */);
|
||||||
LOG(DEBUG) << "deleted " << res << " messages from out_msg_queue";
|
LOG(INFO) << "deleted " << deleted << " messages from out_msg_queue, processed " << total << " messages in total";
|
||||||
if (res < 0) {
|
if (fail) {
|
||||||
return fatal_error("error scanning/updating OutMsgQueue");
|
return fatal_error("error scanning/updating OutMsgQueue");
|
||||||
}
|
}
|
||||||
|
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();
|
auto rt = out_msg_queue_->get_root();
|
||||||
if (verbosity >= 2) {
|
if (verbosity >= 2) {
|
||||||
std::cerr << "new out_msg_queue is ";
|
std::cerr << "new out_msg_queue is ";
|
||||||
|
@ -3277,6 +3309,10 @@ bool Collator::process_inbound_external_messages() {
|
||||||
LOG(INFO) << "skipping processing of inbound external messages";
|
LOG(INFO) << "skipping processing of inbound external messages";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (out_msg_queue_->get_root_cell().not_null() && out_msg_queue_->get_root_cell()->get_depth() > 12) {
|
||||||
|
LOG(INFO) << "skipping processing of inbound external messages: out msg queue is too big";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
bool full = !block_limit_status_->fits(block::ParamLimits::cl_soft);
|
bool full = !block_limit_status_->fits(block::ParamLimits::cl_soft);
|
||||||
for (auto& ext_msg_pair : ext_msg_list_) {
|
for (auto& ext_msg_pair : ext_msg_list_) {
|
||||||
if (full) {
|
if (full) {
|
||||||
|
@ -4130,8 +4166,12 @@ bool Collator::check_block_overload() {
|
||||||
<< " size_estimate=" << block_size_estimate_;
|
<< " size_estimate=" << block_size_estimate_;
|
||||||
auto cl = block_limit_status_->classify();
|
auto cl = block_limit_status_->classify();
|
||||||
if (cl <= block::ParamLimits::cl_underload) {
|
if (cl <= block::ParamLimits::cl_underload) {
|
||||||
|
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;
|
underload_history_ |= 1;
|
||||||
LOG(INFO) << "block is underloaded";
|
LOG(INFO) << "block is underloaded";
|
||||||
|
}
|
||||||
} else if (cl >= block::ParamLimits::cl_soft) {
|
} else if (cl >= block::ParamLimits::cl_soft) {
|
||||||
overload_history_ |= 1;
|
overload_history_ |= 1;
|
||||||
LOG(INFO) << "block is overloaded (category " << cl << ")";
|
LOG(INFO) << "block is overloaded (category " << cl << ")";
|
||||||
|
|
|
@ -39,8 +39,9 @@ namespace ton {
|
||||||
|
|
||||||
namespace validator {
|
namespace validator {
|
||||||
|
|
||||||
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_) {
|
td::actor::ActorOwn<Db> create_db_actor(td::actor::ActorId<ValidatorManager> manager, std::string db_root_,
|
||||||
return td::actor::create_actor<RootDb>("db", manager, db_root_);
|
td::Ref<ValidatorManagerOptions> opts) {
|
||||||
|
return td::actor::create_actor<RootDb>("db", manager, db_root_, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
td::actor::ActorOwn<LiteServerCache> create_liteserver_cache_actor(td::actor::ActorId<ValidatorManager> manager,
|
td::actor::ActorOwn<LiteServerCache> create_liteserver_cache_actor(td::actor::ActorId<ValidatorManager> manager,
|
||||||
|
|
|
@ -901,7 +901,7 @@ void ValidatorManagerImpl::send_top_shard_block_description(td::Ref<ShardTopBloc
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorManagerImpl::start_up() {
|
void ValidatorManagerImpl::start_up() {
|
||||||
db_ = create_db_actor(actor_id(this), db_root_);
|
db_ = create_db_actor(actor_id(this), db_root_, opts_);
|
||||||
|
|
||||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<ValidatorManagerInitResult> R) {
|
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<ValidatorManagerInitResult> R) {
|
||||||
R.ensure();
|
R.ensure();
|
||||||
|
|
|
@ -549,7 +549,7 @@ void ValidatorManagerImpl::register_block_handle(BlockHandle handle, td::Promise
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorManagerImpl::start_up() {
|
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<td::BufferSlice> promise) {
|
void ValidatorManagerImpl::try_get_static_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) {
|
||||||
|
|
|
@ -585,6 +585,12 @@ void ValidatorManagerImpl::run_ext_query(td::BufferSlice data, td::Promise<td::B
|
||||||
|
|
||||||
void ValidatorManagerImpl::wait_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
void ValidatorManagerImpl::wait_block_state(BlockHandle handle, td::uint32 priority, td::Timestamp timeout,
|
||||||
td::Promise<td::Ref<ShardState>> promise) {
|
td::Promise<td::Ref<ShardState>> 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());
|
auto it = wait_state_.find(handle->id());
|
||||||
if (it == wait_state_.end()) {
|
if (it == wait_state_.end()) {
|
||||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
|
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
|
||||||
|
@ -988,6 +994,9 @@ void ValidatorManagerImpl::get_block_by_seqno_from_db(AccountIdPrefixFull accoun
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorManagerImpl::finished_wait_state(BlockHandle handle, td::Result<td::Ref<ShardState>> R) {
|
void ValidatorManagerImpl::finished_wait_state(BlockHandle handle, td::Result<td::Ref<ShardState>> R) {
|
||||||
|
if (R.is_ok()) {
|
||||||
|
block_state_cache_[handle->id()] = {R.ok(), td::Timestamp::in(30.0)};
|
||||||
|
}
|
||||||
auto it = wait_state_.find(handle->id());
|
auto it = wait_state_.find(handle->id());
|
||||||
if (it != wait_state_.end()) {
|
if (it != wait_state_.end()) {
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
|
@ -1441,7 +1450,7 @@ void ValidatorManagerImpl::send_block_broadcast(BlockBroadcast broadcast) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorManagerImpl::start_up() {
|
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_);
|
lite_server_cache_ = create_liteserver_cache_actor(actor_id(this), db_root_);
|
||||||
token_manager_ = td::actor::create_actor<TokenManager>("tokenmanager");
|
token_manager_ = td::actor::create_actor<TokenManager>("tokenmanager");
|
||||||
td::mkdir(db_root_ + "/tmp/").ensure();
|
td::mkdir(db_root_ + "/tmp/").ensure();
|
||||||
|
@ -2373,6 +2382,31 @@ void ValidatorManagerImpl::alarm() {
|
||||||
for (auto &w : shard_client_waiters_) {
|
for (auto &w : shard_client_waiters_) {
|
||||||
w.second.check_timers();
|
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_);
|
alarm_timestamp().relax(check_waiters_at_);
|
||||||
if (check_shard_clients_.is_in_past()) {
|
if (check_shard_clients_.is_in_past()) {
|
||||||
|
|
|
@ -183,6 +183,12 @@ class ValidatorManagerImpl : public ValidatorManager {
|
||||||
std::map<BlockIdExt, WaitList<WaitBlockState, td::Ref<ShardState>>> wait_state_;
|
std::map<BlockIdExt, WaitList<WaitBlockState, td::Ref<ShardState>>> wait_state_;
|
||||||
std::map<BlockIdExt, WaitList<WaitBlockData, td::Ref<BlockData>>> wait_block_data_;
|
std::map<BlockIdExt, WaitList<WaitBlockData, td::Ref<BlockData>>> wait_block_data_;
|
||||||
|
|
||||||
|
struct CachedBlockState {
|
||||||
|
td::Ref<ShardState> state_;
|
||||||
|
td::Timestamp ttl_;
|
||||||
|
};
|
||||||
|
std::map<BlockIdExt, CachedBlockState> block_state_cache_;
|
||||||
|
|
||||||
struct WaitBlockHandle {
|
struct WaitBlockHandle {
|
||||||
std::vector<td::Promise<BlockHandle>> waiting_;
|
std::vector<td::Promise<BlockHandle>> waiting_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,6 +78,17 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat
|
||||||
promise.set_error(td::Status::Error(ErrorCode::notready, "too old"));
|
promise.set_error(td::Status::Error(ErrorCode::notready, "too old"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto next_block_id = create_next_block_id(block.id.root_hash, block.id.file_hash);
|
||||||
|
block.id = next_block_id;
|
||||||
|
|
||||||
|
CacheKey cache_key = block_to_cache_key(block);
|
||||||
|
auto it = approved_candidates_cache_.find(cache_key);
|
||||||
|
if (it != approved_candidates_cache_.end()) {
|
||||||
|
promise.set_result(it->second);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), round_id, block = block.clone(),
|
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), round_id, block = block.clone(),
|
||||||
promise = std::move(promise)](td::Result<ValidateCandidateResult> R) mutable {
|
promise = std::move(promise)](td::Result<ValidateCandidateResult> R) mutable {
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
|
@ -93,10 +104,15 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat
|
||||||
td::Timestamp::in(0.1));
|
td::Timestamp::in(0.1));
|
||||||
} else {
|
} else {
|
||||||
auto v = R.move_as_ok();
|
auto v = R.move_as_ok();
|
||||||
v.visit(td::overloaded([&](UnixTime ts) { promise.set_result(ts); },
|
v.visit(td::overloaded(
|
||||||
|
[&](UnixTime ts) {
|
||||||
|
td::actor::send_closure(SelfId, &ValidatorGroup::update_approve_cache, block_to_cache_key(block),
|
||||||
|
ts);
|
||||||
|
promise.set_result(ts);
|
||||||
|
},
|
||||||
[&](CandidateReject reject) {
|
[&](CandidateReject reject) {
|
||||||
promise.set_error(td::Status::Error(ErrorCode::protoviolation,
|
promise.set_error(
|
||||||
PSTRING() << "bad candidate: " << reject.reason));
|
td::Status::Error(ErrorCode::protoviolation, PSTRING() << "bad candidate: " << reject.reason));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -104,13 +120,16 @@ void ValidatorGroup::validate_block_candidate(td::uint32 round_id, BlockCandidat
|
||||||
P.set_error(td::Status::Error(ErrorCode::notready, "validator group not started"));
|
P.set_error(td::Status::Error(ErrorCode::notready, "validator group not started"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto next_block_id = create_next_block_id(block.id.root_hash, block.id.file_hash);
|
|
||||||
VLOG(VALIDATOR_DEBUG) << "validating block candidate " << next_block_id;
|
VLOG(VALIDATOR_DEBUG) << "validating block candidate " << next_block_id;
|
||||||
block.id = next_block_id;
|
block.id = next_block_id;
|
||||||
run_validate_query(shard_, min_ts_, min_masterchain_block_id_, prev_block_ids_, std::move(block), validator_set_,
|
run_validate_query(shard_, min_ts_, min_masterchain_block_id_, prev_block_ids_, std::move(block), validator_set_,
|
||||||
manager_, td::Timestamp::in(15.0), std::move(P));
|
manager_, td::Timestamp::in(15.0), std::move(P));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ValidatorGroup::update_approve_cache(CacheKey key, UnixTime value) {
|
||||||
|
approved_candidates_cache_[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block_data,
|
void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash src, td::BufferSlice block_data,
|
||||||
RootHash root_hash, FileHash file_hash,
|
RootHash root_hash, FileHash file_hash,
|
||||||
std::vector<BlockSignature> signatures,
|
std::vector<BlockSignature> signatures,
|
||||||
|
@ -155,6 +174,7 @@ void ValidatorGroup::accept_block_candidate(td::uint32 round_id, PublicKeyHash s
|
||||||
std::move(approve_sig_set), src == local_id_, manager_, std::move(P));
|
std::move(approve_sig_set), src == local_id_, manager_, std::move(P));
|
||||||
prev_block_ids_ = std::vector<BlockIdExt>{next_block_id};
|
prev_block_ids_ = std::vector<BlockIdExt>{next_block_id};
|
||||||
cached_collated_block_ = nullptr;
|
cached_collated_block_ = nullptr;
|
||||||
|
approved_candidates_cache_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValidatorGroup::retry_accept_block_query(BlockIdExt block_id, td::Ref<BlockData> block,
|
void ValidatorGroup::retry_accept_block_query(BlockIdExt block_id, td::Ref<BlockData> block,
|
||||||
|
@ -310,6 +330,7 @@ void ValidatorGroup::start(std::vector<BlockIdExt> prev, BlockIdExt min_masterch
|
||||||
min_masterchain_block_id_ = min_masterchain_block_id;
|
min_masterchain_block_id_ = min_masterchain_block_id;
|
||||||
min_ts_ = min_ts;
|
min_ts_ = min_ts;
|
||||||
cached_collated_block_ = nullptr;
|
cached_collated_block_ = nullptr;
|
||||||
|
approved_candidates_cache_.clear();
|
||||||
started_ = true;
|
started_ = true;
|
||||||
|
|
||||||
if (init_) {
|
if (init_) {
|
||||||
|
|
|
@ -126,6 +126,15 @@ class ValidatorGroup : public td::actor::Actor {
|
||||||
std::shared_ptr<CachedCollatedBlock> cached_collated_block_;
|
std::shared_ptr<CachedCollatedBlock> cached_collated_block_;
|
||||||
|
|
||||||
void generated_block_candidate(std::shared_ptr<CachedCollatedBlock> cache, td::Result<BlockCandidate> R);
|
void generated_block_candidate(std::shared_ptr<CachedCollatedBlock> cache, td::Result<BlockCandidate> R);
|
||||||
|
|
||||||
|
typedef std::tuple<td::Bits256, BlockIdExt, FileHash, FileHash> CacheKey;
|
||||||
|
std::map<CacheKey, UnixTime> approved_candidates_cache_;
|
||||||
|
|
||||||
|
void update_approve_cache(CacheKey key, UnixTime value);
|
||||||
|
|
||||||
|
static CacheKey block_to_cache_key(const BlockCandidate& block) {
|
||||||
|
return std::make_tuple(block.pubkey.as_bits256(), block.id, sha256_bits256(block.data), block.collated_file_hash);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -114,6 +114,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
std::string get_session_logs_file() const override {
|
std::string get_session_logs_file() const override {
|
||||||
return session_logs_file_;
|
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 {
|
void set_zero_block_id(BlockIdExt block_id) override {
|
||||||
zero_block_id_ = block_id;
|
zero_block_id_ = block_id;
|
||||||
|
@ -167,6 +170,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
void set_session_logs_file(std::string f) override {
|
void set_session_logs_file(std::string f) override {
|
||||||
session_logs_file_ = std::move(f);
|
session_logs_file_ = std::move(f);
|
||||||
}
|
}
|
||||||
|
void set_celldb_compress_depth(td::uint32 value) override {
|
||||||
|
celldb_compress_depth_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
ValidatorManagerOptionsImpl *make_copy() const override {
|
ValidatorManagerOptionsImpl *make_copy() const override {
|
||||||
return new ValidatorManagerOptionsImpl(*this);
|
return new ValidatorManagerOptionsImpl(*this);
|
||||||
|
@ -209,6 +215,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
BlockSeqno truncate_{0};
|
BlockSeqno truncate_{0};
|
||||||
BlockSeqno sync_upto_{0};
|
BlockSeqno sync_upto_{0};
|
||||||
std::string session_logs_file_;
|
std::string session_logs_file_;
|
||||||
|
td::uint32 celldb_compress_depth_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -81,6 +81,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
||||||
virtual BlockSeqno get_truncate_seqno() const = 0;
|
virtual BlockSeqno get_truncate_seqno() const = 0;
|
||||||
virtual BlockSeqno sync_upto() const = 0;
|
virtual BlockSeqno sync_upto() const = 0;
|
||||||
virtual std::string get_session_logs_file() 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_zero_block_id(BlockIdExt block_id) = 0;
|
||||||
virtual void set_init_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 truncate_db(BlockSeqno seqno) = 0;
|
||||||
virtual void set_sync_upto(BlockSeqno seqno) = 0;
|
virtual void set_sync_upto(BlockSeqno seqno) = 0;
|
||||||
virtual void set_session_logs_file(std::string f) = 0;
|
virtual void set_session_logs_file(std::string f) = 0;
|
||||||
|
virtual void set_celldb_compress_depth(td::uint32 value) = 0;
|
||||||
|
|
||||||
static td::Ref<ValidatorManagerOptions> create(
|
static td::Ref<ValidatorManagerOptions> create(
|
||||||
BlockIdExt zero_block_id, BlockIdExt init_block_id,
|
BlockIdExt zero_block_id, BlockIdExt init_block_id,
|
||||||
|
|
Loading…
Reference in a new issue