blockchain_db: fix db txn ending too early

The db txn in add_block ending caused the entire overarching
batch txn to stop.
Also add a new guard class so a db txn can be stopped in the
face of exceptions.

Also use a read only db txn in init when the db itself is
read only, and do not save the max tx size in that case.
This commit is contained in:
moneromooo-monero
2019-04-05 09:28:30 +00:00
parent 37345921ec
commit 5e673c03fe
9 changed files with 144 additions and 95 deletions
+32 -44
View File
@@ -3611,16 +3611,15 @@ void BlockchainLMDB::block_rtxn_stop() const
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
}
void BlockchainLMDB::block_txn_start(bool readonly)
bool BlockchainLMDB::block_rtxn_start() const
{
if (readonly)
{
MDB_txn *mtxn;
mdb_txn_cursors *mcur;
block_rtxn_start(&mtxn, &mcur);
return;
}
MDB_txn *mtxn;
mdb_txn_cursors *mcur;
return block_rtxn_start(&mtxn, &mcur);
}
void BlockchainLMDB::block_wtxn_start()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
// Distinguish the exceptions here from exceptions that would be thrown while
// using the txn and committing it.
@@ -3652,10 +3651,13 @@ void BlockchainLMDB::block_txn_start(bool readonly)
throw0(DB_ERROR_TXN_START((std::string("Attempted to start new write txn when batch txn already exists in ")+__FUNCTION__).c_str()));
}
void BlockchainLMDB::block_txn_stop()
void BlockchainLMDB::block_wtxn_stop()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
if (m_write_txn && m_writer == boost::this_thread::get_id())
if (!m_write_txn)
throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn when no such txn exists in ")+__FUNCTION__).c_str()));
if (m_writer != boost::this_thread::get_id())
throw0(DB_ERROR_TXN_START((std::string("Attempted to stop write txn from the wrong thread in ")+__FUNCTION__).c_str()));
{
if (! m_batch_active)
{
@@ -3669,38 +3671,29 @@ void BlockchainLMDB::block_txn_stop()
memset(&m_wcursors, 0, sizeof(m_wcursors));
}
}
else if (m_tinfo->m_ti_rtxn)
}
void BlockchainLMDB::block_wtxn_abort()
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
if (!m_write_txn)
throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn when no such txn exists in ")+__FUNCTION__).c_str()));
if (m_writer != boost::this_thread::get_id())
throw0(DB_ERROR_TXN_START((std::string("Attempted to abort write txn from the wrong thread in ")+__FUNCTION__).c_str()));
if (! m_batch_active)
{
mdb_txn_reset(m_tinfo->m_ti_rtxn);
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
delete m_write_txn;
m_write_txn = nullptr;
memset(&m_wcursors, 0, sizeof(m_wcursors));
}
}
void BlockchainLMDB::block_txn_abort()
void BlockchainLMDB::block_rtxn_abort() const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
if (m_write_txn && m_writer == boost::this_thread::get_id())
{
if (! m_batch_active)
{
delete m_write_txn;
m_write_txn = nullptr;
memset(&m_wcursors, 0, sizeof(m_wcursors));
}
}
else if (m_tinfo->m_ti_rtxn)
{
mdb_txn_reset(m_tinfo->m_ti_rtxn);
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
}
else
{
// This would probably mean an earlier exception was caught, but then we
// proceeded further than we should have.
throw0(DB_ERROR((std::string("BlockchainLMDB::") + __func__ +
std::string(": block-level DB transaction abort called when write txn doesn't exist")
).c_str()));
}
mdb_txn_reset(m_tinfo->m_ti_rtxn);
memset(&m_tinfo->m_ti_rflags, 0, sizeof(m_tinfo->m_ti_rflags));
}
uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
@@ -3728,11 +3721,6 @@ uint64_t BlockchainLMDB::add_block(const std::pair<block, blobdata>& blk, size_t
{
throw;
}
catch (...)
{
block_txn_abort();
throw;
}
return ++m_height;
}
@@ -3742,16 +3730,16 @@ void BlockchainLMDB::pop_block(block& blk, std::vector<transaction>& txs)
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
block_txn_start(false);
block_wtxn_start();
try
{
BlockchainDB::pop_block(blk, txs);
block_txn_stop();
block_wtxn_stop();
}
catch (...)
{
block_txn_abort();
block_wtxn_abort();
throw;
}
}
+7 -4
View File
@@ -310,11 +310,14 @@ public:
virtual void batch_stop();
virtual void batch_abort();
virtual void block_txn_start(bool readonly);
virtual void block_txn_stop();
virtual void block_txn_abort();
virtual bool block_rtxn_start(MDB_txn **mtxn, mdb_txn_cursors **mcur) const;
virtual void block_wtxn_start();
virtual void block_wtxn_stop();
virtual void block_wtxn_abort();
virtual bool block_rtxn_start() const;
virtual void block_rtxn_stop() const;
virtual void block_rtxn_abort() const;
bool block_rtxn_start(MDB_txn **mtxn, mdb_txn_cursors **mcur) const;
virtual void pop_block(block& blk, std::vector<transaction>& txs);