mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Make asynchronous celldb interface (#388)
* Asynchronous load_cell in celldb Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
ca00f0ed91
commit
845cbca1e5
5 changed files with 159 additions and 10 deletions
|
@ -86,6 +86,40 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
|
|||
TRY_RESULT(loaded_cell, get_cell_info_force(hash).cell->load_cell());
|
||||
return std::move(loaded_cell.data_cell);
|
||||
}
|
||||
void load_cell_async(td::Slice hash, std::shared_ptr<AsyncExecutor> executor,
|
||||
td::Promise<Ref<DataCell>> promise) override {
|
||||
auto info = hash_table_.get_if_exists(hash);
|
||||
if (info && info->sync_with_db) {
|
||||
TRY_RESULT_PROMISE(promise, loaded_cell, info->cell->load_cell());
|
||||
promise.set_result(loaded_cell.data_cell);
|
||||
return;
|
||||
}
|
||||
SimpleExtCellCreator ext_cell_creator(cell_db_reader_);
|
||||
auto promise_ptr = std::make_shared<td::Promise<Ref<DataCell>>>(std::move(promise));
|
||||
executor->execute_async(
|
||||
[executor, loader = *loader_, hash = CellHash::from_slice(hash), db = this,
|
||||
ext_cell_creator = std::move(ext_cell_creator), promise = std::move(promise_ptr)]() mutable {
|
||||
TRY_RESULT_PROMISE((*promise), res, loader.load(hash.as_slice(), true, ext_cell_creator));
|
||||
if (res.status != CellLoader::LoadResult::Ok) {
|
||||
promise->set_error(td::Status::Error("cell not found"));
|
||||
return;
|
||||
}
|
||||
Ref<Cell> cell = res.cell();
|
||||
executor->execute_sync([hash, db, res = std::move(res),
|
||||
ext_cell_creator = std::move(ext_cell_creator)]() mutable {
|
||||
db->hash_table_.apply(hash.as_slice(), [&](CellInfo &info) {
|
||||
db->update_cell_info_loaded(info, hash.as_slice(), std::move(res));
|
||||
});
|
||||
for (auto &ext_cell : ext_cell_creator.get_created_cells()) {
|
||||
auto ext_cell_hash = ext_cell->get_hash();
|
||||
db->hash_table_.apply(ext_cell_hash.as_slice(), [&](CellInfo &info) {
|
||||
db->update_cell_info_created_ext(info, std::move(ext_cell));
|
||||
});
|
||||
}
|
||||
});
|
||||
promise->set_result(std::move(cell));
|
||||
});
|
||||
}
|
||||
CellInfo &get_cell_info_force(td::Slice hash) {
|
||||
return hash_table_.apply(hash, [&](CellInfo &info) { update_cell_info_force(info, hash); });
|
||||
}
|
||||
|
@ -198,6 +232,27 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
|
|||
return res;
|
||||
}
|
||||
|
||||
class SimpleExtCellCreator : public ExtCellCreator {
|
||||
public:
|
||||
explicit SimpleExtCellCreator(std::shared_ptr<CellDbReader> cell_db_reader) :
|
||||
cell_db_reader_(std::move(cell_db_reader)) {}
|
||||
|
||||
td::Result<Ref<Cell>> ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) override {
|
||||
TRY_RESULT(ext_cell, DynamicBocExtCell::create(PrunnedCellInfo{level_mask, hash, depth},
|
||||
DynamicBocExtCellExtra{cell_db_reader_}));
|
||||
created_cells_.push_back(ext_cell);
|
||||
return std::move(ext_cell);
|
||||
}
|
||||
|
||||
std::vector<Ref<Cell>>& get_created_cells() {
|
||||
return created_cells_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Ref<Cell>> created_cells_;
|
||||
std::shared_ptr<CellDbReader> cell_db_reader_;
|
||||
};
|
||||
|
||||
class CellDbReaderImpl : public CellDbReader,
|
||||
private ExtCellCreator,
|
||||
public std::enable_shared_from_this<CellDbReaderImpl> {
|
||||
|
@ -484,6 +539,33 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
|
|||
info.sync_with_db = true;
|
||||
}
|
||||
|
||||
// same as update_cell_info_force, but with cell provided by a caller
|
||||
void update_cell_info_loaded(CellInfo &info, td::Slice hash, CellLoader::LoadResult res) {
|
||||
if (info.sync_with_db) {
|
||||
return;
|
||||
}
|
||||
DCHECK(res.status == CellLoader::LoadResult::Ok);
|
||||
info.cell = std::move(res.cell());
|
||||
CHECK(info.cell->get_hash().as_slice() == hash);
|
||||
info.in_db = true;
|
||||
info.db_refcnt = res.refcnt();
|
||||
info.sync_with_db = true;
|
||||
}
|
||||
|
||||
// same as update_cell_info_lazy, but with cell provided by a caller
|
||||
void update_cell_info_created_ext(CellInfo &info, Ref<Cell> cell) {
|
||||
if (info.sync_with_db) {
|
||||
CHECK(info.cell.not_null());
|
||||
CHECK(info.cell->get_level_mask() == cell->get_level_mask());
|
||||
CHECK(info.cell->get_hash() == cell->get_hash());
|
||||
return;
|
||||
}
|
||||
if (info.cell.is_null()) {
|
||||
info.cell = std::move(cell);
|
||||
info.in_db = true;
|
||||
}
|
||||
}
|
||||
|
||||
td::Result<Ref<Cell>> create_empty_ext_cell(Cell::LevelMask level_mask, td::Slice hash, td::Slice depth) {
|
||||
TRY_RESULT(res, DynamicBocExtCell::create(PrunnedCellInfo{level_mask, hash, depth},
|
||||
DynamicBocExtCellExtra{cell_db_reader_}));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue