diff --git a/lfs.c b/lfs.c index b812088a..b3503855 100644 --- a/lfs.c +++ b/lfs.c @@ -742,13 +742,14 @@ struct lfsr_attr { LFSR_ATTR_(LFSR_TAG_##_type, _id, _buffer, _size, _next) struct lfsr_attr_from { - lfsr_rbyd_t *rbyd; + const lfsr_rbyd_t *rbyd; + const struct lfsr_attr *attrs; lfs_size_t start; }; -#define LFSR_ATTR_FROM(_id, _rbyd, _start, _stop, _next) \ +#define LFSR_ATTR_FROM(_id, _rbyd, _attrs, _start, _stop, _next) \ LFSR_ATTR(FROM, _id, \ - (&(const struct lfsr_attr_from){_rbyd, _start}), \ + (&(const struct lfsr_attr_from){_rbyd, _attrs, _start}), \ (_stop)-(_start), _next) //#define LFS_MKRATTR_(...) @@ -1138,7 +1139,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { lfs->free.ack -= 1; } - printf("debug: lfs_alloc: %d\n", *block); + printf("debug: lfs_alloc: %x\n", *block); return 0; } } @@ -1564,8 +1565,12 @@ static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd, // save what we found // TODO how many of these need to be conditional? - *tag_ = tag__; - *id_ = id__; + if (tag_) { + *tag_ = tag__; + } + if (id_) { + *id_ = id__; + } if (weight_) { *weight_ = id__ - lower; } @@ -1612,7 +1617,7 @@ static lfs_ssize_t lfsr_rbyd_get(lfs_t *lfs, const lfsr_rbyd_t *rbyd, } // TODO should we merge this into lfsr_rbyd_lookup? -static int lfsr_rbyd_pendinglookup(lfs_t *lfs, +static int lfsr_rbyd_predictedlookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd, const struct lfsr_attr *attrs, lfsr_tag_t tag, lfs_ssize_t id, lfsr_tag_t *tag_, lfs_ssize_t *id_, lfsr_data_t *data_) { @@ -1770,13 +1775,13 @@ found:; } // TODO do we need this function? -static lfs_ssize_t lfsr_rbyd_pendingget(lfs_t *lfs, +static lfs_ssize_t lfsr_rbyd_predictedget(lfs_t *lfs, const lfsr_rbyd_t *rbyd, const struct lfsr_attr *attrs, lfsr_tag_t tag, lfs_ssize_t id, void *buffer, lfs_size_t size) { lfsr_tag_t tag_; lfs_ssize_t id_; lfsr_data_t data_; - int err = lfsr_rbyd_pendinglookup(lfs, rbyd, attrs, tag, id, + int err = lfsr_rbyd_predictedlookup(lfs, rbyd, attrs, tag, id, &tag_, &id_, &data_); if (err) { return err; @@ -1804,7 +1809,8 @@ static lfs_ssize_t lfsr_rbyd_pendingget(lfs_t *lfs, return lfsr_data_len(data_); } -static lfs_ssize_t lfsr_rbyd_compactedsize(lfs_t *lfs, const lfsr_rbyd_t *rbyd, +static lfs_ssize_t lfsr_rbyd_predictedsize( + lfs_t *lfs, const lfsr_rbyd_t *rbyd, const struct lfsr_attr *attrs, lfs_ssize_t start, lfs_ssize_t stop) { // find the strict upper bound on the amount of disk taken by a range of // tags immediately after compaction (when the tags should be perfectly @@ -1816,9 +1822,10 @@ static lfs_ssize_t lfsr_rbyd_compactedsize(lfs_t *lfs, const lfsr_rbyd_t *rbyd, lfs_size_t count = 0; lfs_size_t dsize = 0; while (true) { - lfs_size_t size; - int err = lfsr_rbyd_lookup(lfs, rbyd, lfsr_tag_next(tag), id, - &tag, &id, NULL, NULL, &size); + lfsr_data_t data; + int err = lfsr_rbyd_predictedlookup(lfs, rbyd, attrs, + lfsr_tag_next(tag), id, + &tag, &id, &data); if (err < 0 && err != LFS_ERR_NOENT) { return err; } @@ -1828,7 +1835,7 @@ static lfs_ssize_t lfsr_rbyd_compactedsize(lfs_t *lfs, const lfsr_rbyd_t *rbyd, } count += 1; - dsize += size; + dsize += lfsr_data_len(data); } // make sure to account for both tag and alt metametadata, and assume the @@ -1836,7 +1843,10 @@ static lfs_ssize_t lfsr_rbyd_compactedsize(lfs_t *lfs, const lfsr_rbyd_t *rbyd, // immediately after compaciton, the tree should be perfectly rbyd // balanced, which puts a strict upper bound of 2*log2(n)+1 on the space // overhead per tag - return dsize + count*12 + (2*lfs_nlog2(count)+1)*12; +// printf("predictedsize: %d + %d*(12 + 2*log2(%d)+1)*12 = %d\n", +// dsize, count, count, +// dsize + count*(12 + (2*lfs_nlog2(count)+1)*12)); + return dsize + count*(12 + (2*lfs_nlog2(count)+1)*12); } // TODO this should be a bd operation of some sort @@ -1846,6 +1856,7 @@ static int lfsr_rbyd_prog(lfs_t *lfs, lfsr_rbyd_t *rbyd_, // TODO should we just move this to lfs_bd_prog? // TODO actually should we just build crc into lfs_bd_prog as well? if (rbyd_->off+size > lfs->cfg->block_size) { + lfs_cache_zero(lfs, &lfs->pcache); return LFS_ERR_RANGE; } @@ -1869,6 +1880,69 @@ static int lfsr_rbyd_prog(lfs_t *lfs, lfsr_rbyd_t *rbyd_, return 0; } +// TODO this should be a bd operation of some sort +static int lfsr_rbyd_progdata(lfs_t *lfs, lfsr_rbyd_t *rbyd_, + lfsr_data_t data, uint32_t *crc) { + // check for out-of-bounds here + // TODO should we just move this to lfs_bd_prog? + // TODO actually should we just build crc into lfs_bd_prog as well? + if (rbyd_->off+lfsr_data_len(data) > lfs->cfg->block_size) { + lfs_cache_zero(lfs, &lfs->pcache); + return LFS_ERR_RANGE; + } + + if (lfsr_data_ondisk(data)) { + // TODO byte-level copies have been a pain point, works for prototyping + // but can this be better? configurable? leverage + // rcache/pcache directly? + uint8_t dat; + for (lfs_size_t i = 0; i < lfsr_data_len(data); i++) { + int err = lfs_bd_read(lfs, + &lfs->pcache, &lfs->rcache, lfsr_data_len(data)-i, + data.u.disk.block, data.u.disk.off+i, &dat, 1); + if (err) { + return err; + } + + err = lfs_bd_prog(lfs, + &lfs->pcache, &lfs->rcache, false, + rbyd_->block, rbyd_->off+i, &dat, 1); + if (err) { + return err; + } + + // TODO should this not be optional? should we move the range check + // into bd_prog? so we can get rid of the one use of this in + // lfsr_rbyd_commit? + // optionally crc + if (crc) { + *crc = lfs_crc32c(*crc, &dat, 1); + } + } + + } else { + int err = lfs_bd_prog(lfs, + &lfs->pcache, &lfs->rcache, false, + rbyd_->block, rbyd_->off, data.u.buf, lfsr_data_len(data)); + if (err) { + return err; + } + + // TODO should this not be optional? should we move the range check + // into bd_prog? so we can get rid of the one use of this in + // lfsr_rbyd_commit? + // optionally crc + if (crc) { + *crc = lfs_crc32c(*crc, data.u.buf, lfsr_data_len(data)); + } + } + + // update off + rbyd_->off += lfsr_data_len(data); + + return 0; +} + static int lfsr_rbyd_progtag(lfs_t *lfs, lfsr_rbyd_t *rbyd_, lfsr_tag_t tag, lfs_ssize_t id, lfs_size_t size, uint32_t *crc) { LFS_ASSERT(tag <= 0x3fff); @@ -2012,7 +2086,7 @@ static void lfsr_rbyd_p_red( // core rbyd algorithm static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_, - lfsr_tag_t tag, lfs_ssize_t id, const void *buffer, lfs_size_t size) { + lfsr_tag_t tag, lfs_ssize_t id, lfsr_data_t data) { LFS_ASSERT(tag != 0); // keep track of bounds as we descend down the tree @@ -2038,10 +2112,10 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_, if (tag == LFSR_TAG_GROW) { LFS_ASSERT(id <= rbyd_->weight); // noop? - if (size == 0) { + if (lfsr_data_len(data) == 0) { return 0; } - rbyd_->weight += size; + rbyd_->weight += lfsr_data_len(data); tag_ = 0; id_ = id; @@ -2050,15 +2124,15 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_, } else if (tag == LFSR_TAG_SHRINK) { LFS_ASSERT(id < rbyd_->weight); // noop? - if (size == 0) { + if (lfsr_data_len(data) == 0) { return 0; } - rbyd_->weight -= size; + rbyd_->weight -= lfsr_data_len(data); tag_ = 0; id_ = id; other_tag_ = tag_; - other_id_ = id_ + size; + other_id_ = id_ + lfsr_data_len(data); } else if (lfsr_tag_isrm(tag)) { LFS_ASSERT(id < rbyd_->weight); @@ -2381,12 +2455,12 @@ 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); - weight = upper_id - lower_id - 1 + size; + weight = upper_id - lower_id - 1 + lfsr_data_len(data); } else if (tag == LFSR_TAG_SHRINK) { // decrease weight when shrinking alt = LFSR_TAG_ALT(B, GT, 0); - weight = upper_id - lower_id - 1 - size; + weight = upper_id - lower_id - 1 - lfsr_data_len(data); } else if (id_ > id || (id_ == id && lfsr_tag_key(tag_) > lfsr_tag_key(tag))) { @@ -2427,14 +2501,15 @@ leaf:; // // note we always need something after the alts! without something between // alts we may not be able to find the trunk of our tree - err = lfsr_rbyd_progtag(lfs, rbyd_, tag, id, size, &rbyd_->crc); + err = lfsr_rbyd_progtag(lfs, rbyd_, + tag, id, lfsr_data_len(data), &rbyd_->crc); if (err) { return err; } if (lfsr_tag_hasdata(tag)) { // don't forget the data! - err = lfsr_rbyd_prog(lfs, rbyd_, buffer, size, &rbyd_->crc); + err = lfsr_rbyd_progdata(lfs, rbyd_, data, &rbyd_->crc); if (err) { return err; } @@ -2469,10 +2544,72 @@ int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, // append each tag to the tree for (const struct lfsr_attr *attr = attrs; attr; attr = attr->next) { - int err = lfsr_rbyd_append(lfs, &rbyd_, - attr->tag, attr->id, attr->buffer, attr->size); - if (err) { - return err; + // indirect set of attributes from another rbyd + if (attr->tag == LFSR_TAG_FROM) { + const struct lfsr_attr_from *from = attr->buffer; + +// // first create one grow for the entire from range +// // TODO should LFSR_DATA_BUF be used this way? smells fishy +// int err = lfsr_rbyd_append(lfs, &rbyd_, +// LFSR_TAG_GROW, attr->id, LFSR_DATA_BUF(NULL, attr->size)); +// if (err) { +// return err; +// } + + // now copy over ids + lfsr_tag_t tag = 0; + lfs_ssize_t id = from->start; + while (true) { + lfsr_tag_t tag_; + lfs_ssize_t id_; + lfsr_data_t data_; + int err = lfsr_rbyd_predictedlookup( + lfs, from->rbyd, from->attrs, + lfsr_tag_next(tag), id, + &tag_, &id_, &data_); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + if (err == LFS_ERR_NOENT || id_-from->start >= attr->size) { + break; + } + + // TODO this is really wasteful and throws off our predicted + // size, can we combine grows into the tag append in the rbyd + // somehow? + // create grows as necessary + lfs_size_t weight_ = id_-id + (tag == 0 ? 1 : 0); +// printf("from %d %x w%d\n", id_, tag_, weight_); + if (weight_ > 0) { + int err = lfsr_rbyd_append(lfs, &rbyd_, + LFSR_TAG_GROW, + attr->id+(id_-from->start)-(weight_-1), + // TODO also this is a weird way to use lfsr_data_t + LFSR_DATA_BUF(NULL, weight_)); + if (err) { + return err; + } + } + + err = lfsr_rbyd_append(lfs, &rbyd_, + tag_, attr->id+(id_-from->start), data_); + if (err) { + return err; + } + + tag = tag_; + id = id_; + } + + // a normal attribute + } else { + int err = lfsr_rbyd_append(lfs, &rbyd_, + attr->tag, attr->id, + LFSR_DATA_BUF(attr->buffer, attr->size)); + if (err) { + return err; + } } } @@ -2549,6 +2686,7 @@ int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, // not even space for the crc? if (aligned > lfs->cfg->block_size) { + lfs_cache_zero(lfs, &lfs->pcache); return LFS_ERR_RANGE; } @@ -2617,6 +2755,9 @@ int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd, /// Rbyd b-tree operations /// +// TODO this is a weird null, move weight out of inlined? +#define LFSR_BTREE_NULL ((lfsr_btree_t){.tag=0x2, .u.inlined.weight=0}) + // B-tree on-disk encoding // 2 leb128 => 10 bytes (worst case) @@ -2707,7 +2848,7 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs, lfs_ssize_t rid = id; lfsr_branch_t branch = btree->u.trunk; while (true) { - // fetch each block, this is the main cost of traversal with each fetch + // fetch each block, this is the main cost of lookup with each fetch // needing O(m), and isn't really avoidable int err = lfsr_rbyd_fetch(lfs, rbyd_, branch.block, branch.limit, NULL); if (err) { @@ -2733,6 +2874,8 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs, return err; } +// printf("lookup %x#%x %d => %d %x %d\n", branch.block, branch.limit, rid, rid__, tag__, size_); + // found another branch if (tag__ == LFSR_TAG_BRANCH) { // adjust rid with subtree's weight @@ -2748,11 +2891,13 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs, return err; } - err = lfsr_branch_fromdisk(&branch, buf); - if (err) { - return err; + lfs_ssize_t delta_ = lfsr_branch_fromdisk(&branch, buf); + if (delta_ < 0) { + return delta_; } +// printf("branch %x#%x\n", branch.block, branch.limit); + // found our id } else { // TODO how many of these should be conditional? @@ -2784,9 +2929,9 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs, } // TODO should lfsr_btree_lookup/lfsr_btree_parent be deduplicated? -static lfs_ssize_t lfsr_btree_parent(lfs_t *lfs, +static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree, lfs_size_t id, const lfsr_rbyd_t *child, - lfsr_rbyd_t *rbyd_, lfs_size_t *rid_) { + lfsr_rbyd_t *rbyd_, lfs_ssize_t *rid_) { // inlined? if (btree->tag || ( btree->u.trunk.block == child->block @@ -2811,6 +2956,7 @@ static lfs_ssize_t lfsr_btree_parent(lfs_t *lfs, err = lfsr_rbyd_lookup(lfs, rbyd_, LFSR_TAG_MK, rid, NULL, &rid__, &weight__, NULL, NULL); if (err) { + LFS_ASSERT(err != LFS_ERR_NOENT); return err; } @@ -2821,6 +2967,7 @@ static lfs_ssize_t lfsr_btree_parent(lfs_t *lfs, err = lfsr_rbyd_lookup(lfs, rbyd_, LFSR_TAG_STRUCT, rid__, &tag__, NULL, NULL, &off_, &size_); if (err) { + LFS_ASSERT(err != LFS_ERR_NOENT); return err; } @@ -2842,9 +2989,9 @@ static lfs_ssize_t lfsr_btree_parent(lfs_t *lfs, return err; } - err = lfsr_branch_fromdisk(&branch, buf); - if (err) { - return err; + lfs_ssize_t delta_ = lfsr_branch_fromdisk(&branch, buf); + if (delta_ < 0) { + return delta_; } // found our child? @@ -2858,6 +3005,18 @@ static lfs_ssize_t lfsr_btree_parent(lfs_t *lfs, } } +// TODO do we really need this? +static lfs_ssize_t lfsr_btree_get(lfs_t *lfs, + const lfsr_btree_t *btree, lfs_size_t id, + lfsr_tag_t *tag_, lfs_size_t *id_, lfs_size_t *weight_, + void *buffer, lfs_size_t size) { + // note we need an allocated rbyd in btree lookup + lfsr_rbyd_t rbyd_; + return lfsr_btree_lookup(lfs, btree, id, + tag_, id_, &rbyd_, NULL, weight_, + buffer, size); +} + static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t id, lfsr_rbyd_t *rbyd, const struct lfsr_attr *attrs) { @@ -2868,8 +3027,8 @@ static int lfsr_btree_commit(lfs_t *lfs, // TODO should upper btree layers provide this storage? reuse // with entry attrs? struct lfsr_attr scratch_attrs[7]; - uint8_t scratch_buf1[5]; - uint8_t scratch_buf2[5]; + uint8_t scratch_buf1[LFSR_BRANCH_DSIZE]; + uint8_t scratch_buf2[LFSR_BRANCH_DSIZE]; while (true) { // we will always need our parent, so go ahead and find it @@ -2883,10 +3042,12 @@ static int lfsr_btree_commit(lfs_t *lfs, pid = -1; } lfs_size_t pweight = rbyd->weight; +// printf("parent: %x#%x %dw%d\n", parent.block, parent.off, pid, pweight); // is rbyd erased? can we sneak our commit into any remaining // erased bytes? note that the btree limit prevents this from mutating // other references to the rbyd +// printf("committing to %x+%x...\n", rbyd->block, rbyd->off); err = lfsr_rbyd_commit(lfs, rbyd, attrs); if (err && err != LFS_ERR_RANGE) { // TODO wait should we also move if there is corruption here? @@ -2902,7 +3063,9 @@ static int lfsr_btree_commit(lfs_t *lfs, } // prepare commit to parent, tail recursing upwards - lfs_ssize_t delta = lfs_toleb128(rbyd->block, scratch_buf1, 5); + lfs_ssize_t delta = lfsr_branch_todisk( + &(const lfsr_branch_t){rbyd->block, rbyd->off}, + scratch_buf1); if (delta < 0) { return delta; } @@ -2929,19 +3092,22 @@ static int lfsr_btree_commit(lfs_t *lfs, // no? } else { // the first question is will we fit comfortably after compaction - lfs_ssize_t compacted = lfsr_rbyd_compactedsize(lfs, rbyd, - 0, rbyd->weight); - if (compacted < 0) { - return compacted; + lfs_ssize_t predicted = lfsr_rbyd_predictedsize( + lfs, rbyd, attrs, 0, rbyd->weight); + if (predicted < 0) { + return predicted; } +// printf("predicted: %d/%d\n", predicted, lfs->cfg->block_size/2); + // keep rbyd < 1/2 to avoid degenerate cases with full rbyd - if (compacted <= lfs->cfg->block_size/2) { - lfsr_rbyd_t rbyd_; + if ((lfs_size_t)predicted <= lfs->cfg->block_size/2) { + lfsr_rbyd_t rbyd_ = {.erased=true}; err = lfs_alloc(lfs, &rbyd_.block); if (err) { return err; } +// printf("compacting %x->%x...\n", rbyd->block, rbyd_.block); // TODO should erase be implicit in alloc eventually? err = lfs_bd_erase(lfs, rbyd_.block); @@ -2949,19 +3115,26 @@ static int lfsr_btree_commit(lfs_t *lfs, return err; } + // TODO wait, should from reuse next for attrs? err = lfsr_rbyd_commit(lfs, &rbyd_, - LFSR_ATTR_FROM(0, rbyd, 0, rbyd->weight, attrs)); + // TODO this extra +1 is a hack, need to get the + // actual predictedweight from the attr list! + LFSR_ATTR_FROM(0, rbyd, attrs, 0, rbyd->weight+1, NULL)); if (err) { + printf("ah %d\n", err); return err; } // done? if (pid == -1) { + *rbyd = rbyd_; break; } // prepare commit to parent, tail recursing upwards - lfs_ssize_t delta = lfs_toleb128(rbyd_.block, scratch_buf1, 5); + lfs_ssize_t delta = lfsr_branch_todisk( + &(const lfsr_branch_t){rbyd_.block, rbyd_.off}, + scratch_buf1); if (delta < 0) { return delta; } @@ -2974,11 +3147,11 @@ static int lfsr_btree_commit(lfs_t *lfs, // note grow/shrink with 0 is treated as a noop in rbyd if (rbyd_.weight >= pweight) { scratch_attrs[1] = *LFSR_ATTR( - GROW, pid, NULL, rbyd_.weight-pweight, + GROW, pid-(pweight-1), NULL, rbyd_.weight-pweight, NULL); } else { scratch_attrs[1] = *LFSR_ATTR( - SHRINK, pid, NULL, pweight-rbyd_.weight, + SHRINK, pid-(pweight-1), NULL, pweight-rbyd_.weight, NULL); } @@ -2987,7 +3160,10 @@ static int lfsr_btree_commit(lfs_t *lfs, // time to split } else { - lfsr_rbyd_t children[2]; +// printf("splitting...\n"); + lfsr_rbyd_t children[2] = {{.erased=true}, {.erased=true}}; + // TODO is this a hack or the correct way to do this? + lfs_size_t consumed = 0; for (unsigned i = 0; i < 2; i++) { err = lfs_alloc(lfs, &children[i].block); if (err) { @@ -3002,18 +3178,24 @@ static int lfsr_btree_commit(lfs_t *lfs, // copy over half the ids, note we round up here to avoid // missing any ids during the copy +// printf("child %d: %d..%d\n", i, (i+0)*((rbyd->weight+1)/2), (i+1)*((rbyd->weight+1)/2)); err = lfsr_rbyd_commit(lfs, &children[i], - LFSR_ATTR_FROM(0, rbyd, - (i+0)*((rbyd->weight+1)/2), - (i+1)*((rbyd->weight+1)/2), - attrs)); + LFSR_ATTR_FROM(0, rbyd, attrs, + // TODO this extra +1 is a hack, need to get the + // actual predictedweight from the attr list! + consumed, + (i+1)*((rbyd->weight+1+1)/2), + NULL)); if (err) { return err; } + + consumed += children[i].weight; } // no parent? introduce a new trunk if (pid == -1) { + parent = (lfsr_rbyd_t){.erased=true}; err = lfs_alloc(lfs, &parent.block); if (err) { return err; @@ -3027,37 +3209,45 @@ static int lfsr_btree_commit(lfs_t *lfs, // TODO this can also probably be deduplicated // prepare commit to parent, tail recursing upwards - lfs_ssize_t delta1 = lfs_toleb128(children[0].block, - scratch_buf1, 5); + lfs_ssize_t delta1 = lfsr_branch_todisk( + &(const lfsr_branch_t){ + children[0].block, children[0].off}, + scratch_buf1); if (delta1 < 0) { return delta1; } - lfs_ssize_t delta2 = lfs_toleb128(children[1].block, - scratch_buf2, 5); + lfs_ssize_t delta2 = lfsr_branch_todisk( + &(const lfsr_branch_t){ + children[1].block, children[1].off}, + scratch_buf2); if (delta2 < 0) { return delta2; } scratch_attrs[0] = *LFSR_ATTR( - MKBRANCH, 0, NULL, 0, + GROW, 0, + NULL, children[0].weight, &scratch_attrs[1]); scratch_attrs[1] = *LFSR_ATTR( - BRANCH, 0, scratch_buf1, delta1, + MKBRANCH, 0+children[0].weight-1, + NULL, 0, &scratch_attrs[2]); scratch_attrs[2] = *LFSR_ATTR( - GROW, 0, NULL, children[0].weight-1, + BRANCH, 0+children[0].weight-1, + scratch_buf1, delta1, &scratch_attrs[3]); scratch_attrs[3] = *LFSR_ATTR( - MKBRANCH, children[0].weight, NULL, 0, + GROW, 0+children[0].weight, + NULL, children[1].weight, &scratch_attrs[4]); scratch_attrs[4] = *LFSR_ATTR( - BRANCH, children[0].weight, - scratch_buf1, delta1, + MKBRANCH, 0+children[0].weight+children[1].weight-1, + NULL, 0, &scratch_attrs[5]); scratch_attrs[5] = *LFSR_ATTR( - GROW, children[0].weight, NULL, - children[1].weight-1, + BRANCH, 0+children[0].weight+children[1].weight-1, + scratch_buf2, delta2, NULL); *rbyd = parent; @@ -3066,41 +3256,51 @@ static int lfsr_btree_commit(lfs_t *lfs, // yes parent? push up split } else { // prepare commit to parent, tail recursing upwards - lfs_ssize_t delta1 = lfs_toleb128(children[0].block, - scratch_buf1, 5); + lfs_ssize_t delta1 = lfsr_branch_todisk( + &(const lfsr_branch_t){ + children[0].block, children[0].off}, + scratch_buf1); if (delta1 < 0) { return delta1; } - lfs_ssize_t delta2 = lfs_toleb128(children[1].block, - scratch_buf2, 5); + lfs_ssize_t delta2 = lfsr_branch_todisk( + &(const lfsr_branch_t){ + children[1].block, children[1].off}, + scratch_buf2); if (delta2 < 0) { return delta2; } -// scratch_attrs[0] = *LFSR_ATTR( -// RM, pid, NULL, pweight, -// &scratch_attrs[1]); + scratch_attrs[0] = *LFSR_ATTR( + SHRINK, pid-(pweight-1), NULL, pweight, + &scratch_attrs[1]); scratch_attrs[1] = *LFSR_ATTR( - MKBRANCH, pid, NULL, 0, + GROW, pid-(pweight-1), + NULL, children[0].weight, &scratch_attrs[2]); scratch_attrs[2] = *LFSR_ATTR( - BRANCH, pid, scratch_buf1, delta1, + MKBRANCH, pid-(pweight-1)+children[0].weight-1, + NULL, 0, &scratch_attrs[3]); scratch_attrs[3] = *LFSR_ATTR( - GROW, pid, NULL, children[0].weight-1, + BRANCH, pid-(pweight-1)+children[0].weight-1, + scratch_buf1, delta1, &scratch_attrs[4]); scratch_attrs[4] = *LFSR_ATTR( - MKBRANCH, pid+children[0].weight, NULL, 0, + GROW, pid-(pweight-1)+children[0].weight, + NULL, children[1].weight, &scratch_attrs[5]); scratch_attrs[5] = *LFSR_ATTR( - BRANCH, pid+children[0].weight, - scratch_buf1, delta1, + MKBRANCH, pid-(pweight-1)+children[0].weight + +children[1].weight-1, + NULL, 0, &scratch_attrs[6]); scratch_attrs[6] = *LFSR_ATTR( - GROW, pid+children[0].weight, NULL, - children[1].weight-1, + BRANCH, pid-(pweight-1)+children[0].weight + +children[1].weight-1, + scratch_buf2, delta2, NULL); *rbyd = parent; @@ -3116,6 +3316,85 @@ static int lfsr_btree_commit(lfs_t *lfs, return 0; } +static int lfsr_btree_push(lfs_t *lfs, + lfsr_btree_t *btree, + lfs_size_t id, lfsr_tag_t tag, lfs_size_t weight, + const void *buffer, lfs_size_t size) { +// printf("- push(%d, %x, w%d) -\n", id, tag, weight); + // null btree? + if (btree->tag && btree->u.inlined.weight == 0) { + LFS_ASSERT(id == 0); + + btree->tag = tag; + btree->u.inlined.weight = weight; + + LFS_ASSERT(size <= LFSR_BTREE_INLINE_SIZE); + memcpy(btree->u.inlined.buf, buffer, size); + btree->u.inlined.size = size; + return 0; + + // inlined btree, need to expand into an rbyd + } else if (btree->tag) { + LFS_ASSERT(id == btree->u.inlined.weight); + + // TODO can we move this into lfsr_btree_commit somehow? + // TODO we should have an lfsr_rbyd_alloc + lfsr_rbyd_t rbyd = {.erased=true}; + int err = lfs_alloc(lfs, &rbyd.block); + if (err) { + return err; + } + + // TODO should erase be implicit in alloc eventually? + err = lfs_bd_erase(lfs, rbyd.block); + if (err) { + return err; + } + + // commit our entries + err = lfsr_rbyd_commit(lfs, &rbyd, + LFSR_ATTR(GROW, 0, NULL, btree->u.inlined.weight, + LFSR_ATTR(MKBRANCH, 0+btree->u.inlined.weight-1, NULL, 0, + LFSR_ATTR_(btree->tag, 0+btree->u.inlined.weight-1, + btree->u.inlined.buf, btree->u.inlined.size, + LFSR_ATTR(GROW, id, NULL, weight, + LFSR_ATTR(MKBRANCH, id+weight-1, NULL, 0, + LFSR_ATTR_(tag, id+weight-1, + buffer, size, + NULL))))))); + if (err) { + return err; + } + + btree->tag = 0; + btree->u.trunk.block = rbyd.block; + btree->u.trunk.limit = rbyd.off; + return 0; + + // a normal btree + } else { + // lookup in which leaf our id resides + // TODO currently using our neighbor id since id will just + // return ENOENT, is this ok? + lfsr_rbyd_t rbyd; + lfs_ssize_t rid; + lfs_ssize_t size = lfsr_btree_lookup(lfs, btree, id-weight, + NULL, NULL, &rbyd, &rid, NULL, NULL, 0); + if (size < 0) { + return size; + } + rid += 1; + + // commit our id into the tree, letting lfsr_btree_commit take care + // of the rest + return lfsr_btree_commit(lfs, btree, id-weight, &rbyd, + LFSR_ATTR(GROW, rid, NULL, weight, + LFSR_ATTR(MKBRANCH, rid+weight-1, NULL, 0, + LFSR_ATTR_(tag, rid+weight-1, buffer, size, + NULL)))); + } +} + // // // @@ -3229,7 +3508,7 @@ static int lfsr_btree_commit(lfs_t *lfs, // //// // either our block isn't erased or we have filled the block, so now the //// // question is do we fit after compaction? -//// lfs_ssize_t compacted = lfsr_rbyd_compactedsize(lfs, rbyd, 0, rbyd->weight); +//// lfs_ssize_t compacted = lfsr_rbyd_predictedsize(lfs, rbyd, 0, rbyd->weight); //// if (compacted < 0) { //// return compacted; //// } diff --git a/scripts/dbgrbyd.py b/scripts/dbgrbyd.py index e04cd9a6..55fa9654 100755 --- a/scripts/dbgrbyd.py +++ b/scripts/dbgrbyd.py @@ -62,6 +62,8 @@ def tagrepr(tag, id, w, size, off=None): id, ' w%d' % w if w is not None else '', size) + elif tag == 0x0800: + return 'inlined id%d %d' % (id, size) elif tag == 0x0810: return 'block id%d %d' % (id, size) elif tag == 0x0820: @@ -565,6 +567,7 @@ def show_tree(block_size, data, rev, trunk, weight, *, def main(disk, block_size=None, block1=0, block2=None, *, + limit=None, trunk=None, color='auto', **args): @@ -582,6 +585,10 @@ def main(disk, block_size=None, block1=0, block2=None, *, f.seek(0, os.SEEK_END) block_size = f.tell() + # default limit to the block_size + if limit is None: + limit = block_size + # read each block blocks = [block for block in [block1, block2] if block is not None] datas = [] @@ -600,7 +607,7 @@ def main(disk, block_size=None, block1=0, block2=None, *, weight = 0 weight_ = 0 wastrunk = False - while j_ < block_size: + while j_ < limit: v, tag, id, size, delta = fromtag(data[j_:]) if v != (popc(crc) & 1): break @@ -682,11 +689,6 @@ if __name__ == "__main__": parser.add_argument( 'disk', help="File containing the block device.") - parser.add_argument( - 'block_size', - nargs='?', - type=lambda x: int(x, 0), - help="Block size in bytes.") parser.add_argument( 'block1', nargs='?', @@ -697,6 +699,14 @@ if __name__ == "__main__": nargs='?', type=lambda x: int(x, 0), help="Block address of the second metadata block.") + parser.add_argument( + '-B', '--block-size', + type=lambda x: int(x, 0), + help="Block size in bytes.") + parser.add_argument( + '-L', '--limit', + type=lambda x: int(x, 0), + help="Use this offset as the rbyd limit.") parser.add_argument( '--trunk', type=lambda x: int(x, 0), diff --git a/tests/test_btree.toml b/tests/test_btree.toml new file mode 100644 index 00000000..618b7224 --- /dev/null +++ b/tests/test_btree.toml @@ -0,0 +1,217 @@ + +# maximize lookahead buffer, we don't actually gc so we only get one pass +# of the disk for these tests +defines.LOOKAHEAD_SIZE = 'BLOCK_COUNT / 8' + + +# test an empty tree +[cases.test_btree_zero] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + // create free lookahead + memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); + lfs.free.off = 0; + lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, + lfs.cfg->block_count); + lfs.free.i = 0; + lfs_alloc_ack(&lfs); + + // create an empty tree + lfsr_btree_t btree = LFSR_BTREE_NULL; + + // try looking up tags + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + + lfsr_btree_get(&lfs, &btree, 0, + &tag_, &id_, &weight_, + buffer, 4) => LFS_ERR_NOENT; +''' + +# test an inlined tree +[cases.test_btree_one] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + // create free lookahead + memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); + lfs.free.off = 0; + lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, + lfs.cfg->block_count); + lfs.free.i = 0; + lfs_alloc_ack(&lfs); + + // create a single-entry tree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; + + // try looking up tags + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + + lfsr_btree_get(&lfs, &btree, 0, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == 0); + assert(weight_ == 1); + assert(memcmp(buffer, "a", 1) == 0); + + lfsr_btree_get(&lfs, &btree, 1, + &tag_, &id_, &weight_, + buffer, 4) => LFS_ERR_NOENT; +''' + +# test a single-rbyd tree +[cases.test_btree_two] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + // create free lookahead + memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); + lfs.free.off = 0; + lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, + lfs.cfg->block_count); + lfs.free.i = 0; + lfs_alloc_ack(&lfs); + + // create a two-entry tree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; + lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, "b", 1) => 0; + + // try looking up tags + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + + lfsr_btree_get(&lfs, &btree, 0, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == 0); + assert(weight_ == 1); + assert(memcmp(buffer, "a", 1) == 0); + + lfsr_btree_get(&lfs, &btree, 1, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == 1); + assert(weight_ == 1); + assert(memcmp(buffer, "b", 1) == 0); + + lfsr_btree_get(&lfs, &btree, 2, + &tag_, &id_, &weight_, + buffer, 4) => LFS_ERR_NOENT; +''' + +# still a single-rbyd tree, just making sure it works +[cases.test_btree_three] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + // create free lookahead + memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); + lfs.free.off = 0; + lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, + lfs.cfg->block_count); + lfs.free.i = 0; + lfs_alloc_ack(&lfs); + + // create a two-entry tree + lfsr_btree_t btree = LFSR_BTREE_NULL; + lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, "a", 1) => 0; + lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, "b", 1) => 0; + lfsr_btree_push(&lfs, &btree, 2, LFSR_TAG_INLINED, 1, "c", 1) => 0; + + // try looking up tags + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + + lfsr_btree_get(&lfs, &btree, 0, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == 0); + assert(weight_ == 1); + assert(memcmp(buffer, "a", 1) == 0); + + lfsr_btree_get(&lfs, &btree, 1, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == 1); + assert(weight_ == 1); + assert(memcmp(buffer, "b", 1) == 0); + + lfsr_btree_get(&lfs, &btree, 2, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == 2); + assert(weight_ == 1); + assert(memcmp(buffer, "c", 1) == 0); + + lfsr_btree_get(&lfs, &btree, 3, + &tag_, &id_, &weight_, + buffer, 4) => LFS_ERR_NOENT; +''' + +# try larger trees, when exactly a tree splits depends on the disk geometry, so +# we don't really have a better way of testing multi-rbyd trees +[cases.test_btree_more] +defines.N = 'range(10, 1001, 50)' +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + // create free lookahead + memset(lfs.free.buffer, 0, lfs.cfg->lookahead_size); + lfs.free.off = 0; + lfs.free.size = lfs_min(8*lfs.cfg->lookahead_size, + lfs.cfg->block_count); + lfs.free.i = 0; + lfs_alloc_ack(&lfs); + + // create a tree with N elements + lfsr_btree_t btree = LFSR_BTREE_NULL; + const char *alphas = "abcdefghijklmnopqrstuvwxyz"; + for (lfs_size_t i = 0; i < N; i++) { + lfsr_btree_push(&lfs, &btree, i, LFSR_TAG_INLINED, 1, + &alphas[i % 26], 1) => 0; + } + + // check that the elements are in the tree + uint8_t buffer[4]; + lfsr_tag_t tag_; + lfs_size_t id_; + lfs_size_t weight_; + + for (lfs_size_t i = 0; i < N; i++) { + lfsr_btree_get(&lfs, &btree, i, + &tag_, &id_, &weight_, + buffer, 4) => 1; + assert(tag_ == LFSR_TAG_INLINED); + assert(id_ == i); + assert(weight_ == 1); + assert(memcmp(buffer, &alphas[i % 26], 1) == 0); + } + + // and check that we can't lookup elements that aren't in the tree + lfsr_btree_get(&lfs, &btree, N, + &tag_, &id_, &weight_, + buffer, 4) => LFS_ERR_NOENT; +''' diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index 3db4cc57..714ec3e7 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -12039,7 +12039,7 @@ code = ''' // test lookup both written/unwritten for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, LFSR_TAG_UATTR(j+1), -1, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_UATTR(j+1)); @@ -12051,14 +12051,14 @@ code = ''' tag_ = 0; id_ = -1; for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_UATTR(j+1)); assert(id_ == -1); assert(lfsr_data_len(data_) == 4); } - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => LFS_ERR_NOENT; } @@ -12202,7 +12202,8 @@ code = ''' printf("rbyd: ["); first = true; for (unsigned attr = 0; attr < N; attr++) { - lfs_ssize_t size = lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfs_ssize_t size = lfsr_rbyd_predictedget( + &lfs, &rbyd, unwritten, LFSR_TAG_UATTR(attr), -1, buffer, 4); if (size >= 0) { if (!first) { @@ -12215,7 +12216,8 @@ code = ''' printf("]\n"); for (unsigned attr = 0; attr < N; attr++) { - lfs_ssize_t size = lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfs_ssize_t size = lfsr_rbyd_predictedget( + &lfs, &rbyd, unwritten, LFSR_TAG_UATTR(attr), -1, buffer, 4); if (sim[attr]) { assert(size == 1); @@ -12319,7 +12321,7 @@ code = ''' // test lookup both written/unwritten for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, LFSR_TAG_MKREG, j, buffer, 4) => 4; assert(memcmp(buffer, names[j % 6], 4) == 0); } @@ -12328,14 +12330,14 @@ code = ''' tag_ = 0; id_ = -1; for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_MKREG); assert(id_ == j); assert(lfsr_data_len(data_) == 4); } - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => LFS_ERR_NOENT; } @@ -12484,7 +12486,8 @@ code = ''' printf("]\n"); printf("rbyd: ["); for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - lfs_ssize_t size = lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfs_ssize_t size = lfsr_rbyd_predictedget( + &lfs, &rbyd, unwritten, LFSR_TAG_MKREG, id, buffer, 4); if (size >= 0) { printf("%.*s", size, buffer); @@ -12498,7 +12501,7 @@ code = ''' printf("]\n"); for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, LFSR_TAG_MKREG, id, buffer, 4) => 1; assert(memcmp(&sim[id], buffer, 1) == 0); } @@ -12613,7 +12616,7 @@ code = ''' assert(rbyd.weight == (w >= 0 ? w : 0)); // test lookup both written/unwritten - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, LFSR_TAG_UATTR(3), -1, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_UATTR(3)); @@ -12621,12 +12624,12 @@ code = ''' assert(lfsr_data_len(data_) == 9); for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, LFSR_TAG_MKREG, j, buffer, 4) => 4; assert(memcmp(buffer, names[j % 6], 4) == 0); for (unsigned u = 0; u < M; u++) { - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, LFSR_TAG_UATTR(u+1), j, buffer, 4) => 2; assert(memcmp(buffer, names[j % 6], 2) == 0); } @@ -12635,7 +12638,7 @@ code = ''' // test traverse both written/unwritten tag_ = 0; id_ = -1; - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_UATTR(3)); @@ -12643,7 +12646,7 @@ code = ''' assert(lfsr_data_len(data_) == 9); for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_MKREG); @@ -12651,7 +12654,7 @@ code = ''' assert(lfsr_data_len(data_) == 4); for (unsigned u = 0; u < M; u++) { - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_UATTR(u+1)); @@ -12659,7 +12662,7 @@ code = ''' assert(lfsr_data_len(data_) == 2); } } - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => LFS_ERR_NOENT; } @@ -12863,7 +12866,7 @@ code = ''' printf("]\n"); printf("rbyd: ["); for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - lfs_ssize_t size = lfsr_rbyd_pendingget( + lfs_ssize_t size = lfsr_rbyd_predictedget( &lfs, &rbyd, unwritten, LFSR_TAG_MKREG, id, buffer, 4); if (size >= 0) { @@ -12872,7 +12875,7 @@ code = ''' printf("?"); } for (uint8_t u = 0; u < M; u++) { - lfs_ssize_t size = lfsr_rbyd_pendingget( + lfs_ssize_t size = lfsr_rbyd_predictedget( &lfs, &rbyd, unwritten, LFSR_TAG_UATTR(u), id, buffer, 4); if (size >= 0) { @@ -12888,7 +12891,7 @@ code = ''' printf("]\n"); for (lfs_ssize_t id = 0; id < (lfs_ssize_t)count; id++) { - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, LFSR_TAG_MKREG, id, buffer, 4) => 1; assert(memcmp(&sim[id*(M+1)], buffer, 1) == 0); } @@ -12988,7 +12991,7 @@ code = ''' // test lookup both written/unwritten for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, LFSR_TAG_MKREG, j*W+W-1, buffer, 4) => 4; assert(memcmp(buffer, names[j % 6], 4) == 0); } @@ -12997,14 +13000,14 @@ code = ''' tag_ = 0; id_ = -1; for (unsigned j = 0; j < N; j++) { - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => 0; assert(tag_ == LFSR_TAG_MKREG); assert(id_ == j*W+W-1); assert(lfsr_data_len(data_) == 4); } - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, lfsr_tag_next(tag_), id_, &tag_, &id_, &data_) => LFS_ERR_NOENT; } @@ -13229,12 +13232,12 @@ code = ''' id__ += sim_weights[j]; } - int err = lfsr_rbyd_pendinglookup( + int err = lfsr_rbyd_predictedlookup( &lfs, &rbyd, unwritten, LFSR_TAG_MKREG, id__, &tag_, &id_, &data_); if (!err) { - lfs_ssize_t size = lfsr_rbyd_pendingget( + lfs_ssize_t size = lfsr_rbyd_predictedget( &lfs, &rbyd, unwritten, tag_, id_, buffer, 4); if (size >= 0) { @@ -13258,10 +13261,10 @@ code = ''' id__ += sim_weights[j]; } - lfsr_rbyd_pendinglookup(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedlookup(&lfs, &rbyd, unwritten, LFSR_TAG_MKREG, id__, &tag_, &id_, &data_) => 0; - lfsr_rbyd_pendingget(&lfs, &rbyd, unwritten, + lfsr_rbyd_predictedget(&lfs, &rbyd, unwritten, tag_, id_, buffer, 4) => 1; assert(memcmp(&sim[id], buffer, 1) == 0); }