Skip to content

Commit 60aa96f

Browse files
s26-p2: Update TombstoneCoalesceTest and fix LeafPage type alias (#870)
* s26-p2: Update TombstoneCoalesceTest to depend less on page IDs * s26-p2: Update TombstoneCoalesceTest to ensure indexes are correct * s26-p2: Add NumTombs template parameter in BPlusTree's LeafPage type alias * s26-p2: Justify switching off clang-format to avoid squashing of lines
1 parent a1a0ad3 commit 60aa96f

2 files changed

Lines changed: 58 additions & 30 deletions

File tree

src/include/storage/index/b_plus_tree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ class Context {
7575
FULL_INDEX_TEMPLATE_ARGUMENTS_DEFN
7676
class BPlusTree {
7777
using InternalPage = BPlusTreeInternalPage<KeyType, page_id_t, KeyComparator>;
78-
using LeafPage = BPlusTreeLeafPage<KeyType, ValueType, KeyComparator>;
78+
using LeafPage = BPlusTreeLeafPage<KeyType, ValueType, KeyComparator, NumTombs>;
7979

8080
public:
8181
explicit BPlusTree(std::string name, page_id_t header_page_id, BufferPoolManager *buffer_pool_manager,

test/storage/b_plus_tree_tombstone_test.cpp

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ TEST(BPlusTreeTests, DISABLED_TombstoneCoalesceTest) {
294294
GenericKey<8> index_key;
295295
RID rid;
296296

297+
// insert 0, 1, 2, 3, 4, 5, 6 into the b+ tree
297298
size_t num_keys = 7;
298299
for (size_t i = 0; i < num_keys; i++) {
299300
int64_t value = i & 0xFFFFFFFF;
@@ -302,8 +303,9 @@ TEST(BPlusTreeTests, DISABLED_TombstoneCoalesceTest) {
302303
tree.Insert(index_key, rid);
303304
}
304305

305-
page_id_t larger_pid;
306-
page_id_t smaller_pid;
306+
// there should be a larger leaf page and a smaller leaf page
307+
page_id_t larger_pid = INVALID_PAGE_ID;
308+
page_id_t smaller_pid = INVALID_PAGE_ID;
307309
auto leaf = IndexLeaves<GenericKey<8>, RID, GenericComparator<8>, 2>(tree.GetRootPageId(), bpm);
308310
while (leaf.Valid()) {
309311
if ((*leaf)->GetSize() == 4) {
@@ -313,49 +315,75 @@ TEST(BPlusTreeTests, DISABLED_TombstoneCoalesceTest) {
313315
}
314316
++leaf;
315317
}
318+
ASSERT_NE(larger_pid, INVALID_PAGE_ID);
319+
ASSERT_NE(smaller_pid, INVALID_PAGE_ID);
316320

317-
std::vector<GenericKey<8>> to_delete;
321+
// figure out keys to delete from the larger and smaller pages
322+
std::vector<GenericKey<8>> to_del_from_larger_page;
323+
std::vector<GenericKey<8>> to_del_from_smaller_page;
318324
{
319325
auto larger_page = bpm->ReadPage(larger_pid).As<LeafPage>();
320326
auto smaller_page = bpm->ReadPage(smaller_pid).As<LeafPage>();
321-
for (size_t i = 0; i < 2; i++) {
322-
to_delete.push_back(larger_page->KeyAt(2 + i));
323-
to_delete.push_back(smaller_page->KeyAt(i));
324-
}
325-
to_delete.push_back(larger_page->KeyAt(0));
326-
to_delete.push_back(smaller_page->KeyAt(2));
327+
328+
to_del_from_larger_page = {
329+
larger_page->KeyAt(0),
330+
larger_page->KeyAt(1),
331+
larger_page->KeyAt(2),
332+
};
333+
to_del_from_smaller_page = {
334+
smaller_page->KeyAt(0),
335+
smaller_page->KeyAt(1),
336+
smaller_page->KeyAt(2),
337+
};
327338
}
328-
for (auto k : to_delete) {
339+
340+
// delete keys alternating between the larger and smaller pages.
341+
// The final delete from the smaller page should force a coalesce.
342+
std::vector<GenericKey<8>> to_del = {
343+
// clang-format off
344+
// Otherwise these are folded into two hard-to-read lines
345+
to_del_from_larger_page[0],
346+
to_del_from_smaller_page[0],
347+
to_del_from_larger_page[1],
348+
to_del_from_smaller_page[1],
349+
to_del_from_larger_page[2],
350+
to_del_from_smaller_page[2],
351+
// clang-format on
352+
};
353+
for (auto k : to_del) {
329354
tree.Remove(k);
330355
}
331356

332-
size_t num_leaves = 0;
333-
page_id_t remaining_pid;
357+
// ensure index is still correct
358+
std::vector<page_id_t> leaves;
334359
leaf = IndexLeaves<GenericKey<8>, RID, GenericComparator<8>, 2>(tree.GetRootPageId(), bpm);
335360
while (leaf.Valid()) {
336-
remaining_pid = leaf.guard_->GetPageId();
337-
num_leaves++;
361+
leaves.push_back(leaf.guard_->GetPageId());
338362
++leaf;
339363
}
364+
ASSERT_EQ(leaves, std::vector<page_id_t>{tree.GetRootPageId()});
365+
366+
// get the only leaf page in the b+ tree
367+
page_id_t root_page_id = tree.GetRootPageId();
368+
auto root_page = bpm->ReadPage(root_page_id).As<LeafPage>();
369+
ASSERT_EQ(root_page->IsLeafPage(), true);
340370

341-
EXPECT_EQ(num_leaves, 1);
342-
auto page = bpm->ReadPage(remaining_pid).As<LeafPage>();
343-
auto tombstones = page->GetTombstones();
371+
auto tombstones = root_page->GetTombstones();
344372
EXPECT_EQ(tombstones.size(), 2);
345-
if (remaining_pid == smaller_pid) {
346-
EXPECT_EQ(tombstones[0].GetAsInteger(), to_delete[2].GetAsInteger());
347-
EXPECT_EQ(tombstones[1].GetAsInteger(), to_delete[4].GetAsInteger());
348-
index_key.SetFromInteger(7);
349-
int64_t value = 7 & 0xFFFFFFFF;
350-
rid.Set(static_cast<int32_t>(7L >> 32), value);
351-
tree.Insert(index_key, rid);
352-
EXPECT_EQ(tombstones[0].GetAsInteger(), to_delete[2].GetAsInteger());
353-
EXPECT_EQ(tombstones[1].GetAsInteger(), to_delete[4].GetAsInteger());
354-
} else {
355-
EXPECT_EQ(tombstones[0].GetAsInteger(), to_delete[3].GetAsInteger());
356-
EXPECT_EQ(tombstones[1].GetAsInteger(), to_delete[5].GetAsInteger());
373+
374+
// final set of tombstones should either be the last two keys logically
375+
// deleted from the smaller page or the last two keys logically deleted
376+
// from the larger page.
377+
bool eq_to_smaller_page = true;
378+
bool eq_to_larger_page = true;
379+
for (int i = 0; i < 2; i++) {
380+
eq_to_smaller_page &= tombstones[i].GetAsInteger() == to_del_from_smaller_page[1 + i].GetAsInteger();
381+
eq_to_larger_page &= tombstones[i].GetAsInteger() == to_del_from_larger_page[1 + i].GetAsInteger();
357382
}
358383

384+
ASSERT_EQ(!eq_to_smaller_page || !eq_to_larger_page, true);
385+
EXPECT_EQ(eq_to_smaller_page || eq_to_larger_page, true);
386+
359387
delete bpm;
360388
delete disk_manager;
361389
}

0 commit comments

Comments
 (0)