Skip to content

Commit

Permalink
Merge pull request EOSIO#188 from enumivo/staging
Browse files Browse the repository at this point in the history
Staging
  • Loading branch information
Enumivo authored Jun 5, 2018
2 parents 6d28a12 + 61b5bbd commit 5b51597
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 11 deletions.
6 changes: 5 additions & 1 deletion libraries/chain/block_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ namespace enumivo { namespace chain {
}
} // construct_index

fc::path block_log::repair_log( const fc::path& data_dir ) {
fc::path block_log::repair_log( const fc::path& data_dir, uint32_t truncate_at_block ) {
ilog("Recovering Block Log...");
FC_ASSERT( fc::is_directory(data_dir) && fc::is_regular_file(data_dir / "blocks.log"),
"Block log not found in '${blocks_dir}'", ("blocks_dir", data_dir) );
Expand Down Expand Up @@ -419,6 +419,8 @@ namespace enumivo { namespace chain {
new_block_stream.write( reinterpret_cast<char*>(&pos), sizeof(pos) );
block_num = tmp.block_num();
pos = new_block_stream.tellp();
if( block_num == truncate_at_block )
break;
}

if( bad_block.valid() ) {
Expand Down Expand Up @@ -451,6 +453,8 @@ namespace enumivo { namespace chain {
"has been written out to '${tail_path}'.",
("num", block_num+1)("tail_path", tail_path) );
}
} else if( block_num == truncate_at_block && pos < end_pos ) {
ilog( "Stopped recovery of block log early at specified block number: ${stop}.", ("stop", truncate_at_block) );
} else {
ilog( "Existing block log was undamaged. Recovered all irreversible blocks up to block number ${num}.", ("num", block_num) );
}
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/enumivo/chain/block_log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ namespace enumivo { namespace chain {

static const uint32_t supported_version;

static fc::path repair_log( const fc::path& data_dir );
static fc::path repair_log( const fc::path& data_dir, uint32_t truncate_at_block = 0 );

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

Expand Down
47 changes: 39 additions & 8 deletions plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ void chain_plugin::set_program_options(options_description& cli, options_descrip
"clear chain state database, recover as many blocks as possible from the block log, and then replay those blocks")
("delete-all-blocks", bpo::bool_switch()->default_value(false),
"clear chain state database and block log")
("truncate-at-block", bpo::value<uint32_t>()->default_value(0),
"stop hard replay / block log recovery at this block number (if set to non-zero number)")
;
}

Expand Down Expand Up @@ -282,17 +284,20 @@ void chain_plugin::plugin_initialize(const variables_map& options) {

if( options.at("delete-all-blocks").as<bool>() ) {
ilog("Deleting state database and blocks");
if( options.at("truncate-at-block").as<uint32_t>() > 0 )
wlog("The --truncate-at-block option does not make sense when deleting all blocks.");
fc::remove_all( my->chain_config->state_dir );
fc::remove_all(my->blocks_dir);
} else if( options.at("hard-replay-blockchain").as<bool>() ) {
ilog("Hard replay requested: deleting state database");
fc::remove_all( my->chain_config->state_dir );
auto backup_dir = block_log::repair_log( my->blocks_dir );
auto backup_dir = block_log::repair_log( my->blocks_dir, options.at("truncate-at-block").as<uint32_t>() );
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.
if( !recover_reversible_blocks( backup_dir/config::reversible_blocks_dir_name,
if( !recover_reversible_blocks( backup_dir/config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size,
my->chain_config->blocks_dir/config::reversible_blocks_dir_name ) ) {
my->chain_config->blocks_dir/config::reversible_blocks_dir_name,
options.at("truncate-at-block").as<uint32_t>() ) ) {
ilog("Reversible blocks database was not corrupted. Copying from backup to blocks directory.");
fc::copy( backup_dir / config::reversible_blocks_dir_name,
my->chain_config->blocks_dir / config::reversible_blocks_dir_name );
Expand All @@ -304,21 +309,27 @@ void chain_plugin::plugin_initialize(const variables_map& options) {
}
} else if( options.at("replay-blockchain").as<bool>() ) {
ilog("Replay requested: deleting state database");
if( options.at("truncate-at-block").as<uint32_t>() > 0 )
wlog("The --truncate-at-block option does not work for a regular replay of the blockchain.");
fc::remove_all( my->chain_config->state_dir );
if( options.at("fix-reversible-blocks").as<bool>() ) {
if( !recover_reversible_blocks( my->chain_config->blocks_dir/config::reversible_blocks_dir_name,
if( !recover_reversible_blocks( my->chain_config->blocks_dir/config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size ) ) {
ilog("Reversible blocks database was not corrupted.");
}
}
} else if( options.at("fix-reversible-blocks").as<bool>() ) {
if( !recover_reversible_blocks( my->chain_config->blocks_dir/config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size ) ) {
if( !recover_reversible_blocks( my->chain_config->blocks_dir/config::reversible_blocks_dir_name,
my->chain_config->reversible_cache_size,
optional<fc::path>(),
options.at("truncate-at-block").as<uint32_t>() ) ) {
ilog("Reversible blocks database verified to not be corrupted. Now exiting...");
} else {
ilog("Exiting after fixing reversible blocks database...");
}
ENU_THROW( fixed_reversible_db_exception, "fixed corrupted reversible blocks database" );
} else if( options.at("truncate-at-block").as<uint32_t>() > 0 ) {
wlog("The --truncate-at-block option can only be used with --fix-reversible-blocks without a replay or with --hard-replay-blockchain.");
}

if( options.count("genesis-json") ) {
Expand Down Expand Up @@ -443,10 +454,21 @@ bool chain_plugin::block_is_on_preferred_chain(const block_id_type& block_id) {
return b && b->id() == block_id;
}

bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t cache_size, optional<fc::path> new_db_dir )const {
bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t cache_size,
optional<fc::path> new_db_dir, uint32_t truncate_at_block )const {
try {
chainbase::database reversible( db_dir, database::read_only); // Test if dirty
return false; // If it reaches here, then the reversible database is not dirty
// If it reaches here, then the reversible database is not dirty

if( truncate_at_block == 0 )
return false;

reversible.add_index<reversible_block_index>();
const auto& ubi = reversible.get_index<reversible_block_index,by_num>();

auto itr = ubi.rbegin();
if( itr != ubi.rend() && itr->blocknum <= truncate_at_block )
return false; // Because we are not going to be truncating the reversible database at all.
} catch( const std::runtime_error& ) {
} catch( ... ) {
throw;
Expand Down Expand Up @@ -496,6 +518,10 @@ bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t c
start = itr->blocknum;
end = start - 1;
}
if( truncate_at_block > 0 && start > truncate_at_block ) {
ilog( "Did not recover any reversible blocks since the specified block number to stop at (${stop}) is less than first block in the reversible database (${start}).", ("stop", truncate_at_block)("start", start) );
return true;
}
for( ; itr != ubi.end(); ++itr ) {
FC_ASSERT( itr->blocknum == end + 1, "gap in reversible block database" );
new_reversible.create<reversible_block_object>( [&]( auto& ubo ) {
Expand All @@ -504,9 +530,14 @@ bool chain_plugin::recover_reversible_blocks( const fc::path& db_dir, uint32_t c
});
end = itr->blocknum;
++num;
if( end == truncate_at_block )
break;
}
} catch( ... ) {}

if( end == truncate_at_block )
ilog( "Stopped recovery of reversible blocks early at specified block number: ${stop}", ("stop", truncate_at_block) );

if( num == 0 )
ilog( "There were no recoverable blocks in the reversible block database" );
else if( num == 1 )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,11 @@ class chain_plugin : public plugin<chain_plugin> {

bool block_is_on_preferred_chain(const chain::block_id_type& block_id);

bool recover_reversible_blocks( const fc::path& db_dir, uint32_t cache_size, optional<fc::path> new_db_dir = optional<fc::path>() )const;
bool recover_reversible_blocks( const fc::path& db_dir,
uint32_t cache_size,
optional<fc::path> new_db_dir = optional<fc::path>(),
uint32_t truncate_at_block = 0
)const;

// Only call this in plugin_initialize() to modify controller constructor configuration
controller::config& chain_config();
Expand Down

0 comments on commit 5b51597

Please sign in to comment.