Tweaked lfsr_file_graft_ to take data instead of an rattr
This sort of abuses the bptr/data type overlap again, taking an explicit
delta along with a list of datas where:
- data_count=-1 => single bptr
- data_count>=0 => list of concatenated fragments
It's a bit of a hack, but the previous rattr argument it replaces was
an arguably worse hack. I figured if we're going to interrogate the
rattr to figure out what type it is, we might as well just make the type
explicit.
Saved a surprising amount of stack! So that's nice:
code stack ctx
before: 37192 2360 636
after: 37080 (-0.3%) 2304 (-2.4%) 636 (+0.0%)
This commit is contained in:
@@ -11877,19 +11877,22 @@ static int lfsr_file_commit(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
bid, rattrs, rattr_count);
|
bid, rattrs, rattr_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO replace rattr with bptr + delta?
|
// graft bptr/fragments into our bshrub/btree
|
||||||
static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
|
static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
|
||||||
lfs_off_t pos, lfs_off_t weight, lfsr_rattr_t rattr) {
|
lfs_off_t pos, lfs_off_t weight, lfs_soff_t delta,
|
||||||
|
// data_count=-1 => single bptr
|
||||||
|
// data_count>=0 => list of concatenated fragments
|
||||||
|
const lfsr_data_t *datas, lfs_ssize_t data_count) {
|
||||||
// note! we must never allow our btree size to overflow, even
|
// note! we must never allow our btree size to overflow, even
|
||||||
// temporarily
|
// temporarily
|
||||||
|
|
||||||
// can't carve more than the graft weight
|
// can't carve more than the graft weight
|
||||||
LFS_ASSERT(rattr.weight >= -(lfs_soff_t)weight);
|
LFS_ASSERT(delta >= -(lfs_soff_t)weight);
|
||||||
|
|
||||||
// carving the entire tree? revert to no bshrub/btree
|
// carving the entire tree? revert to no bshrub/btree
|
||||||
if (pos == 0
|
if (pos == 0
|
||||||
&& weight >= file->b.shrub.weight
|
&& weight >= file->b.shrub.weight
|
||||||
&& rattr.weight == -(lfs_soff_t)weight) {
|
&& delta == -(lfs_soff_t)weight) {
|
||||||
lfsr_bshrub_init(&file->b);
|
lfsr_bshrub_init(&file->b);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -12055,7 +12058,7 @@ static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rattr.weight += lfs_min(weight, bid+1 - pos);
|
delta += lfs_min(weight, bid+1 - pos);
|
||||||
weight -= lfs_min(weight, bid+1 - pos);
|
weight -= lfs_min(weight, bid+1 - pos);
|
||||||
rattr_count = 0;
|
rattr_count = 0;
|
||||||
continue;
|
continue;
|
||||||
@@ -12065,7 +12068,7 @@ static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
if (pos+weight < bid+1) {
|
if (pos+weight < bid+1) {
|
||||||
// can we coalesce a hole?
|
// can we coalesce a hole?
|
||||||
if (lfsr_bptr_size(&r) == 0) {
|
if (lfsr_bptr_size(&r) == 0) {
|
||||||
rattr.weight += bid+1 - (pos+weight);
|
delta += bid+1 - (pos+weight);
|
||||||
|
|
||||||
// carve fragment?
|
// carve fragment?
|
||||||
} else if (!lfsr_bptr_isbptr(&bptr_)
|
} else if (!lfsr_bptr_isbptr(&bptr_)
|
||||||
@@ -12082,31 +12085,45 @@ static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rattr.weight += lfs_min(weight, bid+1 - pos);
|
delta += lfs_min(weight, bid+1 - pos);
|
||||||
weight -= lfs_min(weight, bid+1 - pos);
|
weight -= lfs_min(weight, bid+1 - pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// append our data
|
// append our data
|
||||||
if (weight + rattr.weight > 0) {
|
if (weight + delta > 0) {
|
||||||
|
lfs_size_t dsize = 0;
|
||||||
|
for (lfs_size_t i = 0;
|
||||||
|
i < ((data_count < 0) ? 1 : (lfs_size_t)data_count);
|
||||||
|
i++) {
|
||||||
|
dsize += lfsr_data_size(datas[i]);
|
||||||
|
}
|
||||||
|
|
||||||
// can we coalesce a hole?
|
// can we coalesce a hole?
|
||||||
if (lfsr_rattr_dsize(rattr) == 0 && pos > 0) {
|
if (dsize == 0 && pos > 0) {
|
||||||
bid = lfs_min(bid, file->b.shrub.weight-1);
|
bid = lfs_min(bid, file->b.shrub.weight-1);
|
||||||
rattrs[rattr_count++] = LFSR_RATTR(
|
rattrs[rattr_count++] = LFSR_RATTR(
|
||||||
LFSR_TAG_GROW, +(weight + rattr.weight));
|
LFSR_TAG_GROW, +(weight + delta));
|
||||||
|
|
||||||
// need a new hole?
|
// need a new hole?
|
||||||
} else if (lfsr_rattr_dsize(rattr) == 0) {
|
} else if (dsize == 0) {
|
||||||
bid = lfs_min(bid, file->b.shrub.weight);
|
bid = lfs_min(bid, file->b.shrub.weight);
|
||||||
rattrs[rattr_count++] = LFSR_RATTR(
|
rattrs[rattr_count++] = LFSR_RATTR(
|
||||||
LFSR_TAG_DATA, +(weight + rattr.weight));
|
LFSR_TAG_DATA, +(weight + delta));
|
||||||
|
|
||||||
// append new fragment/bptr?
|
// append a new fragment?
|
||||||
|
} else if (data_count >= 0) {
|
||||||
|
bid = lfs_min(bid, file->b.shrub.weight);
|
||||||
|
rattrs[rattr_count++] = LFSR_RATTR_CAT_(
|
||||||
|
LFSR_TAG_DATA, +(weight + delta),
|
||||||
|
datas, data_count);
|
||||||
|
|
||||||
|
// append a new bptr?
|
||||||
} else {
|
} else {
|
||||||
bid = lfs_min(bid, file->b.shrub.weight);
|
bid = lfs_min(bid, file->b.shrub.weight);
|
||||||
rattrs[rattr_count++] = LFSR_RATTR_(
|
rattrs[rattr_count++] = LFSR_RATTR_BPTR(
|
||||||
rattr.tag, +(weight + rattr.weight),
|
LFSR_TAG_BLOCK, +(weight + delta),
|
||||||
rattr.u, rattr.count);
|
(const lfsr_bptr_t*)datas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12129,19 +12146,6 @@ static int lfsr_file_graft_(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfsr_file_graftcrystal(lfs_t *lfs, lfsr_file_t *file,
|
|
||||||
lfs_off_t pos, lfs_off_t weight, const lfsr_bptr_t *bptr) {
|
|
||||||
return lfsr_file_graft_(lfs, file, pos, weight,
|
|
||||||
LFSR_RATTR_BPTR(LFSR_TAG_BLOCK, 0, bptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lfsr_file_graftfragment(lfs_t *lfs, lfsr_file_t *file,
|
|
||||||
lfs_off_t pos, lfs_off_t weight,
|
|
||||||
const lfsr_data_t *datas, lfs_size_t data_count) {
|
|
||||||
return lfsr_file_graft_(lfs, file, pos, weight,
|
|
||||||
LFSR_RATTR_CAT_(LFSR_TAG_DATA, 0, datas, data_count));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lfsr_file_graft(lfs_t *lfs, lfsr_file_t *file) {
|
static int lfsr_file_graft(lfs_t *lfs, lfsr_file_t *file) {
|
||||||
// do nothing if already grafted
|
// do nothing if already grafted
|
||||||
if (!lfsr_o_isungraft(file->b.o.flags)) {
|
if (!lfsr_o_isungraft(file->b.o.flags)) {
|
||||||
@@ -12153,9 +12157,9 @@ static int lfsr_file_graft(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
LFS_ASSERT(lfsr_bptr_isbptr(&file->leaf.bptr));
|
LFS_ASSERT(lfsr_bptr_isbptr(&file->leaf.bptr));
|
||||||
|
|
||||||
// graft our crystal
|
// graft our crystal
|
||||||
int err = lfsr_file_graftcrystal(lfs, file,
|
int err = lfsr_file_graft_(lfs, file,
|
||||||
file->leaf.pos, file->leaf.weight,
|
file->leaf.pos, file->leaf.weight, 0,
|
||||||
&file->leaf.bptr);
|
&file->leaf.bptr.data, -1);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -12788,8 +12792,8 @@ fragment:;
|
|||||||
|
|
||||||
// once we've figured out what fragment to write, graft it into
|
// once we've figured out what fragment to write, graft it into
|
||||||
// our tree
|
// our tree
|
||||||
err = lfsr_file_graftfragment(lfs, file,
|
err = lfsr_file_graft_(lfs, file,
|
||||||
fragment_start, fragment_end - fragment_start,
|
fragment_start, fragment_end - fragment_start, 0,
|
||||||
datas, data_count);
|
datas, data_count);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -12992,9 +12996,9 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
|
|
||||||
// graft any ungrafted leaves
|
// graft any ungrafted leaves
|
||||||
if (lfsr_o_isungraft(file->b.o.flags)) {
|
if (lfsr_o_isungraft(file->b.o.flags)) {
|
||||||
err = lfsr_file_graftcrystal(lfs, file,
|
err = lfsr_file_graft_(lfs, file,
|
||||||
file->leaf.pos, file->leaf.weight,
|
file->leaf.pos, file->leaf.weight, 0,
|
||||||
&file->leaf.bptr);
|
&file->leaf.bptr.data, -1);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@@ -13433,8 +13437,8 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
// truncate our btree
|
// truncate our btree
|
||||||
err = lfsr_file_graft_(lfs, file,
|
err = lfsr_file_graft_(lfs, file,
|
||||||
lfs_min(size, size_), size - lfs_min(size, size_),
|
lfs_min(size, size_), size - lfs_min(size, size_),
|
||||||
LFSR_RATTR(
|
+size_ - size,
|
||||||
LFSR_TAG_DATA, +size_ - size));
|
NULL, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@@ -13517,8 +13521,8 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
|
|||||||
// fruncate our btree
|
// fruncate our btree
|
||||||
err = lfsr_file_graft_(lfs, file,
|
err = lfsr_file_graft_(lfs, file,
|
||||||
0, lfs_smax(size - size_, 0),
|
0, lfs_smax(size - size_, 0),
|
||||||
LFSR_RATTR(
|
+size_ - size,
|
||||||
LFSR_TAG_DATA, +size_ - size));
|
NULL, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user