Use batch transactions when syncing

Faster throughput while avoiding corruption. I.e., makes
running with --db-sync-mode safe more tolerable.
This commit is contained in:
Howard Chu 2016-12-26 14:29:46 -08:00 committed by Howard Chu
parent 374762654e
commit 0693cff925
No known key found for this signature in database
GPG Key ID: FD2A70B44AB11BA7
8 changed files with 23 additions and 15 deletions

View File

@ -1813,9 +1813,10 @@ bool BlockchainBDB::has_key_image(const crypto::key_image& img) const
// Ostensibly BerkeleyDB has batch transaction support built-in, // Ostensibly BerkeleyDB has batch transaction support built-in,
// so the following few functions will be NOP. // so the following few functions will be NOP.
void BlockchainBDB::batch_start(uint64_t batch_num_blocks) bool BlockchainBDB::batch_start(uint64_t batch_num_blocks)
{ {
LOG_PRINT_L3("BlockchainBDB::" << __func__); LOG_PRINT_L3("BlockchainBDB::" << __func__);
return false;
} }
void BlockchainBDB::batch_commit() void BlockchainBDB::batch_commit()

View File

@ -324,7 +324,7 @@ public:
); );
virtual void set_batch_transactions(bool batch_transactions); virtual void set_batch_transactions(bool batch_transactions);
virtual void batch_start(uint64_t batch_num_blocks=0); virtual bool batch_start(uint64_t batch_num_blocks=0);
virtual void batch_commit(); virtual void batch_commit();
virtual void batch_stop(); virtual void batch_stop();
virtual void batch_abort(); virtual void batch_abort();

View File

@ -655,16 +655,17 @@ public:
* been called. In either case, it should end the batch and write to its * been called. In either case, it should end the batch and write to its
* backing store. * backing store.
* *
* If a batch is already in-progress, this function should throw a DB_ERROR. * If a batch is already in-progress, this function must return false.
* This exception may change in the future if it is deemed necessary to * If a batch was started by this call, it must return true.
* have a more granular exception type for this scenario.
* *
* If any of this cannot be done, the subclass should throw the corresponding * If any of this cannot be done, the subclass should throw the corresponding
* subclass of DB_EXCEPTION * subclass of DB_EXCEPTION
* *
* @param batch_num_blocks number of blocks to batch together * @param batch_num_blocks number of blocks to batch together
*
* @return true if we started the batch, false if already started
*/ */
virtual void batch_start(uint64_t batch_num_blocks=0) = 0; virtual bool batch_start(uint64_t batch_num_blocks=0) = 0;
/** /**
* @brief ends a batch transaction * @brief ends a batch transaction

View File

@ -2234,15 +2234,15 @@ bool BlockchainLMDB::for_all_outputs(std::function<bool(uint64_t amount, const c
} }
// batch_num_blocks: (optional) Used to check if resize needed before batch transaction starts. // batch_num_blocks: (optional) Used to check if resize needed before batch transaction starts.
void BlockchainLMDB::batch_start(uint64_t batch_num_blocks) bool BlockchainLMDB::batch_start(uint64_t batch_num_blocks)
{ {
LOG_PRINT_L3("BlockchainLMDB::" << __func__); LOG_PRINT_L3("BlockchainLMDB::" << __func__);
if (! m_batch_transactions) if (! m_batch_transactions)
throw0(DB_ERROR("batch transactions not enabled")); throw0(DB_ERROR("batch transactions not enabled"));
if (m_batch_active) if (m_batch_active)
throw0(DB_ERROR("batch transaction already in progress")); return false;
if (m_write_batch_txn != nullptr) if (m_write_batch_txn != nullptr)
throw0(DB_ERROR("batch transaction already in progress")); return false;
if (m_write_txn) if (m_write_txn)
throw0(DB_ERROR("batch transaction attempted, but m_write_txn already in use")); throw0(DB_ERROR("batch transaction attempted, but m_write_txn already in use"));
check_open(); check_open();
@ -2268,6 +2268,7 @@ void BlockchainLMDB::batch_start(uint64_t batch_num_blocks)
memset(&m_wcursors, 0, sizeof(m_wcursors)); memset(&m_wcursors, 0, sizeof(m_wcursors));
LOG_PRINT_L3("batch transaction: begin"); LOG_PRINT_L3("batch transaction: begin");
return true;
} }
void BlockchainLMDB::batch_commit() void BlockchainLMDB::batch_commit()

View File

@ -245,7 +245,7 @@ public:
); );
virtual void set_batch_transactions(bool batch_transactions); virtual void set_batch_transactions(bool batch_transactions);
virtual void batch_start(uint64_t batch_num_blocks=0); virtual bool batch_start(uint64_t batch_num_blocks=0);
virtual void batch_commit(); virtual void batch_commit();
virtual void batch_stop(); virtual void batch_stop();
virtual void batch_abort(); virtual void batch_abort();

View File

@ -119,9 +119,9 @@ struct fake_core_db
return m_storage.get_db().add_block(blk, block_size, cumulative_difficulty, coins_generated, txs); return m_storage.get_db().add_block(blk, block_size, cumulative_difficulty, coins_generated, txs);
} }
void batch_start(uint64_t batch_num_blocks = 0) bool batch_start(uint64_t batch_num_blocks = 0)
{ {
m_storage.get_db().batch_start(batch_num_blocks); return m_storage.get_db().batch_start(batch_num_blocks);
} }
void batch_stop() void batch_stop()

View File

@ -3377,9 +3377,10 @@ bool Blockchain::add_new_block(const block& bl_, block_verification_context& bvc
void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce) void Blockchain::check_against_checkpoints(const checkpoints& points, bool enforce)
{ {
const auto& pts = points.get_points(); const auto& pts = points.get_points();
bool stop_batch;
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_db->batch_start(); stop_batch = m_db->batch_start();
for (const auto& pt : pts) for (const auto& pt : pts)
{ {
// if the checkpoint is for a block we don't have yet, move on // if the checkpoint is for a block we don't have yet, move on
@ -3403,7 +3404,8 @@ void Blockchain::check_against_checkpoints(const checkpoints& points, bool enfor
} }
} }
} }
m_db->batch_stop(); if (stop_batch)
m_db->batch_stop();
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// returns false if any of the checkpoints loading returns false. // returns false if any of the checkpoints loading returns false.
@ -3477,6 +3479,7 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync)
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
TIME_MEASURE_START(t1); TIME_MEASURE_START(t1);
m_db->batch_stop();
if (m_sync_counter > 0) if (m_sync_counter > 0)
{ {
if (force_sync) if (force_sync)
@ -3546,6 +3549,8 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
if(blocks_entry.size() == 0) if(blocks_entry.size() == 0)
return false; return false;
m_db->batch_start(blocks_entry.size());
if ((m_db->height() + blocks_entry.size()) < m_blocks_hash_check.size()) if ((m_db->height() + blocks_entry.size()) < m_blocks_hash_check.size())
return true; return true;

View File

@ -51,7 +51,7 @@ public:
virtual std::string get_db_name() const { return std::string(); } virtual std::string get_db_name() const { return std::string(); }
virtual bool lock() { return true; } virtual bool lock() { return true; }
virtual void unlock() { } virtual void unlock() { }
virtual void batch_start(uint64_t batch_num_blocks=0) {} virtual bool batch_start(uint64_t batch_num_blocks=0) {}
virtual void batch_stop() {} virtual void batch_stop() {}
virtual void set_batch_transactions(bool) {} virtual void set_batch_transactions(bool) {}
virtual void block_txn_start(bool readonly=false) {} virtual void block_txn_start(bool readonly=false) {}