diff options
author | Howard Chu <hyc@symas.com> | 2016-03-28 18:26:37 +0100 |
---|---|---|
committer | Howard Chu <hyc@symas.com> | 2016-04-05 20:55:16 +0100 |
commit | 118dd69dd553a9b214d7d14e4d15f98b46164c06 (patch) | |
tree | f5b309ba6106baf1acd2543d11db3107dfcfc4da /src/blockchain_db/lmdb | |
parent | More outputs consolidation (diff) | |
download | monero-118dd69dd553a9b214d7d14e4d15f98b46164c06.tar.xz |
Use DUPFIXED for block_info and output_txs
Saves another ~150MB or so on the full blockchain
Diffstat (limited to 'src/blockchain_db/lmdb')
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 101 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.h | 1 |
2 files changed, 46 insertions, 56 deletions
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 604fde0aa..1ccd477f3 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -231,6 +231,7 @@ typedef struct outkey { } outkey; typedef struct outtx { + uint64_t txnum; crypto::hash tx_hash; uint64_t local_index; } outtx; @@ -592,6 +593,7 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const throw0(DB_ERROR(lmdb_error("Failed to add block blob to db transaction: ", result).c_str())); mdb_block_info bi; + bi.bi_height = m_height; bi.bi_timestamp = blk.timestamp; bi.bi_coins = coins_generated; bi.bi_size = block_size; @@ -599,7 +601,7 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const bi.bi_hash = blk_hash; MDB_val val = {sizeof(bi), (void *)&bi}; - result = mdb_cursor_put(m_cur_block_info, &key, &val, MDB_APPEND); + result = mdb_cursor_put(m_cur_block_info, (MDB_val *)&zerokval, &val, MDB_APPENDDUP); if (result) throw0(DB_ERROR(lmdb_error("Failed to add block info to db transaction: ", result).c_str())); @@ -624,8 +626,8 @@ void BlockchainLMDB::remove_block() mdb_txn_cursors *m_cursors = &m_wcursors; CURSOR(block_info) MDB_val_copy<uint64_t> k(m_height - 1); - MDB_val h; - if ((result = mdb_cursor_get(m_cur_block_info, &k, &h, MDB_SET))) + MDB_val h = k; + if ((result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &h, MDB_GET_BOTH))) throw1(BLOCK_DNE(lmdb_error("Attempting to remove block that's not in the db: ", result).c_str())); // must use h now; deleting from m_block_info will invalidate it @@ -749,12 +751,10 @@ void BlockchainLMDB::add_output(const crypto::hash& tx_hash, if (tx_output.target.type() != typeid(txout_to_key)) throw0(DB_ERROR("Wrong output type: expected txout_to_key")); - MDB_val_set(k, m_num_outputs); - - outtx ot = {tx_hash, local_index}; + outtx ot = {m_num_outputs, tx_hash, local_index}; MDB_val_set(vot, ot); - result = mdb_cursor_put(m_cur_output_txs, &k, &vot, MDB_APPEND); + result = mdb_cursor_put(m_cur_output_txs, (MDB_val *)&zerokval, &vot, MDB_APPENDDUP); if (result) throw0(DB_ERROR(lmdb_error("Failed to add output tx hash to db transaction: ", result).c_str())); @@ -849,33 +849,12 @@ void BlockchainLMDB::remove_output(const uint64_t& out_index, const uint64_t amo { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); - - MDB_val_copy<uint64_t> k(out_index); - - auto result = mdb_del(*m_write_txn, m_output_txs, &k, NULL); - if (result == MDB_NOTFOUND) - { - LOG_PRINT_L0("Unexpected: global output index not found in m_output_txs"); - } - else if (result) - { - throw1(DB_ERROR(lmdb_error("Error adding removal of output tx to db transaction", result).c_str())); - } - - remove_amount_output_index(amount, out_index); - - m_num_outputs--; -} - -void BlockchainLMDB::remove_amount_output_index(const uint64_t amount, const uint64_t output_index) -{ - LOG_PRINT_L3("BlockchainLMDB::" << __func__); - check_open(); mdb_txn_cursors *m_cursors = &m_wcursors; CURSOR(output_amounts); + CURSOR(output_txs); MDB_val_set(k, amount); - MDB_val_set(v, output_index); + MDB_val_set(v, out_index); auto result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH); if (result == MDB_NOTFOUND) @@ -883,10 +862,27 @@ void BlockchainLMDB::remove_amount_output_index(const uint64_t amount, const uin else if (result) throw0(DB_ERROR(lmdb_error("DB error attempting to get an output", result).c_str())); - // now delete it + outkey *ok = (outkey *)v.mv_data; + MDB_val_set(otxk, ok->tx_index); + result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &otxk, MDB_GET_BOTH); + if (result == MDB_NOTFOUND) + { + LOG_PRINT_L0("Unexpected: global output index not found in m_output_txs"); + } + else if (result) + { + throw1(DB_ERROR(lmdb_error("Error adding removal of output tx to db transaction", result).c_str())); + } + result = mdb_cursor_del(m_cur_output_txs, 0); + if (result) + throw0(DB_ERROR(lmdb_error(std::string("Error deleting output index ").append(boost::lexical_cast<std::string>(out_index).append(": ")).c_str(), result).c_str())); + + // now delete the amount result = mdb_cursor_del(m_cur_output_amounts, 0); if (result) - throw0(DB_ERROR(lmdb_error(std::string("Error deleting amount for output index ").append(boost::lexical_cast<std::string>(output_index).append(": ")).c_str(), result).c_str())); + throw0(DB_ERROR(lmdb_error(std::string("Error deleting amount for output index ").append(boost::lexical_cast<std::string>(out_index).append(": ")).c_str(), result).c_str())); + + m_num_outputs--; } void BlockchainLMDB::add_spent_key(const crypto::key_image& k_image) @@ -1052,14 +1048,14 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags) // uses macros to avoid having to change things too many places lmdb_db_open(txn, LMDB_BLOCKS, MDB_INTEGERKEY | MDB_CREATE, m_blocks, "Failed to open db handle for m_blocks"); - lmdb_db_open(txn, LMDB_BLOCK_INFO, MDB_INTEGERKEY | MDB_CREATE, m_block_info, "Failed to open db handle for m_block_info"); + lmdb_db_open(txn, LMDB_BLOCK_INFO, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_block_info, "Failed to open db handle for m_block_info"); lmdb_db_open(txn, LMDB_BLOCK_HEIGHTS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_block_heights, "Failed to open db handle for m_block_heights"); lmdb_db_open(txn, LMDB_TXS, MDB_INTEGERKEY | MDB_CREATE, m_txs, "Failed to open db handle for m_txs"); lmdb_db_open(txn, LMDB_TX_INDICES, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_tx_indices, "Failed to open db handle for m_tx_indices"); lmdb_db_open(txn, LMDB_TX_OUTPUTS, MDB_INTEGERKEY | MDB_CREATE, m_tx_outputs, "Failed to open db handle for m_tx_outputs"); - lmdb_db_open(txn, LMDB_OUTPUT_TXS, MDB_INTEGERKEY | MDB_CREATE, m_output_txs, "Failed to open db handle for m_output_txs"); + lmdb_db_open(txn, LMDB_OUTPUT_TXS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_output_txs, "Failed to open db handle for m_output_txs"); lmdb_db_open(txn, LMDB_OUTPUT_AMOUNTS, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_output_amounts, "Failed to open db handle for m_output_amounts"); lmdb_db_open(txn, LMDB_SPENT_KEYS, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_spent_keys, "Failed to open db handle for m_spent_keys"); @@ -1073,6 +1069,8 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags) mdb_set_dupsort(txn, m_block_heights, compare_hash32); mdb_set_dupsort(txn, m_tx_indices, compare_hash32); mdb_set_dupsort(txn, m_output_amounts, compare_uint64); + mdb_set_dupsort(txn, m_output_txs, compare_uint64); + mdb_set_dupsort(txn, m_block_info, compare_uint64); mdb_set_compare(txn, m_hf_starting_heights, compare_uint8); mdb_set_compare(txn, m_properties, compare_string); @@ -1402,9 +1400,8 @@ uint64_t BlockchainLMDB::get_block_timestamp(const uint64_t& height) const TXN_PREFIX_RDONLY(); RCURSOR(block_info); - MDB_val_copy<uint64_t> key(height); - MDB_val result; - auto get_result = mdb_cursor_get(m_cur_block_info, &key, &result, MDB_SET); + MDB_val_set(result, height); + auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { throw0(BLOCK_DNE(std::string("Attempt to get timestamp from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- timestamp not in db").c_str())); @@ -1440,9 +1437,8 @@ size_t BlockchainLMDB::get_block_size(const uint64_t& height) const TXN_PREFIX_RDONLY(); RCURSOR(block_info); - MDB_val_copy<uint64_t> key(height); - MDB_val result; - auto get_result = mdb_cursor_get(m_cur_block_info, &key, &result, MDB_SET); + MDB_val_set(result, height); + auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { throw0(BLOCK_DNE(std::string("Attempt to get block size from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block size not in db").c_str())); @@ -1464,9 +1460,8 @@ difficulty_type BlockchainLMDB::get_block_cumulative_difficulty(const uint64_t& TXN_PREFIX_RDONLY(); RCURSOR(block_info); - MDB_val_copy<uint64_t> key(height); - MDB_val result; - auto get_result = mdb_cursor_get(m_cur_block_info, &key, &result, MDB_SET); + MDB_val_set(result, height); + auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { throw0(BLOCK_DNE(std::string("Attempt to get cumulative difficulty from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- difficulty not in db").c_str())); @@ -1505,9 +1500,8 @@ uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& heigh TXN_PREFIX_RDONLY(); RCURSOR(block_info); - MDB_val_copy<uint64_t> key(height); - MDB_val result; - auto get_result = mdb_cursor_get(m_cur_block_info, &key, &result, MDB_SET); + MDB_val_set(result, height); + auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { throw0(BLOCK_DNE(std::string("Attempt to get generated coins from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- block size not in db").c_str())); @@ -1529,9 +1523,8 @@ crypto::hash BlockchainLMDB::get_block_hash_from_height(const uint64_t& height) TXN_PREFIX_RDONLY(); RCURSOR(block_info); - MDB_val_copy<uint64_t> key(height); - MDB_val result; - auto get_result = mdb_cursor_get(m_cur_block_info, &key, &result, MDB_SET); + MDB_val_set(result, height); + auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) { throw0(BLOCK_DNE(std::string("Attempt to get hash from height ").append(boost::lexical_cast<std::string>(height)).append(" failed -- hash not in db").c_str())); @@ -1856,10 +1849,9 @@ tx_out_index BlockchainLMDB::get_output_tx_and_index_from_global(const uint64_t& TXN_PREFIX_RDONLY(); RCURSOR(output_txs); - MDB_val_copy<uint64_t> k(index); - MDB_val v; + MDB_val_set(v, index); - auto get_result = mdb_cursor_get(m_cur_output_txs, &k, &v, MDB_SET); + auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) throw1(OUTPUT_DNE("output with given index not in db")); else if (get_result) @@ -2437,10 +2429,9 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint6 for (const uint64_t &index : global_indices) { - MDB_val_copy<uint64_t> k(index); - MDB_val v; + MDB_val_set(v, index); - auto get_result = mdb_cursor_get(m_cur_output_txs, &k, &v, MDB_SET); + auto get_result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); if (get_result == MDB_NOTFOUND) throw1(OUTPUT_DNE("output with given index not in db")); else if (get_result) diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index a298ee68f..2ac8b94d8 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -300,7 +300,6 @@ private: void remove_tx_outputs(const uint64_t tx_index, const transaction& tx); void remove_output(const uint64_t& out_index, const uint64_t amount); - void remove_amount_output_index(const uint64_t amount, const uint64_t global_output_index); virtual void add_spent_key(const crypto::key_image& k_image); |