From e5cd2904eeb4d7932e08df1cb338ddb51ec460cf Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 27 Mar 2023 02:17:52 -0500 Subject: [PATCH] Tweaked always-follow alts to follow even for 0 tags Changed always-follow alts that we use to terminated grow/shrink/remove operations to use `altle 0xfff0` instead of `altgt 0`. `altgt 0` gets the job done as long as you make sure tag 0 never ends up in an rbyd query. But this kept showing up as a problem, and recent debugging revealed some erronous 0 tag lookups created vestigial alt pointers (not necessarily a problem, but space-wasting). Since we moved to a strict 16-bit tag, making these `altle 0xfff0` doesn't really have a downside, and means we can expect rbyd lookups around 0 to behave how one would normally expect. As a (very minor) plus, the value zero usually has special encodings in instruction sets, so being able to use it for rbyd_lookups offers a (very minor) code size saving. --- Sidenote: The reasons altle/altgt is how it is and asymmetric: 1. Flipping these alts is a single bit-flip, which only happens if they are asymmetric (only one includes the equal case). 2. Our branches are biased to prefer the larger tag. This makes traversal trivial. It might be possible to make this still work with altlt/altge, but would require some increments/decrements, which might cause problems with boundary conditions around the 16-bit tag limit. --- lfs.c | 16 +++++-------- scripts/dbgbtree.py | 2 +- tests/test_rbyd.toml | 56 ++++++++++++++++++++++---------------------- 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/lfs.c b/lfs.c index 66d9e782..eccd306a 100644 --- a/lfs.c +++ b/lfs.c @@ -1504,10 +1504,6 @@ static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd, lfsr_tag_t *tag_, lfs_ssize_t *id_, lfs_size_t *weight_, // TODO should this take lfsr_data_t for consistency? lfs_off_t *off_, lfs_size_t *size_) { - // tag must be non-zero! zero tags may deceptively look like they work but - // fail when the tree contains a deleted id0 - LFS_ASSERT(tag != 0); - // keep track of bounds as we descend down the tree lfs_off_t branch = rbyd->trunk; lfs_ssize_t lower = -1; @@ -2284,13 +2280,13 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd, } else if (tag == LFSR_TAG_GROW) { // decrease weight when growing - alt = LFSR_TAG_ALT(B, GT, 0); + alt = LFSR_TAG_ALT(B, LE, 0xfff0); weight = upper_id - lower_id - 1 + lfsr_data_len(data); } else if (tag == LFSR_TAG_SHRINK) { // decrease weight when shrinking if (upper_id - lower_id - 1 > (lfs_ssize_t)lfsr_data_len(data)) { - alt = LFSR_TAG_ALT(B, GT, 0); + alt = LFSR_TAG_ALT(B, LE, 0xfff0); weight = upper_id - lower_id - 1 - lfsr_data_len(data); } @@ -2298,7 +2294,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd, || (id_ == id && lfsr_tag_key(tag_) > lfsr_tag_key(tag))) { if (lfsr_tag_isrm(tag)) { // hide our tag during removes - alt = LFSR_TAG_ALT(B, GT, 0); + alt = LFSR_TAG_ALT(B, LE, 0xfff0); weight = upper_id - lower_id - 1; } else { // split greater than @@ -2638,7 +2634,7 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs, lfs_size_t weight__; lfs_off_t off_; lfs_size_t size_; - err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_NAME, rid, + err = lfsr_rbyd_lookup(lfs, &rbyd, 0, rid, &tag__, &rid__, &weight__, &off_, &size_); if (err) { return err; @@ -2736,7 +2732,7 @@ static int lfsr_btree_parent(lfs_t *lfs, lfs_size_t weight__; lfs_off_t off_; lfs_size_t size_; - err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_NAME, rid, + err = lfsr_rbyd_lookup(lfs, &rbyd, 0, rid, &tag__, &rid__, &weight__, &off_, &size_); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); @@ -2860,7 +2856,7 @@ static lfs_ssize_t lfsr_btree_find_(lfs_t *lfs, lfs_size_t weight__; lfs_off_t off_; lfs_size_t size_; - err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_NAME, find.found_id, + err = lfsr_rbyd_lookup(lfs, &rbyd, 0, find.found_id, &tag__, &rid__, &weight__, &off_, &size_); if (err) { return err; diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index bfcff549..a8522d74 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -309,7 +309,7 @@ def main(disk, block_size=None, trunk=0, limit=None, *, while True: # first lookup id/name (done, name_tag, rid_, w, - name_j, name_d, name) = rbyd.lookup(TAG_NAME, rid) + name_j, name_d, name) = rbyd.lookup(0, rid) if done: return (True, id, 0, rbyd, -1, 0, 0, 0, b'', diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index d6a9e25e..f7e020eb 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -2237,7 +2237,7 @@ code = ''' LFSR_ATTR(UATTR(1), -1, "\xaa\xaa\xaa\xaa", 4, LFSR_ATTR(UATTR(2), -1, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2251,7 +2251,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2271,7 +2271,7 @@ code = ''' LFSR_ATTR(UATTR(2), -1, "\xbb\xbb\xbb\xbb", 4, LFSR_ATTR(UATTR(1), -1, "\xaa\xaa\xaa\xaa", 4, NULL))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2285,7 +2285,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2330,7 +2330,7 @@ code = ''' lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTR(UATTR(2), -1, "\xbb\xbb\xbb\xbb", 4, NULL)) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2344,7 +2344,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2365,7 +2365,7 @@ code = ''' lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTR(UATTR(1), -1, "\xaa\xaa\xaa\xaa", 4, NULL)) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -2379,7 +2379,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(1)); assert(id_ == -1); @@ -4424,7 +4424,7 @@ code = ''' LFSR_ATTR(GROW, 1, NULL, 1, LFSR_ATTR(REG, 1, "\xbb\xbb\xbb\xbb", 4, NULL))))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4442,7 +4442,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4468,7 +4468,7 @@ code = ''' LFSR_ATTR(GROW, 0, NULL, 1, LFSR_ATTR(REG, 0, "\xaa\xaa\xaa\xaa", 4, NULL))))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4486,7 +4486,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4538,7 +4538,7 @@ code = ''' LFSR_ATTR(GROW, 1, NULL, 1, LFSR_ATTR(REG, 1, "\xbb\xbb\xbb\xbb", 4, NULL))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4556,7 +4556,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4583,7 +4583,7 @@ code = ''' LFSR_ATTR(GROW, 0, NULL, 1, LFSR_ATTR(REG, 0, "\xaa\xaa\xaa\xaa", 4, NULL))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -4601,7 +4601,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5679,7 +5679,7 @@ code = ''' LFSR_ATTR(REG, 1, "\xbb\xbb\xbb\xbb", 4, LFSR_ATTR(UATTR(1), 1, "\xbb\xbb", 2, NULL))))))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5711,7 +5711,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5753,7 +5753,7 @@ code = ''' LFSR_ATTR(REG, 0, "\xaa\xaa\xaa\xaa", 4, LFSR_ATTR(UATTR(1), 0, "\xaa\xaa", 2, NULL))))))) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5785,7 +5785,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5855,7 +5855,7 @@ code = ''' lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTR(UATTR(1), 1, "\xbb\xbb", 2, NULL)) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5887,7 +5887,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5932,7 +5932,7 @@ code = ''' lfsr_rbyd_commit(&lfs, &rbyd, LFSR_ATTR(UATTR(1), 0, "\xaa\xaa", 2, NULL)) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -5964,7 +5964,7 @@ code = ''' &tag_, &id_, NULL, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, NULL, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -8929,7 +8929,7 @@ code = ''' NULL))))))))))) => 0; // traverse, finding tags and weights - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, &weight_, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -8963,7 +8963,7 @@ code = ''' &tag_, &id_, &weight_, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, &weight_, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_REG); assert(id_ == 0); @@ -9927,7 +9927,7 @@ code = ''' NULL)))))))))))))))))))))))))) => 0; // traverse, finding tags and weights - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, &weight_, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(3)); assert(id_ == -1); @@ -10027,7 +10027,7 @@ code = ''' &tag_, &id_, &weight_, &off_, &size_) => LFS_ERR_NOENT; lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.block, cfg->block_size, NULL) => 0; - lfsr_rbyd_lookup(&lfs, &rbyd, lfsr_tag_next(0), -1, + lfsr_rbyd_lookup(&lfs, &rbyd, 0, -1, &tag_, &id_, &weight_, &off_, &size_) => 0; assert(tag_ == LFSR_TAG_UATTR(3)); assert(id_ == -1);