mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
updated smartcontracts
- updated smartcontracts - updated fullnode database layout - fixed memory leak in blockchain-explorer - updated tonlib
This commit is contained in:
parent
9c9248a9ae
commit
c860ce3d1e
104 changed files with 7309 additions and 1335 deletions
|
@ -10,6 +10,8 @@ add_subdirectory(impl)
|
|||
set(VALIDATOR_DB_SOURCE
|
||||
db/archiver.cpp
|
||||
db/archiver.hpp
|
||||
db/archive-db.cpp
|
||||
db/archive-db.hpp
|
||||
db/blockdb.cpp
|
||||
db/blockdb.hpp
|
||||
db/celldb.cpp
|
||||
|
@ -25,6 +27,9 @@ set(VALIDATOR_DB_SOURCE
|
|||
db/statedb.cpp
|
||||
db/staticfilesdb.cpp
|
||||
db/staticfilesdb.hpp
|
||||
|
||||
db/package.hpp
|
||||
db/package.cpp
|
||||
)
|
||||
|
||||
set(VALIDATOR_HEADERS
|
||||
|
|
|
@ -59,6 +59,7 @@ struct BlockHandleImpl : public BlockHandleInterface {
|
|||
dbf_moved = 0x1000000,
|
||||
dbf_deleted = 0x2000000,
|
||||
dbf_deleted_boc = 0x4000000,
|
||||
dbf_moved_new = 0x8000000,
|
||||
dbf_processed = 0x10000000,
|
||||
};
|
||||
|
||||
|
@ -95,6 +96,9 @@ struct BlockHandleImpl : public BlockHandleInterface {
|
|||
bool moved_to_storage() const override {
|
||||
return flags_.load(std::memory_order_consume) & Flags::dbf_moved;
|
||||
}
|
||||
bool moved_to_archive() const override {
|
||||
return flags_.load(std::memory_order_consume) & Flags::dbf_moved_new;
|
||||
}
|
||||
bool deleted() const override {
|
||||
return flags_.load(std::memory_order_consume) & Flags::dbf_deleted;
|
||||
}
|
||||
|
@ -393,6 +397,15 @@ struct BlockHandleImpl : public BlockHandleInterface {
|
|||
flags_ |= Flags::dbf_moved;
|
||||
unlock();
|
||||
}
|
||||
void set_moved_to_archive() override {
|
||||
if (flags_.load(std::memory_order_consume) & Flags::dbf_moved_new) {
|
||||
return;
|
||||
}
|
||||
lock();
|
||||
flags_ |= Flags::dbf_moved_new;
|
||||
flags_ &= ~Flags::dbf_moved;
|
||||
unlock();
|
||||
}
|
||||
void set_deleted() override {
|
||||
if (flags_.load(std::memory_order_consume) & Flags::dbf_deleted) {
|
||||
return;
|
||||
|
|
332
validator/db/archive-db.cpp
Normal file
332
validator/db/archive-db.cpp
Normal file
|
@ -0,0 +1,332 @@
|
|||
#include "archive-db.hpp"
|
||||
#include "common/errorcode.h"
|
||||
|
||||
#include "common/int-to-string.hpp"
|
||||
#include "files-async.hpp"
|
||||
|
||||
#include "td/db/RocksDb.h"
|
||||
#include "validator/fabric.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace validator {
|
||||
|
||||
void PackageWriter::append(std::string filename, td::BufferSlice data,
|
||||
td::Promise<std::pair<td::uint64, td::uint64>> promise) {
|
||||
auto offset = package_->append(std::move(filename), std::move(data));
|
||||
auto size = package_->size();
|
||||
|
||||
promise.set_value(std::pair<td::uint64, td::uint64>{offset, size});
|
||||
}
|
||||
|
||||
class PackageReader : public td::actor::Actor {
|
||||
public:
|
||||
PackageReader(std::shared_ptr<Package> package, td::uint64 offset,
|
||||
td::Promise<std::pair<std::string, td::BufferSlice>> promise)
|
||||
: package_(std::move(package)), offset_(offset), promise_(std::move(promise)) {
|
||||
}
|
||||
void start_up() {
|
||||
promise_.set_result(package_->read(offset_));
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Package> package_;
|
||||
td::uint64 offset_;
|
||||
td::Promise<std::pair<std::string, td::BufferSlice>> promise_;
|
||||
};
|
||||
|
||||
void ArchiveFile::start_up() {
|
||||
auto R = Package::open(path_, false, true);
|
||||
if (R.is_error()) {
|
||||
LOG(FATAL) << "failed to open/create archive '" << path_ << "': " << R.move_as_error();
|
||||
return;
|
||||
}
|
||||
package_ = std::make_shared<Package>(R.move_as_ok());
|
||||
index_ = std::make_shared<td::RocksDb>(td::RocksDb::open(path_ + ".index").move_as_ok());
|
||||
|
||||
std::string value;
|
||||
auto R2 = index_->get("status", value);
|
||||
R2.ensure();
|
||||
|
||||
if (R2.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto len = td::to_integer<td::uint64>(value);
|
||||
package_->truncate(len);
|
||||
} else {
|
||||
package_->truncate(0);
|
||||
}
|
||||
|
||||
writer_ = td::actor::create_actor<PackageWriter>("writer", package_);
|
||||
}
|
||||
|
||||
void ArchiveFile::write(FileDb::RefId ref_id, td::BufferSlice data, td::Promise<td::Unit> promise) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), ref_id, promise = std::move(promise)](
|
||||
td::Result<std::pair<td::uint64, td::uint64>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
return;
|
||||
}
|
||||
auto v = R.move_as_ok();
|
||||
td::actor::send_closure(SelfId, &ArchiveFile::completed_write, std::move(ref_id), v.first, v.second,
|
||||
std::move(promise));
|
||||
});
|
||||
|
||||
FileHash hash;
|
||||
ref_id.visit([&](const auto &obj) { hash = obj.hash(); });
|
||||
|
||||
td::actor::send_closure(writer_, &PackageWriter::append, hash.to_hex(), std::move(data), std::move(P));
|
||||
}
|
||||
|
||||
void ArchiveFile::write_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
FileHash hash = fileref::BlockInfo{handle->id()}.hash();
|
||||
index_->begin_transaction().ensure();
|
||||
do {
|
||||
auto version = handle->version();
|
||||
index_->set(hash.to_hex(), handle->serialize().as_slice().str()).ensure();
|
||||
handle->flushed_upto(version);
|
||||
} while (handle->need_flush());
|
||||
index_->commit_transaction().ensure();
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
void ArchiveFile::completed_write(FileDb::RefId ref_id, td::uint64 offset, td::uint64 new_size,
|
||||
td::Promise<td::Unit> promise) {
|
||||
FileHash hash;
|
||||
ref_id.visit([&](const auto &obj) { hash = obj.hash(); });
|
||||
index_->begin_transaction().ensure();
|
||||
index_->set("status", td::to_string(new_size)).ensure();
|
||||
index_->set(hash.to_hex(), td::to_string(offset)).ensure();
|
||||
index_->commit_transaction().ensure();
|
||||
promise.set_value(td::Unit());
|
||||
}
|
||||
|
||||
void ArchiveFile::read(FileDb::RefId ref_id, td::Promise<td::BufferSlice> promise) {
|
||||
FileHash hash;
|
||||
ref_id.visit([&](const auto &obj) { hash = obj.hash(); });
|
||||
std::string value;
|
||||
auto R = index_->get(hash.to_hex(), value);
|
||||
R.ensure();
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not in db (archive)"));
|
||||
return;
|
||||
}
|
||||
auto offset = td::to_integer<td::uint64>(value);
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[promise = std::move(promise)](td::Result<std::pair<std::string, td::BufferSlice>> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_error(R.move_as_error());
|
||||
} else {
|
||||
promise.set_value(std::move(R.move_as_ok().second));
|
||||
}
|
||||
});
|
||||
td::actor::create_actor<PackageReader>("reader", package_, offset, std::move(P)).release();
|
||||
}
|
||||
|
||||
void ArchiveFile::read_handle(BlockIdExt block_id, td::Promise<BlockHandle> promise) {
|
||||
FileHash hash = fileref::BlockInfo{block_id}.hash();
|
||||
|
||||
std::string value;
|
||||
auto R = index_->get(hash.to_hex(), value);
|
||||
R.ensure();
|
||||
|
||||
if (R.move_as_ok() == td::KeyValue::GetStatus::NotFound) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not in archive db"));
|
||||
return;
|
||||
}
|
||||
promise.set_result(create_block_handle(td::BufferSlice{value}));
|
||||
}
|
||||
|
||||
ArchiveManager::ArchiveManager(std::string db_root) : db_root_(db_root) {
|
||||
}
|
||||
|
||||
void ArchiveManager::write(UnixTime ts, bool key_block, FileDb::RefId ref_id, td::BufferSlice data,
|
||||
td::Promise<td::Unit> promise) {
|
||||
auto f = get_file(ts, key_block);
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveFile::write, std::move(ref_id), std::move(data),
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void ArchiveManager::write_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
auto f = get_file(handle->unix_time(), handle->is_key_block());
|
||||
update_desc(*f, handle->id().shard_full(), handle->id().seqno(), handle->logical_time());
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveFile::write_handle, std::move(handle), std::move(promise));
|
||||
}
|
||||
|
||||
void ArchiveManager::read(UnixTime ts, bool key_block, FileDb::RefId ref_id, td::Promise<td::BufferSlice> promise) {
|
||||
auto f = get_file(ts, key_block);
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveFile::read, std::move(ref_id), std::move(promise));
|
||||
}
|
||||
|
||||
void ArchiveManager::read_handle(BlockIdExt block_id, td::Promise<BlockHandle> promise) {
|
||||
if (block_id.is_masterchain()) {
|
||||
auto f = get_file_by_seqno(block_id.shard_full(), block_id.seqno(), true);
|
||||
if (!f) {
|
||||
read_handle_cont(block_id, std::move(promise));
|
||||
return;
|
||||
}
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[SelfId = actor_id(this), block_id, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(SelfId, &ArchiveManager::read_handle_cont, block_id, std::move(promise));
|
||||
} else {
|
||||
promise.set_value(R.move_as_ok());
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveFile::read_handle, block_id, std::move(P));
|
||||
} else {
|
||||
read_handle_cont(block_id, std::move(promise));
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveManager::read_handle_cont(BlockIdExt block_id, td::Promise<BlockHandle> promise) {
|
||||
auto f = get_file_by_seqno(block_id.shard_full(), block_id.seqno(), false);
|
||||
if (!f) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not in archive db"));
|
||||
return;
|
||||
}
|
||||
td::actor::send_closure(f->file_actor_id(), &ArchiveFile::read_handle, block_id, std::move(promise));
|
||||
}
|
||||
|
||||
UnixTime ArchiveManager::convert_ts(UnixTime ts, bool key_block) {
|
||||
if (!key_block) {
|
||||
return ts - (ts % (1 << 17));
|
||||
} else {
|
||||
return ts - (ts % (1 << 22));
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveManager::FileDescription *ArchiveManager::get_file(UnixTime ts, bool key_block, bool force) {
|
||||
ts = convert_ts(ts, key_block);
|
||||
auto &f = key_block ? key_files_ : files_;
|
||||
auto it = f.find(ts);
|
||||
if (it != f.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
if (!force) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return add_file(ts, key_block);
|
||||
}
|
||||
|
||||
ArchiveManager::FileDescription *ArchiveManager::add_file(UnixTime ts, bool key_block) {
|
||||
CHECK((key_block ? key_files_ : files_).count(ts) == 0);
|
||||
index_->begin_transaction().ensure();
|
||||
{
|
||||
std::vector<td::int32> t;
|
||||
std::vector<td::int32> tk;
|
||||
for (auto &e : files_) {
|
||||
t.push_back(e.first);
|
||||
}
|
||||
for (auto &e : key_files_) {
|
||||
tk.push_back(e.first);
|
||||
}
|
||||
(key_block ? tk : t).push_back(ts);
|
||||
index_
|
||||
->set(create_serialize_tl_object<ton_api::db_archive_index_key>().as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_archive_index_value>(std::move(t), std::move(tk)).as_slice())
|
||||
.ensure();
|
||||
}
|
||||
{
|
||||
index_
|
||||
->set(create_serialize_tl_object<ton_api::db_archive_package_key>(ts, key_block).as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_archive_package_value>(
|
||||
ts, key_block, std::vector<tl_object_ptr<ton_api::db_archive_package_firstBlock>>(), false)
|
||||
.as_slice())
|
||||
.ensure();
|
||||
}
|
||||
index_->commit_transaction().ensure();
|
||||
FileDescription desc{ts, key_block};
|
||||
auto w = td::actor::create_actor<ArchiveFile>(
|
||||
PSTRING() << "archivefile" << ts,
|
||||
PSTRING() << db_root_ << "/packed/" << (key_block ? "key" : "") << ts << ".pack", ts);
|
||||
desc.file = std::move(w);
|
||||
|
||||
return &(key_block ? key_files_ : files_).emplace(ts, std::move(desc)).first->second;
|
||||
}
|
||||
|
||||
void ArchiveManager::load_package(UnixTime ts, bool key_block) {
|
||||
auto key = create_serialize_tl_object<ton_api::db_archive_package_key>(ts, key_block);
|
||||
|
||||
std::string value;
|
||||
auto v = index_->get(key.as_slice(), value);
|
||||
v.ensure();
|
||||
CHECK(v.move_as_ok() == td::KeyValue::GetStatus::Ok);
|
||||
|
||||
auto R = fetch_tl_object<ton_api::db_archive_package_value>(value, true);
|
||||
R.ensure();
|
||||
auto x = R.move_as_ok();
|
||||
|
||||
if (x->deleted_) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileDescription desc{ts, key_block};
|
||||
for (auto &e : x->firstblocks_) {
|
||||
desc.first_blocks[ShardIdFull{e->workchain_, static_cast<ShardId>(e->shard_)}] =
|
||||
FileDescription::Desc{static_cast<td::uint32>(e->seqno_), static_cast<LogicalTime>(e->lt_)};
|
||||
}
|
||||
desc.file = td::actor::create_actor<ArchiveFile>(
|
||||
PSTRING() << "archivefile" << ts,
|
||||
PSTRING() << db_root_ << "/packed/" << (key_block ? "key" : "") << ts << ".pack", ts);
|
||||
|
||||
(key_block ? key_files_ : files_).emplace(ts, std::move(desc));
|
||||
}
|
||||
|
||||
void ArchiveManager::update_desc(FileDescription &desc, ShardIdFull shard, BlockSeqno seqno, LogicalTime lt) {
|
||||
auto it = desc.first_blocks.find(shard);
|
||||
if (it != desc.first_blocks.end() && it->second.seqno <= seqno) {
|
||||
return;
|
||||
}
|
||||
desc.first_blocks[shard] = FileDescription::Desc{seqno, lt};
|
||||
std::vector<tl_object_ptr<ton_api::db_archive_package_firstBlock>> vec;
|
||||
for (auto &e : desc.first_blocks) {
|
||||
vec.push_back(create_tl_object<ton_api::db_archive_package_firstBlock>(e.first.workchain, e.first.shard,
|
||||
e.second.seqno, e.second.lt));
|
||||
}
|
||||
index_->begin_transaction().ensure();
|
||||
index_
|
||||
->set(create_serialize_tl_object<ton_api::db_archive_package_key>(desc.unix_time, desc.key_block).as_slice(),
|
||||
create_serialize_tl_object<ton_api::db_archive_package_value>(desc.unix_time, desc.key_block,
|
||||
std::move(vec), false)
|
||||
.as_slice())
|
||||
.ensure();
|
||||
index_->commit_transaction().ensure();
|
||||
}
|
||||
|
||||
ArchiveManager::FileDescription *ArchiveManager::get_file_by_seqno(ShardIdFull shard, BlockSeqno seqno,
|
||||
bool key_block) {
|
||||
auto &f = (key_block ? key_files_ : files_);
|
||||
|
||||
for (auto it = f.rbegin(); it != f.rend(); it++) {
|
||||
auto i = it->second.first_blocks.find(shard);
|
||||
if (i != it->second.first_blocks.end() && i->second.seqno <= seqno) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ArchiveManager::start_up() {
|
||||
td::mkdir(db_root_).ensure();
|
||||
td::mkdir(db_root_ + "/packed").ensure();
|
||||
index_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_root_ + "/packed/globalindex").move_as_ok());
|
||||
std::string value;
|
||||
auto v = index_->get(create_serialize_tl_object<ton_api::db_archive_index_key>().as_slice(), value);
|
||||
v.ensure();
|
||||
if (v.move_as_ok() == td::KeyValue::GetStatus::Ok) {
|
||||
auto R = fetch_tl_object<ton_api::db_archive_index_value>(value, true);
|
||||
R.ensure();
|
||||
auto x = R.move_as_ok();
|
||||
|
||||
for (auto &d : x->packages_) {
|
||||
load_package(d, false);
|
||||
}
|
||||
for (auto &d : x->key_packages_) {
|
||||
load_package(d, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
97
validator/db/archive-db.hpp
Normal file
97
validator/db/archive-db.hpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "ton/ton-types.h"
|
||||
#include "td/utils/port/FileFd.h"
|
||||
#include "package.hpp"
|
||||
#include "filedb.hpp"
|
||||
#include "validator/interfaces/block-handle.h"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace validator {
|
||||
|
||||
class PackageWriter : public td::actor::Actor {
|
||||
public:
|
||||
PackageWriter(std::shared_ptr<Package> package) : package_(std::move(package)) {
|
||||
}
|
||||
|
||||
void append(std::string filename, td::BufferSlice data, td::Promise<std::pair<td::uint64, td::uint64>> promise);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Package> package_;
|
||||
};
|
||||
|
||||
class ArchiveFile : public td::actor::Actor {
|
||||
public:
|
||||
ArchiveFile(std::string path, UnixTime ts) : path_(std::move(path)), ts_(ts) {
|
||||
}
|
||||
void start_up() override;
|
||||
void write(FileDb::RefId ref_id, td::BufferSlice data, td::Promise<td::Unit> promise);
|
||||
void write_handle(BlockHandle handle, td::Promise<td::Unit> promise);
|
||||
void read(FileDb::RefId ref_id, td::Promise<td::BufferSlice> promise);
|
||||
void read_handle(BlockIdExt block_id, td::Promise<BlockHandle> promise);
|
||||
|
||||
private:
|
||||
void completed_write(FileDb::RefId ref_id, td::uint64 offset, td::uint64 new_size, td::Promise<td::Unit> promise);
|
||||
|
||||
std::shared_ptr<Package> package_;
|
||||
std::shared_ptr<td::KeyValue> index_;
|
||||
|
||||
td::actor::ActorOwn<PackageWriter> writer_;
|
||||
|
||||
std::string path_;
|
||||
UnixTime ts_;
|
||||
};
|
||||
|
||||
class ArchiveManager : public td::actor::Actor {
|
||||
public:
|
||||
ArchiveManager(std::string db_root);
|
||||
void write(UnixTime ts, bool key_block, FileDb::RefId ref_id, td::BufferSlice data, td::Promise<td::Unit> promise);
|
||||
void write_handle(BlockHandle handle, td::Promise<td::Unit> promise);
|
||||
void read(UnixTime ts, bool key_block, FileDb::RefId ref_id, td::Promise<td::BufferSlice> promise);
|
||||
void read_handle(BlockIdExt block_id, td::Promise<BlockHandle> promise);
|
||||
|
||||
void start_up() override;
|
||||
|
||||
private:
|
||||
void read_handle_cont(BlockIdExt block_id, td::Promise<BlockHandle> promise);
|
||||
struct FileDescription {
|
||||
struct Desc {
|
||||
BlockSeqno seqno;
|
||||
LogicalTime lt;
|
||||
};
|
||||
FileDescription(UnixTime unix_time, bool key_block) : unix_time(unix_time), key_block(key_block) {
|
||||
}
|
||||
auto file_actor_id() const {
|
||||
return file.get();
|
||||
}
|
||||
UnixTime unix_time;
|
||||
bool key_block;
|
||||
|
||||
std::map<ShardIdFull, Desc> first_blocks;
|
||||
td::actor::ActorOwn<ArchiveFile> file;
|
||||
};
|
||||
|
||||
void load_package(UnixTime ts, bool key_block);
|
||||
|
||||
UnixTime convert_ts(UnixTime ts, bool key_block);
|
||||
FileDescription *get_file(UnixTime ts, bool key_block, bool force = true);
|
||||
FileDescription *add_file(UnixTime ts, bool key_block);
|
||||
void update_desc(FileDescription &desc, ShardIdFull shard, BlockSeqno seqno, LogicalTime lt);
|
||||
FileDescription *get_file_by_seqno(ShardIdFull shard, BlockSeqno seqno, bool key_block);
|
||||
|
||||
std::string db_root_;
|
||||
std::map<UnixTime, FileDescription> files_;
|
||||
std::map<UnixTime, FileDescription> key_files_;
|
||||
|
||||
std::shared_ptr<td::KeyValue> index_;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
||||
} // namespace ton
|
|
@ -26,8 +26,13 @@ namespace validator {
|
|||
|
||||
BlockArchiver::BlockArchiver(BlockIdExt block_id, td::actor::ActorId<RootDb> root_db,
|
||||
td::actor::ActorId<FileDb> file_db, td::actor::ActorId<FileDb> archive_db,
|
||||
td::Promise<td::Unit> promise)
|
||||
: block_id_(block_id), root_db_(root_db), file_db_(file_db), archive_db_(archive_db), promise_(std::move(promise)) {
|
||||
td::actor::ActorId<ArchiveManager> archive, td::Promise<td::Unit> promise)
|
||||
: block_id_(block_id)
|
||||
, root_db_(root_db)
|
||||
, file_db_(file_db)
|
||||
, archive_db_(archive_db)
|
||||
, archive_(archive)
|
||||
, promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void BlockArchiver::start_up() {
|
||||
|
@ -40,7 +45,7 @@ void BlockArchiver::start_up() {
|
|||
|
||||
void BlockArchiver::got_block_handle(BlockHandle handle) {
|
||||
handle_ = std::move(handle);
|
||||
if (handle_->moved_to_storage()) {
|
||||
if (handle_->moved_to_archive()) {
|
||||
finish_query();
|
||||
return;
|
||||
}
|
||||
|
@ -63,16 +68,21 @@ void BlockArchiver::got_block_handle(BlockHandle handle) {
|
|||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &BlockArchiver::got_proof, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(file_db_, &FileDb::load_file, FileDb::RefId{fileref::Proof{block_id_}}, std::move(P));
|
||||
|
||||
if (handle_->moved_to_storage()) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::load_file, FileDb::RefId{fileref::Proof{block_id_}}, std::move(P));
|
||||
} else {
|
||||
td::actor::send_closure(file_db_, &FileDb::load_file, FileDb::RefId{fileref::Proof{block_id_}}, std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void BlockArchiver::got_proof(td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<FileHash> R) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &BlockArchiver::written_proof);
|
||||
});
|
||||
td::actor::send_closure(archive_db_, &FileDb::store_file, FileDb::RefId{fileref::Proof{block_id_}}, std::move(data),
|
||||
std::move(P));
|
||||
td::actor::send_closure(archive_, &ArchiveManager::write, handle_->unix_time(), handle_->is_key_block(),
|
||||
FileDb::RefId{fileref::Proof{block_id_}}, std::move(data), std::move(P));
|
||||
}
|
||||
|
||||
void BlockArchiver::written_proof() {
|
||||
|
@ -85,16 +95,21 @@ void BlockArchiver::written_proof() {
|
|||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &BlockArchiver::got_proof_link, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(file_db_, &FileDb::load_file, FileDb::RefId{fileref::ProofLink{block_id_}}, std::move(P));
|
||||
if (handle_->moved_to_storage()) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::load_file, FileDb::RefId{fileref::ProofLink{block_id_}},
|
||||
std::move(P));
|
||||
} else {
|
||||
td::actor::send_closure(file_db_, &FileDb::load_file, FileDb::RefId{fileref::ProofLink{block_id_}}, std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void BlockArchiver::got_proof_link(td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<FileHash> R) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &BlockArchiver::written_proof_link);
|
||||
});
|
||||
td::actor::send_closure(archive_db_, &FileDb::store_file, FileDb::RefId{fileref::ProofLink{block_id_}},
|
||||
std::move(data), std::move(P));
|
||||
td::actor::send_closure(archive_, &ArchiveManager::write, handle_->unix_time(), handle_->is_key_block(),
|
||||
FileDb::RefId{fileref::ProofLink{block_id_}}, std::move(data), std::move(P));
|
||||
}
|
||||
|
||||
void BlockArchiver::written_proof_link() {
|
||||
|
@ -106,20 +121,24 @@ void BlockArchiver::written_proof_link() {
|
|||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &BlockArchiver::got_block_data, R.move_as_ok());
|
||||
});
|
||||
td::actor::send_closure(file_db_, &FileDb::load_file, FileDb::RefId{fileref::Block{block_id_}}, std::move(P));
|
||||
if (handle_->moved_to_storage()) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::load_file, FileDb::RefId{fileref::Block{block_id_}}, std::move(P));
|
||||
} else {
|
||||
td::actor::send_closure(file_db_, &FileDb::load_file, FileDb::RefId{fileref::Block{block_id_}}, std::move(P));
|
||||
}
|
||||
}
|
||||
|
||||
void BlockArchiver::got_block_data(td::BufferSlice data) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<FileHash> R) {
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
td::actor::send_closure(SelfId, &BlockArchiver::written_block_data);
|
||||
});
|
||||
td::actor::send_closure(archive_db_, &FileDb::store_file, FileDb::RefId{fileref::Block{block_id_}}, std::move(data),
|
||||
std::move(P));
|
||||
td::actor::send_closure(archive_, &ArchiveManager::write, handle_->unix_time(), handle_->is_key_block(),
|
||||
FileDb::RefId{fileref::Block{block_id_}}, std::move(data), std::move(P));
|
||||
}
|
||||
|
||||
void BlockArchiver::written_block_data() {
|
||||
handle_->set_moved_to_storage();
|
||||
handle_->set_moved_to_archive();
|
||||
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result<td::Unit> R) {
|
||||
R.ensure();
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "td/actor/actor.h"
|
||||
#include "validator/interfaces/block-handle.h"
|
||||
#include "ton/ton-io.hpp"
|
||||
#include "archive-db.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -33,7 +34,8 @@ class FileDb;
|
|||
class BlockArchiver : public td::actor::Actor {
|
||||
public:
|
||||
BlockArchiver(BlockIdExt block_id, td::actor::ActorId<RootDb> root_db, td::actor::ActorId<FileDb> file_db,
|
||||
td::actor::ActorId<FileDb> archive_db, td::Promise<td::Unit> promise);
|
||||
td::actor::ActorId<FileDb> archive_db, td::actor::ActorId<ArchiveManager> archive,
|
||||
td::Promise<td::Unit> promise);
|
||||
|
||||
void abort_query(td::Status error);
|
||||
|
||||
|
@ -52,6 +54,7 @@ class BlockArchiver : public td::actor::Actor {
|
|||
td::actor::ActorId<RootDb> root_db_;
|
||||
td::actor::ActorId<FileDb> file_db_;
|
||||
td::actor::ActorId<FileDb> archive_db_;
|
||||
td::actor::ActorId<ArchiveManager> archive_;
|
||||
td::Promise<td::Unit> promise_;
|
||||
|
||||
BlockHandle handle_;
|
||||
|
|
|
@ -331,6 +331,9 @@ FileDb::RefId FileDb::get_ref_from_tl(const ton_api::db_filedb_Key& from) {
|
|||
[&](const ton_api::db_filedb_key_candidate& key) {
|
||||
ref_id = fileref::Candidate{PublicKey{key.id_->source_}, create_block_id(key.id_->id_),
|
||||
key.id_->collated_data_file_hash_};
|
||||
},
|
||||
[&](const ton_api::db_filedb_key_blockInfo& key) {
|
||||
ref_id = fileref::BlockInfo{create_block_id(key.block_id_)};
|
||||
}));
|
||||
return ref_id;
|
||||
}
|
||||
|
|
|
@ -130,6 +130,18 @@ class Candidate {
|
|||
BlockIdExt block_id;
|
||||
FileHash collated_data_file_hash;
|
||||
};
|
||||
|
||||
class BlockInfo {
|
||||
public:
|
||||
tl_object_ptr<ton_api::db_filedb_Key> tl() const {
|
||||
return create_tl_object<ton_api::db_filedb_key_blockInfo>(create_tl_block_id(block_id));
|
||||
}
|
||||
FileHash hash() const {
|
||||
return create_hash_tl_object<ton_api::db_filedb_key_blockInfo>(create_tl_block_id(block_id));
|
||||
}
|
||||
|
||||
BlockIdExt block_id;
|
||||
};
|
||||
}; // namespace fileref
|
||||
|
||||
class RootDb;
|
||||
|
@ -138,7 +150,7 @@ class FileDb : public td::actor::Actor {
|
|||
public:
|
||||
using RefId =
|
||||
td::Variant<fileref::Empty, fileref::Block, fileref::ZeroState, fileref::PersistentState, fileref::Proof,
|
||||
fileref::Proof, fileref::ProofLink, fileref::Signatures, fileref::Candidate>;
|
||||
fileref::Proof, fileref::ProofLink, fileref::Signatures, fileref::Candidate, fileref::BlockInfo>;
|
||||
using RefIdHash = td::Bits256;
|
||||
|
||||
void store_file(RefId ref_id, td::BufferSlice data, td::Promise<FileHash> promise);
|
||||
|
|
|
@ -52,7 +52,7 @@ class WriteFile : public td::actor::Actor {
|
|||
auto res = R.move_as_ok();
|
||||
auto file = std::move(res.first);
|
||||
auto old_name = res.second;
|
||||
size_t offset = 0;
|
||||
td::uint64 offset = 0;
|
||||
while (data_.size() > 0) {
|
||||
auto R = file.pwrite(data_.as_slice(), offset);
|
||||
auto s = R.move_as_ok();
|
||||
|
|
143
validator/db/package.cpp
Normal file
143
validator/db/package.cpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
#include "package.hpp"
|
||||
#include "common/errorcode.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr td::uint32 header_size() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
constexpr td::uint32 max_data_size() {
|
||||
return (1u << 31) - 1;
|
||||
}
|
||||
|
||||
constexpr td::uint32 max_filename_size() {
|
||||
return (1u << 16) - 1;
|
||||
}
|
||||
|
||||
constexpr td::uint16 entry_header_magic() {
|
||||
return 0x1e8b;
|
||||
}
|
||||
|
||||
constexpr td::uint32 package_header_magic() {
|
||||
return 0xae8fdd01;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Package::Package(td::FileFd fd) : fd_(std::move(fd)) {
|
||||
}
|
||||
|
||||
td::Status Package::truncate(td::uint64 size) {
|
||||
TRY_STATUS(fd_.seek(size + header_size()));
|
||||
return fd_.truncate_to_current_position(size + header_size());
|
||||
}
|
||||
|
||||
td::uint64 Package::append(std::string filename, td::Slice data) {
|
||||
CHECK(data.size() <= max_data_size());
|
||||
CHECK(filename.size() <= max_filename_size());
|
||||
auto size = fd_.get_size().move_as_ok();
|
||||
auto orig_size = size;
|
||||
td::uint32 header[2];
|
||||
header[0] = entry_header_magic() + (td::narrow_cast<td::uint32>(filename.size()) << 16);
|
||||
header[1] = td::narrow_cast<td::uint32>(data.size());
|
||||
CHECK(fd_.pwrite(td::Slice(reinterpret_cast<const td::uint8*>(header), 8), size).move_as_ok() == 8);
|
||||
size += 8;
|
||||
CHECK(fd_.pwrite(filename, size).move_as_ok() == filename.size());
|
||||
size += filename.size();
|
||||
CHECK(fd_.pwrite(data, size).move_as_ok() == data.size());
|
||||
size += data.size();
|
||||
fd_.sync().ensure();
|
||||
return orig_size - header_size();
|
||||
}
|
||||
|
||||
td::uint64 Package::size() const {
|
||||
return fd_.get_size().move_as_ok() - header_size();
|
||||
}
|
||||
|
||||
td::Result<std::pair<std::string, td::BufferSlice>> Package::read(td::uint64 offset) const {
|
||||
offset += header_size();
|
||||
|
||||
td::uint32 header[2];
|
||||
TRY_RESULT(s1, fd_.pread(td::MutableSlice(reinterpret_cast<td::uint8*>(header), 8), offset));
|
||||
if (s1 != 8) {
|
||||
return td::Status::Error(ErrorCode::notready, "too short read");
|
||||
}
|
||||
if ((header[0] & 0xffff) != entry_header_magic()) {
|
||||
return td::Status::Error(ErrorCode::notready, "bad entry magic");
|
||||
}
|
||||
offset += 8;
|
||||
auto fname_size = header[0] >> 16;
|
||||
auto data_size = header[1];
|
||||
|
||||
std::string fname(fname_size, '\0');
|
||||
TRY_RESULT(s2, fd_.pread(fname, offset));
|
||||
if (s2 != fname_size) {
|
||||
return td::Status::Error(ErrorCode::notready, "too short read (filename)");
|
||||
}
|
||||
offset += fname_size;
|
||||
|
||||
td::BufferSlice data{data_size};
|
||||
TRY_RESULT(s3, fd_.pread(data.as_slice(), offset));
|
||||
if (s3 != data_size) {
|
||||
return td::Status::Error(ErrorCode::notready, "too short read (data)");
|
||||
}
|
||||
return std::pair<std::string, td::BufferSlice>{std::move(fname), std::move(data)};
|
||||
}
|
||||
|
||||
td::Result<td::uint64> Package::advance(td::uint64 offset) {
|
||||
offset += header_size();
|
||||
|
||||
td::uint32 header[2];
|
||||
TRY_RESULT(s1, fd_.pread(td::MutableSlice(reinterpret_cast<td::uint8*>(header), 8), offset));
|
||||
if (s1 != 8) {
|
||||
return td::Status::Error(ErrorCode::notready, "too short read");
|
||||
}
|
||||
if ((header[0] & 0xffff) != entry_header_magic()) {
|
||||
return td::Status::Error(ErrorCode::notready, "bad entry magic");
|
||||
}
|
||||
|
||||
offset += 8 + (header[0] >> 16) + header[1];
|
||||
if (offset > static_cast<td::uint64>(fd_.get_size().move_as_ok())) {
|
||||
return td::Status::Error(ErrorCode::notready, "truncated read");
|
||||
}
|
||||
return offset - header_size();
|
||||
}
|
||||
|
||||
td::Result<Package> Package::open(std::string path, bool read_only, bool create) {
|
||||
td::uint32 flags = td::FileFd::Flags::Read;
|
||||
if (!read_only) {
|
||||
flags |= td::FileFd::Write;
|
||||
}
|
||||
if (create) {
|
||||
flags |= td::FileFd::Create;
|
||||
}
|
||||
|
||||
TRY_RESULT(fd, td::FileFd::open(path, flags));
|
||||
TRY_RESULT(size, fd.get_size());
|
||||
|
||||
if (size < header_size()) {
|
||||
if (!create) {
|
||||
return td::Status::Error(ErrorCode::notready, "db is too short");
|
||||
}
|
||||
td::uint32 header[1];
|
||||
header[0] = package_header_magic();
|
||||
TRY_RESULT(s, fd.pwrite(td::Slice(reinterpret_cast<const td::uint8*>(header), header_size()), size));
|
||||
if (s != header_size()) {
|
||||
return td::Status::Error(ErrorCode::notready, "db write is short");
|
||||
}
|
||||
} else {
|
||||
td::uint32 header[1];
|
||||
TRY_RESULT(s, fd.pread(td::MutableSlice(reinterpret_cast<td::uint8*>(header), header_size()), 0));
|
||||
if (s != header_size()) {
|
||||
return td::Status::Error(ErrorCode::notready, "db read failed");
|
||||
}
|
||||
if (header[0] != package_header_magic()) {
|
||||
return td::Status::Error(ErrorCode::notready, "magic mismatch");
|
||||
}
|
||||
}
|
||||
return Package{std::move(fd)};
|
||||
}
|
||||
|
||||
} // namespace ton
|
40
validator/db/package.hpp
Normal file
40
validator/db/package.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/utils/port/FileFd.h"
|
||||
#include "td/utils/buffer.h"
|
||||
|
||||
namespace ton {
|
||||
|
||||
class Package {
|
||||
public:
|
||||
static td::Result<Package> open(std::string path, bool read_only = false, bool create = false);
|
||||
|
||||
Package(td::FileFd fd);
|
||||
|
||||
td::Status truncate(td::uint64 size);
|
||||
|
||||
td::uint64 append(std::string filename, td::Slice data);
|
||||
td::uint64 size() const;
|
||||
td::Result<std::pair<std::string, td::BufferSlice>> read(td::uint64 offset) const;
|
||||
td::Result<td::uint64> advance(td::uint64 offset);
|
||||
|
||||
struct Iterator {
|
||||
td::uint64 offset;
|
||||
Package &package;
|
||||
|
||||
Iterator operator++(int);
|
||||
const Iterator operator++(int) const;
|
||||
td::Result<std::pair<std::string, td::BufferSlice>> read() const;
|
||||
};
|
||||
|
||||
Iterator begin();
|
||||
const Iterator begin() const;
|
||||
Iterator end();
|
||||
const Iterator end() const;
|
||||
|
||||
private:
|
||||
td::FileFd fd_;
|
||||
};
|
||||
|
||||
} // namespace ton
|
|
@ -32,7 +32,7 @@ namespace ton {
|
|||
namespace validator {
|
||||
|
||||
void RootDb::store_block_data(BlockHandle handle, td::Ref<BlockData> block, td::Promise<td::Unit> promise) {
|
||||
if (handle->moved_to_storage()) {
|
||||
if (handle->moved_to_storage() || handle->moved_to_archive()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
|
@ -64,14 +64,19 @@ void RootDb::get_block_data(BlockHandle handle, td::Promise<td::Ref<BlockData>>
|
|||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(handle->moved_to_storage() ? archive_db_.get() : file_db_.get(), &FileDb::load_file,
|
||||
FileDb::RefId{fileref::Block{handle->id()}}, std::move(P));
|
||||
if (handle->moved_to_archive()) {
|
||||
td::actor::send_closure(new_archive_db_, &ArchiveManager::read, handle->unix_time(), handle->is_key_block(),
|
||||
FileDb::RefId{fileref::Block{handle->id()}}, std::move(P));
|
||||
} else {
|
||||
td::actor::send_closure(handle->moved_to_storage() ? old_archive_db_.get() : file_db_.get(), &FileDb::load_file,
|
||||
FileDb::RefId{fileref::Block{handle->id()}}, std::move(P));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootDb::store_block_signatures(BlockHandle handle, td::Ref<BlockSignatureSet> data,
|
||||
td::Promise<td::Unit> promise) {
|
||||
if (handle->moved_to_storage()) {
|
||||
if (handle->moved_to_storage() || handle->moved_to_archive()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
|
@ -94,7 +99,7 @@ void RootDb::get_block_signatures(BlockHandle handle, td::Promise<td::Ref<BlockS
|
|||
if (!handle->inited_signatures()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::notready, "not in db"));
|
||||
} else {
|
||||
if (handle->moved_to_storage()) {
|
||||
if (handle->moved_to_storage() || handle->moved_to_archive()) {
|
||||
promise.set_error(td::Status::Error(ErrorCode::error, "signatures already gc'd"));
|
||||
return;
|
||||
}
|
||||
|
@ -111,7 +116,7 @@ void RootDb::get_block_signatures(BlockHandle handle, td::Promise<td::Ref<BlockS
|
|||
}
|
||||
|
||||
void RootDb::store_block_proof(BlockHandle handle, td::Ref<Proof> proof, td::Promise<td::Unit> promise) {
|
||||
if (handle->moved_to_storage()) {
|
||||
if (handle->moved_to_storage() || handle->moved_to_archive()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
|
@ -142,13 +147,18 @@ void RootDb::get_block_proof(BlockHandle handle, td::Promise<td::Ref<Proof>> pro
|
|||
promise.set_result(create_proof(id, R.move_as_ok()));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(handle->moved_to_storage() ? archive_db_.get() : file_db_.get(), &FileDb::load_file,
|
||||
FileDb::RefId{fileref::Proof{handle->id()}}, std::move(P));
|
||||
if (handle->moved_to_archive()) {
|
||||
td::actor::send_closure(new_archive_db_, &ArchiveManager::read, handle->unix_time(), handle->is_key_block(),
|
||||
FileDb::RefId{fileref::Proof{handle->id()}}, std::move(P));
|
||||
} else {
|
||||
td::actor::send_closure(handle->moved_to_storage() ? old_archive_db_.get() : file_db_.get(), &FileDb::load_file,
|
||||
FileDb::RefId{fileref::Proof{handle->id()}}, std::move(P));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootDb::store_block_proof_link(BlockHandle handle, td::Ref<ProofLink> proof, td::Promise<td::Unit> promise) {
|
||||
if (handle->moved_to_storage()) {
|
||||
if (handle->moved_to_storage() || handle->moved_to_archive()) {
|
||||
promise.set_value(td::Unit());
|
||||
return;
|
||||
}
|
||||
|
@ -179,8 +189,13 @@ void RootDb::get_block_proof_link(BlockHandle handle, td::Promise<td::Ref<ProofL
|
|||
promise.set_result(create_proof_link(id, R.move_as_ok()));
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(handle->moved_to_storage() ? archive_db_.get() : file_db_.get(), &FileDb::load_file,
|
||||
FileDb::RefId{fileref::ProofLink{handle->id()}}, std::move(P));
|
||||
if (handle->moved_to_archive()) {
|
||||
td::actor::send_closure(new_archive_db_, &ArchiveManager::read, handle->unix_time(), handle->is_key_block(),
|
||||
FileDb::RefId{fileref::ProofLink{handle->id()}}, std::move(P));
|
||||
} else {
|
||||
td::actor::send_closure(handle->moved_to_storage() ? old_archive_db_.get() : file_db_.get(), &FileDb::load_file,
|
||||
FileDb::RefId{fileref::ProofLink{handle->id()}}, std::move(P));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,7 +240,7 @@ void RootDb::get_block_candidate(PublicKey source, BlockIdExt id, FileHash colla
|
|||
|
||||
void RootDb::store_block_state(BlockHandle handle, td::Ref<ShardState> state,
|
||||
td::Promise<td::Ref<ShardState>> promise) {
|
||||
if (handle->moved_to_storage()) {
|
||||
if (handle->moved_to_storage() || handle->moved_to_archive()) {
|
||||
promise.set_value(std::move(state));
|
||||
return;
|
||||
}
|
||||
|
@ -290,27 +305,27 @@ void RootDb::store_persistent_state_file(BlockIdExt block_id, BlockIdExt masterc
|
|||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(archive_db_, &FileDb::store_file,
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::store_file,
|
||||
FileDb::RefId{fileref::PersistentState{block_id, masterchain_block_id}}, std::move(state),
|
||||
std::move(P));
|
||||
}
|
||||
|
||||
void RootDb::get_persistent_state_file(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::Promise<td::BufferSlice> promise) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::load_file,
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::load_file,
|
||||
FileDb::RefId{fileref::PersistentState{block_id, masterchain_block_id}}, std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::get_persistent_state_file_slice(BlockIdExt block_id, BlockIdExt masterchain_block_id, td::int64 offset,
|
||||
td::int64 max_size, td::Promise<td::BufferSlice> promise) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::load_file_slice,
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::load_file_slice,
|
||||
FileDb::RefId{fileref::PersistentState{block_id, masterchain_block_id}}, offset, max_size,
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::check_persistent_state_file_exists(BlockIdExt block_id, BlockIdExt masterchain_block_id,
|
||||
td::Promise<bool> promise) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::check_file,
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::check_file,
|
||||
FileDb::RefId{fileref::PersistentState{block_id, masterchain_block_id}}, std::move(promise));
|
||||
}
|
||||
|
||||
|
@ -325,26 +340,38 @@ void RootDb::store_zero_state_file(BlockIdExt block_id, td::BufferSlice state, t
|
|||
}
|
||||
});
|
||||
|
||||
td::actor::send_closure(archive_db_, &FileDb::store_file, FileDb::RefId{fileref::ZeroState{block_id}},
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::store_file, FileDb::RefId{fileref::ZeroState{block_id}},
|
||||
std::move(state), std::move(P));
|
||||
}
|
||||
|
||||
void RootDb::get_zero_state_file(BlockIdExt block_id, td::Promise<td::BufferSlice> promise) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::load_file, FileDb::RefId{fileref::ZeroState{block_id}},
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::load_file, FileDb::RefId{fileref::ZeroState{block_id}},
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::check_zero_state_file_exists(BlockIdExt block_id, td::Promise<bool> promise) {
|
||||
td::actor::send_closure(archive_db_, &FileDb::check_file, FileDb::RefId{fileref::ZeroState{block_id}},
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::check_file, FileDb::RefId{fileref::ZeroState{block_id}},
|
||||
std::move(promise));
|
||||
}
|
||||
|
||||
void RootDb::store_block_handle(BlockHandle handle, td::Promise<td::Unit> promise) {
|
||||
td::actor::send_closure(block_db_, &BlockDb::store_block_handle, std::move(handle), std::move(promise));
|
||||
if (handle->moved_to_archive()) {
|
||||
td::actor::send_closure(new_archive_db_, &ArchiveManager::write_handle, std::move(handle), std::move(promise));
|
||||
} else {
|
||||
td::actor::send_closure(block_db_, &BlockDb::store_block_handle, std::move(handle), std::move(promise));
|
||||
}
|
||||
}
|
||||
|
||||
void RootDb::get_block_handle(BlockIdExt id, td::Promise<BlockHandle> promise) {
|
||||
td::actor::send_closure(block_db_, &BlockDb::get_block_handle, id, std::move(promise));
|
||||
auto P = td::PromiseCreator::lambda(
|
||||
[db = block_db_.get(), id, promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
td::actor::send_closure(db, &BlockDb::get_block_handle, id, std::move(promise));
|
||||
} else {
|
||||
promise.set_value(R.move_as_ok());
|
||||
}
|
||||
});
|
||||
td::actor::send_closure(new_archive_db_, &ArchiveManager::read_handle, id, std::move(P));
|
||||
}
|
||||
|
||||
void RootDb::try_get_static_file(FileHash file_hash, td::Promise<td::BufferSlice> promise) {
|
||||
|
@ -426,16 +453,17 @@ void RootDb::start_up() {
|
|||
cell_db_ = td::actor::create_actor<CellDb>("celldb", actor_id(this), root_path_ + "/celldb/");
|
||||
block_db_ = td::actor::create_actor<BlockDb>("blockdb", actor_id(this), root_path_ + "/blockdb/");
|
||||
file_db_ = td::actor::create_actor<FileDb>("filedb", actor_id(this), root_path_ + "/files/", depth_, false);
|
||||
archive_db_ =
|
||||
old_archive_db_ =
|
||||
td::actor::create_actor<FileDb>("filedbarchive", actor_id(this), root_path_ + "/archive/", depth_, true);
|
||||
lt_db_ = td::actor::create_actor<LtDb>("ltdb", actor_id(this), root_path_ + "/ltdb/");
|
||||
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/");
|
||||
new_archive_db_ = td::actor::create_actor<ArchiveManager>("archivemanager", root_path_ + "/archive/");
|
||||
}
|
||||
|
||||
void RootDb::archive(BlockIdExt block_id, td::Promise<td::Unit> promise) {
|
||||
td::actor::create_actor<BlockArchiver>("archiveblock", block_id, actor_id(this), file_db_.get(), archive_db_.get(),
|
||||
std::move(promise))
|
||||
td::actor::create_actor<BlockArchiver>("archiveblock", block_id, actor_id(this), file_db_.get(),
|
||||
old_archive_db_.get(), new_archive_db_.get(), std::move(promise))
|
||||
.release();
|
||||
}
|
||||
|
||||
|
@ -480,14 +508,15 @@ void RootDb::allow_gc(FileDb::RefId ref_id, bool is_archive, td::Promise<bool> p
|
|||
CHECK(!is_archive);
|
||||
td::actor::send_closure(validator_manager_, &ValidatorManager::allow_block_candidate_gc,
|
||||
key.block_id, std::move(promise));
|
||||
}));
|
||||
},
|
||||
[&](const fileref::BlockInfo &key) { UNREACHABLE(); }));
|
||||
}
|
||||
|
||||
void RootDb::prepare_stats(td::Promise<std::vector<std::pair<std::string, std::string>>> promise) {
|
||||
auto merger = StatsMerger::create(std::move(promise));
|
||||
|
||||
td::actor::send_closure(file_db_, &FileDb::prepare_stats, merger.make_promise("filedb."));
|
||||
td::actor::send_closure(archive_db_, &FileDb::prepare_stats, merger.make_promise("archivedb."));
|
||||
td::actor::send_closure(old_archive_db_, &FileDb::prepare_stats, merger.make_promise("archivedb."));
|
||||
}
|
||||
|
||||
void RootDb::truncate(td::Ref<MasterchainState> state, td::Promise<td::Unit> promise) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "ltdb.hpp"
|
||||
#include "statedb.hpp"
|
||||
#include "staticfilesdb.hpp"
|
||||
#include "archive-db.hpp"
|
||||
|
||||
namespace ton {
|
||||
|
||||
|
@ -126,10 +127,11 @@ class RootDb : public Db {
|
|||
td::actor::ActorOwn<CellDb> cell_db_;
|
||||
td::actor::ActorOwn<BlockDb> block_db_;
|
||||
td::actor::ActorOwn<FileDb> file_db_;
|
||||
td::actor::ActorOwn<FileDb> archive_db_;
|
||||
td::actor::ActorOwn<FileDb> old_archive_db_;
|
||||
td::actor::ActorOwn<LtDb> lt_db_;
|
||||
td::actor::ActorOwn<StateDb> state_db_;
|
||||
td::actor::ActorOwn<StaticFilesDb> static_files_db_;
|
||||
td::actor::ActorOwn<ArchiveManager> new_archive_db_;
|
||||
};
|
||||
|
||||
} // namespace validator
|
||||
|
|
|
@ -33,6 +33,7 @@ struct BlockHandleInterface {
|
|||
virtual BlockIdExt id() const = 0;
|
||||
virtual bool received() const = 0;
|
||||
virtual bool moved_to_storage() const = 0;
|
||||
virtual bool moved_to_archive() const = 0;
|
||||
virtual bool deleted() const = 0;
|
||||
virtual bool inited_next_left() const = 0;
|
||||
virtual bool inited_next_right() const = 0;
|
||||
|
@ -83,6 +84,7 @@ struct BlockHandleInterface {
|
|||
virtual void set_prev(BlockIdExt prev) = 0;
|
||||
virtual void set_received() = 0;
|
||||
virtual void set_moved_to_storage() = 0;
|
||||
virtual void set_moved_to_archive() = 0;
|
||||
virtual void set_deleted() = 0;
|
||||
virtual void set_split(bool value) = 0;
|
||||
virtual void set_merge(bool value) = 0;
|
||||
|
|
|
@ -1842,6 +1842,27 @@ void ValidatorManagerImpl::allow_block_state_gc(BlockIdExt block_id, td::Promise
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::allow_block_info_gc(BlockIdExt block_id, td::Promise<bool> promise) {
|
||||
auto P =
|
||||
td::PromiseCreator::lambda([db = db_.get(), promise = std::move(promise)](td::Result<BlockHandle> R) mutable {
|
||||
if (R.is_error()) {
|
||||
promise.set_result(false);
|
||||
} else {
|
||||
auto handle = R.move_as_ok();
|
||||
if (!handle->moved_to_archive()) {
|
||||
promise.set_result(false);
|
||||
} else {
|
||||
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::Unit> R) mutable {
|
||||
R.ensure();
|
||||
promise.set_result(true);
|
||||
});
|
||||
td::actor::send_closure(db, &Db::store_block_handle, handle, std::move(P));
|
||||
}
|
||||
}
|
||||
});
|
||||
get_block_handle(block_id, false, std::move(P));
|
||||
}
|
||||
|
||||
void ValidatorManagerImpl::got_next_gc_masterchain_handle(BlockHandle handle) {
|
||||
CHECK(gc_advancing_);
|
||||
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), handle](td::Result<td::Ref<ShardState>> R) {
|
||||
|
|
|
@ -463,11 +463,7 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
void allow_delete(BlockIdExt block_id, td::Promise<bool> promise);
|
||||
void allow_archive(BlockIdExt block_id, td::Promise<bool> promise);
|
||||
void allow_block_data_gc(BlockIdExt block_id, bool is_archive, td::Promise<bool> promise) override {
|
||||
if (!is_archive) {
|
||||
allow_archive(block_id, std::move(promise));
|
||||
} else {
|
||||
allow_delete(block_id, std::move(promise));
|
||||
}
|
||||
allow_archive(block_id, std::move(promise));
|
||||
}
|
||||
void allow_block_state_gc(BlockIdExt block_id, td::Promise<bool> promise) override;
|
||||
void allow_zero_state_file_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
|
@ -479,25 +475,15 @@ class ValidatorManagerImpl : public ValidatorManager {
|
|||
allow_archive(block_id, std::move(promise));
|
||||
}
|
||||
void allow_block_proof_gc(BlockIdExt block_id, bool is_archive, td::Promise<bool> promise) override {
|
||||
if (!is_archive) {
|
||||
allow_archive(block_id, std::move(promise));
|
||||
} else {
|
||||
allow_delete(block_id, std::move(promise));
|
||||
}
|
||||
allow_archive(block_id, std::move(promise));
|
||||
}
|
||||
void allow_block_proof_link_gc(BlockIdExt block_id, bool is_archive, td::Promise<bool> promise) override {
|
||||
if (!is_archive) {
|
||||
allow_archive(block_id, std::move(promise));
|
||||
} else {
|
||||
allow_delete(block_id, std::move(promise));
|
||||
}
|
||||
allow_archive(block_id, std::move(promise));
|
||||
}
|
||||
void allow_block_candidate_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
allow_block_state_gc(block_id, std::move(promise));
|
||||
}
|
||||
void allow_block_info_gc(BlockIdExt block_id, td::Promise<bool> promise) override {
|
||||
allow_delete(block_id, std::move(promise));
|
||||
}
|
||||
void allow_block_info_gc(BlockIdExt block_id, td::Promise<bool> promise) override;
|
||||
|
||||
void send_peek_key_block_request();
|
||||
void got_next_key_blocks(std::vector<BlockIdExt> vec);
|
||||
|
|
|
@ -188,7 +188,7 @@ void DownloadState::got_block_state_part(td::BufferSlice data, td::uint32 reques
|
|||
parts_.push_back(std::move(data));
|
||||
|
||||
if (last_part) {
|
||||
td::BufferSlice res{sum_};
|
||||
td::BufferSlice res{td::narrow_cast<std::size_t>(sum_)};
|
||||
auto S = res.as_slice();
|
||||
for (auto &p : parts_) {
|
||||
S.copy_from(p.as_slice());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue