A working delete implementation?

Though note this still uses tombstoning.
This commit is contained in:
Christopher Haster
2023-01-02 13:23:46 -06:00
parent b621774759
commit fbb6bd0919
+229 -91
View File
@@ -1264,7 +1264,7 @@ static int lfs_rbyd_fetch(lfs_t *lfs,
static lfs_srtag_t lfs_rbyd_lookup(lfs_t *lfs, const lfs_rbyd_t *rbyd, static lfs_srtag_t lfs_rbyd_lookup(lfs_t *lfs, const lfs_rbyd_t *rbyd,
lfs_rtag_t tag, lfs_off_t *off, lfs_size_t *size) { lfs_rtag_t tag, lfs_off_t *off, lfs_size_t *size) {
printf("lookup(%08x)\n", tag); printf("- lookup(%08x) -\n", tag);
// TODO is this true? // TODO is this true?
// check for out-of-bound ids here, otherwise we have issues determining // check for out-of-bound ids here, otherwise we have issues determining
// the found id // the found id
@@ -1513,7 +1513,7 @@ static void lfs_rbyd_p_red(
static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_, static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rtag_t tag, const void *buffer, lfs_size_t size) { lfs_rtag_t tag, const void *buffer, lfs_size_t size) {
printf("append()\n"); printf("- append() -\n");
LFS_ASSERT(lfs_rtag_id(tag) <= rbyd_->count+1); LFS_ASSERT(lfs_rtag_id(tag) <= rbyd_->count+1);
// assume we'll update our trunk // assume we'll update our trunk
@@ -1785,7 +1785,7 @@ leaf:;
static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rtag_t tag, const void *buffer, lfs_size_t size) { lfs_rtag_t tag, const void *buffer, lfs_size_t size) {
printf("delete()\n"); printf("- delete() -\n");
LFS_ASSERT(lfs_rtag_id(tag) <= rbyd_->count+1); LFS_ASSERT(lfs_rtag_id(tag) <= rbyd_->count+1);
// no trunk yet? // no trunk yet?
@@ -1799,6 +1799,9 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
rbyd_->trunk = rbyd_->off; rbyd_->trunk = rbyd_->off;
// keep track of bounds as we descend down the tree // keep track of bounds as we descend down the tree
bool is_lower = true;
bool is_cut = false;
bool is_other_done = false;
lfs_rtag_t lower_lower = 0; lfs_rtag_t lower_lower = 0;
lfs_rtag_t lower_upper = (rbyd_->count+1) << 15; lfs_rtag_t lower_upper = (rbyd_->count+1) << 15;
lfs_rtag_t upper_lower = 0; lfs_rtag_t upper_lower = 0;
@@ -1806,16 +1809,13 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rtag_t lower_tag__ = tag & ~0x7fff; lfs_rtag_t lower_tag__ = tag & ~0x7fff;
lfs_rtag_t upper_tag__ = lower_tag__ + 0x8000; lfs_rtag_t upper_tag__ = lower_tag__ + 0x8000;
// weights for pruning // // weights for pruning
bool is_lower = true; // lfs_srtag_t lower_lt = lfs_rtag_weight_lt(tag & ~0x7fff, rbyd_->count+1);
bool is_cut = false; // lfs_srtag_t lower_gt = lfs_rtag_weight_gt(tag & ~0x7fff, rbyd_->count+1);
bool is_other_done = false; // lfs_srtag_t upper_lt = lfs_rtag_weight_lt((tag | 0x7fff)+1, rbyd_->count+1);
lfs_srtag_t lower_lt = lfs_rtag_weight_lt(tag & ~0x7fff, rbyd_->count+1); // lfs_srtag_t upper_gt = lfs_rtag_weight_gt((tag | 0x7fff)+1, rbyd_->count+1);
lfs_srtag_t lower_gt = lfs_rtag_weight_gt(tag & ~0x7fff, rbyd_->count+1); //
lfs_srtag_t upper_lt = lfs_rtag_weight_lt((tag | 0x7fff)+1, rbyd_->count+1); // printf("lower, upper = (%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt);
lfs_srtag_t upper_gt = lfs_rtag_weight_gt((tag | 0x7fff)+1, rbyd_->count+1);
printf("lower, upper = (%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt);
// queue of pending alts we can emulate rotations with // queue of pending alts we can emulate rotations with
lfs_rtag_t p_alts[3] = {0, 0, 0}; lfs_rtag_t p_alts[3] = {0, 0, 0};
@@ -1827,8 +1827,9 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_off_t branch = is_lower ? lower_branch : upper_branch; lfs_off_t branch = is_lower ? lower_branch : upper_branch;
lfs_rtag_t lower = is_lower ? lower_lower : upper_lower; lfs_rtag_t lower = is_lower ? lower_lower : upper_lower;
lfs_rtag_t upper = is_lower ? lower_upper : upper_upper; lfs_rtag_t upper = is_lower ? lower_upper : upper_upper;
lfs_srtag_t lt = is_lower ? lower_lt : upper_lt; lfs_rtag_t tag__ = is_lower ? lower_tag__ : upper_tag__;
lfs_srtag_t gt = is_lower ? lower_gt : upper_gt; // lfs_srtag_t lt = is_lower ? lower_lt : upper_lt;
// lfs_srtag_t gt = is_lower ? lower_gt : upper_gt;
lfs_rtag_t alt; lfs_rtag_t alt;
lfs_off_t jump; lfs_off_t jump;
@@ -1846,35 +1847,123 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rtag_t branch_ = branch + delta; lfs_rtag_t branch_ = branch + delta;
// do bounds want to take different paths? begin cutting // do bounds want to take different paths? begin cutting
if (!is_cut && lfs_rtag_follow(alt, lower_lt, lower_gt) if (!is_cut && lfs_rtag_follow_(alt, lower_lower, lower_upper, lower_tag__)
!= lfs_rtag_follow(alt, upper_lt, upper_gt)) { != lfs_rtag_follow_(alt, upper_lower, upper_upper, upper_tag__)) {
printf("beginning cut\n"); printf("beginning cut\n");
printf("lower, upper = (%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt); // printf("lower, upper = (%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt);
is_cut = true; is_cut = true;
// TODO do we need this if we flip red alts early? // TODO do we need this if we flip red alts early?
if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { if (p_alts[0] && lfs_rtag_isred(p_alts[0])) {
upper_branch = graft; printf("cut on red %x?\n", graft);
lfs_rtag_untrim(p_alts[0], &upper_lt, &upper_gt); // upper_branch = graft;
lfs_rtag_untrim_(p_alts[0], &upper_lower, &upper_upper); //// lfs_rtag_untrim(p_alts[0], &upper_lt, &upper_gt);
// lfs_rtag_untrim_(p_alts[0], &upper_lower, &upper_upper);
//
// lower_branch = graft;
// lfs_rtag_untrim_(p_alts[0], &lower_lower, &lower_upper);
//
// lfs_rbyd_p_pop(p_alts, p_jumps);
//
// continue;
}
}
// TODO can this be combined with prune? maybe not?
// cut?
if (is_cut) {
// cut while following
if ((is_lower
&& lfs_rtag_islt(alt)
&& lfs_rtag_follow_(alt, lower, upper, tag__))
|| (!is_lower
&& lfs_rtag_isgt(alt)
&& lfs_rtag_follow_(alt, lower, upper, tag__))) {
if (p_alts[0] && lfs_rtag_isred(p_alts[0])) {
printf("cut follow red\n");
lfs_rtag_trim_(lfs_rtag_flip_(alt, lower, upper),
&lower, &upper);
alt = lfs_rtag_black(p_alts[0]);
branch_ = jump;
jump = p_jumps[0];
lfs_rbyd_p_pop(p_alts, p_jumps);
lfs_rtag_untrim_(alt, &lower, &upper);
} else {
printf("cut follow\n");
lfs_rtag_trim_(lfs_rtag_flip_(alt, lower, upper),
&lower, &upper);
graft = branch; // TODO?
branch = jump;
goto next;
}
// cut while not following
} else if ((is_lower
&& lfs_rtag_isgt(alt)
&& !lfs_rtag_follow_(alt, lower, upper, tag__))
|| (!is_lower
&& lfs_rtag_islt(alt)
&& !lfs_rtag_follow_(alt, lower, upper, tag__))) {
if (p_alts[0] && lfs_rtag_isred(p_alts[0])) {
printf("cut nofollow red\n");
lfs_rtag_trim_(alt, &lower, &upper);
alt = lfs_rtag_black(p_alts[0]);
jump = p_jumps[0];
lfs_rbyd_p_pop(p_alts, p_jumps);
lfs_rtag_untrim_(alt, &lower, &upper);
} else {
printf("cut nofollow\n");
lfs_rtag_trim_(alt, &lower, &upper);
graft = branch; // TODO?
branch = branch_;
goto next;
}
} }
} }
// prune? // prune?
if (lfs_rtag_weight(alt) >= lt+gt+1) { if (lfs_rtag_weight_(alt) >= (upper-lower)) {
printf("prune!\n"); if (p_alts[0] && lfs_rtag_isred(p_alts[0])) {
LFS_ASSERT(p_alts[0]); printf("prune red!\n");
LFS_ASSERT(lfs_rtag_isred(p_alts[0]));
alt = lfs_rtag_black(p_alts[0]); alt = lfs_rtag_black(p_alts[0]);
branch_ = jump; branch_ = jump;
jump = p_jumps[0]; jump = p_jumps[0];
lfs_rbyd_p_pop(p_alts, p_jumps); lfs_rbyd_p_pop(p_alts, p_jumps);
lfs_rtag_untrim(alt, &lt, &gt); lfs_rtag_untrim_(alt, &lower, &upper);
lfs_rtag_untrim_(alt, &lower, &upper); } else {
printf("prune!\n");
graft = branch; // TODO?
branch = jump;
goto next;
}
} }
// // prune?
// if (lfs_rtag_weight_(alt) >= (upper-lower)) {
//// if (lfs_rtag_weight(alt) >= lt+gt+1) {
// printf("prune!\n");
// LFS_ASSERT(p_alts[0]);
// LFS_ASSERT(lfs_rtag_isred(p_alts[0]));
//
// alt = lfs_rtag_black(p_alts[0]);
// branch_ = jump;
// jump = p_jumps[0];
// lfs_rbyd_p_pop(p_alts, p_jumps);
//
//// lfs_rtag_untrim(alt, &lt, &gt);
// lfs_rtag_untrim_(alt, &lower, &upper);
// }
// two reds makes a yellow, split? // two reds makes a yellow, split?
if (lfs_rtag_isred(alt) if (lfs_rtag_isred(alt)
&& p_alts[0] && p_alts[0]
@@ -1884,20 +1973,20 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
// if we take the red or yellow alt we can just point // if we take the red or yellow alt we can just point
// to the black alt, otherwise we need to point to the // to the black alt, otherwise we need to point to the
// yellow alt and prune later // yellow alt and prune later
if (lfs_rtag_follow(alt, lt, gt)) { if (lfs_rtag_follow_(alt, lower, upper, tag__)) {
printf("ysplit follow\n"); printf("ysplit follow\n");
lfs_rtag_t alt_ = p_alts[0]; lfs_rtag_t alt_ = p_alts[0];
lfs_off_t jump_ = p_jumps[0]; lfs_off_t jump_ = p_jumps[0];
p_alts[0] = lfs_rtag_black( p_alts[0] = lfs_rtag_black(
lfs_rtag_flip(alt, lt, gt)); lfs_rtag_flip_(alt, lower, upper));
p_jumps[0] = branch_; p_jumps[0] = branch_;
alt = lfs_rtag_black(alt_); alt = lfs_rtag_black(alt_);
branch_ = jump; branch_ = jump;
jump = jump_; jump = jump_;
lfs_rtag_untrim(alt, &lt, &gt); // lfs_rtag_untrim(alt, &lt, &gt);
lfs_rtag_untrim_(alt, &lower, &upper); lfs_rtag_untrim_(alt, &lower, &upper);
lfs_rtag_trim(p_alts[0], &lt, &gt); // lfs_rtag_trim(p_alts[0], &lt, &gt);
lfs_rtag_trim_(p_alts[0], &lower, &upper); lfs_rtag_trim_(p_alts[0], &lower, &upper);
lfs_rbyd_p_red(p_alts, p_jumps); lfs_rbyd_p_red(p_alts, p_jumps);
@@ -1908,7 +1997,7 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lfs_rtag_merge(alt, p_alts[0])); lfs_rtag_merge(alt, p_alts[0]));
p_jumps[0] = graft; p_jumps[0] = graft;
lfs_rtag_trim(alt, &lt, &gt); // lfs_rtag_trim(alt, &lt, &gt);
lfs_rtag_trim_(alt, &lower, &upper); lfs_rtag_trim_(alt, &lower, &upper);
lfs_rbyd_p_red(p_alts, p_jumps); lfs_rbyd_p_red(p_alts, p_jumps);
@@ -1919,17 +2008,19 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
} }
// should've taken red alt? needs a flip // should've taken red alt? needs a flip
if (lt < 0 || gt < 0) { // TODO should we just get rid of follows and prefer explicit comparisons?
printf("rflip %s (%x,%x)\n", if (p_alts[0]
lfs_rtag_isparallel(alt, p_alts[0]) ? "parallel" : "perpendicular", && ((lfs_rtag_islt(p_alts[0]) && tag__ < lower)
lt, gt); || (lfs_rtag_isgt(p_alts[0]) && tag__ >= upper))) {
LFS_ASSERT(p_alts[0]);
LFS_ASSERT(lfs_rtag_isred(p_alts[0])); LFS_ASSERT(lfs_rtag_isred(p_alts[0]));
LFS_ASSERT(lfs_rtag_isblack(alt)); LFS_ASSERT(lfs_rtag_isblack(alt));
printf("rflip %s\n",
lfs_rtag_isparallel(alt, p_alts[0]) ? "parallel" : "perpendicular");
// if black alt would've been taken, it also needs a flip // if black alt would've been taken, it also needs a flip
if (lfs_rtag_isparallel(alt, p_alts[0])) { if (lfs_rtag_isparallel(alt, p_alts[0])) {
alt = lfs_rtag_flip(alt, lt, gt); alt = lfs_rtag_flip_(alt, lower, upper);
lfs_off_t jump_ = jump; lfs_off_t jump_ = jump;
jump = branch_; jump = branch_;
branch_ = jump_; branch_ = jump_;
@@ -1942,38 +2033,38 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
alt = lfs_rtag_black(alt_); alt = lfs_rtag_black(alt_);
jump = jump_; jump = jump_;
lfs_rtag_untrim(alt, &lt, &gt); // lfs_rtag_untrim(alt, &lt, &gt);
lfs_rtag_untrim_(alt, &lower, &upper); lfs_rtag_untrim_(alt, &lower, &upper);
lfs_rtag_trim(p_alts[0], &lt, &gt); // lfs_rtag_trim(p_alts[0], &lt, &gt);
lfs_rtag_trim_(p_alts[0], &lower, &upper); lfs_rtag_trim_(p_alts[0], &lower, &upper);
} }
// take black alt? needs a flip // take black alt? needs a flip
if (lfs_rtag_isblack(alt) && lfs_rtag_follow(alt, lt, gt)) { if (lfs_rtag_isblack(alt) && lfs_rtag_follow_(alt, lower, upper, tag__)) {
printf("bflip\n"); printf("bflip\n");
alt = lfs_rtag_flip(alt, lt, gt); alt = lfs_rtag_flip_(alt, lower, upper);
lfs_off_t jump_ = jump; lfs_off_t jump_ = jump;
jump = branch_; jump = branch_;
branch_ = jump_; branch_ = jump_;
} }
// TODO can this be combined with prune? maybe not? // // TODO can this be combined with prune? maybe not?
// cut? // // cut?
if (is_cut && lfs_rtag_isblack(alt) // if (is_cut && lfs_rtag_isblack(alt)
&& ((is_lower && lfs_rtag_isgt(alt)) // && ((is_lower && lfs_rtag_isgt(alt))
|| (!is_lower && lfs_rtag_islt(alt)))) { // || (!is_lower && lfs_rtag_islt(alt)))) {
printf("bcut (%s, %s)\n", is_lower ? "lower" : "upper", lfs_rtag_isgt(alt) ? "gt" : "lt"); // printf("bcut (%s, %s)\n", is_lower ? "lower" : "upper", lfs_rtag_isgt(alt) ? "gt" : "lt");
if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { // if (p_alts[0] && lfs_rtag_isred(p_alts[0])) {
p_alts[0] = lfs_rtag_black(p_alts[0]); // p_alts[0] = lfs_rtag_black(p_alts[0]);
//
if ((is_lower && lfs_rtag_isgt(p_alts[0])) // if ((is_lower && lfs_rtag_isgt(p_alts[0]))
|| (!is_lower && lfs_rtag_islt(p_alts[0]))) { // || (!is_lower && lfs_rtag_islt(p_alts[0]))) {
printf("rcut (%s, %s)\n", is_lower ? "lower" : "upper", lfs_rtag_isgt(p_alts[0]) ? "gt" : "lt"); // printf("rcut (%s, %s)\n", is_lower ? "lower" : "upper", lfs_rtag_isgt(p_alts[0]) ? "gt" : "lt");
lfs_rbyd_p_pop(p_alts, p_jumps); // lfs_rbyd_p_pop(p_alts, p_jumps);
} // }
} // }
goto dont_push; // goto dont_push;
} // }
// push alt onto queue // push alt onto queue
int err = lfs_rbyd_p_push(lfs, rbyd_, int err = lfs_rbyd_p_push(lfs, rbyd_,
@@ -1983,9 +2074,9 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
return err; return err;
} }
dont_push:; // dont_push:;
// continue to next alt // continue to next alt
lfs_rtag_trim(alt, &lt, &gt); // lfs_rtag_trim(alt, &lt, &gt);
lfs_rtag_trim_(alt, &lower, &upper); lfs_rtag_trim_(alt, &lower, &upper);
graft = branch; graft = branch;
branch = branch_; branch = branch_;
@@ -1995,15 +2086,15 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
lower_branch = branch; lower_branch = branch;
lower_lower = lower; lower_lower = lower;
lower_upper = upper; lower_upper = upper;
lower_lt = lt; // lower_lt = lt;
lower_gt = gt; // lower_gt = gt;
} }
if (!is_cut || !is_lower) { if (!is_cut || !is_lower) {
upper_branch = branch; upper_branch = branch;
upper_lower = lower; upper_lower = lower;
upper_upper = upper; upper_upper = upper;
upper_lt = lt; // upper_lt = lt;
upper_gt = gt; // upper_gt = gt;
} }
// switch bounds we are following? // switch bounds we are following?
@@ -2016,34 +2107,79 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
// TODO just break? the gotos above are smelly // TODO just break? the gotos above are smelly
} else { } else {
// update the tag id // update the tag id
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag)); //lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag));
lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(upper-1));
printf("found %x (%x, %x, lower=%d)\n", tag_, lt, gt, is_lower); // printf("found %x (%x, %x, lower=%d)\n", tag_, lt, gt, is_lower);
printf("(%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt); // printf("(%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt);
// note, when deleting we should always find some tag with the // note, when deleting we should always find some tag with the
// expected id // expected id
// TODO note this only applies with deletes // TODO note this only applies with deletes
LFS_ASSERT(lfs_rtag_id(tag_) == lfs_rtag_id(tag)); //LFS_ASSERT(lfs_rtag_id(tag_) == lfs_rtag_id(tag));
if (is_cut && !is_lower) { // if (is_cut && !is_lower) {
// TODO deduplicate this with append? // // TODO deduplicate this with append?
// if we're on the upper bound, create a new alt // // if we're on the upper bound, create a new alt
alt = LFS_MKRALT(B, GT, (1 << 12) + gt+1); // alt = LFS_MKRALT__(B, GT, (1 << 12) + gt+1);
//
// int err = lfs_rbyd_p_push(lfs, rbyd_,
// p_alts, p_jumps,
// alt, branch);
// if (err) {
// return err;
// }
//
// lfs_rbyd_p_red(p_alts, p_jumps);
// } else {
// LFS_ASSERT(lfs_rtag_id(tag_) == lfs_rtag_id(tag));
// // increase weight to make this path unreachable
// if (p_alts[0] && lfs_rtag_islt(p_alts[0])) {
// // TODO function for this
// p_alts[0] += tag_ - lower;
// }
// }
int err = lfs_rbyd_p_push(lfs, rbyd_, if (tag_ != tag) {
p_alts, p_jumps, // note we bias the weights here so that lfs_rbyd_lookup
alt, branch); // always finds the next biggest tag
if (err) { if (lfs_rtag_weight_(tag_)
return err; < lfs_rtag_weight_(tag & ~0x7fff)) {
} if (!is_cut || is_lower) {
printf("bsplit lt\n");
alt = LFS_MKRALT__(B, LT,
(lfs_rtag_weight_(tag_)+0x8) - lower);
lfs_rbyd_p_red(p_alts, p_jumps); // TODO can we rededuplicate this?
} else { int err = lfs_rbyd_p_push(lfs, rbyd_,
// increase weight to make this path unreachable p_alts, p_jumps,
if (p_alts[0] && lfs_rtag_islt(p_alts[0])) { alt, branch);
// TODO function for this if (err) {
p_alts[0] += (lt << 3); return err;
}
// TODO hmmm, red while cutting causes problems?
lfs_rbyd_p_red(p_alts, p_jumps);
}
} else if (lfs_rtag_weight_(tag_)
>= lfs_rtag_weight_(tag & ~0x7fff)+0x8000) {
if (!is_cut || !is_lower) {
printf("bsplit gt\n");
alt = LFS_MKRALT__(B, GT,
upper - (lfs_rtag_weight_(tag & ~0x7fff)
+0x8000+0x8));
// TODO can we rededuplicate this?
int err = lfs_rbyd_p_push(lfs, rbyd_,
p_alts, p_jumps,
alt, branch);
if (err) {
return err;
}
// TODO hmmm, red while cutting causes problems?
lfs_rbyd_p_red(p_alts, p_jumps);
}
} }
} }
@@ -2051,7 +2187,7 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
if (is_cut && !is_other_done) { if (is_cut && !is_other_done) {
is_other_done = true; is_other_done = true;
is_lower = !is_lower; is_lower = !is_lower;
printf("switch bounds -> %s\n", is_lower ? "lower" : "upper"); printf("switch bounds => %s\n", is_lower ? "lower" : "upper");
continue; continue;
} }
@@ -2085,6 +2221,8 @@ leaf:;
// //
// TODO handle an empty tree // TODO handle an empty tree
if (lfs_rtag_type1(tag) == LFS_TYPE1_DELETE) { if (lfs_rtag_type1(tag) == LFS_TYPE1_DELETE) {
// TODO this assert should be earlier
LFS_ASSERT(rbyd_->count > 0);
rbyd_->count -= 1; rbyd_->count -= 1;
} }
@@ -2093,7 +2231,7 @@ leaf:;
static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd, static int lfs_rbyd_commit(lfs_t *lfs, lfs_rbyd_t *rbyd,
const struct lfs_rattr *attrs) { const struct lfs_rattr *attrs) {
printf("commit()\n"); printf("- commit() -\n");
LFS_ASSERT(rbyd->erased); LFS_ASSERT(rbyd->erased);
// mark as unerased in case we fail // mark as unerased in case we fail