From 79ff6a5a56888ed5ca9d75db0c1fcac94a51e65c Mon Sep 17 00:00:00 2001 From: warptangent Date: Sun, 13 Dec 2015 08:45:03 -0800 Subject: Add LMDB error string to database transaction exception message When throwing an exception from being unable to begin an LMDB transaction, include the reason. It's often been due to a write transaction attempted within a write transaction (batch mode), but there can be other reasons such as write transaction attempted while database was opened read only, or environment's map needs to be resized. --- src/blockchain_db/lmdb/db_lmdb.cpp | 142 +++++++++++++++++++------------------ 1 file changed, 74 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index de8066123..808058d1e 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -208,6 +208,12 @@ inline void lmdb_db_open(MDB_txn* txn, const char* name, int flags, MDB_dbi& dbi throw0(cryptonote::DB_OPEN_FAILURE(error_string.c_str())); } +const std::string lmdb_error(const std::string& error_string, int mdb_res) +{ + const std::string full_string = error_string + mdb_strerror(mdb_res); + return full_string; +} + } // anonymous namespace namespace cryptonote @@ -994,8 +1000,8 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags) // get a read/write MDB_txn, depending on mdb_flags mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, txn_flags, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, txn_flags, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); // open necessary databases, and set properties as needed // uses macros to avoid having to change things too many places @@ -1206,8 +1212,8 @@ bool BlockchainLMDB::block_exists(const crypto::hash& h) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_val_copy key(h); MDB_val result; @@ -1239,8 +1245,8 @@ uint64_t BlockchainLMDB::get_block_height(const crypto::hash& h) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_val_copy key(h); MDB_val result; @@ -1269,8 +1275,8 @@ block BlockchainLMDB::get_block_from_height(const uint64_t& height) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_val_copy key(height); MDB_val result; @@ -1305,8 +1311,8 @@ uint64_t BlockchainLMDB::get_block_timestamp(const uint64_t& height) const txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(height); MDB_val result; @@ -1348,8 +1354,8 @@ size_t BlockchainLMDB::get_block_size(const uint64_t& height) const txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(height); @@ -1378,8 +1384,8 @@ difficulty_type BlockchainLMDB::get_block_cumulative_difficulty(const uint64_t& txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(height); MDB_val result; @@ -1424,8 +1430,8 @@ uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& heigh txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(height); @@ -1454,8 +1460,8 @@ crypto::hash BlockchainLMDB::get_block_hash_from_height(const uint64_t& height) txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(height); @@ -1547,8 +1553,8 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(h); @@ -1577,8 +1583,8 @@ uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash& h) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_val_copy key(h); MDB_val result; @@ -1602,8 +1608,8 @@ transaction BlockchainLMDB::get_tx(const crypto::hash& h) const txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(h); @@ -1632,8 +1638,8 @@ uint64_t BlockchainLMDB::get_tx_count() const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_stat db_stats; if (mdb_stat(txn, m_txs, &db_stats)) @@ -1669,8 +1675,8 @@ uint64_t BlockchainLMDB::get_tx_block_height(const crypto::hash& h) const txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy key(h); @@ -1695,8 +1701,8 @@ uint64_t BlockchainLMDB::get_num_outputs(const uint64_t& amount) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); lmdb_cur cur(txn, m_output_amounts); @@ -1724,8 +1730,8 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t &global_index) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_val_copy k(global_index); MDB_val v; @@ -1758,8 +1764,8 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t& txn_ptr = m_write_txn; else { - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); } MDB_val_copy k(index); MDB_val v; @@ -1803,8 +1809,8 @@ std::vector BlockchainLMDB::get_tx_output_indices(const crypto::hash& std::vector index_vec; mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); lmdb_cur cur(txn, m_tx_outputs); @@ -1848,8 +1854,8 @@ std::vector BlockchainLMDB::get_tx_amount_output_indices(const crypto: transaction tx = get_tx(h); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); uint64_t i = 0; uint64_t global_index; @@ -1919,8 +1925,8 @@ bool BlockchainLMDB::has_key_image(const crypto::key_image& img) const check_open(); mdb_txn_safe txn; - if (mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, MDB_RDONLY, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); MDB_val_copy val_key(img); MDB_val unused; @@ -1940,8 +1946,8 @@ bool BlockchainLMDB::for_all_key_images(std::functionm_batch_txn = true; @@ -2210,8 +2216,8 @@ uint64_t BlockchainLMDB::add_block(const block& blk, const size_t& block_size, c mdb_txn_safe txn; if (! m_batch_active) { - if (mdb_txn_begin(m_env, NULL, 0, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, 0, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); m_write_txn = &txn; } @@ -2248,8 +2254,8 @@ void BlockchainLMDB::pop_block(block& blk, std::vector& txs) mdb_txn_safe txn; if (! m_batch_active) { - if (mdb_txn_begin(m_env, NULL, 0, txn)) - throw0(DB_ERROR("Failed to create a transaction for the db")); + if (auto mdb_res = mdb_txn_begin(m_env, NULL, 0, txn)) + throw0(DB_ERROR(lmdb_error("Failed to create a transaction for the db: ", mdb_res).c_str())); m_write_txn = &txn; } @@ -2287,8 +2293,8 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector