Changed GROW/SHRINK to always be explicit, dropped LFSR_TAG_RM
Generally, less implicit behavior => simpler systems, which is the goal here.
This commit is contained in:
@@ -457,7 +457,6 @@ enum lfsr_tag_type {
|
||||
LFSR_TAG_MKBRANCH = 0x0400,
|
||||
LFSR_TAG_MKREG = 0x0410,
|
||||
LFSR_TAG_MKDIR = 0x0420,
|
||||
LFSR_TAG_RM = 0x0402, // in-device only
|
||||
|
||||
LFSR_TAG_STRUCT = 0x0800,
|
||||
LFSR_TAG_INLINED = 0x0800,
|
||||
@@ -1508,6 +1507,7 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
static int lfsr_rbyd_lookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||
lfsr_tag_t tag, lfs_ssize_t id,
|
||||
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
|
||||
@@ -1596,6 +1596,7 @@ static lfs_ssize_t lfsr_rbyd_get(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||
return LFS_ERR_NOENT;
|
||||
}
|
||||
|
||||
// TODO should this be its own lfsr_data_ function?
|
||||
lfs_size_t delta = lfs_min(size, size_);
|
||||
err = lfs_bd_read(lfs,
|
||||
&lfs->pcache, &lfs->rcache, delta,
|
||||
@@ -1607,6 +1608,120 @@ static lfs_ssize_t lfsr_rbyd_get(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||
return size_;
|
||||
}
|
||||
|
||||
//// TODO should we merge this into lfsr_rbyd_lookup?
|
||||
//static int lfsr_rbyd_lookupattrs(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_, lfs_size_t *weight_) {
|
||||
// // 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);
|
||||
//
|
||||
// lfs_ssize_t lower_id = -1;
|
||||
// lfs_ssize_t upper_id = rbyd->weight;
|
||||
// lfsr_tag_t upper_tag = -1;
|
||||
//
|
||||
//
|
||||
// // TODO hmm, reverse iteration over a linked-list? this is a bad design
|
||||
// // first try to find tag in the unwritten attributes
|
||||
// lfs_ssize_t attr_best_id = 0;
|
||||
// lfs_tag_t attr_best_tag = 0;
|
||||
// lfs_ssize_t attr_weight = 0;
|
||||
// unsigned attr_count = 0;
|
||||
// for (const struct lfsr_attr *attr = attrs; attr; attr = attr->next) {
|
||||
// attr_count += 1;
|
||||
// }
|
||||
// for (unsigned i = 0; i < count; i++) {
|
||||
// const struct lfsr_attr *attr = attrs;
|
||||
// for (unsigned j = 0; j < count-1-i; j++) {
|
||||
// attr = attr->next;
|
||||
// }
|
||||
//
|
||||
// // TODO can this be simplified a bit?
|
||||
// if (lfsr_tag_ismk(attr->tag)) {
|
||||
// if (attr->id < id) {
|
||||
// id -= 1;
|
||||
// }
|
||||
// } else if (attr->tag == LFSR_TAG_RM) {
|
||||
// if (attr->id < id) {
|
||||
// id += attr->size;
|
||||
// }
|
||||
// } else if (attr->tag == LFSR_TAG_GROW) {
|
||||
// if (attr->id < id) {
|
||||
// id -= attr->size;
|
||||
// }
|
||||
// } else if (attr->tag == LFSR_TAG_SHRINK) {
|
||||
// if (attr->id < id) {
|
||||
// id += attr->size;
|
||||
// }
|
||||
// } else if (attr->tag == LFSR_TAG_FROM) {
|
||||
// // TODO
|
||||
// LFS_ASSERT(false);
|
||||
// } else if (lfsr_tag_isrm(attr->tag)) {
|
||||
// } else {
|
||||
// if (attr->id == id
|
||||
// && attr->tag >= tag
|
||||
// && (attr->id < best_attr_id
|
||||
// || (attr->id == best_attr_id
|
||||
// && attr->tag < best_attr_tag))) {
|
||||
// // TODO track best attr?
|
||||
// best_attr_id = attr->id;
|
||||
// best_attr_tag = attr->tag;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// lfs_off_t off_;
|
||||
// lfs_size_t size_;
|
||||
// int err = lfsr_rbyd_lookup(lfs, rbyd, tag, id,
|
||||
// tag_, id_, weight_, &off_, &size_);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
//
|
||||
// if (data_) {
|
||||
// *data_ = LFSR_DATA_DISK(rbyd->block, off_, size_);
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
//
|
||||
//// TODO do we need this function?
|
||||
//static lfs_ssize_t lfsr_rbyd_getattrs(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_lookupattrs(lfs, rbyd, attrs, tag, id,
|
||||
// &tag_, &id_, &data_, NULL);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
//
|
||||
// // lookup finds the next-smallest tag, for get, we need to fail
|
||||
// // if it's not an exact match
|
||||
// if (id_ != id || tag_ != tag) {
|
||||
// return LFS_ERR_NOENT;
|
||||
// }
|
||||
//
|
||||
// // TODO should this be its own lfsr_data_ function?
|
||||
// lfs_size_t delta = lfs_min(size, lfsr_data_len(data_));
|
||||
// if (!lfsr_data_ondisk(data_)) {
|
||||
// memcpy(buffer, data_.u.buf, delta);
|
||||
// } else {
|
||||
// err = lfs_bd_read(lfs,
|
||||
// &lfs->pcache, &lfs->rcache, delta,
|
||||
// data_.u.disk.block, data_.u.disk.off, buffer, delta);
|
||||
// if (err) {
|
||||
// return err;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return lfsr_data_len(data_);
|
||||
//}
|
||||
|
||||
static lfs_ssize_t lfsr_rbyd_compactedsize(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
|
||||
lfs_ssize_t start, lfs_ssize_t stop) {
|
||||
// find the strict upper bound on the amount of disk taken by a range of
|
||||
@@ -1838,44 +1953,8 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||
lfs_ssize_t id_;
|
||||
lfsr_tag_t other_tag_;
|
||||
lfs_ssize_t other_id_;
|
||||
if (lfsr_tag_ismk(tag)) {
|
||||
if (tag == LFSR_TAG_GROW) {
|
||||
LFS_ASSERT(id <= rbyd_->weight);
|
||||
rbyd_->weight += 1;
|
||||
|
||||
// In-driver, mk tags implicitly grows the weight by one, this
|
||||
// simplifies a few things. On-disk, however, we want to make this
|
||||
// explicit so fetch parses fewer things.
|
||||
//
|
||||
// We can do this by prepending mk trunks with isolated grow tags. But
|
||||
// this only works because we always immediately replace the grow trunk
|
||||
// with our mk trunk!
|
||||
//
|
||||
// Note this also makes the order of operations with our current branch
|
||||
// above and new trunk below a bit sensitive.
|
||||
int err = lfsr_rbyd_progtag(lfs, rbyd_,
|
||||
LFSR_TAG_GROW, id, 1, &rbyd_->crc);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
tag_ = 0;
|
||||
id_ = id;
|
||||
other_tag_ = tag_;
|
||||
other_id_ = id_;
|
||||
} else if (tag == LFSR_TAG_RM) {
|
||||
LFS_ASSERT(id < rbyd_->weight);
|
||||
LFS_ASSERT(id >= size-1);
|
||||
rbyd_->weight -= size;
|
||||
|
||||
// rm tags are just an in-driver convenience
|
||||
tag = LFSR_TAG_SHRINK;
|
||||
|
||||
tag_ = 0;
|
||||
id_ = id;
|
||||
other_tag_ = tag_;
|
||||
other_id_ = id_ + 1;
|
||||
} else if (tag == LFSR_TAG_GROW) {
|
||||
LFS_ASSERT(id < rbyd_->weight);
|
||||
// noop?
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
@@ -1888,7 +1967,6 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||
other_id_ = id_;
|
||||
} else if (tag == LFSR_TAG_SHRINK) {
|
||||
LFS_ASSERT(id < rbyd_->weight);
|
||||
LFS_ASSERT(id >= size-1);
|
||||
// noop?
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
@@ -1898,7 +1976,7 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||
tag_ = 0;
|
||||
id_ = id;
|
||||
other_tag_ = tag_;
|
||||
other_id_ = id_;
|
||||
other_id_ = id_ + size;
|
||||
} else if (lfsr_tag_isrm(tag)) {
|
||||
LFS_ASSERT(id < rbyd_->weight);
|
||||
|
||||
@@ -2218,11 +2296,6 @@ static int lfsr_rbyd_append(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||
alt = LFSR_TAG_ALT(R, LE, tag_);
|
||||
weight = id_ - lower_id;
|
||||
|
||||
} else if (lfsr_tag_ismk(tag)) {
|
||||
// increase weight when creating
|
||||
alt = LFSR_TAG_ALT(R, GT, tag);
|
||||
weight = upper_id - id - 1 + 1;
|
||||
|
||||
} else if (tag == LFSR_TAG_GROW) {
|
||||
// decrease weight when growing
|
||||
alt = LFSR_TAG_ALT(B, GT, 0);
|
||||
@@ -2922,9 +2995,9 @@ static int lfsr_btree_commit(lfs_t *lfs,
|
||||
return delta2;
|
||||
}
|
||||
|
||||
scratch_attrs[0] = *LFSR_ATTR(
|
||||
RM, pid, NULL, pweight,
|
||||
&scratch_attrs[1]);
|
||||
// scratch_attrs[0] = *LFSR_ATTR(
|
||||
// RM, pid, NULL, pweight,
|
||||
// &scratch_attrs[1]);
|
||||
|
||||
scratch_attrs[1] = *LFSR_ATTR(
|
||||
MKBRANCH, pid, NULL, 0,
|
||||
|
||||
+4
-2
@@ -198,7 +198,9 @@ def show_log(block_size, data, rev, off, *,
|
||||
j_ += size
|
||||
|
||||
if grow is not None:
|
||||
if (tag & ~0x3f0) == 0x0400 and id == grow[1]:
|
||||
if ((tag & ~0x3f0) == 0x0400
|
||||
and id >= grow[1]
|
||||
and id < grow[1]+grow[2]):
|
||||
i, p = index(weights, id)
|
||||
weights[i:i+1] = [p+1, weights[i]-(p+1)]
|
||||
colors[i:i+1] = [COLORS[colors_i % len(COLORS)], colors[i]]
|
||||
@@ -214,7 +216,7 @@ def show_log(block_size, data, rev, off, *,
|
||||
if tag == 0x0006:
|
||||
i, _ = index(weights, id)
|
||||
weights[i] += size
|
||||
grow = j, id
|
||||
grow = j, id, size
|
||||
elif tag == 0x0016:
|
||||
i, _ = index(weights, id)
|
||||
if weights[i] == size and len(weights) > 1:
|
||||
|
||||
+377
-211
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user