Implemented a number of minor B-tree optimizations
- Added cleanup of vestigial names on inner branches. - Avoided extra struct lookups when there is no name on a branch. - Simplified merge name lookup a little bit, probably at some runtime cost but merge is an exceptional operation. - Moved commit before split lookup, in theory this should help stack shrink-wrapping slightly, in practice it's probably a premature optimization. - Removed debugging asserts/printfs.
This commit is contained in:
@@ -457,7 +457,6 @@ enum lfsr_tag_type {
|
|||||||
LFSR_TAG_MKBRANCH = 0x0400,
|
LFSR_TAG_MKBRANCH = 0x0400,
|
||||||
LFSR_TAG_MKREG = 0x0410,
|
LFSR_TAG_MKREG = 0x0410,
|
||||||
LFSR_TAG_MKDIR = 0x0420,
|
LFSR_TAG_MKDIR = 0x0420,
|
||||||
LFSR_TAG_RMMKBRANCH = 0x0402,
|
|
||||||
|
|
||||||
LFSR_TAG_STRUCT = 0x0800,
|
LFSR_TAG_STRUCT = 0x0800,
|
||||||
LFSR_TAG_INLINED = 0x0800,
|
LFSR_TAG_INLINED = 0x0800,
|
||||||
@@ -1419,8 +1418,6 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("cmp 0x%x.%x \"%.*s\" => %d (id%d > id%d?)\n", block, off, find->name_len, find->name, cmp, id, find->predicted_id);
|
|
||||||
|
|
||||||
// found match?
|
// found match?
|
||||||
if (cmp == LFS_CMP_EQ) {
|
if (cmp == LFS_CMP_EQ) {
|
||||||
find->predicted_tag = tag;
|
find->predicted_tag = tag;
|
||||||
@@ -1432,51 +1429,6 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int cmp;
|
|
||||||
// if (lfsr_tag_pat(pattern->predicted) == LFSR_PAT_LEB128) {
|
|
||||||
// uint8_t buf[5];
|
|
||||||
// err = lfs_bd_read(lfs,
|
|
||||||
// NULL, &lfs->rcache, limit-off,
|
|
||||||
// block, off, buf, lfs_min(size, 5));
|
|
||||||
// if (err) {
|
|
||||||
// if (err == LFS_ERR_CORRUPT) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// return err;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// uint32_t found;
|
|
||||||
// lfs_ssize_t delta = lfs_fromleb128(&found, buf, 5);
|
|
||||||
// if (delta < 0) {
|
|
||||||
// return delta;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cmp = pattern->u.leb128 - found;
|
|
||||||
// } else if (lfsr_tag_pat(pattern->predicted) == LFSR_PAT_NAME) {
|
|
||||||
// // TODO handle names
|
|
||||||
// LFS_ASSERT(false);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// // note this already handles the shifting of ids
|
|
||||||
// if (cmp == 0) {
|
|
||||||
// pattern->predicted = lfsr_tag_mkfound(
|
|
||||||
// tag | lfsr_tag_pat(pattern->predicted));
|
|
||||||
// } else if (cmp < 0) {
|
|
||||||
// pattern->predicted += 0x8000;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } else if (pattern && lfsr_tag_suptype(tag) == LFSR_TAG_RM) {
|
|
||||||
// // update any found tags
|
|
||||||
// if (lfsr_tag_id(tag) == lfsr_tag_id(pattern->predicted)) {
|
|
||||||
// pattern->predicted = lfsr_tag_mknotfound(
|
|
||||||
// pattern->predicted);
|
|
||||||
// } else if (lfsr_tag_id(tag) < lfsr_tag_id(pattern->predicted)) {
|
|
||||||
// pattern->predicted -= 0x8000;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// is an end-of-commit crc
|
// is an end-of-commit crc
|
||||||
} else {
|
} else {
|
||||||
uint32_t crc_ = 0;
|
uint32_t crc_ = 0;
|
||||||
@@ -1546,17 +1498,6 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
rbyd->erased = (fcrc_ == fcrc.crc);
|
rbyd->erased = (fcrc_ == fcrc.crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (pattern) {
|
|
||||||
// LFS_ASSERT(lfsr_tag_isvalid(pattern->found));
|
|
||||||
// if (lfsr_tag_isfound(pattern->found)) {
|
|
||||||
// return pattern->found;
|
|
||||||
// } else {
|
|
||||||
// return LFS_ERR_NOENT;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2697,22 +2638,24 @@ static lfs_ssize_t lfsr_btree_lookup(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// each branch is a pair of optional name + on-disk structure
|
// each branch is a pair of optional name + on-disk structure
|
||||||
|
lfsr_tag_t tag__;
|
||||||
lfs_ssize_t rid__;
|
lfs_ssize_t rid__;
|
||||||
lfs_size_t weight__;
|
lfs_size_t weight__;
|
||||||
|
lfs_off_t off_;
|
||||||
|
lfs_size_t size_;
|
||||||
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_MK, rid,
|
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_MK, rid,
|
||||||
NULL, &rid__, &weight__, NULL, NULL);
|
&tag__, &rid__, &weight__, &off_, &size_);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO what if we don't find a struct? ENOENT?
|
if (lfsr_tag_ismk(tag__)) {
|
||||||
lfsr_tag_t tag__;
|
// TODO what if we don't find a struct? ENOENT?
|
||||||
lfs_off_t off_;
|
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_STRUCT, rid__,
|
||||||
lfs_size_t size_;
|
&tag__, NULL, NULL, &off_, &size_);
|
||||||
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_STRUCT, rid__,
|
if (err) {
|
||||||
&tag__, NULL, NULL, &off_, &size_);
|
return err;
|
||||||
if (err) {
|
}
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// found another branch
|
// found another branch
|
||||||
@@ -2793,24 +2736,26 @@ static int lfsr_btree_parent(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// each branch is a pair of optional name + on-disk structure
|
// each branch is a pair of optional name + on-disk structure
|
||||||
|
lfsr_tag_t tag__;
|
||||||
lfs_ssize_t rid__;
|
lfs_ssize_t rid__;
|
||||||
lfs_size_t weight__;
|
lfs_size_t weight__;
|
||||||
|
lfs_off_t off_;
|
||||||
|
lfs_size_t size_;
|
||||||
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_MK, rid,
|
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_MK, rid,
|
||||||
NULL, &rid__, &weight__, NULL, NULL);
|
&tag__, &rid__, &weight__, &off_, &size_);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO what if we don't find a struct? ENOENT?
|
if (lfsr_tag_ismk(tag__)) {
|
||||||
lfsr_tag_t tag__;
|
// TODO what if we don't find a struct? ENOENT?
|
||||||
lfs_off_t off_;
|
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_STRUCT, rid__,
|
||||||
lfs_size_t size_;
|
&tag__, NULL, NULL, &off_, &size_);
|
||||||
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_STRUCT, rid__,
|
if (err) {
|
||||||
&tag__, NULL, NULL, &off_, &size_);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
if (err) {
|
return err;
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
}
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// didn't find our child?
|
// didn't find our child?
|
||||||
@@ -2903,15 +2848,11 @@ static lfs_ssize_t lfsr_btree_find_(lfs_t *lfs,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("find 0x%x.%x \"%.*s\" => %d\n", branch.block, branch.limit, find.name_len, find.name, find.found_id);
|
// assume lowest id if no name found
|
||||||
|
//
|
||||||
// // TODO this doesn't work if id is weighted, how do we make that work?
|
// note this ignore any name attached to the lowest id, this is
|
||||||
// if (find.found_id == rbyd.weight) {
|
// intentional as allowing for "vestigial" names in our blocks helps
|
||||||
// find.found_id -= 1;
|
// simplify some of the more complicated merge/split interactions
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO is this a hack? happens if we have a name on id0
|
|
||||||
//LFS_ASSERT(find.found_id >= 0);
|
|
||||||
if (find.found_id < 0) {
|
if (find.found_id < 0) {
|
||||||
find.found_id = 0;
|
find.found_id = 0;
|
||||||
}
|
}
|
||||||
@@ -2919,22 +2860,24 @@ static lfs_ssize_t lfsr_btree_find_(lfs_t *lfs,
|
|||||||
// the find may not match exactly, but it will indicate which id we
|
// the find may not match exactly, but it will indicate which id we
|
||||||
// should follow
|
// should follow
|
||||||
// TODO can we actually get weight in follow?
|
// TODO can we actually get weight in follow?
|
||||||
|
lfsr_tag_t tag__;
|
||||||
lfs_ssize_t rid__;
|
lfs_ssize_t rid__;
|
||||||
lfs_size_t weight__;
|
lfs_size_t weight__;
|
||||||
|
lfs_off_t off_;
|
||||||
|
lfs_size_t size_;
|
||||||
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_MK, find.found_id,
|
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_MK, find.found_id,
|
||||||
NULL, &rid__, &weight__, NULL, NULL);
|
&tag__, &rid__, &weight__, &off_, &size_);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO what if we don't find a struct? ENOENT?
|
if (lfsr_tag_ismk(tag__)) {
|
||||||
lfsr_tag_t tag__;
|
// TODO what if we don't find a struct? ENOENT?
|
||||||
lfs_off_t off_;
|
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_STRUCT, rid__,
|
||||||
lfs_size_t size_;
|
&tag__, NULL, NULL, &off_, &size_);
|
||||||
err = lfsr_rbyd_lookup(lfs, &rbyd, LFSR_TAG_STRUCT, rid__,
|
if (err) {
|
||||||
&tag__, NULL, NULL, &off_, &size_);
|
return err;
|
||||||
if (err) {
|
}
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// found another branch
|
// found another branch
|
||||||
@@ -3018,7 +2961,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
lfs_ssize_t rid;
|
lfs_ssize_t rid;
|
||||||
int err = lfsr_btree_parent(lfs, btree, id, rbyd, &parent, &rid);
|
int err = lfsr_btree_parent(lfs, btree, id, rbyd, &parent, &rid);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
@@ -3032,7 +2974,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_commit(lfs, rbyd, attrs);
|
err = lfsr_rbyd_commit(lfs, rbyd, attrs);
|
||||||
if (err && err != LFS_ERR_RANGE) {
|
if (err && err != LFS_ERR_RANGE) {
|
||||||
// TODO wait should we also move if there is corruption here?
|
// TODO wait should we also move if there is corruption here?
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3114,6 +3055,18 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because it makes a lot of the split-sensitive cross-id operations
|
||||||
|
// easier, we can end up with an occasional "vestigial" name tag on
|
||||||
|
// the first id in a block. We make sure to ignore these during
|
||||||
|
// lookup, but it would be more complicated then it's worth to
|
||||||
|
// clean these up proactively.
|
||||||
|
//
|
||||||
|
// Discarding these during compaction is easy and prevents any
|
||||||
|
// real storage cost.
|
||||||
|
if (lfsr_tag_ismk(tag) && id-(weight-1) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// append the attr
|
// append the attr
|
||||||
err = lfsr_rbyd_append(lfs, &rbyd_,
|
err = lfsr_rbyd_append(lfs, &rbyd_,
|
||||||
tag, id, LFSR_DATA_DISK(rbyd->block, off, size));
|
tag, id, LFSR_DATA_DISK(rbyd->block, off, size));
|
||||||
@@ -3130,16 +3083,19 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
|
|
||||||
// is our compacted size too small? try to merge with one of
|
// is our compacted size too small? try to merge with one of
|
||||||
// our siblings
|
// our siblings
|
||||||
if (rbyd_.off < lfs->cfg->block_size/4) {
|
if (rbyd_.off < lfs->cfg->block_size/4
|
||||||
|
// no parent? can't merge
|
||||||
|
&& rid != -1
|
||||||
|
// only child? can't merge
|
||||||
|
&& rweight != parent.weight) {
|
||||||
goto merge;
|
goto merge;
|
||||||
abort:;
|
merge_abort:;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalize commit with new attrs, it's up to upper
|
// finalize commit with new attrs, it's up to upper
|
||||||
// layers to make sure these always fit
|
// layers to make sure these always fit
|
||||||
err = lfsr_rbyd_commit(lfs, &rbyd_, attrs);
|
err = lfsr_rbyd_commit(lfs, &rbyd_, attrs);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3181,7 +3137,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
// find out which id we need to split around
|
// find out which id we need to split around
|
||||||
lfs_ssize_t bisect = lfsr_rbyd_bisect(lfs, rbyd);
|
lfs_ssize_t bisect = lfsr_rbyd_bisect(lfs, rbyd);
|
||||||
if (bisect < 0) {
|
if (bisect < 0) {
|
||||||
assert(!err);
|
|
||||||
return bisect;
|
return bisect;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3195,7 +3150,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
bisect,
|
bisect,
|
||||||
LFSR_DATA_BUF(NULL, rbyd_.weight-bisect));
|
LFSR_DATA_BUF(NULL, rbyd_.weight-bisect));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3210,7 +3164,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_append(lfs, &rbyd_,
|
err = lfsr_rbyd_append(lfs, &rbyd_,
|
||||||
attr->tag, attr->id, attr->data);
|
attr->tag, attr->id, attr->data);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3228,7 +3181,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
// finalize commit
|
// finalize commit
|
||||||
err = lfsr_rbyd_commit(lfs, &rbyd_, NULL);
|
err = lfsr_rbyd_commit(lfs, &rbyd_, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3238,7 +3190,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
lfsr_rbyd_t sibling;
|
lfsr_rbyd_t sibling;
|
||||||
err = lfsr_rbyd_alloc(lfs, &sibling, rbyd->rev+1);
|
err = lfsr_rbyd_alloc(lfs, &sibling, rbyd->rev+1);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3252,7 +3203,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_lookup(lfs, rbyd, lfsr_tag_next(tag), id,
|
err = lfsr_rbyd_lookup(lfs, rbyd, lfsr_tag_next(tag), id,
|
||||||
&tag, &id, &weight, &off, &size);
|
&tag, &id, &weight, &off, &size);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
@@ -3269,7 +3219,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
// TODO also this is a weird way to use lfsr_data_t
|
// TODO also this is a weird way to use lfsr_data_t
|
||||||
LFSR_DATA_BUF(NULL, weight));
|
LFSR_DATA_BUF(NULL, weight));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3278,7 +3227,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
tag, id - bisect,
|
tag, id - bisect,
|
||||||
LFSR_DATA_DISK(rbyd->block, off, size));
|
LFSR_DATA_DISK(rbyd->block, off, size));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3292,7 +3240,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_append(lfs, &sibling,
|
err = lfsr_rbyd_append(lfs, &sibling,
|
||||||
attr->tag, attr->id-bisect_, attr->data);
|
attr->tag, attr->id-bisect_, attr->data);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3307,6 +3254,12 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finalize commit
|
||||||
|
err = lfsr_rbyd_commit(lfs, &sibling, NULL);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// lookup first name in sibling to use as the split name
|
// lookup first name in sibling to use as the split name
|
||||||
//
|
//
|
||||||
// note we need to do this after playing out pending attrs in case
|
// note we need to do this after playing out pending attrs in case
|
||||||
@@ -3318,31 +3271,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_lookup(lfs, &sibling, LFSR_TAG_MK, 0,
|
err = lfsr_rbyd_lookup(lfs, &sibling, LFSR_TAG_MK, 0,
|
||||||
&stag, &sid, NULL, &soff, &ssize);
|
&stag, &sid, NULL, &soff, &ssize);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// // remove the first name since we are moving it up as part of our split
|
|
||||||
// //
|
|
||||||
// // note if we wanted to just not write out the first name it would
|
|
||||||
// // checking the attr last for mks that insert a new first name last
|
|
||||||
// // minute, this is just easier as long as split fixups are not the block
|
|
||||||
// // size bottleneck
|
|
||||||
// if (lfsr_tag_ismk(stag)) {
|
|
||||||
// err = lfsr_rbyd_append(lfs, &sibling,
|
|
||||||
// lfsr_tag_mkrm(stag), sid,
|
|
||||||
// LFSR_DATA_NULL);
|
|
||||||
// if (err) {
|
|
||||||
// assert(!err);
|
|
||||||
// return err;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO can move this up?
|
|
||||||
// finalize commit
|
|
||||||
err = lfsr_rbyd_commit(lfs, &sibling, NULL);
|
|
||||||
if (err) {
|
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3446,16 +3374,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
merge:;
|
merge:;
|
||||||
// no parent? can't merge
|
|
||||||
if (rid == -1) {
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only child? can't merge
|
|
||||||
if (rweight == parent.weight) {
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
// last child? try the left sibling
|
// last child? try the left sibling
|
||||||
// lfs_ssize_t sid;
|
// lfs_ssize_t sid;
|
||||||
lfs_ssize_t sdelta;
|
lfs_ssize_t sdelta;
|
||||||
@@ -3470,21 +3388,15 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
|
|
||||||
// try looking up the sibling
|
// try looking up the sibling
|
||||||
lfs_size_t sweight;
|
lfs_size_t sweight;
|
||||||
// keep track of our siblings name
|
|
||||||
lfsr_tag_t split_tag;
|
|
||||||
lfs_off_t split_off;
|
|
||||||
lfs_size_t split_size;
|
|
||||||
|
|
||||||
err = lfsr_rbyd_lookup(lfs, &parent, LFSR_TAG_MK, sid,
|
err = lfsr_rbyd_lookup(lfs, &parent, LFSR_TAG_MK, sid,
|
||||||
&split_tag, &sid, &sweight, &split_off, &split_size);
|
NULL, &sid, &sweight, NULL, NULL);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no sibling? can't merge
|
// no sibling? can't merge
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
goto abort;
|
goto merge_abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lfsr_tag_t stag;
|
// lfsr_tag_t stag;
|
||||||
@@ -3493,13 +3405,12 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_lookup(lfs, &parent, LFSR_TAG_BRANCH, sid,
|
err = lfsr_rbyd_lookup(lfs, &parent, LFSR_TAG_BRANCH, sid,
|
||||||
&stag, NULL, NULL, &off, &size);
|
&stag, NULL, NULL, &off, &size);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no sibling? can't merge
|
// no sibling? can't merge
|
||||||
if (err == LFS_ERR_NOENT || stag != LFSR_TAG_BRANCH) {
|
if (err == LFS_ERR_NOENT || stag != LFSR_TAG_BRANCH) {
|
||||||
goto abort;
|
goto merge_abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buf[LFSR_BRANCH_DSIZE];
|
uint8_t buf[LFSR_BRANCH_DSIZE];
|
||||||
@@ -3508,20 +3419,17 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
&lfs->pcache, &lfs->rcache, delta,
|
&lfs->pcache, &lfs->rcache, delta,
|
||||||
parent.block, off, buf, delta);
|
parent.block, off, buf, delta);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
lfsr_branch_t branch;
|
lfsr_branch_t branch;
|
||||||
delta = lfsr_branch_fromdisk(&branch, buf);
|
delta = lfsr_branch_fromdisk(&branch, buf);
|
||||||
if (delta < 0) {
|
if (delta < 0) {
|
||||||
assert(!delta);
|
|
||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lfsr_rbyd_fetch(lfs, &sibling, branch.block, branch.limit, NULL);
|
err = lfsr_rbyd_fetch(lfs, &sibling, branch.block, branch.limit, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3533,7 +3441,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_lookup(lfs, &sibling, lfsr_tag_next(tag), id,
|
err = lfsr_rbyd_lookup(lfs, &sibling, lfsr_tag_next(tag), id,
|
||||||
&tag, &id, &weight, &off, &size);
|
&tag, &id, &weight, &off, &size);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
@@ -3550,7 +3457,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
// TODO also this is a weird way to use lfsr_data_t
|
// TODO also this is a weird way to use lfsr_data_t
|
||||||
LFSR_DATA_BUF(NULL, weight));
|
LFSR_DATA_BUF(NULL, weight));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3558,12 +3464,11 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
err = lfsr_rbyd_append(lfs, &rbyd_,
|
err = lfsr_rbyd_append(lfs, &rbyd_,
|
||||||
tag, sdelta + id, LFSR_DATA_DISK(sibling.block, off, size));
|
tag, sdelta + id, LFSR_DATA_DISK(sibling.block, off, size));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we exceed our compaction threshold our merge has
|
// if we exceed our compaction threshold our merge has
|
||||||
// failed, clean up ids and abort
|
// failed, clean up ids and merge_abort
|
||||||
if (rbyd_.off > lfs->cfg->block_size/2) {
|
if (rbyd_.off > lfs->cfg->block_size/2) {
|
||||||
err = lfsr_rbyd_append(lfs, &rbyd_,
|
err = lfsr_rbyd_append(lfs, &rbyd_,
|
||||||
LFSR_TAG_SHRINK,
|
LFSR_TAG_SHRINK,
|
||||||
@@ -3571,23 +3476,22 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
// TODO also this is a weird way to use lfsr_data_t
|
// TODO also this is a weird way to use lfsr_data_t
|
||||||
LFSR_DATA_BUF(NULL, rbyd_.weight - rweight));
|
LFSR_DATA_BUF(NULL, rbyd_.weight - rweight));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto abort;
|
goto merge_abort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// bring in name that previously split the siblings
|
// bring in name that previously split the siblings
|
||||||
if (sdelta == 0) {
|
lfsr_tag_t split_tag;
|
||||||
// if we're merging left we need to actually use our name
|
lfs_off_t split_off;
|
||||||
err = lfsr_rbyd_lookup(lfs, &parent, LFSR_TAG_MK, rid,
|
lfs_size_t split_size;
|
||||||
&split_tag, NULL, NULL, &split_off, &split_size);
|
err = lfsr_rbyd_lookup(lfs, &parent,
|
||||||
if (err) {
|
LFSR_TAG_MK, (sdelta == 0 ? rid : sid),
|
||||||
assert(!err);
|
&split_tag, NULL, NULL, &split_off, &split_size);
|
||||||
return err;
|
if (err) {
|
||||||
}
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lfsr_tag_ismk(split_tag)) {
|
if (lfsr_tag_ismk(split_tag)) {
|
||||||
@@ -3598,7 +3502,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
LFSR_TAG_MK, (sdelta == 0 ? sweight : rweight),
|
LFSR_TAG_MK, (sdelta == 0 ? sweight : rweight),
|
||||||
NULL, &split_id, NULL, NULL, NULL);
|
NULL, &split_id, NULL, NULL, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3606,7 +3509,6 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
LFSR_TAG_MKBRANCH, split_id,
|
LFSR_TAG_MKBRANCH, split_id,
|
||||||
LFSR_DATA_DISK(parent.block, split_off, split_size));
|
LFSR_DATA_DISK(parent.block, split_off, split_size));
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3619,14 +3521,12 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
attr->tag, attr->id + (sdelta == 0 ? sweight : 0),
|
attr->tag, attr->id + (sdelta == 0 ? sweight : 0),
|
||||||
attr->data);
|
attr->data);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lfsr_rbyd_commit(lfs, &rbyd_, NULL);
|
err = lfsr_rbyd_commit(lfs, &rbyd_, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
assert(!err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3642,16 +3542,11 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// lfs_ssize_t mid = lfs_smax32(rid, sid);
|
|
||||||
// lfs_size_t mweight = rweight + sweight;
|
|
||||||
|
|
||||||
// push up merge
|
// push up merge
|
||||||
lfs_ssize_t delta1 = lfsr_branch_todisk(
|
lfs_ssize_t delta1 = lfsr_branch_todisk(
|
||||||
&(const lfsr_branch_t){rbyd_.block, rbyd_.off},
|
&(const lfsr_branch_t){rbyd_.block, rbyd_.off},
|
||||||
scratch_buf1);
|
scratch_buf1);
|
||||||
if (delta1 < 0) {
|
if (delta1 < 0) {
|
||||||
assert(!delta1);
|
|
||||||
return delta1;
|
return delta1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3894,10 +3789,6 @@ static int lfsr_btree_pop(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t id) {
|
|||||||
// of the rest
|
// of the rest
|
||||||
return lfsr_btree_commit(lfs, btree, id, &rbyd,
|
return lfsr_btree_commit(lfs, btree, id, &rbyd,
|
||||||
LFSR_ATTR(SHRINK, rid-(rweight-1), NULL, rweight,
|
LFSR_ATTR(SHRINK, rid-(rweight-1), NULL, rweight,
|
||||||
// // TODO conditional? merge with above?
|
|
||||||
// LFSR_ATTR_IF(
|
|
||||||
// rid-(rweight-1) == 0 && rweight < rbyd.weight,
|
|
||||||
// RMMKBRANCH, 0, NULL, 0,
|
|
||||||
NULL));
|
NULL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user