BlockchainLMDB: When removing, find amount output index fast by starting at end

This improves blockchain reorganization time by allowing one of the more
expensive DB lookups when popping a block to not have to seek through a
long dup list in the "output_amounts" subdb. This is most noticeable for
HDDs.

As before, the dup list is still walked if necessary (but in reverse),
and the global output index still confirmed to be the one looked for.
But under proper use, the result will be found at the end of the dup
list, so we start there.

Removing an amount output index is always done in the context of popping
a block, so the global output index being looked for should be the last
one in that amount key's dup list. Even if the txs themselves aren't
removed in reverse order (supposed to be according to original
implementation), the specified amount output index will still be near
the end, because the txs are in the same block.

TEST:

Pop blocks with blockchain_import.

Blocks should be successfully removed with no errors shown.

bitmonerod should be able to start syncing from the reduced blockchain
height.
This commit is contained in:
warptangent 2015-12-24 12:25:07 -08:00
parent f11def012f
commit ffcf6bdb95
No known key found for this signature in database
GPG key ID: 0E490BEBFBE4E92D

View file

@ -806,22 +806,23 @@ void BlockchainLMDB::remove_amount_output_index(const uint64_t amount, const uin
size_t num_elems = 0; size_t num_elems = 0;
mdb_cursor_count(cur, &num_elems); mdb_cursor_count(cur, &num_elems);
mdb_cursor_get(cur, &k, &v, MDB_FIRST_DUP); mdb_cursor_get(cur, &k, &v, MDB_LAST_DUP);
uint64_t amount_output_index = 0; uint64_t amount_output_index = 0;
uint64_t goi = 0; uint64_t goi = 0;
bool found_index = false; bool found_index = false;
for (uint64_t i = 0; i < num_elems; ++i) for (uint64_t i = num_elems; i > 0; --i)
{ {
mdb_cursor_get(cur, &k, &v, MDB_GET_CURRENT); mdb_cursor_get(cur, &k, &v, MDB_GET_CURRENT);
goi = *(const uint64_t *)v.mv_data; goi = *(const uint64_t *)v.mv_data;
if (goi == global_output_index) if (goi == global_output_index)
{ {
amount_output_index = i; amount_output_index = i-1;
found_index = true; found_index = true;
break; break;
} }
mdb_cursor_get(cur, &k, &v, MDB_NEXT_DUP); if (i > 1)
mdb_cursor_get(cur, &k, &v, MDB_PREV_DUP);
} }
if (found_index) if (found_index)
{ {