Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
update database api #512
Browse files Browse the repository at this point in the history
  • Loading branch information
bytemaster committed Oct 14, 2017
1 parent 867e4da commit e0c183e
Show file tree
Hide file tree
Showing 3 changed files with 353 additions and 151 deletions.
93 changes: 70 additions & 23 deletions libraries/blockchain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ database::database( const path& dir, uint64_t shared_file_size ) {
if( !_scopes ) {
BOOST_THROW_EXCEPTION( std::runtime_error( "unable to find 'scopes' in shared memory file" ) );
}
_undo_stack = _segment->find< shared_deque<undo_state> >( "undo_stack" ).first;
_undo_stack = _segment->find< shared_deque<database_undo_state> >( "undo_stack" ).first;
if( !_undo_stack ) {
BOOST_THROW_EXCEPTION( std::runtime_error( "unable to find 'undo_stack' in shared memory file" ) );
}
Expand All @@ -73,7 +73,7 @@ database::database( const path& dir, uint64_t shared_file_size ) {
_segment->find_or_construct< environment_check >( "environment" )();

_scopes = _segment->find_or_construct< scopes_type >( "scopes" )( _segment->get_segment_manager() );
_undo_stack = _segment->find_or_construct< shared_deque<undo_state> >( "undo_stack" )( _segment->get_segment_manager() );
_undo_stack = _segment->find_or_construct< shared_deque<database_undo_state> >( "undo_stack" )( _segment->get_segment_manager() );
}
}

Expand Down Expand Up @@ -111,7 +111,9 @@ scope_state& database::get_scope( scope_name scope ) {
}


const scope_state& database::create_scope( scope_name scope ) {
void database::create_scope( database_undo_state& duds, scope_name scope ) {
FC_ASSERT( &duds == &_undo_stack->back(), "attempt to create scope in prior revision" );

auto memory = _segment->get_segment_manager();

auto scope_itr = _scopes->find( scope );
Expand All @@ -122,12 +124,11 @@ const scope_state& database::create_scope( scope_name scope ) {
scope_itr = _scopes->emplace( scope, state ).first;
scope_itr->second->_name = scope;

if( _undo_stack->size() ) {
_undo_stack->back().new_scopes.emplace_back( state );
}
duds.new_scopes.emplace_back( state );
}
return *scope_itr->second;
/*return *scope_itr->second;*/
}

void database::delete_scope( scope_state& scope ) {
auto scope_name = scope._name;
idump((scope_name));
Expand Down Expand Up @@ -174,9 +175,11 @@ void database::undo()
auto& changes = _undo_stack->back();
auto prior_revision = changes.revision - 1;

for( const auto& thread : changes.threads ) {
for( const auto& thread : changes.shards ) {
for( const auto& mod_table : thread.modified_tables ) {
ilog( ".");
get_interface(*mod_table.second).undo_until( *mod_table.second, prior_revision );
ilog( ".");
}
for( auto new_table : thread.new_tables )
delete_table( get_scope( new_table.first ).get_table( new_table.second ) );
Expand Down Expand Up @@ -204,42 +207,44 @@ void database::set_revision( uint64_t revision ) {
_undo_stack->back().revision = revision;
}

database::thread_undo_state* database::find_thread_undo_state_for_scope( scope_name scope )const {
shard_undo_state* database::find_shard_undo_state_for_scope( scope_name scope )const {
if( !_undo_stack->size() ) return nullptr;
auto& head = _undo_stack->back();
auto itr = head.thread_undo_states.find( scope );
if( itr == head.thread_undo_states.end() )
auto itr = head.shard_undo_states.find( scope );
if( itr == head.shard_undo_states.end() )
return nullptr;
return itr->second.get();
}

database::thread database::start_thread( const flat_set<scope_name>& scopes, const flat_set<scope_name>& read_scopes ) {
shard database::start_shard( database_undo_state& duds, const flat_set<scope_name>& scopes, const flat_set<scope_name>& read_scopes ) {
FC_ASSERT( _undo_stack->size() );
auto& head = _undo_stack->back();

FC_ASSERT( &head == &duds, "attempt to start a shard in a prior database revision" ); /// TODO: make this a debug assert, this is a programmer error

for( const auto& scope : scopes ) {
auto tuds = find_thread_undo_state_for_scope( scope );
FC_ASSERT( tuds == nullptr, "scope already in use by another thread" );
auto suds = find_shard_undo_state_for_scope( scope );
FC_ASSERT( suds == nullptr, "scope already in use by another shard" );
FC_ASSERT( head.read_locks.find( scope ) == head.read_locks.end(), "scope ${n} is already locked for reading", ("n",scope) );
}

for( auto read_scope : read_scopes ) {
FC_ASSERT( scopes.find(read_scope) == scopes.end(), "cannot ask for RO & RW for same scope: ${n}", ("n",read_scope) );
auto tuds = find_thread_undo_state_for_scope( read_scope );
FC_ASSERT( !tuds, "attempt to grab read scope for scope '${n}' that is already open with write lock", ("n",read_scope) );
auto suds = find_shard_undo_state_for_scope( read_scope );
FC_ASSERT( !suds, "attempt to grab read scope for scope '${n}' that is already open with write lock", ("n",read_scope) );
head.read_locks.insert(read_scope);
}

head.threads.emplace_back( _segment->get_segment_manager() );
auto& tuds = head.threads.back();
tuds.db_undo_state = &head;
tuds.write_scopes.reserve(scopes.size());
head.shards.emplace_back( _segment->get_segment_manager() );
auto& suds = head.shards.back();
suds.db_undo_state = &head;
suds.write_scopes.reserve(scopes.size());
for( auto scope : scopes ) {
head.thread_undo_states[scope] = &tuds;
tuds.write_scopes.push_back(scope);
head.shard_undo_states[scope] = &suds;
suds.write_scopes.push_back(scope);
}

return thread( *this, tuds );
return shard( *this, suds );
} /// start_thread

void database::push_revision(uint64_t revision) {
Expand All @@ -254,6 +259,48 @@ void database::pop_revision( uint64_t revision ) {
while( _undo_stack->size() && _undo_stack->back().revision >= revision )
undo();
}
void database::commit_revision( uint64_t revision ) {
while( _undo_stack->size() && _undo_stack->front().revision < revision )
_undo_stack->pop_front();
}


void shard::delete_table( const table& tbl ) {
/// TODO: verify scope
_db.delete_table( tbl );
}

session database::start_session( uint64_t revision ) {
push_revision( revision );
return session( *this, _undo_stack->back() );
}

session::session( database& db, database_undo_state& duds )
:_db(db),_duds(duds){}

session::~session() {
if( _undo ) undo();
}

void session::undo() {
ilog( "undo session" );
FC_ASSERT( _undo, "changes already undone or committed" );
_undo = false;
_db.pop_revision( _duds.revision );
}

void session::push() {
ilog( "commit session" );
_undo = false;
}

shard session::start_shard( const flat_set<scope_name>& scopes, const flat_set<scope_name>& read_scopes ) {
return _db.start_shard( _duds, scopes, read_scopes );
}

void session::create_scope( scope_name s ) {
_db.create_scope( _duds, s );
}


} } /// eosio::blockchain
Loading

0 comments on commit e0c183e

Please sign in to comment.