diff options
Diffstat (limited to 'src/blockchain_db/lmdb')
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 100 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.h | 11 |
2 files changed, 93 insertions, 18 deletions
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index f978ef307..5093015f2 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -163,7 +163,15 @@ int BlockchainLMDB::compare_string(const MDB_val *a, const MDB_val *b) { const char *va = (const char*) a->mv_data; const char *vb = (const char*) b->mv_data; - return strcmp(va, vb); + const size_t sz = std::min(a->mv_size, b->mv_size); + int ret = strncmp(va, vb, sz); + if (ret) + return ret; + if (a->mv_size < b->mv_size) + return -1; + if (a->mv_size > b->mv_size) + return 1; + return 0; } } @@ -1771,7 +1779,7 @@ void BlockchainLMDB::update_txpool_tx(const crypto::hash &txid, const txpool_tx_ } } -uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const +uint64_t BlockchainLMDB::get_txpool_tx_count(relay_category category) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1781,7 +1789,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const TXN_PREFIX_RDONLY(); - if (include_unrelayed_txes) + if (category == relay_category::all) { // No filtering, we can get the number of tx the "fast" way MDB_stat db_stats; @@ -1807,7 +1815,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const if (result) throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str())); const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data; - if (!meta.do_not_relay) + if (meta.matches(category)) ++num_entries; } } @@ -1816,7 +1824,7 @@ uint64_t BlockchainLMDB::get_txpool_tx_count(bool include_unrelayed_txes) const return num_entries; } -bool BlockchainLMDB::txpool_has_tx(const crypto::hash& txid) const +bool BlockchainLMDB::txpool_has_tx(const crypto::hash& txid, relay_category tx_category) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1825,11 +1833,21 @@ bool BlockchainLMDB::txpool_has_tx(const crypto::hash& txid) const RCURSOR(txpool_meta) MDB_val k = {sizeof(txid), (void *)&txid}; - auto result = mdb_cursor_get(m_cur_txpool_meta, &k, NULL, MDB_SET); + MDB_val v; + auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET); if (result != 0 && result != MDB_NOTFOUND) throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str())); + if (result == MDB_NOTFOUND) + return false; + + bool found = true; + if (tx_category != relay_category::all) + { + const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data; + found = meta.matches(tx_category); + } TXN_POSTFIX_RDONLY(); - return result != MDB_NOTFOUND; + return found; } void BlockchainLMDB::remove_txpool_tx(const crypto::hash& txid) @@ -1883,7 +1901,7 @@ bool BlockchainLMDB::get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta return true; } -bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const +bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -1893,6 +1911,21 @@ bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::bl MDB_val k = {sizeof(txid), (void *)&txid}; MDB_val v; + + // if filtering, make sure those requirements are met before copying blob + if (tx_category != relay_category::all) + { + auto result = mdb_cursor_get(m_cur_txpool_meta, &k, &v, MDB_SET); + if (result == MDB_NOTFOUND) + return false; + if (result != 0) + throw1(DB_ERROR(lmdb_error("Error finding txpool tx meta: ", result).c_str())); + + const txpool_tx_meta_t& meta = *(const txpool_tx_meta_t*)v.mv_data; + if (!meta.matches(tx_category)) + return false; + } + auto result = mdb_cursor_get(m_cur_txpool_blob, &k, &v, MDB_SET); if (result == MDB_NOTFOUND) return false; @@ -1904,10 +1937,10 @@ bool BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, cryptonote::bl return true; } -cryptonote::blobdata BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid) const +cryptonote::blobdata BlockchainLMDB::get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const { cryptonote::blobdata bd; - if (!get_txpool_tx_blob(txid, bd)) + if (!get_txpool_tx_blob(txid, bd, tx_category)) throw1(DB_ERROR("Tx not found in txpool: ")); return bd; } @@ -2245,7 +2278,7 @@ bool BlockchainLMDB::check_pruning() return prune_worker(prune_mode_check, 0); } -bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, bool include_unrelayed_txes) const +bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, relay_category category) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -2269,8 +2302,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx metadata: ", result).c_str())); const crypto::hash txid = *(const crypto::hash*)k.mv_data; const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data; - if (!include_unrelayed_txes && meta.do_not_relay) - // Skipping that tx + if (!meta.matches(category)) continue; const cryptonote::blobdata *passed_bd = NULL; cryptonote::blobdata bd; @@ -3033,6 +3065,48 @@ bool BlockchainLMDB::get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobd return true; } +bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const +{ + LOG_PRINT_L3("BlockchainLMDB::" << __func__); + check_open(); + + if (!count) + return true; + + TXN_PREFIX_RDONLY(); + RCURSOR(tx_indices); + RCURSOR(txs_pruned); + + bd.reserve(bd.size() + count); + + MDB_val_set(v, h); + MDB_val result; + int res = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); + if (res == MDB_NOTFOUND) + return false; + if (res) + throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", res).c_str())); + + const txindex *tip = (const txindex *)v.mv_data; + const uint64_t id = tip->data.tx_id; + MDB_val_set(val_tx_id, id); + MDB_cursor_op op = MDB_SET; + while (count--) + { + res = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result, op); + op = MDB_NEXT; + if (res == MDB_NOTFOUND) + return false; + if (res) + throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx blob", res).c_str())); + bd.emplace_back(reinterpret_cast<char*>(result.mv_data), result.mv_size); + } + + TXN_POSTFIX_RDONLY(); + + return true; +} + bool BlockchainLMDB::get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 61a551476..7c0b4c72c 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -254,6 +254,7 @@ public: virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const; virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const; + virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const; virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const; virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const; @@ -281,12 +282,12 @@ public: virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& meta); virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& meta); - virtual uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const; - virtual bool txpool_has_tx(const crypto::hash &txid) const; + virtual uint64_t get_txpool_tx_count(relay_category category = relay_category::broadcasted) const; + virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const; virtual void remove_txpool_tx(const crypto::hash& txid); virtual bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const; - virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd) const; - virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid) const; + virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata& bd, relay_category tx_category) const; + virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const; virtual uint32_t get_blockchain_pruning_seed() const; virtual bool prune_blockchain(uint32_t pruning_seed = 0); virtual bool update_pruning(); @@ -298,7 +299,7 @@ public: virtual uint64_t get_alt_block_count(); virtual void drop_alt_blocks(); - virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, bool include_unrelayed_txes = true) const; + virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, relay_category category = relay_category::broadcasted) const; virtual bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const; virtual bool for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const; |