Skip to content

Commit ce1321c

Browse files
authored
Merge branch 'develop' into feature/GRPH-99
2 parents 0a00ced + 96161db commit ce1321c

18 files changed

Lines changed: 361 additions & 220 deletions

libraries/app/application.cpp

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,6 @@ namespace detail {
300300

301301
~application_impl()
302302
{
303-
fc::remove_all(_data_dir / "blockchain/dblock");
304303
}
305304

306305
void set_dbg_init_key( genesis_state_type& genesis, const std::string& init_key )
@@ -314,8 +313,7 @@ namespace detail {
314313

315314
void startup()
316315
{ try {
317-
bool clean = !fc::exists(_data_dir / "blockchain/dblock");
318-
fc::create_directories(_data_dir / "blockchain/dblock");
316+
fc::create_directories(_data_dir / "blockchain");
319317

320318
auto initial_state = [&] {
321319
ilog("Initializing database...");
@@ -381,64 +379,17 @@ namespace detail {
381379
bool replay = false;
382380
std::string replay_reason = "reason not provided";
383381

384-
// never replay if data dir is empty
385-
if( fc::exists( _data_dir ) && fc::directory_iterator( _data_dir ) != fc::directory_iterator() )
386-
{
387-
if( _options->count("replay-blockchain") )
388-
{
389-
replay = true;
390-
replay_reason = "replay-blockchain argument specified";
391-
}
392-
else if( !clean )
393-
{
394-
replay = true;
395-
replay_reason = "unclean shutdown detected";
396-
}
397-
else if( !fc::exists( _data_dir / "db_version" ) )
398-
{
399-
replay = true;
400-
replay_reason = "db_version file not found";
401-
}
402-
else
403-
{
404-
std::string version_string;
405-
fc::read_file_contents( _data_dir / "db_version", version_string );
382+
if( _options->count("replay-blockchain") )
383+
_chain_db->wipe( _data_dir / "blockchain", false );
406384

407-
if( version_string != GRAPHENE_CURRENT_DB_VERSION )
408-
{
409-
replay = true;
410-
replay_reason = "db_version file content mismatch";
411-
}
412-
}
413-
}
414-
415-
if( !replay )
385+
try
416386
{
417-
try
418-
{
419-
_chain_db->open( _data_dir / "blockchain", initial_state );
420-
}
421-
catch( const fc::exception& e )
422-
{
423-
ilog( "Caught exception ${e} in open()", ("e", e.to_detail_string()) );
424-
425-
replay = true;
426-
replay_reason = "exception in open()";
427-
}
387+
_chain_db->open( _data_dir / "blockchain", initial_state, GRAPHENE_CURRENT_DB_VERSION );
428388
}
429-
430-
if( replay )
389+
catch( const fc::exception& e )
431390
{
432-
ilog( "Replaying blockchain due to: ${reason}", ("reason", replay_reason) );
433-
434-
fc::remove_all( _data_dir / "db_version" );
435-
_chain_db->reindex( _data_dir / "blockchain", initial_state() );
436-
437-
const auto mode = std::ios::out | std::ios::binary | std::ios::trunc;
438-
std::ofstream db_version( (_data_dir / "db_version").generic_string().c_str(), mode );
439-
std::string version_string = GRAPHENE_CURRENT_DB_VERSION;
440-
db_version.write( version_string.c_str(), version_string.size() );
441-
db_version.close();
391+
elog( "Caught exception ${e} in open(), you might want to force a replay", ("e", e.to_detail_string()) );
392+
throw;
442393
}
443394

444395
if( _options->count("force-validate") )

libraries/chain/block_database.cpp

Lines changed: 44 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,15 @@ void block_database::open( const fc::path& dbdir )
4545
_block_num_to_pos.exceptions(std::ios_base::failbit | std::ios_base::badbit);
4646
_blocks.exceptions(std::ios_base::failbit | std::ios_base::badbit);
4747

48-
if( !fc::exists( dbdir/"index" ) )
48+
_index_filename = dbdir / "index";
49+
if( !fc::exists( _index_filename ) )
4950
{
50-
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
51+
_block_num_to_pos.open( _index_filename.generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
5152
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
5253
}
5354
else
5455
{
55-
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
56+
_block_num_to_pos.open( _index_filename.generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
5657
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
5758
}
5859
} FC_CAPTURE_AND_RETHROW( (dbdir) ) }
@@ -121,7 +122,7 @@ bool block_database::contains( const block_id_type& id )const
121122
index_entry e;
122123
auto index_pos = sizeof(e)*block_header::num_from_id(id);
123124
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
124-
if ( _block_num_to_pos.tellg() <= index_pos )
125+
if ( _block_num_to_pos.tellg() < index_pos + sizeof(e) )
125126
return false;
126127
_block_num_to_pos.seekg( index_pos );
127128
_block_num_to_pos.read( (char*)&e, sizeof(e) );
@@ -206,77 +207,69 @@ optional<signed_block> block_database::fetch_by_number( uint32_t block_num )cons
206207
return optional<signed_block>();
207208
}
208209

209-
optional<signed_block> block_database::last()const
210-
{
210+
optional<index_entry> block_database::last_index_entry()const {
211211
try
212212
{
213213
index_entry e;
214+
214215
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
216+
std::streampos pos = _block_num_to_pos.tellg();
217+
if( pos < sizeof(index_entry) )
218+
return optional<index_entry>();
215219

216-
if( _block_num_to_pos.tellp() < sizeof(index_entry) )
217-
return optional<signed_block>();
220+
pos -= pos % sizeof(index_entry);
218221

219-
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
220-
_block_num_to_pos.read( (char*)&e, sizeof(e) );
221-
uint64_t pos = _block_num_to_pos.tellg();
222-
while( e.block_size == 0 && pos > 0 )
222+
_blocks.seekg( 0, _block_num_to_pos.end );
223+
const std::streampos blocks_size = _blocks.tellg();
224+
while( pos > 0 )
223225
{
224226
pos -= sizeof(index_entry);
225227
_block_num_to_pos.seekg( pos );
226228
_block_num_to_pos.read( (char*)&e, sizeof(e) );
229+
if( _block_num_to_pos.gcount() == sizeof(e) && e.block_size > 0
230+
&& e.block_pos + e.block_size <= blocks_size )
231+
try
232+
{
233+
vector<char> data( e.block_size );
234+
_blocks.seekg( e.block_pos );
235+
_blocks.read( data.data(), e.block_size );
236+
if( _blocks.gcount() == e.block_size )
237+
{
238+
const signed_block block = fc::raw::unpack<signed_block>(data);
239+
if( block.id() == e.block_id )
240+
return e;
241+
}
242+
}
243+
catch (const fc::exception&)
244+
{
245+
}
246+
catch (const std::exception&)
247+
{
248+
}
249+
fc::resize_file( _index_filename, pos );
227250
}
228-
229-
if( e.block_size == 0 )
230-
return optional<signed_block>();
231-
232-
vector<char> data( e.block_size );
233-
_blocks.seekg( e.block_pos );
234-
_blocks.read( data.data(), e.block_size );
235-
auto result = fc::raw::unpack<signed_block>(data);
236-
return result;
237251
}
238252
catch (const fc::exception&)
239253
{
240254
}
241255
catch (const std::exception&)
242256
{
243257
}
258+
return optional<index_entry>();
259+
}
260+
261+
optional<signed_block> block_database::last()const
262+
{
263+
optional<index_entry> entry = last_index_entry();
264+
if( entry.valid() ) return fetch_by_number( block_header::num_from_id(entry->block_id) );
244265
return optional<signed_block>();
245266
}
246267

247268
optional<block_id_type> block_database::last_id()const
248269
{
249-
try
250-
{
251-
index_entry e;
252-
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
253-
254-
if( _block_num_to_pos.tellp() < sizeof(index_entry) )
255-
return optional<block_id_type>();
256-
257-
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
258-
_block_num_to_pos.read( (char*)&e, sizeof(e) );
259-
uint64_t pos = _block_num_to_pos.tellg();
260-
while( e.block_size == 0 && pos > 0 )
261-
{
262-
pos -= sizeof(index_entry);
263-
_block_num_to_pos.seekg( pos );
264-
_block_num_to_pos.read( (char*)&e, sizeof(e) );
265-
}
266-
267-
if( e.block_size == 0 )
268-
return optional<block_id_type>();
269-
270-
return e.block_id;
271-
}
272-
catch (const fc::exception&)
273-
{
274-
}
275-
catch (const std::exception&)
276-
{
277-
}
270+
optional<index_entry> entry = last_index_entry();
271+
if( entry.valid() ) return entry->block_id;
278272
return optional<block_id_type>();
279273
}
280274

281-
282275
} }

libraries/chain/db_block.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,15 @@ bool database::_push_block(const signed_block& new_block)
215215

216216
// pop blocks until we hit the forked block
217217
while( head_block_id() != branches.second.back()->data.previous )
218+
{
219+
ilog( "popping block #${n} ${id}", ("n",head_block_num())("id",head_block_id()) );
218220
pop_block();
221+
}
219222

220223
// push all blocks on the new fork
221224
for( auto ritr = branches.first.rbegin(); ritr != branches.first.rend(); ++ritr )
222225
{
223-
ilog( "pushing blocks from fork ${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->data.id()) );
226+
ilog( "pushing block from fork #${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->id) );
224227
optional<fc::exception> except;
225228
try {
226229
undo_database::session session = _undo_db.start_undo_session();
@@ -235,21 +238,27 @@ bool database::_push_block(const signed_block& new_block)
235238
// remove the rest of branches.first from the fork_db, those blocks are invalid
236239
while( ritr != branches.first.rend() )
237240
{
238-
_fork_db.remove( (*ritr)->data.id() );
241+
ilog( "removing block from fork_db #${n} ${id}", ("n",(*ritr)->data.block_num())("id",(*ritr)->id) );
242+
_fork_db.remove( (*ritr)->id );
239243
++ritr;
240244
}
241245
_fork_db.set_head( branches.second.front() );
242246

243247
// pop all blocks from the bad fork
244248
while( head_block_id() != branches.second.back()->data.previous )
249+
{
250+
ilog( "popping block #${n} ${id}", ("n",head_block_num())("id",head_block_id()) );
245251
pop_block();
252+
}
246253

254+
ilog( "Switching back to fork: ${id}", ("id",branches.second.front()->data.id()) );
247255
// restore all blocks from the good fork
248-
for( auto ritr = branches.second.rbegin(); ritr != branches.second.rend(); ++ritr )
256+
for( auto ritr2 = branches.second.rbegin(); ritr2 != branches.second.rend(); ++ritr2 )
249257
{
258+
ilog( "pushing block #${n} ${id}", ("n",(*ritr2)->data.block_num())("id",(*ritr2)->id) );
250259
auto session = _undo_db.start_undo_session();
251-
apply_block( (*ritr)->data, skip );
252-
_block_id_to_block.store( new_block.id(), (*ritr)->data );
260+
apply_block( (*ritr2)->data, skip );
261+
_block_id_to_block.store( (*ritr2)->id, (*ritr2)->data );
253262
session.commit();
254263
}
255264
throw *except;
@@ -506,7 +515,6 @@ void database::pop_block()
506515
GRAPHENE_ASSERT( head_block.valid(), pop_empty_chain, "there are no blocks to pop" );
507516

508517
_fork_db.pop_block();
509-
_block_id_to_block.remove( head_id );
510518
pop_undo();
511519

512520
_popped_tx.insert( _popped_tx.begin(), head_block->transactions.begin(), head_block->transactions.end() );

0 commit comments

Comments
 (0)