Merge branch 'remove_leveldb'

This commit is contained in:
Daniel Larimer 2015-06-16 18:46:25 -04:00
commit 4aa1d6b339
7 changed files with 139 additions and 34 deletions

View file

@ -53,6 +53,7 @@ namespace graphene { namespace chain {
checksum_type signed_block::calculate_merkle_root()const
{
if( transactions.size() == 0 ) return checksum_type();
wdump((transactions.size()));
vector<digest_type> ids;
ids.resize( ((transactions.size() + 1)/2)*2 );

View file

@ -8,12 +8,29 @@ struct index_entry
uint32_t block_size = 0;
block_id_type block_id;
};
}}
FC_REFLECT( graphene::chain::index_entry, (block_pos)(block_size)(block_id) );
namespace graphene { namespace chain {
void block_database::open( const fc::path& dbdir )
{
_block_num_to_pos.open( (dbdir/"index").generic_string().c_str(), std::fstream::binary );
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary );
}
{ try {
idump((sizeof(index_entry)) );
fc::create_directories(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" ) )
{
_block_num_to_pos.open( (dbdir/"index").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 );
_blocks.open( (dbdir/"blocks").generic_string().c_str(), std::fstream::binary | std::fstream::in | std::fstream::out );
}
} FC_CAPTURE_AND_RETHROW( (dbdir) ) }
bool block_database::is_open()const
@ -51,7 +68,7 @@ void block_database::store( const block_id_type& id, const signed_block& b )
void block_database::remove( const block_id_type& id )
{
{ try {
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 );
@ -60,12 +77,13 @@ void block_database::remove( const block_id_type& id )
_block_num_to_pos.seekg( index_pos );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
FC_ASSERT( e.block_id == id );
e.block_size = 0;
_block_num_to_pos.seekp( sizeof(e)*block_header::num_from_id(id) );
_block_num_to_pos.write( (char*)&e, sizeof(e) );
}
if( e.block_id == id )
{
e.block_size = 0;
_block_num_to_pos.seekp( sizeof(e)*block_header::num_from_id(id) );
_block_num_to_pos.write( (char*)&e, sizeof(e) );
}
} FC_CAPTURE_AND_RETHROW( (id) ) }
@ -100,7 +118,7 @@ block_id_type block_database::fetch_block_id( uint32_t block_num )const
optional<signed_block> block_database::fetch_optional( const block_id_type& id )const
{
{ try {
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 );
@ -114,25 +132,31 @@ optional<signed_block> block_database::fetch_optional( const block_id_type& id )
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
return fc::raw::unpack<signed_block>(data);
}
auto result = fc::raw::unpack<signed_block>(data);
FC_ASSERT( result.id() == e.block_id );
return result;
} FC_CAPTURE_AND_RETHROW( (id) ) }
optional<signed_block> block_database::fetch_by_number( uint32_t block_num )const
{
{ try {
index_entry e;
auto index_pos = sizeof(e)*block_num;
_block_num_to_pos.seekg( 0, _block_num_to_pos.end );
FC_ASSERT( _block_num_to_pos.tellg() > index_pos );
_block_num_to_pos.seekg( index_pos );
_block_num_to_pos.seekg( index_pos, _block_num_to_pos.beg );
wdump((int64_t(_block_num_to_pos.tellg())) );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
wdump((block_num)(e));
vector<char> data( e.block_size );
_blocks.seekg( e.block_pos );
_blocks.read( data.data(), e.block_size );
return fc::raw::unpack<signed_block>(data);
}
auto result = fc::raw::unpack<signed_block>(data);
FC_ASSERT( result.id() == e.block_id );
return result;
} FC_CAPTURE_AND_RETHROW( (block_num) ) }
optional<signed_block> block_database::last()const
@ -145,14 +169,21 @@ optional<signed_block> block_database::last()const
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.end );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
while( e.block_size == 0 && _blocks.tellg() > 0 )
{
_block_num_to_pos.seekg( -sizeof(index_entry), _block_num_to_pos.cur );
_block_num_to_pos.read( (char*)&e, sizeof(e) );
}
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 );
return fc::raw::unpack<signed_block>(data);
auto result = fc::raw::unpack<signed_block>(data);
wdump((result));
return result;
}

View file

