Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Add support for block log splitting #9184

Merged
merged 22 commits into from
Jun 23, 2020
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e9cfda6
Add support for block log splitting
huangminghuang May 29, 2020
3ac568f
Merge branch 'develop' into block-log-split
huangminghuang Jun 10, 2020
efec3c7
bug fixes and PR comments
huangminghuang Jun 10, 2020
34c81d3
rename blocks-split-factor to blocks-log-stride
huangminghuang Jun 11, 2020
f9937b6
allows log file version upgrade after spliting
huangminghuang Jun 11, 2020
dce3cc3
more stride rename
huangminghuang Jun 11, 2020
0745026
add support to recover from incomplete block head automatically
huangminghuang Jun 11, 2020
dd10241
fix bug and modify restart chain test with block num with 3 digits.
huangminghuang Jun 15, 2020
68ec5ae
Merge branch 'develop' into block-log-split
huangminghuang Jun 16, 2020
ebf48b0
add test to split from v1 log
huangminghuang Jun 16, 2020
00eb6c9
use RAII to set blocklog version in unittests
huangminghuang Jun 16, 2020
d15e3b5
remove unneeded code
huangminghuang Jun 17, 2020
d2f8e5b
add comment to address PR concern
huangminghuang Jun 17, 2020
0ebb3fd
added tests for different max_retained_block_files configuration
huangminghuang Jun 18, 2020
5fb2af4
handle retained block log with overlapping ranges
huangminghuang Jun 18, 2020
b069f54
add assertion to protect against bad memory access
huangminghuang Jun 18, 2020
3063759
Address more PR comments
huangminghuang Jun 19, 2020
e2dd458
extend block-log-auto-fix to recovery from corrupted index file
huangminghuang Jun 22, 2020
a674825
change command line option description
huangminghuang Jun 22, 2020
ee3a733
more command line description change
huangminghuang Jun 22, 2020
c158c7b
Some more PR comments fix
huangminghuang Jun 23, 2020
3207d7d
rename allow_block_log_auto_fix to fix_irreversible_blocks
huangminghuang Jun 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
547 changes: 426 additions & 121 deletions libraries/chain/block_log.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ struct controller_impl {
reversible_blocks( cfg.blocks_dir/config::reversible_blocks_dir_name,
cfg.read_only ? database::read_only : database::read_write,
cfg.reversible_cache_size, false, cfg.db_map_mode, cfg.db_hugepage_paths ),
blog( cfg.blocks_dir ),
blog( cfg.blocks_dir, cfg.blocks_archive_dir, cfg.blocks_log_stride, cfg.max_retained_block_files, cfg.allow_block_log_auto_fix),
fork_db( cfg.state_dir ),
wasmif( cfg.wasm_runtime, cfg.eosvmoc_tierup, db, cfg.state_dir, cfg.eosvmoc_config ),
resource_limits( db, [&s]() { return s.get_deep_mind_logger(); }),
Expand Down
8 changes: 5 additions & 3 deletions libraries/chain/include/eosio/chain/block_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace eosio { namespace chain {
namespace detail { class block_log_impl; }

/* The block log is an external append only log of the blocks with a header. Blocks should only
* be written to the log after they irreverisble as the log is append only. The log is a doubly
* be written to the log after they irreversible as the log is append only. The log is a doubly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"after they are irreversible"

* linked list of blocks. There is a secondary index file of only block positions that enables
* O(1) random access lookup by block number.
*
Expand All @@ -34,7 +34,8 @@ namespace eosio { namespace chain {

class block_log {
public:
block_log(const fc::path& data_dir);
block_log(const fc::path& data_dir, fc::path backup_dir = fc::path(), uint64_t stride=1000,
uint16_t max_retained_files=10, bool allow_block_log_auto_fix=false);
block_log(block_log&& other) = default;
~block_log();

Expand Down Expand Up @@ -64,7 +65,7 @@ namespace eosio { namespace chain {
static const uint32_t min_supported_version;
static const uint32_t max_supported_version;

static fc::path repair_log( const fc::path& data_dir, uint32_t truncate_at_block = UINT32_MAX );
static fc::path repair_log( const fc::path& data_dir, uint32_t truncate_at_block = UINT32_MAX, const char* reversible_block_dir_name="" );

static fc::optional<genesis_state> extract_genesis_state( const fc::path& data_dir );

Expand All @@ -83,6 +84,7 @@ namespace eosio { namespace chain {

// used for unit test to generate older version blocklog
static void set_version(uint32_t);
uint32_t version() const;

/**
* @param n Only test 1 block out of every n blocks. If n is 0, it is maximum between 1 and the ceiling of the total number blocks divided by 8.
Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/include/eosio/chain/chain_id_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace chain {

void reflector_init()const;

bool empty() const { return *this == chain_id_type{};}

private:
chain_id_type() = default;

Expand All @@ -51,6 +53,7 @@ namespace chain {
friend struct eosio::handshake_message;
friend class block_log;
friend struct block_log_preamble;
friend struct block_log_catalog;
friend class controller;
friend struct controller_impl;
friend class global_property_object;
Expand Down
5 changes: 4 additions & 1 deletion libraries/chain/include/eosio/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ namespace eosio { namespace chain { namespace config {
typedef __uint128_t uint128_t;

const static auto default_blocks_dir_name = "blocks";
const static auto reversible_blocks_dir_name = "reversible";
const static auto default_blocks_archive_dir_name = "archive";
const static auto default_blocks_log_stride = UINT32_MAX;
const static auto default_max_retained_block_files = 10;
const static auto reversible_blocks_dir_name = "reversible";
const static auto default_reversible_cache_size = 340*1024*1024ll;/// 1MB * 340 blocks based on 21 producer BFT delay
const static auto default_reversible_guard_size = 2*1024*1024ll;/// 1MB * 340 blocks based on 21 producer BFT delay

Expand Down
4 changes: 4 additions & 0 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,23 @@ namespace eosio { namespace chain {
flat_set< pair<account_name, action_name> > action_blacklist;
flat_set<public_key_type> key_blacklist;
path blocks_dir = chain::config::default_blocks_dir_name;
path blocks_archive_dir = chain::config::default_blocks_archive_dir_name;
path state_dir = chain::config::default_state_dir_name;
uint64_t state_size = chain::config::default_state_size;
uint64_t state_guard_size = chain::config::default_state_guard_size;
uint64_t reversible_cache_size = chain::config::default_reversible_cache_size;
uint64_t reversible_guard_size = chain::config::default_reversible_guard_size;
uint32_t sig_cpu_bill_pct = chain::config::default_sig_cpu_bill_pct;
uint16_t thread_pool_size = chain::config::default_controller_thread_pool_size;
uint16_t max_retained_block_files = chain::config::default_max_retained_block_files;
uint64_t blocks_log_stride = chain::config::default_blocks_log_stride;
fc::microseconds abi_serializer_max_time_us = fc::microseconds(chain::config::default_abi_serializer_max_time_us);
bool read_only = false;
bool force_all_checks = false;
bool disable_replay_opts = false;
bool contracts_console = false;
bool allow_ram_billing_in_notify = false;
bool allow_block_log_auto_fix = false;
uint32_t maximum_variable_signature_length = chain::config::default_max_variable_signature_length;
bool disable_all_subjective_mitigations = false; //< for developer & testing purposes, can be configured using `disable-all-subjective-mitigations` when `EOSIO_DEVELOPER` build option is provided
uint32_t terminate_at_block = 0; //< primarily for testing purposes
Expand Down
1 change: 1 addition & 0 deletions libraries/fc/include/fc/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ namespace fc {

bool is_relative()const;
bool is_absolute()const;
bool empty() const;

static char separator_char;

Expand Down
2 changes: 2 additions & 0 deletions libraries/fc/src/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ namespace fc {
bool path::is_relative()const { return _p->is_relative(); }
bool path::is_absolute()const { return _p->is_absolute(); }

bool path::empty() const { return _p->empty(); }

directory_iterator::directory_iterator( const fc::path& p )
:_p(p){}

Expand Down
22 changes: 20 additions & 2 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ class chain_plugin_impl {


fc::optional<fork_database> fork_db;
fc::optional<block_log> block_logger;
fc::optional<controller::config> chain_config;
fc::optional<controller> chain;
fc::optional<genesis_state> genesis;
Expand Down Expand Up @@ -228,6 +227,21 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
cfg.add_options()
("blocks-dir", bpo::value<bfs::path>()->default_value("blocks"),
"the location of the blocks directory (absolute path or relative to application data dir)")
("blocks-log-stride", bpo::value<uint32_t>()->default_value(config::default_blocks_log_stride),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add here (and also in PR API documentation) something like "When the stride is breached, the current blog log and index will be renamed 'blocks--.log/index' and a new current block log and index will be created with the most recent block. All files following this format will be used to construct an extended block log."

"split the block log file when the head block number is the multiple of the split factor\n"
"When the stride is reached, the current block log and index will be renamed 'blocks-num_begin-num_end.log/index'\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use 'block--.log/index' to make it clearer? (here and in the PR documentation)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, markup removed my text
block-<start num>-<end num>.log/index

"and a new current block log and index will be created with the most recent block. All files following\n"
"this format will be used to construct an extended block log.")
("max-retained-block-files", bpo::value<uint16_t>()->default_value(config::default_max_retained_block_files),
"the maximum number of blocks files to retain so that the blocks in those files can be queried.\n"
"When the number is reached, the oldest block file would be move to archive dir or deleted if the archive dir is empty.\n"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"would be moved to archive dir"

"The retained block log files should not be manipulated by users." )
("blocks-archive-dir", bpo::value<bfs::path>()->default_value(config::default_blocks_archive_dir_name),
"the location of the blocks archive directory (absolute path or relative to blocks dir).\n"
"If the value is empty, blocks files beyond the retained limit will be deleted.\n"
"All files in the archive directory are completely under user's control, i.e. they won't be accessed by nodeos anymore.")
("allow-block-log-auto-fix", bpo::value<bool>()->default_value("false"),
"When the existing block log is inconsistent with the index, allows fixing the block log and index files")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should add that it will take the highest indexed block, if it is valid, otherwise it will repair the block log and reconstruct the index.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, add the same to the PR description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

("protocol-features-dir", bpo::value<bfs::path>()->default_value("protocol_features"),
"the location of the protocol_features directory (absolute path or relative to application config dir)")
("checkpoint", bpo::value<vector<string>>()->composing(), "Pairs of [BLOCK_NUM,BLOCK_ID] that should be enforced as checkpoints.")
Expand Down Expand Up @@ -612,7 +626,7 @@ void
chain_plugin::do_hard_replay(const variables_map& options) {
ilog( "Hard replay requested: deleting state database" );
clear_directory_contents( my->chain_config->state_dir );
auto backup_dir = block_log::repair_log( my->blocks_dir, options.at( "truncate-at-block" ).as<uint32_t>());
auto backup_dir = block_log::repair_log( my->blocks_dir, options.at( "truncate-at-block" ).as<uint32_t>(),config::reversible_blocks_dir_name);
if( fc::exists( backup_dir / config::reversible_blocks_dir_name ) ||
options.at( "fix-reversible-blocks" ).as<bool>()) {
// Do not try to recover reversible blocks if the directory does not exist, unless the option was explicitly provided.
Expand Down Expand Up @@ -742,6 +756,10 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
my->chain_config->blocks_dir = my->blocks_dir;
my->chain_config->state_dir = app().data_dir() / config::default_state_dir_name;
my->chain_config->read_only = my->readonly;
my->chain_config->blocks_archive_dir = options.at("blocks-archive-dir").as<bfs::path>();
my->chain_config->blocks_log_stride = options.at("blocks-log-stride").as<uint32_t>();
my->chain_config->max_retained_block_files = options.at("max-retained-block-files").as<uint16_t>();
my->chain_config->allow_block_log_auto_fix = options.at("allow-block-log-auto-fix").as<bool>();

if (auto resmon_plugin = app().find_plugin<resource_monitor_plugin>()) {
resmon_plugin->monitor_directory(my->chain_config->blocks_dir);
Expand Down
1 change: 0 additions & 1 deletion unittests/auth_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <eosio/chain/resource_limits.hpp>
#include <eosio/chain/resource_limits_private.hpp>

#include <eosio/testing/tester_network.hpp>

#ifdef NON_VALIDATING_TEST
#define TESTER tester
Expand Down
1 change: 0 additions & 1 deletion unittests/delay_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <eosio/chain/generated_transaction_object.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/testing/tester_network.hpp>

#include <boost/test/unit_test.hpp>

Expand Down
Loading