42 namespace graphene {
namespace chain {
47 initialize_evaluators();
57 auto last_block = _block_id_to_block.
last();
59 elog(
"!no last block" );
65 ilog(
"reindexing blockchain" );
67 const auto last_block_num = last_block->block_num();
83 std::queue< std::tuple< size_t, signed_block, fc::future< void > > > blocks;
85 uint32_t i = next_block_num;
86 while( next_block_num <= last_block_num || !blocks.empty() )
88 if( next_block_num <= last_block_num && blocks.size() < 20 )
94 if( block->timestamp >= last_block->timestamp - gpo.parameters.maximum_time_until_expiration )
96 blocks.emplace( processed_block_size, std::move(*block),
fc::future<void>() );
101 wlog(
"Reindexing terminated due to gap: Block ${i} does not exist!", (
"i", i) );
102 uint32_t dropped_count = 0;
107 if( !last_id.
valid() )
112 _block_id_to_block.
remove( *last_id );
115 wlog(
"Dropped ${n} blocks from after the gap", (
"n", dropped_count) );
116 next_block_num = last_block_num + 1;
121 std::get<2>(blocks.front()).
wait();
122 const signed_block& block = std::get<1>(blocks.front());
126 std::stringstream bysize;
127 std::stringstream bynum;
128 size_t current_pos = std::get<0>(blocks.front());
129 if( current_pos > total_block_size )
130 total_block_size = current_pos;
131 bysize << std::fixed << std::setprecision(5) << double(current_pos) / total_block_size * 100;
132 bynum << std::fixed << std::setprecision(5) << double(i)*100/last_block_num;
134 " [by size: ${size}% ${processed} of ${total}] [by num: ${num}% ${i} of ${last}]",
135 (
"size", bysize.str())
136 (
"processed", current_pos)
137 (
"total", total_block_size)
140 (
"last", last_block_num)
143 if( i == undo_point )
145 ilog(
"Writing object database to disk at block ${i}, please DO NOT kill the program", (
"i", i) );
147 ilog(
"Done writing object database to disk" );
162 ilog(
"Done reindexing, elapsed time: ${t} sec", (
"t",
double((end-start).count())/1000000.0 ) );
167 ilog(
"Wiping database", (
"include_blocks", include_blocks));
179 const std::string& db_version)
183 bool wipe_object_db =
false;
185 wipe_object_db =
true;
188 std::string version_string;
190 wipe_object_db = ( version_string != db_version );
192 if( wipe_object_db ) {
193 ilog(
"Wiping object_database due to missing or wrong version");
195 std::ofstream version_file( (data_dir /
"db_version").generic_string().c_str(),
196 std::ios::out | std::ios::binary | std::ios::trunc );
197 version_file.write( db_version.c_str(), db_version.size() );
198 version_file.close();
203 _block_id_to_block.
open(data_dir /
"database" /
"block_num_to_block");
205 if( !
find(global_property_id_type()) )
206 init_genesis(genesis_loader());
209 _p_core_asset_obj = &
get( asset_id_type() );
210 _p_core_dynamic_data_obj = &
get( asset_dynamic_data_id_type() );
211 _p_global_prop_obj = &
get( global_property_id_type() );
212 _p_chain_property_obj = &
get( chain_property_id_type() );
213 _p_dyn_global_prop_obj = &
get( dynamic_global_property_id_type() );
214 _p_witness_schedule_obj = &
get( witness_schedule_id_type() );
218 if( last_block.
valid() )
221 "last block ID does not match current chain state",
222 (
"last_block->id", last_block)(
"head_block_id",
head_block_num()) );
246 ilog(
"Rewinding from ${head} to ${cutoff}", (
"head",
head_block_num())(
"cutoff",cutoff) );
251 _fork_db.
remove(popped_block_id);
256 wlog(
"Database close unexpected exception: ${e}", (
"e", e) );
265 ilog(
"Writing object database to disk at block ${i}, please DO NOT kill the program", (
"i",
head_block_num()) );
267 ilog(
"Done writing object database to disk" );
271 if( _block_id_to_block.
is_open() )
272 _block_id_to_block.
close();
bool exists(const path &p)
uint32_t last_irreversible_block_num
void reindex(fc::path data_dir)
Rebuild object graph from block history and open detabase.
optional< signed_block > fetch_by_number(uint32_t block_num) const
void wipe(const fc::path &data_dir, bool include_blocks)
wipe Delete database from disk, and potentially the raw chain as well.
T wait(boost::signals2::signal< void(T)> &sig, const microseconds &timeout_us=microseconds::maximum())
void start_block(signed_block b)
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
size_t total_block_size() const
void open(const fc::path &dbdir)
void remove_all(const path &p)
void read_file_contents(const fc::path &filename, std::string &result)
bool push_block(const signed_block &b, uint32_t skip=skip_nothing)
block_id_type head_block_id() const
provides stack-based nullable value similar to boost::optional
void apply_block(const signed_block &next_block, uint32_t skip=skip_nothing)
void open(const fc::path &data_dir, std::function< genesis_state_type()> genesis_loader, const std::string &db_version)
Open a database, creating a new one if necessary.
optional< signed_block > last() const
const T * find(const object_id_type &id) const
void remove(const block_id_type &id)
#define FC_CAPTURE_AND_RETHROW(...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
void wipe(const fc::path &data_dir)
optional< block_id_type > last_id() const
void initialize_indexes()
Reset the object graph in-memory.
void remove(block_id_type b)
void open(const fc::path &data_dir)
uint32_t head_block_num() const
node_property_object & node_properties()
const dynamic_global_property_object & get_dynamic_global_properties() const
#define FC_CAPTURE_LOG_AND_RETHROW(...)
wraps boost::filesystem::path to provide platform independent path manipulation.
size_t blocks_current_position() const
optional< signed_block > fetch_block_by_number(uint32_t num) const
fc::future< void > precompute_parallel(const signed_block &block, const uint32_t skip=skip_nothing) const
#define GRAPHENE_MAX_UNDO_HISTORY
const global_property_object & get_global_properties() const