Fix repeated rollbacks in bs_heap
This commit is contained in:
@@ -2038,7 +2038,10 @@ void blockstore_heap_t::iterate_with_stable(heap_entry_t *obj, uint64_t max_lsn,
|
|||||||
{
|
{
|
||||||
if (old_wr->type() == BS_HEAP_ROLLBACK)
|
if (old_wr->type() == BS_HEAP_ROLLBACK)
|
||||||
{
|
{
|
||||||
rollback_version = old_wr->version;
|
if (rollback_version > old_wr->version)
|
||||||
|
{
|
||||||
|
rollback_version = old_wr->version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (old_wr->type() == BS_HEAP_COMMIT)
|
else if (old_wr->type() == BS_HEAP_COMMIT)
|
||||||
{
|
{
|
||||||
@@ -2090,7 +2093,10 @@ heap_compact_t blockstore_heap_t::iterate_compaction(heap_entry_t *obj, uint64_t
|
|||||||
res.compact_lsn = wr->lsn;
|
res.compact_lsn = wr->lsn;
|
||||||
res.compact_version = wr->version;
|
res.compact_version = wr->version;
|
||||||
}
|
}
|
||||||
rollback_version = wr->version;
|
if (rollback_version > wr->version)
|
||||||
|
{
|
||||||
|
rollback_version = wr->version;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (wr->type() == BS_HEAP_COMMIT && wr->lsn <= fsynced_lsn)
|
if (wr->type() == BS_HEAP_COMMIT && wr->lsn <= fsynced_lsn)
|
||||||
|
|||||||
@@ -965,6 +965,78 @@ void test_iterate_compaction()
|
|||||||
assert(small_writes == 1);
|
assert(small_writes == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
blockstore_heap_t heap(&dsk, buffer_area.data());
|
||||||
|
heap.finish_recheck();
|
||||||
|
|
||||||
|
// Case: BIG_STABLE(v1 l1) SMALL(v2 l2) SMALL(v3 l3) ROLLBACK(v2 l4) ROLLBACK(v1 l5)
|
||||||
|
// -> compact by adding BIG_STABLE(v1 l6) and skip l2 and l3
|
||||||
|
uint32_t mblock = 0;
|
||||||
|
_test_big_write(heap, dsk, 1, 0, 1, 0, true, 0, 4096, buffer_area.data());
|
||||||
|
_test_small_write(heap, dsk, 1, 0, 2, 0, 4096, 0, false, buffer_area.data(), false);
|
||||||
|
_test_small_write(heap, dsk, 1, 0, 3, 4096, 4096, 4096, false, buffer_area.data(), false);
|
||||||
|
|
||||||
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||||
|
auto obj = heap.read_entry(oid);
|
||||||
|
assert(obj->lsn == 3);
|
||||||
|
|
||||||
|
res = heap.add_rollback(obj, 2, &mblock);
|
||||||
|
assert(res == 0);
|
||||||
|
heap.start_block_write(mblock);
|
||||||
|
heap.complete_block_write(mblock);
|
||||||
|
|
||||||
|
res = heap.add_rollback(obj, 1, &mblock);
|
||||||
|
assert(res == 0);
|
||||||
|
heap.start_block_write(mblock);
|
||||||
|
heap.complete_block_write(mblock);
|
||||||
|
|
||||||
|
obj = heap.read_entry(oid);
|
||||||
|
assert(count_writes(heap, obj) == 5);
|
||||||
|
|
||||||
|
assert(heap.get_fsynced_lsn() == 5);
|
||||||
|
int small_writes = 0;
|
||||||
|
obj = heap.read_entry(oid);
|
||||||
|
auto compact_info = heap.iterate_compaction(obj, heap.get_fsynced_lsn(), false, [&](heap_entry_t *wr)
|
||||||
|
{
|
||||||
|
small_writes++;
|
||||||
|
});
|
||||||
|
assert(small_writes == 0);
|
||||||
|
assert(compact_info.compact_lsn == 5);
|
||||||
|
assert(compact_info.compact_version == 1);
|
||||||
|
assert(compact_info.clean_wr->lsn == 1);
|
||||||
|
assert(!compact_info.do_delete);
|
||||||
|
|
||||||
|
// persist
|
||||||
|
assert(heap.get_meta_block_used_space(0) > 0);
|
||||||
|
tmp.resize(dsk.meta_block_size);
|
||||||
|
heap.get_meta_block(0, tmp.data());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// reload heap and check that object state isn't changed and validation passes
|
||||||
|
blockstore_heap_t heap(&dsk, buffer_area.data());
|
||||||
|
uint64_t entries_loaded;
|
||||||
|
heap.load_blocks(0, dsk.meta_block_size, tmp.data(), false, entries_loaded);
|
||||||
|
heap.finish_load();
|
||||||
|
bool done = heap.recheck_small_writes([&](bool, uint64_t, uint64_t, uint8_t*, std::function<void()> cb) {}, 1);
|
||||||
|
assert(done);
|
||||||
|
heap.finish_recheck();
|
||||||
|
auto mod = heap.get_recheck_modified_blocks();
|
||||||
|
assert(mod.size() == 0);
|
||||||
|
|
||||||
|
object_id oid = { .inode = INODE_WITH_POOL(1, 1), .stripe = 0 };
|
||||||
|
auto obj = heap.read_entry(oid);
|
||||||
|
int small_writes = 0;
|
||||||
|
auto compact_info = heap.iterate_compaction(obj, heap.get_fsynced_lsn(), true, [&](heap_entry_t *wr)
|
||||||
|
{
|
||||||
|
small_writes++;
|
||||||
|
});
|
||||||
|
assert(compact_info.compact_lsn == 5);
|
||||||
|
assert(compact_info.compact_version == 1);
|
||||||
|
assert(compact_info.clean_wr->lsn == 1);
|
||||||
|
assert(!compact_info.do_delete);
|
||||||
|
assert(small_writes == 0);
|
||||||
|
}
|
||||||
|
|
||||||
printf("OK test_iterate_compaction\n");
|
printf("OK test_iterate_compaction\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user