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

Ported startup improvements from BitShares #62

Merged
merged 4 commits into from
Jan 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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