Skip to content
This repository has been archived by the owner on Dec 29, 2018. It is now read-only.

Commit

Permalink
Merge pull request #62 from pmconrad/issue_5
Browse files Browse the repository at this point in the history
Ported startup improvements from BitShares
  • Loading branch information
pmconrad committed Jan 21, 2018
2 parents f618f3a + 37d20bb commit ba38260
Show file tree
Hide file tree
Showing 13 changed files with 321 additions and 246 deletions.
74 changes: 16 additions & 58 deletions libraries/app/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ namespace detail {

~application_impl()
{
fc::remove_all(_data_dir / "blockchain/dblock");
}

void register_builtin_apis()
Expand All @@ -248,29 +247,23 @@ namespace detail {

void startup()
{ try {
bool clean = !fc::exists(_data_dir / "blockchain/dblock");
fc::create_directories(_data_dir / "blockchain/dblock");
fc::create_directories(_data_dir / "blockchain");
fc::create_directories(_data_dir / "node/transaction_history");



auto initial_state = [&] {
auto initial_state = [this] {
ilog("Initializing database...");
if( _options->count("genesis-json") ){
//FC_ASSERT( egenesis_json != "" );
//FC_ASSERT( muse::egenesis::get_egenesis_json_hash() == fc::sha256::hash( egenesis_json ) );
if( _options->count("genesis-json") )
{
fc::path genesis_path(_options->at("genesis-json").as<boost::filesystem::path>());
auto genesis = fc::json::from_file( genesis_path ).as<genesis_state_type>();
genesis.initial_chain_id = MUSE_CHAIN_ID; //fc::sha256::hash( egenesis_json );
genesis.initial_chain_id = MUSE_CHAIN_ID;
return genesis;

} else {
std::string egenesis_json;
muse::egenesis::compute_egenesis_json(egenesis_json);
//FC_ASSERT( egenesis_json != "" );
//FC_ASSERT( muse::egenesis::get_egenesis_json_hash() == fc::sha256::hash( egenesis_json ) );
auto genesis = fc::json::from_string(egenesis_json).as<genesis_state_type>();
genesis.initial_chain_id = MUSE_CHAIN_ID; //fc::sha256::hash( egenesis_json );
genesis.initial_chain_id = MUSE_CHAIN_ID;
return genesis;
}
};
Expand All @@ -295,53 +288,18 @@ namespace detail {
_chain_db->add_checkpoints( loaded_checkpoints );

if( _options->count("replay-blockchain") )
{
ilog("Replaying blockchain on user request.");
_chain_db->reindex(_data_dir/"blockchain", initial_state() );
} else if( clean ) {
_chain_db->wipe( _data_dir / "blockchain", false );

auto is_new = [&]() -> bool
{
// directory doesn't exist
if( !fc::exists( _data_dir ) )
return true;
// if directory exists but is empty, return true; else false.
return ( fc::directory_iterator( _data_dir ) == fc::directory_iterator() );
};

auto is_outdated = [&]() -> bool
{
if( !fc::exists( _data_dir / "db_version" ) )
return true;
std::string version_str;
fc::read_file_contents( _data_dir / "db_version", version_str );
return (version_str != GRAPHENE_CURRENT_DB_VERSION);
};
if( !is_new() && is_outdated() )
{
ilog("Replaying blockchain due to version upgrade");

fc::remove_all( _data_dir / "db_version" );
_chain_db->reindex(_data_dir / "blockchain", initial_state() );

// doing this down here helps ensure that DB will be wiped
// if any of the above steps were interrupted on a previous run
if( !fc::exists( _data_dir / "db_version" ) )
{
std::ofstream db_version(
(_data_dir / "db_version").generic_string().c_str(),
std::ios::out | std::ios::binary | std::ios::trunc );
std::string version_string = GRAPHENE_CURRENT_DB_VERSION;
db_version.write( version_string.c_str(), version_string.size() );
db_version.close();
}
} else {
_chain_db->open(_data_dir / "blockchain", initial_state() );
}
} else {
wlog("Detected unclean shutdown. Replaying blockchain...");
_chain_db->reindex(_data_dir / "blockchain", initial_state() );
try
{
_chain_db->open( _data_dir / "blockchain", initial_state(), GRAPHENE_CURRENT_DB_VERSION );
}
catch( const fc::exception& e )
{
elog( "Caught exception ${e} in open(), you might want to force a replay", ("e", e.to_detail_string()) );
throw;
}

_pending_trx_db->open(_data_dir / "node/transaction_history" );

if( _options->count("force-validate") )
Expand Down
95 changes: 44 additions & 51 deletions libraries/chain/block_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ void block_database::open( const fc::path& dbdir )
_block_num_to_pos.exceptions(std::ios_base::failbit | std::ios_base::badbit);
_blocks.exceptions(std::ios_base::failbit | std::ios_base::badbit);

if( !fc::exists( dbdir/"index" ) )
_index_filename = dbdir / "index";
if( !fc::exists( _index_filename ) )
{
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
_block_num_to_pos.open( _index_filename.generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
}
else
{
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
_block_num_to_pos.open( _index_filename.generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
}
} FC_CAPTURE_AND_RETHROW( (dbdir) ) }
Expand Down Expand Up @@ -96,7 +97,7 @@ bool block_database::contains( const block_id_type& id )const
index_entry e;
auto index_pos = sizeof(e)*block_header::num_from_id(id);
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
if ( _block_num_to_pos.tellg() <= index_pos )
if ( _block_num_to_pos.tellg() < index_pos + sizeof(e) )
return false;
_block_num_to_pos.seekg( index_pos );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
Expand Down Expand Up @@ -181,77 +182,69 @@ optional<signed_block> block_database::fetch_by_number( uint32_t block_num )cons
return optional<signed_block>();
}

optional<signed_block> block_database::last()const
{
optional<index_entry> block_database::last_index_entry()const {
try
{
index_entry e;

_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
std::streampos pos = _block_num_to_pos.tellg();
if( pos < sizeof(index_entry) )
return optional<index_entry>();

if( _block_num_to_pos.tellp() < sizeof(index_entry) )
return optional<signed_block>();
pos -= pos % sizeof(index_entry);

_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
uint64_t pos = _block_num_to_pos.tellg();
while( e.block_size == 0 && pos > 0 )
_blocks.seekg( 0, _block_num_to_pos.end );
const std::streampos blocks_size = _blocks.tellg();
while( pos > 0 )
{
pos -= sizeof(index_entry);
_block_num_to_pos.seekg( pos );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
if( _block_num_to_pos.gcount() == sizeof(e) && e.block_size > 0
&& e.block_pos + e.block_size <= blocks_size )
try
{
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
if( _blocks.gcount() == e.block_size )
{
const signed_block block = fc::raw::unpack<signed_block>(data);
if( block.id() == e.block_id )
return e;
}
}
catch (const fc::exception&)
{
}
catch (const std::exception&)
{
}
fc::resize_file( _index_filename, pos );
}

if( e.block_size == 0 )
return optional<signed_block>();

vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
auto result = fc::raw::unpack<signed_block>(data);
return result;
}
catch (const fc::exception&)
{
}
catch (const std::exception&)
{
}
return optional<index_entry>();
}

optional<signed_block> block_database::last()const
{
optional<index_entry> entry = last_index_entry();
if( entry.valid() ) return fetch_by_number( block_header::num_from_id(entry->block_id) );
return optional<signed_block>();
}

optional<block_id_type> block_database::last_id()const
{
try
{
index_entry e;
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );

if( _block_num_to_pos.tellp() < sizeof(index_entry) )
return optional<block_id_type>();

_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
uint64_t pos = _block_num_to_pos.tellg();
while( e.block_size == 0 && pos > 0 )
{
pos -= sizeof(index_entry);
_block_num_to_pos.seekg( pos );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
}

if( e.block_size == 0 )
return optional<block_id_type>();

return e.block_id;
}
catch (const fc::exception&)
{
}
catch (const std::exception&)
{
}
optional<index_entry> entry = last_index_entry();
if( entry.valid() ) return entry->block_id;
return optional<block_id_type>();
}


} }
Loading

0 comments on commit ba38260

Please sign in to comment.