Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
block_log.hpp
Go to the documentation of this file.
1#pragma once
2#include <fc/filesystem.hpp>
5
6namespace sysio { namespace chain {
7
8 namespace detail { class block_log_impl; }
9
10 /* The block log is an external append only log of the blocks with a header. Blocks should only
11 * be written to the log after they irreverisble as the log is append only. The log is a doubly
12 * linked list of blocks. There is a secondary index file of only block positions that enables
13 * O(1) random access lookup by block number.
14 *
15 * +---------+----------------+---------+----------------+-----+------------+-------------------+
16 * | Block 1 | Pos of Block 1 | Block 2 | Pos of Block 2 | ... | Head Block | Pos of Head Block |
17 * +---------+----------------+---------+----------------+-----+------------+-------------------+
18 *
19 * +----------------+----------------+-----+-------------------+
20 * | Pos of Block 1 | Pos of Block 2 | ... | Pos of Head Block |
21 * +----------------+----------------+-----+-------------------+
22 *
23 * The block log can be walked in order by deserializing a block, skipping 8 bytes, deserializing a
24 * block, repeat... The head block of the file can be found by seeking to the position contained
25 * in the last 8 bytes the file. The block log can be read backwards by jumping back 8 bytes, following
26 * the position, reading the block, jumping back 8 bytes, etc.
27 *
28 * Blocks can be accessed at random via block number through the index file. Seek to 8 * (block_num - 1)
29 * to find the position of the block in the main file.
30 *
31 * The main file is the only file that needs to persist. The index file can be reconstructed during a
32 * linear scan of the main file.
33 *
34 * An optional "pruned" mode can be activated which stores a 4 byte trailer on the log file indicating
35 * how many blocks at the end of the log are valid. Any earlier blocks in the log are assumed destroyed
36 * and unreadable due to reclamation for purposes of saving space.
37 */
38
40 uint32_t prune_blocks; //number of blocks to prune to when doing a prune
41 size_t prune_threshold = 4*1024*1024; //(approximately) how many bytes need to be added before a prune is performed
42 std::optional<size_t> vacuum_on_close; //when set, a vacuum is performed on dtor if log contains less than this many live bytes
43 };
44
45 class block_log {
46 public:
47 block_log(const fc::path& data_dir, std::optional<block_log_prune_config> prune_config);
48 block_log(block_log&& other);
49 ~block_log();
50
51 void append(const signed_block_ptr& b);
52 void flush();
53 void reset( const genesis_state& gs, const signed_block_ptr& genesis_block );
54 void reset( const chain_id_type& chain_id, uint32_t first_block_num );
55
57 void read_block_header(block_header& bh, uint64_t file_pos)const;
63
67 uint64_t get_block_pos(uint32_t block_num) const;
69 const signed_block_ptr& head()const;
70 const block_id_type& head_id()const;
72
73 static const uint64_t npos = std::numeric_limits<uint64_t>::max();
74
77
78 static fc::path repair_log( const fc::path& data_dir, uint32_t truncate_at_block = 0, const char* reversible_block_dir_name="" );
79
80 static std::optional<genesis_state> extract_genesis_state( const fc::path& data_dir );
81
82 static chain_id_type extract_chain_id( const fc::path& data_dir );
83
84 static void construct_index(const fc::path& block_file_name, const fc::path& index_file_name);
85
87
89
90 static bool is_supported_version(uint32_t version);
91
92 static bool is_pruned_log(const fc::path& data_dir);
93
94 static bool trim_blocklog_front(const fc::path& block_dir, const fc::path& temp_dir, uint32_t truncate_at_block);
95
96 private:
97 void open(const fc::path& data_dir);
98 void construct_index();
99
100 std::unique_ptr<detail::block_log_impl> my;
101 };
102
103//to derive blknum_offset==14 see block_header.hpp and note on disk struct is packed
104// block_timestamp_type timestamp; //bytes 0:3
105// account_name producer; //bytes 4:11
106// uint16_t confirmed; //bytes 12:13
107// block_id_type previous; //bytes 14:45, low 4 bytes is big endian block number of previous block
108
109 struct trim_data { //used by trim_blocklog_front(), trim_blocklog_end(), and smoke_test()
111 ~trim_data();
114 fc::path block_file_name, index_file_name; //full pathname for blocks.log and blocks.index
115 uint32_t version = 0; //blocklog version
116 uint32_t first_block = 0; //first block in blocks.log
117 uint32_t last_block = 0; //last block in blocks.log
118 FILE* blk_in = nullptr; //C style files for reading blocks.log and blocks.index
119 FILE* ind_in = nullptr; //C style files for reading blocks.log and blocks.index
120 //we use low level file IO because it is distinctly faster than C++ filebuf or iostream
121 uint64_t first_block_pos = 0; //file position in blocks.log for the first block in the log
123
124 static constexpr int blknum_offset{14}; //offset from start of block to 4 byte block number, valid for the only allowed versions
125 };
126} }
wraps boost::filesystem::path to provide platform independent path manipulation.
static bool trim_blocklog_front(const fc::path &block_dir, const fc::path &temp_dir, uint32_t truncate_at_block)
static const uint64_t npos
Definition block_log.hpp:73
static std::optional< genesis_state > extract_genesis_state(const fc::path &data_dir)
static fc::path repair_log(const fc::path &data_dir, uint32_t truncate_at_block=0, const char *reversible_block_dir_name="")
signed_block_ptr read_head() const
static bool contains_chain_id(uint32_t version, uint32_t first_block_num)
const block_id_type & head_id() const
static bool is_supported_version(uint32_t version)
block_log(const fc::path &data_dir, std::optional< block_log_prune_config > prune_config)
static bool is_pruned_log(const fc::path &data_dir)
block_id_type read_block_id_by_num(uint32_t block_num) const
signed_block_ptr read_block(uint64_t file_pos) const
static const uint32_t min_supported_version
Definition block_log.hpp:75
signed_block_ptr read_block_by_id(const block_id_type &id) const
Definition block_log.hpp:60
signed_block_ptr read_block_by_num(uint32_t block_num) const
static void construct_index(const fc::path &block_file_name, const fc::path &index_file_name)
void read_block_header(block_header &bh, uint64_t file_pos) const
uint32_t first_block_num() const
void append(const signed_block_ptr &b)
static chain_id_type extract_chain_id(const fc::path &data_dir)
static bool contains_genesis_state(uint32_t version, uint32_t first_block_num)
uint64_t get_block_pos(uint32_t block_num) const
static const uint32_t max_supported_version
Definition block_log.hpp:76
const signed_block_ptr & head() const
void reset(const genesis_state &gs, const signed_block_ptr &genesis_block)
std::shared_ptr< signed_block > signed_block_ptr
Definition block.hpp:105
const string block_dir
Definition main.cpp:48
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
static uint32_t num_from_id(const block_id_type &id)
std::optional< size_t > vacuum_on_close
Definition block_log.hpp:42
uint64_t block_pos(uint32_t n)
trim_data(fc::path block_dir)
uint64_t block_index(uint32_t n) const
static constexpr int blknum_offset