mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Limit file descriptors num by adding archive slice lru (#892)
* --max-archive-fd option limits open files in archive manager * Don't close the latest archives + bugfix * Delete temp packages early --------- Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
e723213d5c
commit
12c1b1a2e6
12 changed files with 316 additions and 88 deletions
|
@ -1364,6 +1364,7 @@ td::Status ValidatorEngine::load_global_config() {
|
||||||
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_);
|
validator_options_.write().set_celldb_compress_depth(celldb_compress_depth_);
|
||||||
|
validator_options_.write().set_max_open_archive_files(max_open_archive_files_);
|
||||||
|
|
||||||
std::vector<ton::BlockIdExt> h;
|
std::vector<ton::BlockIdExt> h;
|
||||||
for (auto &x : conf.validator_->hardforks_) {
|
for (auto &x : conf.validator_->hardforks_) {
|
||||||
|
@ -3793,6 +3794,13 @@ int main(int argc, char *argv[]) {
|
||||||
});
|
});
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
});
|
});
|
||||||
|
p.add_checked_option(
|
||||||
|
'\0', "max-archive-fd", "limit for a number of open file descriptirs in archive manager. 0 is unlimited (default)",
|
||||||
|
[&](td::Slice s) -> td::Status {
|
||||||
|
TRY_RESULT(v, td::to_integer_safe<size_t>(s));
|
||||||
|
acts.push_back([&x, v]() { td::actor::send_closure(x, &ValidatorEngine::set_max_open_archive_files, v); });
|
||||||
|
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();
|
||||||
|
|
|
@ -204,6 +204,7 @@ class ValidatorEngine : public td::actor::Actor {
|
||||||
double archive_ttl_ = 0;
|
double archive_ttl_ = 0;
|
||||||
double key_proof_ttl_ = 0;
|
double key_proof_ttl_ = 0;
|
||||||
td::uint32 celldb_compress_depth_ = 0;
|
td::uint32 celldb_compress_depth_ = 0;
|
||||||
|
size_t max_open_archive_files_ = 0;
|
||||||
bool read_config_ = false;
|
bool read_config_ = false;
|
||||||
bool started_keyring_ = false;
|
bool started_keyring_ = false;
|
||||||
bool started_ = false;
|
bool started_ = false;
|
||||||
|
@ -264,6 +265,9 @@ class ValidatorEngine : public td::actor::Actor {
|
||||||
void set_celldb_compress_depth(td::uint32 value) {
|
void set_celldb_compress_depth(td::uint32 value) {
|
||||||
celldb_compress_depth_ = value;
|
celldb_compress_depth_ = value;
|
||||||
}
|
}
|
||||||
|
void set_max_open_archive_files(size_t value) {
|
||||||
|
max_open_archive_files_ = value;
|
||||||
|
}
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
ValidatorEngine() {
|
ValidatorEngine() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,9 @@ std::string PackageId::name() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiveManager::ArchiveManager(td::actor::ActorId<RootDb> root, std::string db_root) : db_root_(db_root) {
|
ArchiveManager::ArchiveManager(td::actor::ActorId<RootDb> root, std::string db_root,
|
||||||
|
td::Ref<ValidatorManagerOptions> opts)
|
||||||
|
: db_root_(db_root), opts_(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchiveManager::add_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
void ArchiveManager::add_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||||
|
@ -598,9 +600,11 @@ void ArchiveManager::load_package(PackageId id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_);
|
desc.file =
|
||||||
|
td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get());
|
||||||
|
|
||||||
m.emplace(id, std::move(desc));
|
m.emplace(id, std::move(desc));
|
||||||
|
update_permanent_slices();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArchiveManager::FileDescription *ArchiveManager::get_file_desc(ShardIdFull shard, PackageId id, BlockSeqno seqno,
|
const ArchiveManager::FileDescription *ArchiveManager::get_file_desc(ShardIdFull shard, PackageId id, BlockSeqno seqno,
|
||||||
|
@ -631,7 +635,8 @@ const ArchiveManager::FileDescription *ArchiveManager::add_file_desc(ShardIdFull
|
||||||
FileDescription new_desc{id, false};
|
FileDescription new_desc{id, false};
|
||||||
td::mkdir(db_root_ + id.path()).ensure();
|
td::mkdir(db_root_ + id.path()).ensure();
|
||||||
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
||||||
new_desc.file = td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_);
|
new_desc.file =
|
||||||
|
td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get());
|
||||||
const FileDescription &desc = f.emplace(id, std::move(new_desc));
|
const FileDescription &desc = f.emplace(id, std::move(new_desc));
|
||||||
if (!id.temp) {
|
if (!id.temp) {
|
||||||
update_desc(f, desc, shard, seqno, ts, lt);
|
update_desc(f, desc, shard, seqno, ts, lt);
|
||||||
|
@ -673,6 +678,7 @@ const ArchiveManager::FileDescription *ArchiveManager::add_file_desc(ShardIdFull
|
||||||
.ensure();
|
.ensure();
|
||||||
}
|
}
|
||||||
index_->commit_transaction().ensure();
|
index_->commit_transaction().ensure();
|
||||||
|
update_permanent_slices();
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,6 +826,9 @@ void ArchiveManager::start_up() {
|
||||||
td::mkdir(db_root_ + "/archive/states/").ensure();
|
td::mkdir(db_root_ + "/archive/states/").ensure();
|
||||||
td::mkdir(db_root_ + "/files/").ensure();
|
td::mkdir(db_root_ + "/files/").ensure();
|
||||||
td::mkdir(db_root_ + "/files/packages/").ensure();
|
td::mkdir(db_root_ + "/files/packages/").ensure();
|
||||||
|
if (opts_->get_max_open_archive_files() > 0) {
|
||||||
|
archive_lru_ = td::actor::create_actor<ArchiveLru>("archive_lru", opts_->get_max_open_archive_files());
|
||||||
|
}
|
||||||
index_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_root_ + "/files/globalindex").move_as_ok());
|
index_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_root_ + "/files/globalindex").move_as_ok());
|
||||||
std::string value;
|
std::string value;
|
||||||
auto v = index_->get(create_serialize_tl_object<ton_api::db_files_index_key>().as_slice(), value);
|
auto v = index_->get(create_serialize_tl_object<ton_api::db_files_index_key>().as_slice(), value);
|
||||||
|
@ -878,8 +887,8 @@ void ArchiveManager::start_up() {
|
||||||
persistent_state_gc(FileHash::zero());
|
persistent_state_gc(FileHash::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchiveManager::run_gc(UnixTime ts, UnixTime archive_ttl) {
|
void ArchiveManager::run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl) {
|
||||||
auto p = get_temp_package_id_by_unixtime(ts);
|
auto p = get_temp_package_id_by_unixtime(std::max(gc_ts, mc_ts - TEMP_PACKAGES_TTL));
|
||||||
std::vector<PackageId> vec;
|
std::vector<PackageId> vec;
|
||||||
for (auto &x : temp_files_) {
|
for (auto &x : temp_files_) {
|
||||||
if (x.first < p) {
|
if (x.first < p) {
|
||||||
|
@ -907,7 +916,7 @@ void ArchiveManager::run_gc(UnixTime ts, UnixTime archive_ttl) {
|
||||||
if (it == desc.first_blocks.end()) {
|
if (it == desc.first_blocks.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (it->second.ts < ts - archive_ttl) {
|
if (it->second.ts < gc_ts - archive_ttl) {
|
||||||
vec.push_back(f.first);
|
vec.push_back(f.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1200,6 +1209,7 @@ void ArchiveManager::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle han
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
update_permanent_slices();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchiveManager::FileMap::shard_index_add(const FileDescription &desc) {
|
void ArchiveManager::FileMap::shard_index_add(const FileDescription &desc) {
|
||||||
|
@ -1298,6 +1308,23 @@ const ArchiveManager::FileDescription *ArchiveManager::FileMap::get_next_file_de
|
||||||
return it2->second->deleted ? nullptr : it2->second;
|
return it2->second->deleted ? nullptr : it2->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArchiveManager::update_permanent_slices() {
|
||||||
|
if (archive_lru_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::vector<PackageId> ids;
|
||||||
|
if (!files_.empty()) {
|
||||||
|
ids.push_back(files_.rbegin()->first);
|
||||||
|
}
|
||||||
|
if (!key_files_.empty()) {
|
||||||
|
ids.push_back(key_files_.rbegin()->first);
|
||||||
|
}
|
||||||
|
if (!temp_files_.empty()) {
|
||||||
|
ids.push_back(temp_files_.rbegin()->first);
|
||||||
|
}
|
||||||
|
td::actor::send_closure(archive_lru_, &ArchiveLru::set_permanent_slices, std::move(ids));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
||||||
} // namespace ton
|
} // namespace ton
|
||||||
|
|
|
@ -28,7 +28,7 @@ class RootDb;
|
||||||
|
|
||||||
class ArchiveManager : public td::actor::Actor {
|
class ArchiveManager : public td::actor::Actor {
|
||||||
public:
|
public:
|
||||||
ArchiveManager(td::actor::ActorId<RootDb> root, std::string db_root);
|
ArchiveManager(td::actor::ActorId<RootDb> root, std::string db_root, td::Ref<ValidatorManagerOptions> opts);
|
||||||
|
|
||||||
void add_handle(BlockHandle handle, td::Promise<td::Unit> promise);
|
void add_handle(BlockHandle handle, td::Promise<td::Unit> promise);
|
||||||
void update_handle(BlockHandle handle, td::Promise<td::Unit> promise);
|
void update_handle(BlockHandle handle, td::Promise<td::Unit> promise);
|
||||||
|
@ -58,7 +58,7 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
||||||
//void truncate_continue(BlockSeqno masterchain_seqno, td::Promise<td::Unit> promise);
|
//void truncate_continue(BlockSeqno masterchain_seqno, td::Promise<td::Unit> promise);
|
||||||
|
|
||||||
void run_gc(UnixTime ts, UnixTime archive_ttl);
|
void run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl);
|
||||||
|
|
||||||
/* from LTDB */
|
/* from LTDB */
|
||||||
void get_block_by_unix_time(AccountIdPrefixFull account_id, UnixTime ts, td::Promise<ConstBlockHandle> promise);
|
void get_block_by_unix_time(AccountIdPrefixFull account_id, UnixTime ts, td::Promise<ConstBlockHandle> promise);
|
||||||
|
@ -123,6 +123,9 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return files_.size();
|
return files_.size();
|
||||||
}
|
}
|
||||||
|
bool empty() const {
|
||||||
|
return files_.empty();
|
||||||
|
}
|
||||||
std::map<PackageId, FileDescription>::const_iterator lower_bound(const PackageId &x) const {
|
std::map<PackageId, FileDescription>::const_iterator lower_bound(const PackageId &x) const {
|
||||||
return files_.lower_bound(x);
|
return files_.lower_bound(x);
|
||||||
}
|
}
|
||||||
|
@ -164,6 +167,7 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
void shard_index_del(const FileDescription &desc);
|
void shard_index_del(const FileDescription &desc);
|
||||||
};
|
};
|
||||||
FileMap files_, key_files_, temp_files_;
|
FileMap files_, key_files_, temp_files_;
|
||||||
|
td::actor::ActorOwn<ArchiveLru> archive_lru_;
|
||||||
BlockSeqno finalized_up_to_{0};
|
BlockSeqno finalized_up_to_{0};
|
||||||
bool async_mode_ = false;
|
bool async_mode_ = false;
|
||||||
bool huge_transaction_started_ = false;
|
bool huge_transaction_started_ = false;
|
||||||
|
@ -206,6 +210,7 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
void got_gc_masterchain_handle(ConstBlockHandle handle, FileHash hash);
|
void got_gc_masterchain_handle(ConstBlockHandle handle, FileHash hash);
|
||||||
|
|
||||||
std::string db_root_;
|
std::string db_root_;
|
||||||
|
td::Ref<ValidatorManagerOptions> opts_;
|
||||||
|
|
||||||
std::shared_ptr<td::KeyValue> index_;
|
std::shared_ptr<td::KeyValue> index_;
|
||||||
|
|
||||||
|
@ -215,6 +220,10 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
PackageId get_temp_package_id() const;
|
PackageId get_temp_package_id() const;
|
||||||
PackageId get_key_package_id(BlockSeqno seqno) const;
|
PackageId get_key_package_id(BlockSeqno seqno) const;
|
||||||
PackageId get_temp_package_id_by_unixtime(UnixTime ts) const;
|
PackageId get_temp_package_id_by_unixtime(UnixTime ts) const;
|
||||||
|
|
||||||
|
void update_permanent_slices();
|
||||||
|
|
||||||
|
static const td::uint32 TEMP_PACKAGES_TTL = 86400 * 7;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "td/actor/MultiPromise.h"
|
#include "td/actor/MultiPromise.h"
|
||||||
#include "validator/fabric.h"
|
#include "validator/fabric.h"
|
||||||
#include "td/db/RocksDb.h"
|
#include "td/db/RocksDb.h"
|
||||||
#include "ton/ton-io.hpp"
|
|
||||||
#include "td/utils/port/path.h"
|
#include "td/utils/port/path.h"
|
||||||
#include "common/delay.h"
|
#include "common/delay.h"
|
||||||
#include "files-async.hpp"
|
#include "files-async.hpp"
|
||||||
|
@ -32,9 +31,16 @@ namespace validator {
|
||||||
|
|
||||||
void PackageWriter::append(std::string filename, td::BufferSlice data,
|
void PackageWriter::append(std::string filename, td::BufferSlice data,
|
||||||
td::Promise<std::pair<td::uint64, td::uint64>> promise) {
|
td::Promise<std::pair<td::uint64, td::uint64>> promise) {
|
||||||
auto offset = package_->append(std::move(filename), std::move(data), !async_mode_);
|
td::uint64 offset, size;
|
||||||
auto size = package_->size();
|
{
|
||||||
|
auto p = package_.lock();
|
||||||
|
if (!p) {
|
||||||
|
promise.set_error(td::Status::Error("Package is closed"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
offset = p->append(std::move(filename), std::move(data), !async_mode_);
|
||||||
|
size = p->size();
|
||||||
|
}
|
||||||
promise.set_value(std::pair<td::uint64, td::uint64>{offset, size});
|
promise.set_value(std::pair<td::uint64, td::uint64>{offset, size});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +50,10 @@ class PackageReader : public td::actor::Actor {
|
||||||
td::Promise<std::pair<std::string, td::BufferSlice>> promise)
|
td::Promise<std::pair<std::string, td::BufferSlice>> promise)
|
||||||
: package_(std::move(package)), offset_(offset), promise_(std::move(promise)) {
|
: package_(std::move(package)), offset_(offset), promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
void start_up() {
|
void start_up() override {
|
||||||
promise_.set_result(package_->read(offset_));
|
auto result = package_->read(offset_);
|
||||||
|
package_ = {};
|
||||||
|
promise_.set_result(std::move(result));
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +72,7 @@ void ArchiveSlice::add_handle(BlockHandle handle, td::Promise<td::Unit> promise)
|
||||||
update_handle(std::move(handle), std::move(promise));
|
update_handle(std::move(handle), std::move(promise));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
CHECK(!key_blocks_only_);
|
CHECK(!key_blocks_only_);
|
||||||
CHECK(!temp_);
|
CHECK(!temp_);
|
||||||
CHECK(handle->inited_unix_time());
|
CHECK(handle->inited_unix_time());
|
||||||
|
@ -146,6 +155,7 @@ void ArchiveSlice::update_handle(BlockHandle handle, td::Promise<td::Unit> promi
|
||||||
promise.set_value(td::Unit());
|
promise.set_value(td::Unit());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
CHECK(!key_blocks_only_);
|
CHECK(!key_blocks_only_);
|
||||||
|
|
||||||
begin_transaction();
|
begin_transaction();
|
||||||
|
@ -168,6 +178,7 @@ void ArchiveSlice::add_file(BlockHandle handle, FileReference ref_id, td::Buffer
|
||||||
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
TRY_RESULT_PROMISE(
|
TRY_RESULT_PROMISE(
|
||||||
promise, p,
|
promise, p,
|
||||||
choose_package(
|
choose_package(
|
||||||
|
@ -179,6 +190,7 @@ void ArchiveSlice::add_file(BlockHandle handle, FileReference ref_id, td::Buffer
|
||||||
promise.set_value(td::Unit());
|
promise.set_value(td::Unit());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
promise = begin_async_query(std::move(promise));
|
||||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), idx = p->idx, ref_id, promise = std::move(promise)](
|
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), idx = p->idx, ref_id, promise = std::move(promise)](
|
||||||
td::Result<std::pair<td::uint64, td::uint64>> R) mutable {
|
td::Result<std::pair<td::uint64, td::uint64>> R) mutable {
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
|
@ -217,6 +229,7 @@ void ArchiveSlice::get_handle(BlockIdExt block_id, td::Promise<BlockHandle> prom
|
||||||
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
CHECK(!key_blocks_only_);
|
CHECK(!key_blocks_only_);
|
||||||
std::string value;
|
std::string value;
|
||||||
auto R = kv_->get(get_db_key_block_info(block_id), value);
|
auto R = kv_->get(get_db_key_block_info(block_id), value);
|
||||||
|
@ -239,6 +252,7 @@ void ArchiveSlice::get_temp_handle(BlockIdExt block_id, td::Promise<ConstBlockHa
|
||||||
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
CHECK(!key_blocks_only_);
|
CHECK(!key_blocks_only_);
|
||||||
std::string value;
|
std::string value;
|
||||||
auto R = kv_->get(get_db_key_block_info(block_id), value);
|
auto R = kv_->get(get_db_key_block_info(block_id), value);
|
||||||
|
@ -261,6 +275,7 @@ void ArchiveSlice::get_file(ConstBlockHandle handle, FileReference ref_id, td::P
|
||||||
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
std::string value;
|
std::string value;
|
||||||
auto R = kv_->get(ref_id.hash().to_hex(), value);
|
auto R = kv_->get(ref_id.hash().to_hex(), value);
|
||||||
R.ensure();
|
R.ensure();
|
||||||
|
@ -273,6 +288,7 @@ void ArchiveSlice::get_file(ConstBlockHandle handle, FileReference ref_id, td::P
|
||||||
promise, p,
|
promise, p,
|
||||||
choose_package(
|
choose_package(
|
||||||
handle ? handle->id().is_masterchain() ? handle->id().seqno() : handle->masterchain_ref_block() : 0, false));
|
handle ? handle->id().is_masterchain() ? handle->id().seqno() : handle->masterchain_ref_block() : 0, false));
|
||||||
|
promise = begin_async_query(std::move(promise));
|
||||||
auto P = td::PromiseCreator::lambda(
|
auto P = td::PromiseCreator::lambda(
|
||||||
[promise = std::move(promise)](td::Result<std::pair<std::string, td::BufferSlice>> R) mutable {
|
[promise = std::move(promise)](td::Result<std::pair<std::string, td::BufferSlice>> R) mutable {
|
||||||
if (R.is_error()) {
|
if (R.is_error()) {
|
||||||
|
@ -292,6 +308,7 @@ void ArchiveSlice::get_block_common(AccountIdPrefixFull account_id,
|
||||||
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
promise.set_error(td::Status::Error(ErrorCode::notready, "package already gc'd"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
bool f = false;
|
bool f = false;
|
||||||
BlockIdExt block_id;
|
BlockIdExt block_id;
|
||||||
td::uint32 ls = 0;
|
td::uint32 ls = 0;
|
||||||
|
@ -312,7 +329,7 @@ void ArchiveSlice::get_block_common(AccountIdPrefixFull account_id,
|
||||||
auto G = fetch_tl_object<ton_api::db_lt_desc_value>(value, true);
|
auto G = fetch_tl_object<ton_api::db_lt_desc_value>(value, true);
|
||||||
G.ensure();
|
G.ensure();
|
||||||
auto g = G.move_as_ok();
|
auto g = G.move_as_ok();
|
||||||
if (compare_desc(*g.get()) > 0) {
|
if (compare_desc(*g) > 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
td::uint32 l = g->first_idx_ - 1;
|
td::uint32 l = g->first_idx_ - 1;
|
||||||
|
@ -328,7 +345,7 @@ void ArchiveSlice::get_block_common(AccountIdPrefixFull account_id,
|
||||||
auto E = fetch_tl_object<ton_api::db_lt_el_value>(td::BufferSlice{value}, true);
|
auto E = fetch_tl_object<ton_api::db_lt_el_value>(td::BufferSlice{value}, true);
|
||||||
E.ensure();
|
E.ensure();
|
||||||
auto e = E.move_as_ok();
|
auto e = E.move_as_ok();
|
||||||
int cmp_val = compare(*e.get());
|
int cmp_val = compare(*e);
|
||||||
|
|
||||||
if (cmp_val < 0) {
|
if (cmp_val < 0) {
|
||||||
rseq = create_block_id(e->id_);
|
rseq = create_block_id(e->id_);
|
||||||
|
@ -342,9 +359,7 @@ void ArchiveSlice::get_block_common(AccountIdPrefixFull account_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rseq.is_valid()) {
|
if (rseq.is_valid()) {
|
||||||
if (!block_id.is_valid()) {
|
if (!block_id.is_valid() || block_id.id.seqno > rseq.id.seqno) {
|
||||||
block_id = rseq;
|
|
||||||
} else if (block_id.id.seqno > rseq.id.seqno) {
|
|
||||||
block_id = rseq;
|
block_id = rseq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -430,12 +445,15 @@ void ArchiveSlice::get_slice(td::uint64 archive_id, td::uint64 offset, td::uint3
|
||||||
promise.set_error(td::Status::Error(ErrorCode::error, "bad archive id"));
|
promise.set_error(td::Status::Error(ErrorCode::error, "bad archive id"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
auto value = static_cast<td::uint32>(archive_id >> 32);
|
auto value = static_cast<td::uint32>(archive_id >> 32);
|
||||||
TRY_RESULT_PROMISE(promise, p, choose_package(value, false));
|
TRY_RESULT_PROMISE(promise, p, choose_package(value, false));
|
||||||
|
promise = begin_async_query(std::move(promise));
|
||||||
td::actor::create_actor<db::ReadFile>("readfile", p->path, offset, limit, 0, std::move(promise)).release();
|
td::actor::create_actor<db::ReadFile>("readfile", p->path, offset, limit, 0, std::move(promise)).release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchiveSlice::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise) {
|
void ArchiveSlice::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise) {
|
||||||
|
before_query();
|
||||||
if (!sliced_mode_) {
|
if (!sliced_mode_) {
|
||||||
promise.set_result(archive_id_);
|
promise.set_result(archive_id_);
|
||||||
} else {
|
} else {
|
||||||
|
@ -444,62 +462,107 @@ void ArchiveSlice::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchiveSlice::start_up() {
|
void ArchiveSlice::before_query() {
|
||||||
PackageId p_id{archive_id_, key_blocks_only_, temp_};
|
if (status_ == st_closed) {
|
||||||
std::string db_path = PSTRING() << db_root_ << p_id.path() << p_id.name() << ".index";
|
LOG(DEBUG) << "Opening archive slice " << db_path_;
|
||||||
kv_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_path).move_as_ok());
|
kv_ = std::make_unique<td::RocksDb>(td::RocksDb::open(db_path_).move_as_ok());
|
||||||
|
std::string value;
|
||||||
|
auto R2 = kv_->get("status", value);
|
||||||
|
R2.ensure();
|
||||||
|
sliced_mode_ = false;
|
||||||
|
slice_size_ = 100;
|
||||||
|
|
||||||
std::string value;
|
if (R2.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||||
auto R2 = kv_->get("status", value);
|
if (value == "sliced") {
|
||||||
R2.ensure();
|
sliced_mode_ = true;
|
||||||
|
R2 = kv_->get("slices", value);
|
||||||
if (R2.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
|
||||||
if (value == "sliced") {
|
|
||||||
sliced_mode_ = true;
|
|
||||||
R2 = kv_->get("slices", value);
|
|
||||||
R2.ensure();
|
|
||||||
auto tot = td::to_integer<td::uint32>(value);
|
|
||||||
R2 = kv_->get("slice_size", value);
|
|
||||||
R2.ensure();
|
|
||||||
slice_size_ = td::to_integer<td::uint32>(value);
|
|
||||||
CHECK(slice_size_ > 0);
|
|
||||||
for (td::uint32 i = 0; i < tot; i++) {
|
|
||||||
R2 = kv_->get(PSTRING() << "status." << i, value);
|
|
||||||
R2.ensure();
|
R2.ensure();
|
||||||
auto len = td::to_integer<td::uint64>(value);
|
auto tot = td::to_integer<td::uint32>(value);
|
||||||
R2 = kv_->get(PSTRING() << "version." << i, value);
|
R2 = kv_->get("slice_size", value);
|
||||||
R2.ensure();
|
R2.ensure();
|
||||||
td::uint32 ver = 0;
|
slice_size_ = td::to_integer<td::uint32>(value);
|
||||||
if (R2.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
CHECK(slice_size_ > 0);
|
||||||
ver = td::to_integer<td::uint32>(value);
|
for (td::uint32 i = 0; i < tot; i++) {
|
||||||
|
R2 = kv_->get(PSTRING() << "status." << i, value);
|
||||||
|
R2.ensure();
|
||||||
|
auto len = td::to_integer<td::uint64>(value);
|
||||||
|
R2 = kv_->get(PSTRING() << "version." << i, value);
|
||||||
|
R2.ensure();
|
||||||
|
td::uint32 ver = 0;
|
||||||
|
if (R2.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||||
|
ver = td::to_integer<td::uint32>(value);
|
||||||
|
}
|
||||||
|
auto v = archive_id_ + slice_size_ * i;
|
||||||
|
add_package(v, len, ver);
|
||||||
}
|
}
|
||||||
auto v = archive_id_ + slice_size_ * i;
|
} else {
|
||||||
add_package(v, len, ver);
|
auto len = td::to_integer<td::uint64>(value);
|
||||||
|
add_package(archive_id_, len, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto len = td::to_integer<td::uint64>(value);
|
if (!temp_ && !key_blocks_only_) {
|
||||||
add_package(archive_id_, len, 0);
|
sliced_mode_ = true;
|
||||||
|
kv_->begin_transaction().ensure();
|
||||||
|
kv_->set("status", "sliced").ensure();
|
||||||
|
kv_->set("slices", "1").ensure();
|
||||||
|
kv_->set("slice_size", td::to_string(slice_size_)).ensure();
|
||||||
|
kv_->set("status.0", "0").ensure();
|
||||||
|
kv_->set("version.0", td::to_string(default_package_version())).ensure();
|
||||||
|
kv_->commit_transaction().ensure();
|
||||||
|
add_package(archive_id_, 0, default_package_version());
|
||||||
|
} else {
|
||||||
|
kv_->begin_transaction().ensure();
|
||||||
|
kv_->set("status", "0").ensure();
|
||||||
|
kv_->commit_transaction().ensure();
|
||||||
|
add_package(archive_id_, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (!temp_ && !key_blocks_only_) {
|
status_ = st_open;
|
||||||
sliced_mode_ = true;
|
if (!archive_lru_.empty()) {
|
||||||
kv_->begin_transaction().ensure();
|
td::actor::send_closure(archive_lru_, &ArchiveLru::on_query, actor_id(this), p_id_,
|
||||||
kv_->set("status", "sliced").ensure();
|
packages_.size() + ESTIMATED_DB_OPEN_FILES);
|
||||||
kv_->set("slices", "1").ensure();
|
}
|
||||||
kv_->set("slice_size", td::to_string(slice_size_)).ensure();
|
}
|
||||||
kv_->set("status.0", "0").ensure();
|
|
||||||
kv_->set("version.0", td::to_string(default_package_version())).ensure();
|
void ArchiveSlice::close_files() {
|
||||||
kv_->commit_transaction().ensure();
|
if (status_ == st_open) {
|
||||||
add_package(archive_id_, 0, default_package_version());
|
if (active_queries_ == 0) {
|
||||||
|
do_close();
|
||||||
} else {
|
} else {
|
||||||
kv_->begin_transaction().ensure();
|
status_ = st_want_close;
|
||||||
kv_->set("status", "0").ensure();
|
|
||||||
kv_->commit_transaction().ensure();
|
|
||||||
add_package(archive_id_, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArchiveSlice::do_close() {
|
||||||
|
if (destroyed_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CHECK(status_ != st_closed && active_queries_ == 0);
|
||||||
|
LOG(DEBUG) << "Closing archive slice " << db_path_;
|
||||||
|
status_ = st_closed;
|
||||||
|
kv_ = {};
|
||||||
|
packages_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
td::Promise<T> ArchiveSlice::begin_async_query(td::Promise<T> promise) {
|
||||||
|
++active_queries_;
|
||||||
|
return [SelfId = actor_id(this), promise = std::move(promise)](td::Result<T> R) mutable {
|
||||||
|
td::actor::send_closure(SelfId, &ArchiveSlice::end_async_query);
|
||||||
|
promise.set_result(std::move(R));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveSlice::end_async_query() {
|
||||||
|
CHECK(active_queries_ > 0);
|
||||||
|
--active_queries_;
|
||||||
|
if (active_queries_ == 0 && status_ == st_want_close) {
|
||||||
|
do_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ArchiveSlice::begin_transaction() {
|
void ArchiveSlice::begin_transaction() {
|
||||||
if (!async_mode_ || !huge_transaction_started_) {
|
if (!async_mode_ || !huge_transaction_started_) {
|
||||||
kv_->begin_transaction().ensure();
|
kv_->begin_transaction().ensure();
|
||||||
|
@ -521,7 +584,7 @@ void ArchiveSlice::commit_transaction() {
|
||||||
|
|
||||||
void ArchiveSlice::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
void ArchiveSlice::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
||||||
async_mode_ = mode;
|
async_mode_ = mode;
|
||||||
if (!async_mode_ && huge_transaction_started_) {
|
if (!async_mode_ && huge_transaction_started_ && kv_) {
|
||||||
kv_->commit_transaction().ensure();
|
kv_->commit_transaction().ensure();
|
||||||
huge_transaction_size_ = 0;
|
huge_transaction_size_ = 0;
|
||||||
huge_transaction_started_ = false;
|
huge_transaction_started_ = false;
|
||||||
|
@ -536,12 +599,16 @@ void ArchiveSlice::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiveSlice::ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root)
|
ArchiveSlice::ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root,
|
||||||
|
td::actor::ActorId<ArchiveLru> archive_lru)
|
||||||
: archive_id_(archive_id)
|
: archive_id_(archive_id)
|
||||||
, key_blocks_only_(key_blocks_only)
|
, key_blocks_only_(key_blocks_only)
|
||||||
, temp_(temp)
|
, temp_(temp)
|
||||||
, finalized_(finalized)
|
, finalized_(finalized)
|
||||||
, db_root_(std::move(db_root)) {
|
, p_id_(archive_id_, key_blocks_only_, temp_)
|
||||||
|
, db_root_(std::move(db_root))
|
||||||
|
, archive_lru_(std::move(archive_lru)) {
|
||||||
|
db_path_ = PSTRING() << db_root_ << p_id_.path() << p_id_.name() << ".index";
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Result<ArchiveSlice::PackageInfo *> ArchiveSlice::choose_package(BlockSeqno masterchain_seqno, bool force) {
|
td::Result<ArchiveSlice::PackageInfo *> ArchiveSlice::choose_package(BlockSeqno masterchain_seqno, bool force) {
|
||||||
|
@ -587,7 +654,7 @@ void ArchiveSlice::add_package(td::uint32 seqno, td::uint64 size, td::uint32 ver
|
||||||
if (version >= 1) {
|
if (version >= 1) {
|
||||||
pack->truncate(size).ensure();
|
pack->truncate(size).ensure();
|
||||||
}
|
}
|
||||||
auto writer = td::actor::create_actor<PackageWriter>("writer", pack);
|
auto writer = td::actor::create_actor<PackageWriter>("writer", pack, async_mode_);
|
||||||
packages_.emplace_back(std::move(pack), std::move(writer), seqno, path, idx, version);
|
packages_.emplace_back(std::move(pack), std::move(writer), seqno, path, idx, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,6 +678,7 @@ void destroy_db(std::string name, td::uint32 attempt, td::Promise<td::Unit> prom
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ArchiveSlice::destroy(td::Promise<td::Unit> promise) {
|
void ArchiveSlice::destroy(td::Promise<td::Unit> promise) {
|
||||||
|
before_query();
|
||||||
td::MultiPromise mp;
|
td::MultiPromise mp;
|
||||||
auto ig = mp.init_guard();
|
auto ig = mp.init_guard();
|
||||||
ig.add_promise(std::move(promise));
|
ig.add_promise(std::move(promise));
|
||||||
|
@ -763,6 +831,7 @@ void ArchiveSlice::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handl
|
||||||
destroy(std::move(promise));
|
destroy(std::move(promise));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
before_query();
|
||||||
LOG(INFO) << "TRUNCATE: slice " << archive_id_ << " maxseqno= " << max_masterchain_seqno()
|
LOG(INFO) << "TRUNCATE: slice " << archive_id_ << " maxseqno= " << max_masterchain_seqno()
|
||||||
<< " truncate_upto=" << masterchain_seqno;
|
<< " truncate_upto=" << masterchain_seqno;
|
||||||
if (max_masterchain_seqno() <= masterchain_seqno) {
|
if (max_masterchain_seqno() <= masterchain_seqno) {
|
||||||
|
@ -819,7 +888,7 @@ void ArchiveSlice::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handl
|
||||||
pack->writer.reset();
|
pack->writer.reset();
|
||||||
td::unlink(pack->path).ensure();
|
td::unlink(pack->path).ensure();
|
||||||
td::rename(pack->path + ".new", pack->path).ensure();
|
td::rename(pack->path + ".new", pack->path).ensure();
|
||||||
pack->writer = td::actor::create_actor<PackageWriter>("writer", new_package);
|
pack->writer = td::actor::create_actor<PackageWriter>("writer", new_package, async_mode_);
|
||||||
|
|
||||||
for (auto idx = pack->idx + 1; idx < packages_.size(); idx++) {
|
for (auto idx = pack->idx + 1; idx < packages_.size(); idx++) {
|
||||||
td::unlink(packages_[idx].path).ensure();
|
td::unlink(packages_[idx].path).ensure();
|
||||||
|
@ -831,6 +900,61 @@ void ArchiveSlice::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handl
|
||||||
promise.set_value(td::Unit());
|
promise.set_value(td::Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::tuple<td::uint32, bool, bool> to_tuple(const PackageId &id) {
|
||||||
|
return {id.id, id.temp, id.key};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveLru::on_query(td::actor::ActorId<ArchiveSlice> slice, PackageId id, size_t files_count) {
|
||||||
|
SliceInfo &info = slices_[to_tuple(id)];
|
||||||
|
if (info.opened_idx != 0) {
|
||||||
|
total_files_ -= info.files_count;
|
||||||
|
lru_.erase(info.opened_idx);
|
||||||
|
}
|
||||||
|
info.actor = std::move(slice);
|
||||||
|
total_files_ += (info.files_count = files_count);
|
||||||
|
info.opened_idx = current_idx_++;
|
||||||
|
if (!info.is_permanent) {
|
||||||
|
lru_.emplace(info.opened_idx, id);
|
||||||
|
}
|
||||||
|
enforce_limit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveLru::set_permanent_slices(std::vector<PackageId> ids) {
|
||||||
|
for (auto id : permanent_slices_) {
|
||||||
|
SliceInfo &info = slices_[to_tuple(id)];
|
||||||
|
if (!info.is_permanent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
info.is_permanent = false;
|
||||||
|
if (info.opened_idx) {
|
||||||
|
lru_.emplace(info.opened_idx, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permanent_slices_ = std::move(ids);
|
||||||
|
for (auto id : permanent_slices_) {
|
||||||
|
SliceInfo &info = slices_[to_tuple(id)];
|
||||||
|
if (info.is_permanent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
info.is_permanent = true;
|
||||||
|
if (info.opened_idx) {
|
||||||
|
lru_.erase(info.opened_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enforce_limit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveLru::enforce_limit() {
|
||||||
|
while (total_files_ > max_total_files_ && lru_.size() > 1) {
|
||||||
|
auto it = lru_.begin();
|
||||||
|
auto it2 = slices_.find(to_tuple(it->second));
|
||||||
|
lru_.erase(it);
|
||||||
|
total_files_ -= it2->second.files_count;
|
||||||
|
td::actor::send_closure(it2->second.actor, &ArchiveSlice::close_files);
|
||||||
|
it2->second.opened_idx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
||||||
} // namespace ton
|
} // namespace ton
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "validator/interfaces/db.h"
|
#include "validator/interfaces/db.h"
|
||||||
#include "package.hpp"
|
#include "package.hpp"
|
||||||
#include "fileref.hpp"
|
#include "fileref.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ struct PackageId {
|
||||||
std::string path() const;
|
std::string path() const;
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
|
|
||||||
bool is_empty() {
|
bool is_empty() const {
|
||||||
return id == std::numeric_limits<td::uint32>::max();
|
return id == std::numeric_limits<td::uint32>::max();
|
||||||
}
|
}
|
||||||
static PackageId empty(bool key, bool temp) {
|
static PackageId empty(bool key, bool temp) {
|
||||||
|
@ -54,26 +55,33 @@ struct PackageId {
|
||||||
|
|
||||||
class PackageWriter : public td::actor::Actor {
|
class PackageWriter : public td::actor::Actor {
|
||||||
public:
|
public:
|
||||||
PackageWriter(std::shared_ptr<Package> package) : package_(std::move(package)) {
|
PackageWriter(std::weak_ptr<Package> package, bool async_mode = false)
|
||||||
|
: package_(std::move(package)), async_mode_(async_mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(std::string filename, td::BufferSlice data, td::Promise<std::pair<td::uint64, td::uint64>> promise);
|
void append(std::string filename, td::BufferSlice data, td::Promise<std::pair<td::uint64, td::uint64>> promise);
|
||||||
void set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
void set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
||||||
async_mode_ = mode;
|
async_mode_ = mode;
|
||||||
if (!async_mode_) {
|
if (!async_mode_) {
|
||||||
package_->sync();
|
auto p = package_.lock();
|
||||||
|
if (p) {
|
||||||
|
p->sync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
promise.set_value(td::Unit());
|
promise.set_value(td::Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Package> package_;
|
std::weak_ptr<Package> package_;
|
||||||
bool async_mode_ = false;
|
bool async_mode_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ArchiveLru;
|
||||||
|
|
||||||
class ArchiveSlice : public td::actor::Actor {
|
class ArchiveSlice : public td::actor::Actor {
|
||||||
public:
|
public:
|
||||||
ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root);
|
ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root,
|
||||||
|
td::actor::ActorId<ArchiveLru> archive_lru);
|
||||||
|
|
||||||
void get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise);
|
void get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise);
|
||||||
|
|
||||||
|
@ -95,16 +103,23 @@ class ArchiveSlice : public td::actor::Actor {
|
||||||
|
|
||||||
void get_slice(td::uint64 archive_id, td::uint64 offset, td::uint32 limit, td::Promise<td::BufferSlice> promise);
|
void get_slice(td::uint64 archive_id, td::uint64 offset, td::uint32 limit, td::Promise<td::BufferSlice> promise);
|
||||||
|
|
||||||
void start_up() override;
|
|
||||||
void destroy(td::Promise<td::Unit> promise);
|
void destroy(td::Promise<td::Unit> promise);
|
||||||
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
void truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handle, td::Promise<td::Unit> promise);
|
||||||
|
|
||||||
void begin_transaction();
|
|
||||||
void commit_transaction();
|
|
||||||
void set_async_mode(bool mode, td::Promise<td::Unit> promise);
|
void set_async_mode(bool mode, td::Promise<td::Unit> promise);
|
||||||
|
|
||||||
|
void close_files();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void written_data(BlockHandle handle, td::Promise<td::Unit> promise);
|
void before_query();
|
||||||
|
void do_close();
|
||||||
|
template<typename T>
|
||||||
|
td::Promise<T> begin_async_query(td::Promise<T> promise);
|
||||||
|
void end_async_query();
|
||||||
|
|
||||||
|
void begin_transaction();
|
||||||
|
void commit_transaction();
|
||||||
|
|
||||||
void add_file_cont(size_t idx, FileReference ref_id, td::uint64 offset, td::uint64 size,
|
void add_file_cont(size_t idx, FileReference ref_id, td::uint64 offset, td::uint64 size,
|
||||||
td::Promise<td::Unit> promise);
|
td::Promise<td::Unit> promise);
|
||||||
|
|
||||||
|
@ -112,13 +127,14 @@ class ArchiveSlice : public td::actor::Actor {
|
||||||
td::BufferSlice get_db_key_lt_desc(ShardIdFull shard);
|
td::BufferSlice get_db_key_lt_desc(ShardIdFull shard);
|
||||||
td::BufferSlice get_db_key_lt_el(ShardIdFull shard, td::uint32 idx);
|
td::BufferSlice get_db_key_lt_el(ShardIdFull shard, td::uint32 idx);
|
||||||
td::BufferSlice get_db_key_block_info(BlockIdExt block_id);
|
td::BufferSlice get_db_key_block_info(BlockIdExt block_id);
|
||||||
td::BufferSlice get_lt_from_db(ShardIdFull shard, td::uint32 idx);
|
|
||||||
|
|
||||||
td::uint32 archive_id_;
|
td::uint32 archive_id_;
|
||||||
|
|
||||||
bool key_blocks_only_;
|
bool key_blocks_only_;
|
||||||
bool temp_;
|
bool temp_;
|
||||||
bool finalized_;
|
bool finalized_;
|
||||||
|
PackageId p_id_;
|
||||||
|
std::string db_path_;
|
||||||
|
|
||||||
bool destroyed_ = false;
|
bool destroyed_ = false;
|
||||||
bool async_mode_ = false;
|
bool async_mode_ = false;
|
||||||
|
@ -127,8 +143,14 @@ class ArchiveSlice : public td::actor::Actor {
|
||||||
td::uint32 huge_transaction_size_ = 0;
|
td::uint32 huge_transaction_size_ = 0;
|
||||||
td::uint32 slice_size_{100};
|
td::uint32 slice_size_{100};
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
st_closed, st_open, st_want_close
|
||||||
|
} status_ = st_closed;
|
||||||
|
size_t active_queries_ = 0;
|
||||||
|
|
||||||
std::string db_root_;
|
std::string db_root_;
|
||||||
std::shared_ptr<td::KeyValue> kv_;
|
td::actor::ActorId<ArchiveLru> archive_lru_;
|
||||||
|
std::unique_ptr<td::KeyValue> kv_;
|
||||||
|
|
||||||
struct PackageInfo {
|
struct PackageInfo {
|
||||||
PackageInfo(std::shared_ptr<Package> package, td::actor::ActorOwn<PackageWriter> writer, BlockSeqno id,
|
PackageInfo(std::shared_ptr<Package> package, td::actor::ActorOwn<PackageWriter> writer, BlockSeqno id,
|
||||||
|
@ -164,6 +186,32 @@ class ArchiveSlice : public td::actor::Actor {
|
||||||
static constexpr td::uint32 default_package_version() {
|
static constexpr td::uint32 default_package_version() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const size_t ESTIMATED_DB_OPEN_FILES = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArchiveLru : public td::actor::Actor {
|
||||||
|
public:
|
||||||
|
explicit ArchiveLru(size_t max_total_files) : max_total_files_(max_total_files) {
|
||||||
|
CHECK(max_total_files_ > 0);
|
||||||
|
}
|
||||||
|
void on_query(td::actor::ActorId<ArchiveSlice> slice, PackageId id, size_t files_count);
|
||||||
|
void set_permanent_slices(std::vector<PackageId> ids);
|
||||||
|
private:
|
||||||
|
size_t current_idx_ = 1;
|
||||||
|
struct SliceInfo {
|
||||||
|
td::actor::ActorId<ArchiveSlice> actor;
|
||||||
|
size_t files_count = 0;
|
||||||
|
size_t opened_idx = 0; // 0 - not opened
|
||||||
|
bool is_permanent = false;
|
||||||
|
};
|
||||||
|
std::map<std::tuple<td::uint32, bool, bool>, SliceInfo> slices_;
|
||||||
|
std::map<size_t, PackageId> lru_;
|
||||||
|
size_t total_files_ = 0;
|
||||||
|
size_t max_total_files_ = 0;
|
||||||
|
std::vector<PackageId> permanent_slices_;
|
||||||
|
|
||||||
|
void enforce_limit();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -400,7 +400,7 @@ void RootDb::start_up() {
|
||||||
cell_db_ = td::actor::create_actor<CellDb>("celldb", actor_id(this), root_path_ + "/celldb/", opts_);
|
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_, opts_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootDb::archive(BlockHandle handle, td::Promise<td::Unit> promise) {
|
void RootDb::archive(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||||
|
@ -497,8 +497,8 @@ void RootDb::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
||||||
td::actor::send_closure(archive_db_, &ArchiveManager::set_async_mode, mode, std::move(promise));
|
td::actor::send_closure(archive_db_, &ArchiveManager::set_async_mode, mode, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootDb::run_gc(UnixTime ts, UnixTime archive_ttl) {
|
void RootDb::run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl) {
|
||||||
td::actor::send_closure(archive_db_, &ArchiveManager::run_gc, ts, archive_ttl);
|
td::actor::send_closure(archive_db_, &ArchiveManager::run_gc, mc_ts, gc_ts, archive_ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -134,11 +134,10 @@ class RootDb : public Db {
|
||||||
td::Promise<td::BufferSlice> promise) override;
|
td::Promise<td::BufferSlice> promise) override;
|
||||||
void set_async_mode(bool mode, td::Promise<td::Unit> promise) override;
|
void set_async_mode(bool mode, td::Promise<td::Unit> promise) override;
|
||||||
|
|
||||||
void run_gc(UnixTime ts, UnixTime archive_ttl) override;
|
void run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
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::Ref<ValidatorManagerOptions> opts_;
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ class Db : public td::actor::Actor {
|
||||||
td::Promise<td::BufferSlice> promise) = 0;
|
td::Promise<td::BufferSlice> promise) = 0;
|
||||||
virtual void set_async_mode(bool mode, td::Promise<td::Unit> promise) = 0;
|
virtual void set_async_mode(bool mode, td::Promise<td::Unit> promise) = 0;
|
||||||
|
|
||||||
virtual void run_gc(UnixTime ts, UnixTime archive_ttl) = 0;
|
virtual void run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -2385,9 +2385,9 @@ void ValidatorManagerImpl::state_serializer_update(BlockSeqno seqno) {
|
||||||
void ValidatorManagerImpl::alarm() {
|
void ValidatorManagerImpl::alarm() {
|
||||||
try_advance_gc_masterchain_block();
|
try_advance_gc_masterchain_block();
|
||||||
alarm_timestamp() = td::Timestamp::in(1.0);
|
alarm_timestamp() = td::Timestamp::in(1.0);
|
||||||
if (gc_masterchain_handle_) {
|
if (last_masterchain_block_handle_ && gc_masterchain_handle_) {
|
||||||
td::actor::send_closure(db_, &Db::run_gc, gc_masterchain_handle_->unix_time(),
|
td::actor::send_closure(db_, &Db::run_gc, last_masterchain_block_handle_->unix_time(),
|
||||||
static_cast<UnixTime>(opts_->archive_ttl()));
|
gc_masterchain_handle_->unix_time(), static_cast<UnixTime>(opts_->archive_ttl()));
|
||||||
}
|
}
|
||||||
if (log_status_at_.is_in_past()) {
|
if (log_status_at_.is_in_past()) {
|
||||||
if (last_masterchain_block_handle_) {
|
if (last_masterchain_block_handle_) {
|
||||||
|
|
|
@ -117,6 +117,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
td::uint32 get_celldb_compress_depth() const override {
|
td::uint32 get_celldb_compress_depth() const override {
|
||||||
return celldb_compress_depth_;
|
return celldb_compress_depth_;
|
||||||
}
|
}
|
||||||
|
size_t get_max_open_archive_files() const override {
|
||||||
|
return max_open_archive_files_;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -173,6 +176,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
void set_celldb_compress_depth(td::uint32 value) override {
|
void set_celldb_compress_depth(td::uint32 value) override {
|
||||||
celldb_compress_depth_ = value;
|
celldb_compress_depth_ = value;
|
||||||
}
|
}
|
||||||
|
void set_max_open_archive_files(size_t value) override {
|
||||||
|
max_open_archive_files_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
ValidatorManagerOptionsImpl *make_copy() const override {
|
ValidatorManagerOptionsImpl *make_copy() const override {
|
||||||
return new ValidatorManagerOptionsImpl(*this);
|
return new ValidatorManagerOptionsImpl(*this);
|
||||||
|
@ -216,6 +222,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
BlockSeqno sync_upto_{0};
|
BlockSeqno sync_upto_{0};
|
||||||
std::string session_logs_file_;
|
std::string session_logs_file_;
|
||||||
td::uint32 celldb_compress_depth_{0};
|
td::uint32 celldb_compress_depth_{0};
|
||||||
|
size_t max_open_archive_files_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -82,6 +82,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
||||||
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 td::uint32 get_celldb_compress_depth() const = 0;
|
||||||
|
virtual size_t get_max_open_archive_files() 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;
|
||||||
|
@ -102,6 +103,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
||||||
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;
|
virtual void set_celldb_compress_depth(td::uint32 value) = 0;
|
||||||
|
virtual void set_max_open_archive_files(size_t 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…
Add table
Add a link
Reference in a new issue