@ -84,7 +84,6 @@ bool database::push_block( const signed_block& new_block, uint32_t skip )
{ try {
if( !(skip&skip_fork_db) )
{
wdump((new_block.id())(new_block.previous));
auto new_head = _fork_db.push_block( new_block );
//If the head block from the longest chain does not build off of the current head, we need to switch forks.
if( new_head->data.previous != head_block_id() )
@ -115,12 +114,13 @@ bool database::push_block( const signed_block& new_block, uint32_t skip )
try {
auto session = _undo_db.start_undo_session();
apply_block( (*ritr)->data, skip );
_block_id_to_block.store( new_block.id(), (*ritr)->data );
_block_id_to_block.store( (*ritr)->id, (*ritr)->data );
session.commit();
}
catch ( const fc::exception& e ) { except = e; }
if( except )
{
wdump((except->to_detail_string()));
elog( "Encountered error when switching to a longer fork at id ${id}. Going back.",
("id", (*ritr)->id) );
// remove the rest of branches.first from the fork_db, those blocks are invalid
@ -325,7 +325,7 @@ void database::apply_block( const signed_block& next_block, uint32_t skip )
{ try {
_applied_ops.clear();
FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root() );
FC_ASSERT( (skip & skip_merkle_check) || next_block.transaction_merkle_root == next_block.calculate_merkle_root(), "", ("next_block.transaction_merkle_root",next_block.transaction_merkle_root)("calc",next_block.calculate_merkle_root())("next_block",next_block)("id",next_block.id()) );
const witness_object& signing_witness = validate_block_header(skip, next_block);
const auto& global_props = get_global_properties();

View file

@ -41,7 +41,10 @@ void database::open( const fc::path& data_dir, const genesis_allocation& initial
_block_id_to_block.open( data_dir / "database" / "block_num_to_block" );
if( !find(global_property_id_type()) )
{
ilog( "Init Genesis State" );
init_genesis(initial_allocation);
}
_pending_block.previous = head_block_id();
_pending_block.timestamp = head_block_time();
@ -96,6 +99,7 @@ void database::close(uint32_t blocks_to_rewind)
for(uint32_t i = 0; i < blocks_to_rewind && head_block_num() > 0; ++i)
pop_block();
object_database::flush();
object_database::close();
if( _block_id_to_block.is_open() )

View file

@ -177,7 +177,7 @@ namespace graphene { namespace db {
virtual void set_next_id( object_id_type id )override { _next_id = id; }
virtual void open( const path& db )override
{
{
if( !fc::exists( db ) ) return;
fc::file_mapping fm( db.generic_string().c_str(), fc::read_only );
fc::mapped_region mr( fm, fc::read_only, 0, fc::file_size(db) );
@ -195,7 +195,9 @@ namespace graphene { namespace db {
virtual void save( const path& db ) override
{
std::ofstream out( db.generic_string(), std::ofstream::binary );
std::ofstream out( db.generic_string(),
std::ofstream::binary | std::ofstream::out | std::ofstream::trunc );
FC_ASSERT( out );
out.write( (char*)&_next_id, sizeof(_next_id) );
this->inspect_all_objects( [&]( const object& o ) {
auto vec = fc::raw::pack( static_cast<const object_type&>(o) );

View file

@ -68,6 +68,7 @@ void object_database::flush()
ilog("Save object_database in ${d}", ("d", _data_dir));
for( uint32_t space = 0; space < _index.size(); ++space )
{
fc::create_directories( _data_dir / "object_database" / fc::to_string(space) );
const auto types = _index[space].size();
for( uint32_t type = 0; type < types; ++type )
if( _index[space][type] )

View file

@ -37,6 +37,73 @@ using namespace graphene::chain;
BOOST_AUTO_TEST_SUITE(block_tests)
BOOST_AUTO_TEST_CASE( block_database_test )
{
try {
fc::temp_directory data_dir;
block_database bdb;
bdb.open( data_dir.path() );
FC_ASSERT( bdb.is_open() );
bdb.close();
FC_ASSERT( !bdb.is_open() );
bdb.open( data_dir.path() );
signed_block b;
for( uint32_t i = 0; i < 5; ++i )
{
if( i > 0 ) b.previous = b.id();
b.witness = witness_id_type(i+1);
edump((b));
bdb.store( b.id(), b );
auto fetch = bdb.fetch_by_number( b.block_num() );
idump((fetch));
FC_ASSERT( fetch.valid() );
FC_ASSERT( fetch->witness == b.witness );
fetch = bdb.fetch_by_number( i+1 );
idump((fetch));
FC_ASSERT( fetch.valid() );
FC_ASSERT( fetch->witness == b.witness );
fetch = bdb.fetch_optional( b.id() );
idump((fetch));
FC_ASSERT( fetch.valid() );
FC_ASSERT( fetch->witness == b.witness );
}
ilog("-----------" );
for( uint32_t i = 1; i < 5; ++i )
{
auto blk = bdb.fetch_by_number( i );
FC_ASSERT( blk.valid() );
idump((blk)(i));
FC_ASSERT( blk->witness == witness_id_type(blk->block_num()) );
}
auto last = bdb.last();
FC_ASSERT( last );
FC_ASSERT( last->id() == b.id() );
bdb.close();
bdb.open( data_dir.path() );
last = bdb.last();
FC_ASSERT( last );
FC_ASSERT( last->id() == b.id() );
for( uint32_t i = 0; i < 5; ++i )
{
auto blk = bdb.fetch_by_number( i+1 );
FC_ASSERT( blk.valid() );
idump((blk)(i));
FC_ASSERT( blk->witness == witness_id_type(blk->block_num()) );
}
} catch (fc::exception& e) {
edump((e.to_detail_string()));
throw;
}
}
BOOST_AUTO_TEST_CASE( generate_empty_blocks )
{
try {
@ -142,7 +209,7 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
db2.open( data_dir2.path(), genesis_allocation() );
auto delegate_priv_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis")) );
for( uint32_t i = 0; i < 20; ++i )
for( uint32_t i = 0; i < 10; ++i )
{
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
@ -150,20 +217,19 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
db2.push_block(b);
} FC_CAPTURE_AND_RETHROW( ("db2") );
}
for( uint32_t i = 20; i < 23; ++i )
for( uint32_t i = 10; i < 13; ++i )
{
now += db1.block_interval();
auto b = db1.generate_block( now, db1.get_scheduled_witness( 1 ).first, delegate_priv_key );
}
string db1_tip = db1.head_block_id().str();
for( uint32_t i = 23; i < 26; ++i )
for( uint32_t i = 13; i < 16; ++i )
{
now += db2.block_interval();
auto b = db2.generate_block( now, db2.get_scheduled_witness( db2.get_slot_at_time( now ) ).first, delegate_priv_key );
// notify both databases of the new block.
// only db2 should switch to the new fork, db1 should not
db1.push_block(b);
db2.push_block(b);
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db1_tip);
BOOST_CHECK_EQUAL(db2.head_block_id().str(), b.id().str());
}
@ -171,8 +237,8 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
//The two databases are on distinct forks now, but at the same height. Make a block on db2, make it invalid, then
//pass it to db1 and assert that db1 doesn't switch to the new fork.
signed_block good_block;
BOOST_CHECK_EQUAL(db1.head_block_num(), 23);
BOOST_CHECK_EQUAL(db2.head_block_num(), 23);
BOOST_CHECK_EQUAL(db1.head_block_num(), 13);
BOOST_CHECK_EQUAL(db2.head_block_num(), 13);
{
now += db2.block_interval();
auto b = db2.generate_block( now, db2.get_scheduled_witness( 1 ).first, delegate_priv_key );
@ -180,14 +246,14 @@ BOOST_AUTO_TEST_CASE( fork_blocks )
b.transactions.emplace_back(signed_transaction());
b.transactions.back().operations.emplace_back(transfer_operation());
b.sign(delegate_priv_key);
BOOST_CHECK_EQUAL(b.block_num(), 24);
BOOST_CHECK_EQUAL(b.block_num(), 14);
BOOST_CHECK_THROW(db1.push_block(b), fc::exception);
}
BOOST_CHECK_EQUAL(db1.head_block_num(), 23);
BOOST_CHECK_EQUAL(db1.head_block_num(), 13);
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db1_tip);
// assert that db1 switches to new fork with good block
BOOST_CHECK_EQUAL(db2.head_block_num(), 24);
BOOST_CHECK_EQUAL(db2.head_block_num(), 14);
db1.push_block(good_block);
BOOST_CHECK_EQUAL(db1.head_block_id().str(), db2.head_block_id().str());
} catch (fc::exception& e) {