Changed rbyd/btree namelookups to only compare raw bytes
This is a simplification of the rbyd/btree layers, but implies
behavioral changes to the mtree/mdir layers.
Instead of ordering by leb128 did + name:
82 02 61 61 61 < 81 04 62 62 62
(0x102, "aaa") (0x201, "bbb")
We now order by the raw encoding, lexicographically:
82 02 61 61 61 > 81 04 62 62 62
(0x102, "aaa") (0x201, "bbb")
This may be unintuitive, but note:
1. Files _within_ a directory are still ordered, since they share a did
prefix.
2. We don't really care about the relative ordering of dids, just
that they are unique. Changing the ordering at this level does not
interfere with any of our did-related functions.
3. The only thing we may care about is that the root, did=0, is the
first mtree entry. This is still true. No leb128 encoding is < 0x00
even after encoding.
The motivation for this change is to allow for other named-btrees in the
system that may used non-did-prefixed names. At least one of these makes
sense for a sort of "content-tree" (cksum -> data block mapping).
As a plus, this change makes it possible to compare names and do btree
namelookups without needing to decode the leb128 prefix. Although I'm
struggling a bit to figure out exactly where this is useful...
One downside, this ordering only works if dids are always stored in
their canonical encoding, that is, the smallest leb128 encoding possible
for a given did. I think this is a reasonable requirement for just our
dids.
Another downside is this did add a decent chunk of code.
I did try limiting the changes to lfsr_data_namecmp, but it didn't have
much impact. I guess most of the cost comes from the reworked
lfsr_data_cmp function, which, to be fair, is quite a bit more
complicated now (it now supports limited data<=>data comparisons):
code stack
before: 34148 2896
namecmp: 34324 (+0.5%) 2896 (+0.0%)
after: 34340 (+0.6%) 2896 (+0.0%)
This commit is contained in:
@@ -1357,73 +1357,73 @@ static inline int lfsr_data_readlleb128(lfs_t *lfs, lfsr_data_t *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static lfs_scmp_t lfsr_data_cmp(lfs_t *lfs, const lfsr_data_t *data,
|
||||
const void *buffer, lfs_size_t size) {
|
||||
// limit our size to data range
|
||||
lfs_size_t d = lfs_min32(size, lfsr_data_size(data));
|
||||
static lfs_scmp_t lfsr_data_cmp_(lfs_t *lfs,
|
||||
const lfsr_data_t *a,
|
||||
const lfsr_data_t *b,
|
||||
lfs_size_t size) {
|
||||
// on-disk cmp buffer?
|
||||
if (lfsr_data_ondisk(a) && lfsr_data_isbuf(b)) {
|
||||
return lfsr_bd_cmp(lfs, a->u.disk.block, a->u.disk.off, 0,
|
||||
b->u.buf.buffer, size);
|
||||
|
||||
// on-disk?
|
||||
if (lfsr_data_ondisk(data)) {
|
||||
int cmp = lfsr_bd_cmp(lfs, data->u.disk.block, data->u.disk.off, 0,
|
||||
buffer, d);
|
||||
// on-disk cmp inlined?
|
||||
} else if (lfsr_data_ondisk(a) && lfsr_data_isimm(b)) {
|
||||
return lfsr_bd_cmp(lfs, a->u.disk.block, a->u.disk.off, 0,
|
||||
b->u.imm.buf, size);
|
||||
|
||||
// not supported
|
||||
} else {
|
||||
LFS_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
static lfs_scmp_t lfsr_data_cmp(lfs_t *lfs,
|
||||
const lfsr_data_t *a,
|
||||
const lfsr_data_t *b) {
|
||||
// simple data?
|
||||
if (!lfsr_data_iscat(b)) {
|
||||
// compare common prefix
|
||||
lfs_scmp_t cmp = lfsr_data_cmp_(lfs, a, b,
|
||||
lfs_min32(
|
||||
lfsr_data_size(a),
|
||||
lfsr_data_size(b)));
|
||||
if (cmp != LFS_CMP_EQ) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
// buffer?
|
||||
} else if (lfsr_data_isbuf(data)) {
|
||||
int cmp = memcmp(data->u.buf.buffer, buffer, d);
|
||||
if (cmp < 0) {
|
||||
return LFS_CMP_LT;
|
||||
} else if (cmp > 0) {
|
||||
return LFS_CMP_GT;
|
||||
}
|
||||
|
||||
// inlined?
|
||||
} else if (lfsr_data_isimm(data)) {
|
||||
int cmp = memcmp(data->u.imm.buf, buffer, d);
|
||||
if (cmp < 0) {
|
||||
return LFS_CMP_LT;
|
||||
} else if (cmp > 0) {
|
||||
return LFS_CMP_GT;
|
||||
}
|
||||
|
||||
// concatenated? not supported
|
||||
// concatenated data? handle specially to avoid recursion
|
||||
} else {
|
||||
LFS_UNREACHABLE();
|
||||
// compare common prefix
|
||||
lfs_size_t size = lfs_min32(
|
||||
lfsr_data_size(a),
|
||||
lfsr_data_size(b));
|
||||
lfsr_data_t a_ = *a;
|
||||
const lfsr_data_t *b_ = b->u.cat.datas;
|
||||
while (size > 0) {
|
||||
lfs_size_t d = lfs_min32(
|
||||
size,
|
||||
lfsr_data_size(b_));
|
||||
lfs_scmp_t cmp = lfsr_data_cmp_(lfs, &a_, b_, d);
|
||||
if (cmp != LFS_CMP_EQ) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
a_ = lfsr_data_slice(a_, d, -1);
|
||||
size -= d;
|
||||
b_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if data is equal, check for size mismatch
|
||||
if (lfsr_data_size(data) < size) {
|
||||
if (lfsr_data_size(a) < lfsr_data_size(b)) {
|
||||
return LFS_CMP_LT;
|
||||
} else if (lfsr_data_size(data) > size) {
|
||||
} else if (lfsr_data_size(a) > lfsr_data_size(b)) {
|
||||
return LFS_CMP_GT;
|
||||
} else {
|
||||
return LFS_CMP_EQ;
|
||||
}
|
||||
}
|
||||
|
||||
static lfs_scmp_t lfsr_data_namecmp(lfs_t *lfs, const lfsr_data_t *data,
|
||||
lfsr_did_t did, const char *name, lfs_size_t name_size) {
|
||||
// first compare the did
|
||||
lfsr_data_t data_ = *data;
|
||||
lfsr_did_t did_;
|
||||
int err = lfsr_data_readleb128(lfs, &data_, &did_);
|
||||
if (err) {
|
||||
LFS_ASSERT(err < 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (did_ < did) {
|
||||
return LFS_CMP_LT;
|
||||
} else if (did_ > did) {
|
||||
return LFS_CMP_GT;
|
||||
}
|
||||
|
||||
// then compare the actual name
|
||||
return lfsr_data_cmp(lfs, &data_, name, name_size);
|
||||
}
|
||||
|
||||
static int lfsr_bd_progdata_(lfs_t *lfs,
|
||||
lfs_block_t block, lfs_size_t off, lfsr_data_t data,
|
||||
uint32_t *cksum_, uint32_t *flcksum_) {
|
||||
@@ -1468,11 +1468,8 @@ static int lfsr_bd_progdata(lfs_t *lfs,
|
||||
uint32_t *cksum_, uint32_t *flcksum_) {
|
||||
// simple data?
|
||||
if (!lfsr_data_iscat(&data)) {
|
||||
int err = lfsr_bd_progdata_(lfs, block, off, data,
|
||||
return lfsr_bd_progdata_(lfs, block, off, data,
|
||||
cksum_, flcksum_);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// concatenated data? handle specially to avoid recursion
|
||||
} else {
|
||||
@@ -1489,9 +1486,9 @@ static int lfsr_bd_progdata(lfs_t *lfs,
|
||||
size -= lfsr_data_size(datas);
|
||||
datas += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3741,7 +3738,7 @@ static int lfsr_rbyd_appendshrub(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
// binary search an rbyd for a name, leaving the rid_/tag_/weight_/data_
|
||||
// with the best matching name if not found
|
||||
static lfs_scmp_t lfsr_rbyd_namelookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||
lfsr_did_t did, const char *name, lfs_size_t name_size,
|
||||
const lfsr_data_t *name,
|
||||
lfsr_srid_t *rid_,
|
||||
lfsr_tag_t *tag_, lfsr_rid_t *weight_, lfsr_data_t *data_) {
|
||||
// empty rbyd? leave it up to upper layers to handle this
|
||||
@@ -3775,7 +3772,7 @@ static lfs_scmp_t lfsr_rbyd_namelookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||
|
||||
// compare names
|
||||
} else {
|
||||
cmp = lfsr_data_namecmp(lfs, &data__, did, name, name_size);
|
||||
cmp = lfsr_data_cmp(lfs, &data__, name);
|
||||
if (cmp < 0) {
|
||||
return cmp;
|
||||
}
|
||||
@@ -4701,7 +4698,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, lfsr_bid_t bid,
|
||||
|
||||
// lookup in a btree by name
|
||||
static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
|
||||
lfsr_did_t did, const char *name, lfs_size_t name_size,
|
||||
const lfsr_data_t *name,
|
||||
lfsr_bid_t *bid_,
|
||||
lfsr_tag_t *tag_, lfsr_bid_t *weight_, lfsr_data_t *data_) {
|
||||
// an empty tree?
|
||||
@@ -4716,8 +4713,7 @@ static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
|
||||
// lookup our name in the rbyd via binary search
|
||||
lfsr_srid_t rid__;
|
||||
lfsr_rid_t weight__;
|
||||
lfs_scmp_t cmp = lfsr_rbyd_namelookup(lfs, &branch,
|
||||
did, name, name_size,
|
||||
lfs_scmp_t cmp = lfsr_rbyd_namelookup(lfs, &branch, name,
|
||||
&rid__, NULL, &weight__, NULL);
|
||||
if (cmp < 0) {
|
||||
LFS_ASSERT(cmp != LFS_ERR_NOENT);
|
||||
@@ -6926,7 +6922,9 @@ static int lfsr_mdir_namelookup(lfs_t *lfs, const lfsr_mdir_t *mdir,
|
||||
lfsr_srid_t rid;
|
||||
lfsr_tag_t tag;
|
||||
lfs_scmp_t cmp = lfsr_rbyd_namelookup(lfs, &mdir->rbyd,
|
||||
did, name, name_size,
|
||||
&LFSR_DATA_CAT(
|
||||
LFSR_DATA_LEB128(did),
|
||||
LFSR_DATA_BUF(name, name_size)),
|
||||
&rid, &tag, NULL, data_);
|
||||
if (cmp < 0) {
|
||||
LFS_ASSERT(cmp != LFS_ERR_NOENT);
|
||||
@@ -6985,7 +6983,9 @@ static int lfsr_mtree_namelookup(lfs_t *lfs, const lfsr_mtree_t *mtree,
|
||||
lfsr_bid_t weight;
|
||||
lfsr_data_t data;
|
||||
lfs_scmp_t cmp = lfsr_btree_namelookup(lfs, &mtree->u.btree,
|
||||
did, name, name_size,
|
||||
&LFSR_DATA_CAT(
|
||||
LFSR_DATA_LEB128(did),
|
||||
LFSR_DATA_BUF(name, name_size)),
|
||||
&bid, &tag, &weight, &data);
|
||||
if (cmp < 0) {
|
||||
LFS_ASSERT(cmp != LFS_ERR_NOENT);
|
||||
@@ -7746,7 +7746,8 @@ static int lfsr_mountmroot(lfs_t *lfs, const lfsr_mdir_t *mroot) {
|
||||
return err;
|
||||
}
|
||||
|
||||
lfs_scmp_t cmp = lfsr_data_cmp(lfs, &data, "littlefs", 8);
|
||||
lfs_scmp_t cmp = lfsr_data_cmp(lfs, &data,
|
||||
&LFSR_DATA_BUF("littlefs", 8));
|
||||
if (cmp < 0) {
|
||||
return cmp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user