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.
This commit is contained in:
Christopher Haster
2023-03-27 02:17:52 -05:00
parent 8f26b68af2
commit e5cd2904ee
3 changed files with 35 additions and 39 deletions

16
lfs.c
View File

@@ -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;

View File

@@ -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'',

View File

@@ -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);