More btree tweaks, now with better handling of degenerate parents

Normally, in btrees, the height of the btree only decreases when nodes
are merged.

But not in our btree! Thanks again to lazy merging, btree nodes can be
dropped instead of merged.

We don't have enough information to decrease the height of the btree
exactly when we drop a btree node, since we don't know how many siblings
the original node had, but we can at least decrease the height of the
btree if we notice this condition during normal commits.
This commit is contained in:
Christopher Haster
2023-08-17 17:52:59 -05:00
parent 256488d4b4
commit 5ecdc8b4f7
+15 -9
View File
@@ -3962,7 +3962,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
goto compact;
}
goto commit_recurse;
goto commit;
compact:;
// can't commit, try to compact
@@ -4099,7 +4099,9 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
return err;
}
commit_recurse:;
goto commit;
commit:;
// done?
if (rid == -1) {
LFS_ASSERT(bid == 0);
@@ -4107,15 +4109,19 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
return 0;
}
// is our parent the root and is the root degenerate?
if (rbyd.weight == lfsr_btree_weight(btree)) {
// collapse the root, decreasing the height of the tree
btree->u.r.rbyd = rbyd_;
return 0;
}
lfs_ssize_t scratch_dsize = lfsr_branch_todisk(lfs, &rbyd_,
scratch_buf);
if (scratch_dsize < 0) {
return scratch_dsize;
}
// TODO can split and merge both end up with zero weight rbyds
// as well? do our tests cover this?
// prepare commit to parent, tail recursing upwards
//
// note that since we defer merges to compaction time, we can
@@ -4207,7 +4213,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
if (rbyd_.weight == 0) {
rbyd_ = sibling;
}
goto commit_recurse;
goto commit;
}
// lookup first name in sibling to use as the split name
@@ -4336,11 +4342,11 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
return err;
}
// TODO we should also do this when dropping no?
// we must have a parent at this point, but is our parent degenerate?
// we must have a parent at this point, but is our parent the root
// and is the root degenerate?
LFS_ASSERT(rid != -1);
if (rbyd.weight+sibling.weight == lfsr_btree_weight(btree)) {
// collapse our parent, decreasing the height of the tree
// collapse the root, decreasing the height of the tree
btree->u.r.rbyd = rbyd__;
return 0;
}