1
0
mirror of https://github.com/danog/ton.git synced 2024-12-02 17:38:33 +01:00
ton/crypto/block/block-db-impl.h
2019-09-07 14:33:36 +04:00

136 lines
5.1 KiB
C++

/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2017-2019 Telegram Systems LLP
*/
#pragma once
#include <string>
#include <map>
#include "vm/cells.h"
#include "block/Binlog.h"
#include "block/block-db.h"
#include "block/block-binlog.h"
namespace block {
using td::Ref;
/*
*
* BLOCK DATABASE
*
*/
class BlockDbImpl;
class BlockBinlogCallback : public BinlogCallback {
BlockDbImpl& db;
td::Status init_new_binlog(BinlogBuffer& bb) override;
int replay_log_event(BinlogBuffer& bb, const unsigned* ptr, std::size_t len, unsigned long long log_pos) override;
int replay(const block::log::Start& lev, unsigned long long log_pos) const;
int replay(const block::log::SetZeroState& lev, unsigned long long log_pos) const;
int replay(const block::log::NewBlock& lev, unsigned long long log_pos) const;
int replay(const block::log::NewState& lev, unsigned long long log_pos) const;
template <typename T>
inline int try_interpret(const unsigned* ptr, std::size_t len, unsigned long long log_pos);
public:
BlockBinlogCallback(BlockDbImpl& _db) : db(_db) {
}
};
template <typename T>
inline int BlockBinlogCallback::try_interpret(const unsigned* ptr, std::size_t len, unsigned long long log_pos) {
if (len < sizeof(T)) {
return 0x80000000 + sizeof(T);
} else {
int res = replay(*reinterpret_cast<const T*>(ptr), log_pos);
return res >= 0 ? sizeof(T) : res;
}
}
class BlockDbImpl final : public BlockDb {
int status;
bool allow_uninit;
bool created;
int depth;
std::unique_ptr<ZerostateInfo> zstate;
std::string base_dir;
std::string binlog_name;
BinlogBuffer bb;
ton::Bits256 zstate_rhash, zstate_fhash;
unsigned created_at;
std::map<ton::FileHash, td::BufferSlice> file_cache;
std::map<ton::BlockId, Ref<FileInfo>> block_info;
std::map<ton::BlockId, Ref<FileInfo>> state_info;
//
td::Result<int> do_init();
public:
enum FMode {
chk_none = 0,
chk_if_exists = 1,
fail_if_exists = 2,
overwrite = 4,
chk_size_only = 16,
chk_file_hash = 32
};
static constexpr const char* default_binlog_name = "blockdb";
static constexpr const char* default_binlog_suffix = ".bin";
static constexpr int default_depth = 4;
BlockDbImpl(td::Result<int>& _res, std::string _base_dir, std::unique_ptr<ZerostateInfo> _zstate = nullptr,
bool _allow_uninit = false, int _depth = 4, std::string _binlog_name = "");
~BlockDbImpl();
bool ok() const {
return status >= 0;
}
bool initialized() const {
return status != 0;
}
bool init_ok() const {
return status > 0;
}
protected:
friend class BlockBinlogCallback;
td::Ref<FileInfo> zerostate;
td::Status init_from_zstate();
td::Status update_block_info(Ref<FileInfo> blk_info);
td::Status update_state_info(Ref<FileInfo> state);
private:
std::string compute_db_filename(const FileHash& file_hash) const;
std::string compute_db_tmp_filename(const FileHash& file_hash, int i, bool makedirs) const;
td::Status save_db_file(const FileHash& file_hash, const td::BufferSlice& data, int fmode = 0);
td::Status load_data(FileInfo& file_info, bool force = false);
// actor BlockDb implementation
void get_top_block_id(ton::ShardIdFull shard, int authority, td::Promise<ton::BlockIdExt> promise) override;
void get_top_block_state_id(ton::ShardIdFull shard, int authority, td::Promise<ton::BlockIdExt> promise) override;
void get_block_by_id(ton::BlockId blk_id, bool need_data, td::Promise<td::Ref<FileInfo>> promise) override;
void get_state_by_id(ton::BlockId blk_id, bool need_data, td::Promise<td::Ref<FileInfo>> promise) override;
void get_out_queue_info_by_id(ton::BlockId blk_id, td::Promise<td::Ref<OutputQueueInfoDescr>> promise) override;
void get_object_by_file_hash(FileHash file_hash, bool need_data, bool force_file_load,
td::Promise<td::Ref<FileInfo>> promise) override;
void get_object_by_root_hash(RootHash root_hash, bool need_data, bool force_file_load,
td::Promise<td::Ref<FileInfo>> promise) override;
void save_new_block(ton::BlockIdExt blk_id, td::BufferSlice data, int authority,
td::Promise<td::Unit> promise) override;
void save_new_state(ton::BlockIdExt state_id, td::BufferSlice data, int authority,
td::Promise<td::Unit> promise) override;
bool file_cache_insert(const FileHash& file_hash, const td::BufferSlice& data, int mode = 0);
};
} // namespace block