Bug/issue317 #682

Closed
pavel.baykov wants to merge 4 commits from bug/issue317 into develop
9 changed files with 43 additions and 16 deletions

View file

@ -585,14 +585,16 @@ signed_block database::_generate_block(
* Removes the most recent block from the database and * Removes the most recent block from the database and
* undoes any changes it made. * undoes any changes it made.
*/ */
void database::pop_block() void database::pop_block(bool check)
{ try { { try {
_pending_tx_session.reset(); _pending_tx_session.reset();
auto head_id = head_block_id(); auto head_id = head_block_id();
optional<signed_block> head_block = fetch_block_by_id( head_id ); optional<signed_block> head_block = fetch_block_by_id( head_id );
GRAPHENE_ASSERT( head_block.valid(), pop_empty_chain, "there are no blocks to pop" ); GRAPHENE_ASSERT( head_block.valid(), pop_empty_chain, "there are no blocks to pop" );
_fork_db.pop_block(); ilog( "head_block is ${dump}", ("dump", head_block) );
_fork_db.pop_block(check);
pop_undo(); pop_undo();
_popped_tx.insert( _popped_tx.begin(), head_block->transactions.begin(), head_block->transactions.end() ); _popped_tx.insert( _popped_tx.begin(), head_block->transactions.begin(), head_block->transactions.end() );

View file

@ -259,11 +259,12 @@ void database::close(bool rewind)
try try
{ {
uint32_t cutoff = get_dynamic_global_properties().last_irreversible_block_num; uint32_t cutoff = get_dynamic_global_properties().last_irreversible_block_num;
//ilog("cutoff = ${c}", ("c", cutoff));
while( head_block_num() > cutoff ) while( head_block_num() > cutoff )
{ {
//ilog("head_block_num() = ${id}", ("id", head_block_num()));
block_id_type popped_block_id = head_block_id(); block_id_type popped_block_id = head_block_id();
pop_block(); pop_block( head_block_num() == cutoff + 1 ? false : true);
_fork_db.remove(popped_block_id); // doesn't throw on missing _fork_db.remove(popped_block_id); // doesn't throw on missing
} }
} }

View file

@ -35,11 +35,13 @@ void fork_database::reset()
_index.clear(); _index.clear();
} }
void fork_database::pop_block() void fork_database::pop_block(bool check)
{ {
FC_ASSERT( _head, "no blocks to pop" ); FC_ASSERT( _head, "no blocks to pop" );
auto prev = _head->prev.lock(); auto prev = _head->prev.lock();
FC_ASSERT( prev, "poping block would leave head block null" ); if (check){
FC_ASSERT( prev, "poping block would leave head block null" );
}
_head = prev; _head = prev;
} }

View file

@ -163,7 +163,7 @@ namespace graphene { namespace chain {
const fc::ecc::private_key& block_signing_private_key const fc::ecc::private_key& block_signing_private_key
); );
void pop_block(); void pop_block(bool check = true);
void clear_pending(); void clear_pending();
/** /**

View file

@ -92,7 +92,7 @@ namespace graphene { namespace chain {
*/ */
shared_ptr<fork_item> push_block(const signed_block& b); shared_ptr<fork_item> push_block(const signed_block& b);
shared_ptr<fork_item> head()const { return _head; } shared_ptr<fork_item> head()const { return _head; }
void pop_block(); void pop_block(bool check);
/** /**
* Given two head blocks, return two branches of the fork graph that * Given two head blocks, return two branches of the fork graph that

View file

@ -34,9 +34,6 @@ namespace graphene { namespace chain {
>, >,
ordered_unique< tag<by_valid_from>, ordered_unique< tag<by_valid_from>,
member<son_wallet_object, time_point_sec, &son_wallet_object::valid_from> member<son_wallet_object, time_point_sec, &son_wallet_object::valid_from>
>,
ordered_unique< tag<by_expires>,
member<son_wallet_object, time_point_sec, &son_wallet_object::expires>
> >
> >
>; >;

View file

@ -25,6 +25,9 @@
#include <graphene/db/object.hpp> #include <graphene/db/object.hpp>
#include <deque> #include <deque>
#include <fc/exception/exception.hpp> #include <fc/exception/exception.hpp>
#include <fc/thread/spin_yield_lock.hpp>
#include <fc/fwd.hpp>
#include <fc/thread/unique_lock.hpp>
namespace graphene { namespace db { namespace graphene { namespace db {
@ -132,6 +135,8 @@ namespace graphene { namespace db {
std::deque<undo_state> _stack; std::deque<undo_state> _stack;
object_database& _db; object_database& _db;
size_t _max_size = 256; size_t _max_size = 256;
mutable fc::spin_yield_lock _spin_yield;
}; };
} } // graphene::db } } // graphene::db

View file

@ -25,6 +25,8 @@
#include <graphene/db/undo_database.hpp> #include <graphene/db/undo_database.hpp>
#include <fc/reflect/variant.hpp> #include <fc/reflect/variant.hpp>
#include <fc/thread/spin_yield_lock.hpp>
namespace graphene { namespace db { namespace graphene { namespace db {
void undo_database::enable() { _disabled = false; } void undo_database::enable() { _disabled = false; }
@ -44,6 +46,8 @@ undo_database::session::~session() {
undo_database::session undo_database::start_undo_session( bool force_enable ) undo_database::session undo_database::start_undo_session( bool force_enable )
{ {
synchronized(_spin_yield)
if( _disabled && !force_enable ) return session(*this); if( _disabled && !force_enable ) return session(*this);
bool disable_on_exit = _disabled && force_enable; bool disable_on_exit = _disabled && force_enable;
if( force_enable ) if( force_enable )
@ -58,6 +62,8 @@ undo_database::session undo_database::start_undo_session( bool force_enable )
} }
void undo_database::on_create( const object& obj ) void undo_database::on_create( const object& obj )
{ {
synchronized(_spin_yield)
if( _disabled ) return; if( _disabled ) return;
if( _stack.empty() ) if( _stack.empty() )
@ -73,6 +79,8 @@ void undo_database::on_modify( const object& obj )
{ {
if( _disabled ) return; if( _disabled ) return;
synchronized(_spin_yield)
if( _stack.empty() ) if( _stack.empty() )
_stack.emplace_back(); _stack.emplace_back();
auto& state = _stack.back(); auto& state = _stack.back();
@ -86,6 +94,8 @@ void undo_database::on_remove( const object& obj )
{ {
if( _disabled ) return; if( _disabled ) return;
synchronized(_spin_yield)
if( _stack.empty() ) if( _stack.empty() )
_stack.emplace_back(); _stack.emplace_back();
undo_state& state = _stack.back(); undo_state& state = _stack.back();
@ -105,7 +115,9 @@ void undo_database::on_remove( const object& obj )
} }
void undo_database::undo() void undo_database::undo()
{ try { {
synchronized(_spin_yield)
try {
FC_ASSERT( !_disabled ); FC_ASSERT( !_disabled );
FC_ASSERT( _active_sessions > 0 ); FC_ASSERT( _active_sessions > 0 );
disable(); disable();
@ -136,6 +148,8 @@ void undo_database::undo()
void undo_database::merge() void undo_database::merge()
{ {
synchronized(_spin_yield)
FC_ASSERT( _active_sessions > 0 ); FC_ASSERT( _active_sessions > 0 );
if( _active_sessions == 1 && _stack.size() == 1 ) if( _active_sessions == 1 && _stack.size() == 1 )
{ {
@ -256,12 +270,16 @@ void undo_database::merge()
} }
void undo_database::commit() void undo_database::commit()
{ {
synchronized(_spin_yield)
FC_ASSERT( _active_sessions > 0 ); FC_ASSERT( _active_sessions > 0 );
--_active_sessions; --_active_sessions;
} }
void undo_database::pop_commit() void undo_database::pop_commit()
{ {
synchronized(_spin_yield)
FC_ASSERT( _active_sessions == 0 ); FC_ASSERT( _active_sessions == 0 );
FC_ASSERT( !_stack.empty() ); FC_ASSERT( !_stack.empty() );
@ -299,6 +317,8 @@ void undo_database::pop_commit()
} }
const undo_state& undo_database::head()const const undo_state& undo_database::head()const
{ {
synchronized(_spin_yield)
FC_ASSERT( !_stack.empty() ); FC_ASSERT( !_stack.empty() );
return _stack.back(); return _stack.back();
} }

View file

@ -114,16 +114,16 @@ namespace graphene { namespace net {
void peer_database_impl::close() void peer_database_impl::close()
{ {
std::vector<potential_peer_record> peer_records; //std::vector<potential_peer_record> peer_records;
peer_records.reserve(_potential_peer_set.size()); //peer_records.reserve(_potential_peer_set.size());
std::copy(_potential_peer_set.begin(), _potential_peer_set.end(), std::back_inserter(peer_records)); //std::copy(_potential_peer_set.begin(), _potential_peer_set.end(), std::back_inserter(peer_records));
try try
{ {
fc::path peer_database_filename_dir = _peer_database_filename.parent_path(); fc::path peer_database_filename_dir = _peer_database_filename.parent_path();
if (!fc::exists(peer_database_filename_dir)) if (!fc::exists(peer_database_filename_dir))
fc::create_directories(peer_database_filename_dir); fc::create_directories(peer_database_filename_dir);
fc::json::save_to_file( peer_records, _peer_database_filename, GRAPHENE_NET_MAX_NESTED_OBJECTS ); fc::json::save_to_file( /*peer_records*/ _potential_peer_set, _peer_database_filename, GRAPHENE_NET_MAX_NESTED_OBJECTS );
} }
catch (const fc::exception& e) catch (const fc::exception& e)
{ {