Merge pull request #538

d462c62 db_lmdb: always use a batch tx if possible (moneromooo-monero)
This commit is contained in:
Riccardo Spagni 2015-12-15 15:25:22 +02:00
commit 617b8c4376
No known key found for this signature in database
GPG Key ID: 55432DF31CCD4FCD

View File

@ -29,6 +29,7 @@
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
#include <boost/current_function.hpp>
#include <memory> // std::unique_ptr
#include <cstring> // memcpy
#include <random>
@ -1232,28 +1233,45 @@ void BlockchainLMDB::unlock()
check_open();
}
#define TXN_PREFIX(flags); \
mdb_txn_safe auto_txn; \
mdb_txn_safe* txn_ptr = &auto_txn; \
if (m_batch_active) \
txn_ptr = m_write_txn; \
else \
{ \
if (auto mdb_res = mdb_txn_begin(m_env, NULL, flags, auto_txn)) \
throw0(DB_ERROR(lmdb_error(std::string("Failed to create a transaction for the db in ")+__FUNCTION__+": ", mdb_res).c_str())); \
} \
#define TXN_PREFIX_RDONLY(); TXN_PREFIX(MDB_RDONLY);
#define TXN_POSTFIX_SUCCESS() \
do { \
if (! m_batch_active) \
auto_txn.commit(); \
} while(0)
bool BlockchainLMDB::block_exists(const crypto::hash& h) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::hash> key(h);
MDB_val result;
auto get_result = mdb_get(txn, m_block_heights, &key, &result);
auto get_result = mdb_get(*txn_ptr, m_block_heights, &key, &result);
if (get_result == MDB_NOTFOUND)
{
txn.commit();
TXN_POSTFIX_SUCCESS();
LOG_PRINT_L3("Block with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
return false;
}
else if (get_result)
throw0(DB_ERROR("DB error attempting to fetch block index from hash"));
txn.commit();
TXN_POSTFIX_SUCCESS();
return true;
}
@ -1270,21 +1288,18 @@ uint64_t BlockchainLMDB::get_block_height(const crypto::hash& h) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint64_t ret;
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::hash> key(h);
MDB_val result;
auto get_result = mdb_get(txn, m_block_heights, &key, &result);
auto get_result = mdb_get(*txn_ptr, m_block_heights, &key, &result);
if (get_result == MDB_NOTFOUND)
throw1(BLOCK_DNE("Attempted to retrieve non-existent block height"));
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve a block height from the db"));
ret = *(const uint64_t *)result.mv_data;
txn.commit();
uint64_t ret = *(const uint64_t *)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1302,13 +1317,11 @@ block BlockchainLMDB::get_block_from_height(const uint64_t& height) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> key(height);
MDB_val result;
auto get_result = mdb_get(txn, m_blocks, &key, &result);
auto get_result = mdb_get(*txn_ptr, m_blocks, &key, &result);
if (get_result == MDB_NOTFOUND)
{
throw0(BLOCK_DNE(std::string("Attempt to get block from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block not in db").c_str()));
@ -1323,7 +1336,7 @@ block BlockchainLMDB::get_block_from_height(const uint64_t& height) const
if (!parse_and_validate_block_from_blob(bd, b))
throw0(DB_ERROR("Failed to parse block from blob retrieved from the db"));
txn.commit();
TXN_POSTFIX_SUCCESS();
return b;
}
@ -1333,16 +1346,8 @@ uint64_t BlockchainLMDB::get_block_timestamp(const uint64_t& height) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint64_t ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> key(height);
MDB_val result;
auto get_result = mdb_get(*txn_ptr, m_block_timestamps, &key, &result);
@ -1353,9 +1358,8 @@ uint64_t BlockchainLMDB::get_block_timestamp(const uint64_t& height) const
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve a timestamp from the db"));
ret = *(const uint64_t *)result.mv_data;
if (! m_batch_active)
txn.commit();
uint64_t ret = *(const uint64_t *)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1378,17 +1382,8 @@ size_t BlockchainLMDB::get_block_size(const uint64_t& height) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
size_t ret;
MDB_val_copy<uint64_t> key(height);
MDB_val result;
auto get_result = mdb_get(*txn_ptr, m_block_sizes, &key, &result);
@ -1399,9 +1394,8 @@ size_t BlockchainLMDB::get_block_size(const uint64_t& height) const
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve a block size from the db"));
ret = *(const size_t *)result.mv_data;
if (! m_batch_active)
txn.commit();
size_t ret = *(const size_t *)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1410,16 +1404,8 @@ difficulty_type BlockchainLMDB::get_block_cumulative_difficulty(const uint64_t&
LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " height: " << height);
check_open();
difficulty_type ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> key(height);
MDB_val result;
auto get_result = mdb_get(*txn_ptr, m_block_diffs, &key, &result);
@ -1430,9 +1416,8 @@ difficulty_type BlockchainLMDB::get_block_cumulative_difficulty(const uint64_t&
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve a cumulative difficulty from the db"));
ret = *(difficulty_type*)result.mv_data;
if (! m_batch_active)
txn.commit();
difficulty_type ret = *(const difficulty_type*)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1458,16 +1443,7 @@ uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& heigh
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint64_t ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> key(height);
MDB_val result;
@ -1479,9 +1455,8 @@ uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& heigh
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve a total generated coins from the db"));
ret = *(const uint64_t*)result.mv_data;
if (! m_batch_active)
txn.commit();
uint64_t ret = *(const uint64_t*)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1490,16 +1465,7 @@ crypto::hash BlockchainLMDB::get_block_hash_from_height(const uint64_t& height)
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
crypto::hash ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> key(height);
MDB_val result;
@ -1512,9 +1478,8 @@ crypto::hash BlockchainLMDB::get_block_hash_from_height(const uint64_t& height)
throw0(DB_ERROR(std::string("Error attempting to retrieve a block hash from the db: ").
append(mdb_strerror(get_result)).c_str()));
ret = *(crypto::hash*)result.mv_data;
if (! m_batch_active)
txn.commit();
crypto::hash ret = *(const crypto::hash*)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1585,15 +1550,7 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::hash> key(h);
MDB_val result;
@ -1602,8 +1559,9 @@ bool BlockchainLMDB::tx_exists(const crypto::hash& h) const
auto get_result = mdb_get(*txn_ptr, m_txs, &key, &result);
TIME_MEASURE_FINISH(time1);
time_tx_exists += time1;
if (! m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
if (get_result == MDB_NOTFOUND)
{
LOG_PRINT_L1("transaction with hash " << epee::string_tools::pod_to_hex(h) << " not found in db");
@ -1620,21 +1578,18 @@ uint64_t BlockchainLMDB::get_tx_unlock_time(const crypto::hash& h) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint64_t ret;
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::hash> key(h);
MDB_val result;
auto get_result = mdb_get(txn, m_tx_unlocks, &key, &result);
auto get_result = mdb_get(*txn_ptr, m_tx_unlocks, &key, &result);
if (get_result == MDB_NOTFOUND)
throw1(TX_DNE(std::string("tx unlock time with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str()));
else if (get_result)
throw0(DB_ERROR("DB error attempting to fetch tx unlock time from hash"));
ret = *(const uint64_t*)result.mv_data;
txn.commit();
uint64_t ret = *(const uint64_t*)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1643,15 +1598,7 @@ transaction BlockchainLMDB::get_tx(const crypto::hash& h) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::hash> key(h);
MDB_val result;
@ -1667,8 +1614,8 @@ transaction BlockchainLMDB::get_tx(const crypto::hash& h) const
transaction tx;
if (!parse_and_validate_tx_from_blob(bd, tx))
throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
if (! m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
return tx;
}
@ -1678,15 +1625,13 @@ uint64_t BlockchainLMDB::get_tx_count() const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_stat db_stats;
if (mdb_stat(txn, m_txs, &db_stats))
if (mdb_stat(*txn_ptr, m_txs, &db_stats))
throw0(DB_ERROR("Failed to query m_txs"));
txn.commit();
TXN_POSTFIX_SUCCESS();
return db_stats.ms_entries;
}
@ -1710,16 +1655,7 @@ uint64_t BlockchainLMDB::get_tx_block_height(const crypto::hash& h) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint64_t ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::hash> key(h);
MDB_val result;
@ -1731,10 +1667,8 @@ uint64_t BlockchainLMDB::get_tx_block_height(const crypto::hash& h) const
else if (get_result)
throw0(DB_ERROR("DB error attempting to fetch tx height from hash"));
ret = *(const uint64_t*)result.mv_data;
if (! m_batch_active)
txn.commit();
uint64_t ret = *(const uint64_t*)result.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1743,17 +1677,16 @@ uint64_t BlockchainLMDB::get_num_outputs(const uint64_t& amount) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
lmdb_cur cur(txn, m_output_amounts);
lmdb_cur cur(*txn_ptr, m_output_amounts);
MDB_val_copy<uint64_t> k(amount);
MDB_val v;
auto result = mdb_cursor_get(cur, &k, &v, MDB_SET);
if (result == MDB_NOTFOUND)
{
TXN_POSTFIX_SUCCESS();
return 0;
}
else if (result)
@ -1762,7 +1695,7 @@ uint64_t BlockchainLMDB::get_num_outputs(const uint64_t& amount) const
size_t num_elems = 0;
mdb_cursor_count(cur, &num_elems);
txn.commit();
TXN_POSTFIX_SUCCESS();
return num_elems;
}
@ -1772,20 +1705,17 @@ output_data_t BlockchainLMDB::get_output_key(const uint64_t &global_index) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
output_data_t ret;
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> k(global_index);
MDB_val v;
auto get_result = mdb_get(txn, m_output_keys, &k, &v);
auto get_result = mdb_get(*txn_ptr, m_output_keys, &k, &v);
if (get_result == MDB_NOTFOUND)
throw1(OUTPUT_DNE("Attempting to get output pubkey by global index, but key does not exist"));
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db"));
ret = *(output_data_t *) v.mv_data;
txn.commit();
output_data_t ret = *(const output_data_t *) v.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1803,16 +1733,8 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t&
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
tx_out_index ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> k(index);
MDB_val v;
@ -1822,7 +1744,7 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t&
else if (get_result)
throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
crypto::hash tx_hash = *(crypto::hash*)v.mv_data;
crypto::hash tx_hash = *(const crypto::hash*)v.mv_data;
get_result = mdb_get(*txn_ptr, m_output_indices, &k, &v);
if (get_result == MDB_NOTFOUND)
@ -1830,10 +1752,8 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t&
else if (get_result)
throw0(DB_ERROR("DB error attempting to fetch output tx index"));
ret = tx_out_index(tx_hash, *(const uint64_t *)v.mv_data);
if (! m_batch_active)
txn.commit();
tx_out_index ret = tx_out_index(tx_hash, *(const uint64_t *)v.mv_data);
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -1856,11 +1776,9 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_output_indices(const crypto::hash&
check_open();
std::vector<uint64_t> index_vec;
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
lmdb_cur cur(txn, m_tx_outputs);
lmdb_cur cur(*txn_ptr, m_tx_outputs);
MDB_val_copy<crypto::hash> k(h);
MDB_val v;
@ -1883,7 +1801,7 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_output_indices(const crypto::hash&
}
cur.close();
txn.commit();
TXN_POSTFIX_SUCCESS();
return index_vec;
}
@ -1901,9 +1819,7 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const crypto:
transaction tx = get_tx(h);
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
uint64_t i = 0;
uint64_t global_index;
@ -1913,7 +1829,7 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const crypto:
global_index = index_vec[i];
lmdb_cur cur(txn, m_output_amounts);
lmdb_cur cur(*txn_ptr, m_output_amounts);
MDB_val_copy<uint64_t> k(amount);
MDB_val v;
@ -1952,7 +1868,7 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const crypto:
{
// not found
cur.close();
txn.commit();
TXN_POSTFIX_SUCCESS();
throw1(OUTPUT_DNE("specified output not found in db"));
}
@ -1960,7 +1876,7 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const crypto:
++i;
}
txn.commit();
TXN_POSTFIX_SUCCESS();
return index_vec2;
}
@ -1972,19 +1888,17 @@ bool BlockchainLMDB::has_key_image(const crypto::key_image& img) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val_copy<crypto::key_image> val_key(img);
MDB_val unused;
if (mdb_get(txn, m_spent_keys, &val_key, &unused) == 0)
if (mdb_get(*txn_ptr, m_spent_keys, &val_key, &unused) == 0)
{
txn.commit();
TXN_POSTFIX_SUCCESS();
return true;
}
txn.commit();
TXN_POSTFIX_SUCCESS();
return false;
}
@ -1993,15 +1907,13 @@ bool BlockchainLMDB::for_all_key_images(std::function<bool(const crypto::key_ima
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val k;
MDB_val v;
bool ret = true;
lmdb_cur cur(txn, m_spent_keys);
lmdb_cur cur(*txn_ptr, m_spent_keys);
MDB_cursor_op op = MDB_FIRST;
while (1)
{
@ -2011,7 +1923,7 @@ bool BlockchainLMDB::for_all_key_images(std::function<bool(const crypto::key_ima
break;
if (ret < 0)
throw0(DB_ERROR("Failed to enumerate key images"));
const crypto::key_image k_image = *(crypto::key_image*)k.mv_data;
const crypto::key_image k_image = *(const crypto::key_image*)k.mv_data;
if (!f(k_image)) {
ret = false;
break;
@ -2019,7 +1931,7 @@ bool BlockchainLMDB::for_all_key_images(std::function<bool(const crypto::key_ima
}
cur.close();
txn.commit();
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -2029,15 +1941,13 @@ bool BlockchainLMDB::for_all_blocks(std::function<bool(uint64_t, const crypto::h
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val k;
MDB_val v;
bool ret = true;
lmdb_cur cur(txn, m_blocks);
lmdb_cur cur(*txn_ptr, m_blocks);
MDB_cursor_op op = MDB_FIRST;
while (1)
{
@ -2047,7 +1957,7 @@ bool BlockchainLMDB::for_all_blocks(std::function<bool(uint64_t, const crypto::h
break;
if (ret)
throw0(DB_ERROR("Failed to enumerate blocks"));
uint64_t height = *(uint64_t*)k.mv_data;
uint64_t height = *(const uint64_t*)k.mv_data;
blobdata bd;
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
block b;
@ -2063,7 +1973,7 @@ bool BlockchainLMDB::for_all_blocks(std::function<bool(uint64_t, const crypto::h
}
cur.close();
txn.commit();
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -2073,15 +1983,13 @@ bool BlockchainLMDB::for_all_transactions(std::function<bool(const crypto::hash&
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val k;
MDB_val v;
bool ret = true;
lmdb_cur cur(txn, m_txs);
lmdb_cur cur(*txn_ptr, m_txs);
MDB_cursor_op op = MDB_FIRST;
while (1)
{
@ -2091,7 +1999,7 @@ bool BlockchainLMDB::for_all_transactions(std::function<bool(const crypto::hash&
break;
if (ret)
throw0(DB_ERROR("Failed to enumerate transactions"));
const crypto::hash hash = *(crypto::hash*)k.mv_data;
const crypto::hash hash = *(const crypto::hash*)k.mv_data;
blobdata bd;
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
transaction tx;
@ -2104,7 +2012,7 @@ bool BlockchainLMDB::for_all_transactions(std::function<bool(const crypto::hash&
}
cur.close();
txn.commit();
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -2114,15 +2022,13 @@ bool BlockchainLMDB::for_all_outputs(std::function<bool(uint64_t amount, const c
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
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()));
TXN_PREFIX_RDONLY();
MDB_val k;
MDB_val v;
bool ret = true;
lmdb_cur cur(txn, m_output_amounts);
lmdb_cur cur(*txn_ptr, m_output_amounts);
MDB_cursor_op op = MDB_FIRST;
while (1)
{
@ -2132,8 +2038,8 @@ bool BlockchainLMDB::for_all_outputs(std::function<bool(uint64_t amount, const c
break;
if (ret)
throw0(DB_ERROR("Failed to enumerate outputs"));
uint64_t amount = *(uint64_t*)k.mv_data;
uint64_t global_index = *(uint64_t*)v.mv_data;
uint64_t amount = *(const uint64_t*)k.mv_data;
uint64_t global_index = *(const uint64_t*)v.mv_data;
tx_out_index toi = get_output_tx_and_index_from_global(global_index);
if (!f(amount, toi.first, toi.second)) {
ret = false;
@ -2142,7 +2048,7 @@ bool BlockchainLMDB::for_all_outputs(std::function<bool(uint64_t amount, const c
}
cur.close();
txn.commit();
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -2335,15 +2241,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint6
check_open();
tx_out_indices.clear();
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
for (const uint64_t &index : global_indices)
{
@ -2356,7 +2254,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint6
else if (get_result)
throw0(DB_ERROR("DB error attempting to fetch output tx hash"));
crypto::hash tx_hash = *(crypto::hash*) v.mv_data;
crypto::hash tx_hash = *(const crypto::hash*) v.mv_data;
get_result = mdb_get(*txn_ptr, m_output_indices, &k, &v);
if (get_result == MDB_NOTFOUND)
@ -2368,8 +2266,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint6
tx_out_indices.push_back(result);
}
if (!m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
}
void BlockchainLMDB::get_output_global_indices(const uint64_t& amount, const std::vector<uint64_t> &offsets,
@ -2387,15 +2284,7 @@ void BlockchainLMDB::get_output_global_indices(const uint64_t& amount, const std
max = index;
}
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if(m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
lmdb_cur cur(*txn_ptr, m_output_amounts);
@ -2474,8 +2363,7 @@ void BlockchainLMDB::get_output_global_indices(const uint64_t& amount, const std
}
cur.close();
if(!m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
TIME_MEASURE_FINISH(txx);
LOG_PRINT_L3("txx: " << txx << " db1: " << t_dbmul << " db2: " << t_dbscan);
@ -2493,15 +2381,8 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector<ui
if (global_indices.size() > 0)
{
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
}
TXN_PREFIX_RDONLY();
for (const uint64_t &index : global_indices)
{
MDB_val_copy<uint64_t> k(index);
@ -2513,12 +2394,11 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector<ui
else if (get_result)
throw0(DB_ERROR("Error attempting to retrieve an output pubkey from the db"));
output_data_t data = *(output_data_t *) v.mv_data;
output_data_t data = *(const output_data_t *) v.mv_data;
outputs.push_back(data);
}
if (!m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
}
TIME_MEASURE_FINISH(db3);
@ -2548,24 +2428,14 @@ void BlockchainLMDB::set_hard_fork_starting_height(uint8_t version, uint64_t hei
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
txn_ptr = &txn;
}
TXN_PREFIX(0);
MDB_val_copy<uint8_t> val_key(version);
MDB_val_copy<uint64_t> val_value(height);
if (auto result = mdb_put(*txn_ptr, m_hf_starting_heights, &val_key, &val_value, 0))
throw1(DB_ERROR(std::string("Error adding hard fork starting height to db transaction: ").append(mdb_strerror(result)).c_str()));
if (!m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
}
uint64_t BlockchainLMDB::get_hard_fork_starting_height(uint8_t version) const
@ -2573,17 +2443,7 @@ uint64_t BlockchainLMDB::get_hard_fork_starting_height(uint8_t version) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint64_t ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
txn_ptr = &txn;
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint8_t> val_key(version);
MDB_val val_ret;
@ -2593,9 +2453,8 @@ uint64_t BlockchainLMDB::get_hard_fork_starting_height(uint8_t version) const
if (result)
throw0(DB_ERROR("Error attempting to retrieve a hard fork starting height from the db"));
ret = *(const uint64_t*)val_ret.mv_data;
if (!m_batch_active)
txn.commit();
uint64_t ret = *(const uint64_t*)val_ret.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}
@ -2604,25 +2463,14 @@ void BlockchainLMDB::set_hard_fork_version(uint64_t height, uint8_t version)
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
//LOG_PRINT_L1("BlockchainLMDB::set_hard_fork_version: batch " << m_batch_active << ", height " << height << ", version " << (int)version);
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
txn_ptr = &txn;
}
TXN_PREFIX(0);
MDB_val_copy<uint64_t> val_key(height);
MDB_val_copy<uint8_t> val_value(version);
if (auto result = mdb_put(*txn_ptr, m_hf_versions, &val_key, &val_value, 0))
throw1(DB_ERROR(std::string("Error adding hard fork version to db transaction: ").append(mdb_strerror(result)).c_str()));
if (!m_batch_active)
txn.commit();
TXN_POSTFIX_SUCCESS();
}
uint8_t BlockchainLMDB::get_hard_fork_version(uint64_t height) const
@ -2630,17 +2478,7 @@ uint8_t BlockchainLMDB::get_hard_fork_version(uint64_t height) const
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
uint8_t ret;
mdb_txn_safe txn;
mdb_txn_safe* txn_ptr = &txn;
if (m_batch_active)
txn_ptr = m_write_txn;
else
{
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()));
txn_ptr = &txn;
}
TXN_PREFIX_RDONLY();
MDB_val_copy<uint64_t> val_key(height);
MDB_val val_ret;
@ -2648,9 +2486,8 @@ uint8_t BlockchainLMDB::get_hard_fork_version(uint64_t height) const
if (result == MDB_NOTFOUND || result)
throw0(DB_ERROR("Error attempting to retrieve a hard fork version from the db"));
ret = *(const uint8_t*)val_ret.mv_data;
if (!m_batch_active)
txn.commit();
uint8_t ret = *(const uint8_t*)val_ret.mv_data;
TXN_POSTFIX_SUCCESS();
return ret;
}