Reworked btree-commit/flushbuffer to incrementally build attrs
This basically turns these functions into tiny bounded compilers, which
is interesting to think about. I wonder if this sort of evolution led to
how queries are compiled in modern databases.
This method of attr generation is both easier to use and more flexible.
It also saves some code, but note lfsr_file_flushbuffer underwent
significant tweaking leveraging this, so the actual code savings are a
bit muddy:
code stack
before: 25672 2024
after: 25452 (-0.9%) 1920 (-5.4%)
This commit is contained in:
@@ -1027,12 +1027,11 @@ static lfs_ssize_t lfsr_bd_progtag(lfs_t *lfs,
|
|||||||
((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_grm_t*){_grm}})
|
((lfsr_data_t){.u.direct.buffer=(const void*)(lfsr_grm_t*){_grm}})
|
||||||
|
|
||||||
// writing to an unrelated trunk in the rbyd
|
// writing to an unrelated trunk in the rbyd
|
||||||
#define LFSR_DATA_SHRUBATTRS(_file, ...) \
|
#define LFSR_DATA_SHRUBATTRS(_file, _attrs, _attr_count) \
|
||||||
((lfsr_data_t){.u.direct.buffer=(const void*)&(const lfsr_shrubattrs_t){ \
|
((lfsr_data_t){.u.direct.buffer=(const void*)&(const lfsr_shrubattrs_t){ \
|
||||||
.file=_file, \
|
.file=_file, \
|
||||||
.attrs=(const lfsr_attr_t[]){__VA_ARGS__}, \
|
.attrs=_attrs, \
|
||||||
.attr_count=sizeof((const lfsr_attr_t[]){__VA_ARGS__}) \
|
.attr_count=_attr_count}})
|
||||||
/ sizeof(lfsr_attr_t)}})
|
|
||||||
|
|
||||||
// the reason for lazily encoding inlined trunks is because they can change
|
// the reason for lazily encoding inlined trunks is because they can change
|
||||||
// underneath us during mdir compaction, the horror
|
// underneath us during mdir compaction, the horror
|
||||||
@@ -4338,27 +4337,25 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
bid -= rid - (rbyd.weight-1);
|
bid -= rid - (rbyd.weight-1);
|
||||||
LFS_ASSERT(rbyd_.weight > 0);
|
LFS_ASSERT(rbyd_.weight > 0);
|
||||||
LFS_ASSERT(sibling.weight > 0);
|
LFS_ASSERT(sibling.weight > 0);
|
||||||
|
lfsr_attr_t *attrs_ = scratch_attrs;
|
||||||
if (rbyd.weight == 0) {
|
if (rbyd.weight == 0) {
|
||||||
scratch_attrs[0] = LFSR_ATTR(bid,
|
*attrs_++ = LFSR_ATTR(bid,
|
||||||
BTREE, +rbyd_.weight, FROMBTREE(&rbyd_, scratch_buf));
|
BTREE, +rbyd_.weight, FROMBTREE(&rbyd_, scratch_buf));
|
||||||
scratch_attrs[1] = LFSR_ATTR_NOOP;
|
|
||||||
} else {
|
} else {
|
||||||
scratch_attrs[0] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
BTREE, 0, FROMBTREE(&rbyd_, scratch_buf));
|
BTREE, 0, FROMBTREE(&rbyd_, scratch_buf));
|
||||||
scratch_attrs[1] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
GROW, -rbyd.weight + rbyd_.weight, NULL);
|
GROW, -rbyd.weight + rbyd_.weight, NULL);
|
||||||
}
|
}
|
||||||
scratch_attrs[2] = LFSR_ATTR(bid+rid - rbyd.weight + rbyd_.weight + 1,
|
*attrs_++ = LFSR_ATTR(bid+rid - rbyd.weight + rbyd_.weight + 1,
|
||||||
BTREE, +sibling.weight, FROMBTREE(&sibling, scratch_buf_));
|
BTREE, +sibling.weight, FROMBTREE(&sibling, scratch_buf_));
|
||||||
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
|
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
|
||||||
scratch_attrs[3] = LFSR_ATTR(
|
*attrs_++ = LFSR_ATTR(
|
||||||
bid+rid - rbyd.weight + rbyd_.weight + sibling.weight,
|
bid+rid - rbyd.weight + rbyd_.weight + sibling.weight,
|
||||||
BRANCH, 0, DATA(split_data));
|
BRANCH, 0, DATA(split_data));
|
||||||
} else {
|
|
||||||
scratch_attrs[3] = LFSR_ATTR_NOOP;
|
|
||||||
}
|
}
|
||||||
attrs = scratch_attrs;
|
attrs = scratch_attrs;
|
||||||
attr_count = 4;
|
attr_count = attrs_ - scratch_attrs;
|
||||||
|
|
||||||
rbyd = parent;
|
rbyd = parent;
|
||||||
continue;
|
continue;
|
||||||
@@ -4444,14 +4441,15 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
// prepare commit to parent, tail recursing upwards
|
// prepare commit to parent, tail recursing upwards
|
||||||
bid -= rid - (rbyd.weight-1);
|
bid -= rid - (rbyd.weight-1);
|
||||||
LFS_ASSERT(rbyd_.weight > 0);
|
LFS_ASSERT(rbyd_.weight > 0);
|
||||||
scratch_attrs[0] = LFSR_ATTR(bid+rid+sibling.weight,
|
attrs_ = scratch_attrs;
|
||||||
|
*attrs_++ = LFSR_ATTR(bid+rid+sibling.weight,
|
||||||
RM, -sibling.weight, NULL);
|
RM, -sibling.weight, NULL);
|
||||||
scratch_attrs[1] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
BTREE, 0, FROMBTREE(&rbyd_, scratch_buf));
|
BTREE, 0, FROMBTREE(&rbyd_, scratch_buf));
|
||||||
scratch_attrs[2] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
GROW, -rbyd.weight + rbyd_.weight, NULL);
|
GROW, -rbyd.weight + rbyd_.weight, NULL);
|
||||||
attrs = scratch_attrs;
|
attrs = scratch_attrs;
|
||||||
attr_count = 3;
|
attr_count = attrs_ - scratch_attrs;
|
||||||
|
|
||||||
rbyd = parent;
|
rbyd = parent;
|
||||||
continue;
|
continue;
|
||||||
@@ -4476,19 +4474,18 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
// note that since we defer merges to compaction time, we can
|
// note that since we defer merges to compaction time, we can
|
||||||
// end up removing an rbyd here
|
// end up removing an rbyd here
|
||||||
bid -= rid - (rbyd.weight-1);
|
bid -= rid - (rbyd.weight-1);
|
||||||
|
attrs_ = scratch_attrs;
|
||||||
if (rbyd_.weight == 0) {
|
if (rbyd_.weight == 0) {
|
||||||
scratch_attrs[0] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
RM, -rbyd.weight, NULL);
|
RM, -rbyd.weight, NULL);
|
||||||
attrs = scratch_attrs;
|
|
||||||
attr_count = 1;
|
|
||||||
} else {
|
} else {
|
||||||
scratch_attrs[0] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
BTREE, 0, FROMBTREE(&rbyd_, scratch_buf));
|
BTREE, 0, FROMBTREE(&rbyd_, scratch_buf));
|
||||||
scratch_attrs[1] = LFSR_ATTR(bid+rid,
|
*attrs_++ = LFSR_ATTR(bid+rid,
|
||||||
GROW, -rbyd.weight + rbyd_.weight, NULL);
|
GROW, -rbyd.weight + rbyd_.weight, NULL);
|
||||||
attrs = scratch_attrs;
|
|
||||||
attr_count = 2;
|
|
||||||
}
|
}
|
||||||
|
attrs = scratch_attrs;
|
||||||
|
attr_count = attrs_ - scratch_attrs;
|
||||||
|
|
||||||
rbyd = parent;
|
rbyd = parent;
|
||||||
}
|
}
|
||||||
@@ -8371,42 +8368,50 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
|
static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
|
||||||
while (file->buffer_size > 0) {
|
while (file->buffer_size > 0) {
|
||||||
// figure out how to flush
|
// figure out how to flush
|
||||||
lfsr_attr_t hole_attr = LFSR_ATTR_NOOP;
|
lfsr_attr_t scratch_attrs[5];
|
||||||
|
lfsr_attr_t *attrs_ = scratch_attrs;
|
||||||
|
|
||||||
lfs_off_t pos = file->buffer_pos;
|
lfs_off_t pos = file->buffer_pos;
|
||||||
lfs_off_t weight = file->buffer_size;
|
lfs_off_t weight = 0;
|
||||||
lfsr_data_t datas[3] = {
|
lfsr_data_t scratch_datas[3];
|
||||||
LFSR_DATA_NULL,
|
lfsr_data_t *datas_ = scratch_datas;
|
||||||
LFSR_DATA_BUF(file->buffer, file->buffer_size),
|
|
||||||
LFSR_DATA_NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
// have inlined data?
|
// have inlined data?
|
||||||
if (!lfsr_file_hasshrub(file)) {
|
if (!lfsr_file_hasshrub(file)) {
|
||||||
// merge/carve inlined data and our buffer?
|
// need a hole?
|
||||||
if (lfsr_data_size(&file->inlined.u.data) >= file->buffer_pos) {
|
if (file->buffer_pos > lfsr_data_size(&file->inlined.u.data)) {
|
||||||
pos = 0;
|
*attrs_++ = LFSR_ATTR(0,
|
||||||
weight = lfs_max32(
|
|
||||||
file->buffer_pos + file->buffer_size,
|
|
||||||
lfsr_data_size(&file->inlined.u.data));
|
|
||||||
datas[0] = LFSR_DATA_DISK(
|
|
||||||
file->inlined.u.data.u.disk.block,
|
|
||||||
file->inlined.u.data.u.disk.off,
|
|
||||||
lfs_min32(
|
|
||||||
lfsr_data_size(&file->inlined.u.data),
|
|
||||||
file->buffer_pos));
|
|
||||||
datas[2] = LFSR_DATA_DISK(
|
|
||||||
file->inlined.u.data.u.disk.block,
|
|
||||||
file->inlined.u.data.u.disk.off
|
|
||||||
+ file->buffer_pos + file->buffer_size,
|
|
||||||
lfsr_data_size(&file->inlined.u.data) - lfs_min32(
|
|
||||||
file->buffer_pos + file->buffer_size,
|
|
||||||
lfsr_data_size(&file->inlined.u.data)));
|
|
||||||
|
|
||||||
// we can't merge if we have a hole, create two-leaf shrub
|
|
||||||
} else {
|
|
||||||
hole_attr = LFSR_ATTR(0,
|
|
||||||
SHRUB(INLINED), +file->buffer_pos, DATA(
|
SHRUB(INLINED), +file->buffer_pos, DATA(
|
||||||
file->inlined.u.data));
|
file->inlined.u.data));
|
||||||
|
|
||||||
|
// left data?
|
||||||
|
} else if (file->buffer_pos > 0) {
|
||||||
|
lfs_size_t left_size = file->buffer_pos;
|
||||||
|
pos = 0;
|
||||||
|
weight += left_size;
|
||||||
|
*datas_++ = LFSR_DATA_DISK(
|
||||||
|
file->inlined.u.data.u.disk.block,
|
||||||
|
file->inlined.u.data.u.disk.off,
|
||||||
|
left_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffer data?
|
||||||
|
*datas_++ = LFSR_DATA_BUF(file->buffer, file->buffer_size);
|
||||||
|
weight += file->buffer_size;
|
||||||
|
|
||||||
|
// right data?
|
||||||
|
if (lfsr_data_size(&file->inlined.u.data)
|
||||||
|
> file->buffer_pos + file->buffer_size) {
|
||||||
|
lfs_size_t right_size
|
||||||
|
= lfsr_data_size(&file->inlined.u.data)
|
||||||
|
- (file->buffer_pos + file->buffer_size);
|
||||||
|
weight += right_size;
|
||||||
|
*datas_++ = LFSR_DATA_DISK(
|
||||||
|
file->inlined.u.data.u.disk.block,
|
||||||
|
file->inlined.u.data.u.disk.off
|
||||||
|
+ lfsr_data_size(&file->inlined.u.data)
|
||||||
|
- right_size,
|
||||||
|
right_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// have a shrub?
|
// have a shrub?
|
||||||
@@ -8415,171 +8420,118 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
// should revert to an inlined file
|
// should revert to an inlined file
|
||||||
LFS_ASSERT(file->inlined.u.rbyd.weight > 0);
|
LFS_ASSERT(file->inlined.u.rbyd.weight > 0);
|
||||||
|
|
||||||
// find left sibling
|
// left sibling?
|
||||||
lfsr_srid_t left_rid;
|
if (file->buffer_pos > 0) {
|
||||||
lfsr_tag_t left_tag;
|
lfsr_srid_t left_rid;
|
||||||
lfsr_rid_t left_weight;
|
lfsr_tag_t left_tag;
|
||||||
lfsr_data_t left_data;
|
lfsr_rid_t left_weight;
|
||||||
int err = lfsr_rbyd_lookupnext(lfs, &file->inlined.u.rbyd,
|
lfsr_data_t left_data;
|
||||||
lfs_min32(
|
int err = lfsr_rbyd_lookupnext(lfs, &file->inlined.u.rbyd,
|
||||||
file->buffer_pos,
|
lfs_min32(
|
||||||
file->inlined.u.rbyd.weight)-1, 0,
|
file->buffer_pos,
|
||||||
&left_rid, &left_tag, &left_weight, &left_data);
|
file->inlined.u.rbyd.weight)-1, 0,
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
&left_rid, &left_tag, &left_weight, &left_data);
|
||||||
return err;
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
}
|
return err;
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
}
|
||||||
LFS_ASSERT(left_tag == LFSR_TAG_SHRUB(INLINED));
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
|
LFS_ASSERT(left_tag == LFSR_TAG_SHRUB(INLINED));
|
||||||
|
|
||||||
// left sibling overlaps? need to merge/carve
|
// need to grow/shrink a hole?
|
||||||
// left sibling touches? only merge if we won't end up
|
if (file->buffer_pos != (lfs_off_t)left_rid+1
|
||||||
// carving later
|
&& file->buffer_pos
|
||||||
lfs_soff_t left_overlap
|
>= left_rid-(left_weight-1)
|
||||||
= (left_rid-(left_weight-1) + lfsr_data_size(&left_data))
|
+ lfsr_data_size(&left_data)) {
|
||||||
- file->buffer_pos;
|
*attrs_++ = LFSR_ATTR(left_rid,
|
||||||
if (left_overlap > 0
|
GROW, +file->buffer_pos - (left_rid+1), NULL);
|
||||||
|| (left_overlap == 0
|
|
||||||
&& weight + lfsr_data_size(&left_data)
|
// left data?
|
||||||
<= lfs->cfg->coalesce_size)) {
|
} else if (file->buffer_pos
|
||||||
pos = left_rid - (left_weight-1);
|
< left_rid-(left_weight-1)
|
||||||
weight += file->buffer_pos - pos;
|
+ lfsr_data_size(&left_data)) {
|
||||||
datas[0] = LFSR_DATA_DISK(
|
lfs_size_t left_size
|
||||||
left_data.u.disk.block,
|
= file->buffer_pos
|
||||||
left_data.u.disk.off,
|
- (left_rid-(left_weight-1));
|
||||||
file->buffer_pos - pos);
|
pos = left_rid-(left_weight-1);
|
||||||
} else {
|
weight += left_size;
|
||||||
// need a hole?
|
*datas_++ = LFSR_DATA_DISK(
|
||||||
if (left_overlap < 0) {
|
left_data.u.disk.block,
|
||||||
hole_attr = LFSR_ATTR(left_rid, GROW, -left_overlap, NULL);
|
left_data.u.disk.off,
|
||||||
|
left_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// find right sibling
|
// buffer data?
|
||||||
lfsr_srid_t right_rid;
|
*datas_++ = LFSR_DATA_BUF(file->buffer, file->buffer_size);
|
||||||
lfsr_tag_t right_tag;
|
weight += file->buffer_size;
|
||||||
lfsr_rid_t right_weight;
|
|
||||||
lfsr_data_t right_data;
|
|
||||||
err = lfsr_rbyd_lookupnext(lfs, &file->inlined.u.rbyd,
|
|
||||||
file->buffer_pos + file->buffer_size, 0,
|
|
||||||
&right_rid, &right_tag, &right_weight, &right_data);
|
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
LFS_ASSERT(err == LFS_ERR_NOENT
|
|
||||||
|| right_tag == LFSR_TAG_SHRUB(INLINED));
|
|
||||||
|
|
||||||
if (err != LFS_ERR_NOENT) {
|
// right sibling?
|
||||||
// right sibling overlaps? need to merge/carve
|
if (file->buffer_pos + file->buffer_size
|
||||||
// right sibling touches? only merge if we won't end up
|
< (lfs_off_t)file->inlined.u.rbyd.weight) {
|
||||||
// carving later
|
lfsr_srid_t right_rid;
|
||||||
lfs_soff_t right_overlap
|
lfsr_tag_t right_tag;
|
||||||
= (file->buffer_pos + file->buffer_size)
|
lfsr_rid_t right_weight;
|
||||||
- (right_rid - (right_weight-1));
|
lfsr_data_t right_data;
|
||||||
LFS_ASSERT(right_overlap >= 0);
|
int err = lfsr_rbyd_lookupnext(lfs, &file->inlined.u.rbyd,
|
||||||
if (right_overlap > 0
|
file->buffer_pos + file->buffer_size, 0,
|
||||||
|| (right_overlap == 0
|
&right_rid, &right_tag, &right_weight, &right_data);
|
||||||
&& weight + lfsr_data_size(&right_data)
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
<= lfs->cfg->coalesce_size)) {
|
return err;
|
||||||
// note physical right data size risks going negative here
|
}
|
||||||
// because of holes
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
weight += right_weight - right_overlap;
|
LFS_ASSERT(right_tag == LFSR_TAG_SHRUB(INLINED));
|
||||||
datas[2] = LFSR_DATA_DISK(
|
|
||||||
|
// right data?
|
||||||
|
if (right_rid-(right_weight-1) + lfsr_data_size(&right_data)
|
||||||
|
> file->buffer_pos + file->buffer_size) {
|
||||||
|
lfs_size_t right_size
|
||||||
|
= (right_rid-(right_weight-1)
|
||||||
|
+ lfsr_data_size(&right_data))
|
||||||
|
- (file->buffer_pos + file->buffer_size);
|
||||||
|
*datas_++ = LFSR_DATA_DISK(
|
||||||
right_data.u.disk.block,
|
right_data.u.disk.block,
|
||||||
right_data.u.disk.off + right_overlap,
|
right_data.u.disk.off
|
||||||
lfsr_data_size(&right_data) - lfs_min32(
|
+ lfsr_data_size(&right_data)
|
||||||
right_overlap,
|
- right_size,
|
||||||
lfsr_data_size(&right_data)));
|
right_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// need to bring over a hole?
|
||||||
|
weight += right_rid+1 - (file->buffer_pos + file->buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure we remove any data we're overwriting
|
||||||
|
*attrs_++ = LFSR_ATTR(
|
||||||
|
lfs_min32(
|
||||||
|
pos + weight,
|
||||||
|
file->inlined.u.rbyd.weight)-1,
|
||||||
|
RM,
|
||||||
|
-(lfs_min32(
|
||||||
|
pos + weight,
|
||||||
|
file->inlined.u.rbyd.weight)
|
||||||
|
- pos),
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// can we coalesce any of our data?
|
// compile our data references into attributes
|
||||||
// TODO a better way to do this?
|
const lfsr_data_t *datas = scratch_datas;
|
||||||
lfsr_attr_t coalesce_attrs[3] = {
|
lfs_size_t data_count = datas_ - scratch_datas;
|
||||||
LFSR_ATTR_NOOP,
|
for (lfs_size_t i = 0; i < data_count; i++) {
|
||||||
LFSR_ATTR_NOOP,
|
*attrs_++ = LFSR_ATTR(pos,
|
||||||
LFSR_ATTR_NOOP,
|
// include the remaining weight if we are the last data
|
||||||
};
|
SHRUB(INLINED), +(i == data_count-1
|
||||||
if (lfsr_data_size(&datas[0])
|
? weight
|
||||||
+ lfsr_data_size(&datas[1])
|
: lfsr_data_size(&datas[i])),
|
||||||
+ lfsr_data_size(&datas[2])
|
DATA(datas[i]));
|
||||||
// make sure to never write null siblings, even when
|
pos += lfsr_data_size(&datas[i]);
|
||||||
// buffer > cache size
|
weight -= lfsr_data_size(&datas[i]);
|
||||||
<= lfs_max32(lfs->cfg->coalesce_size, file->buffer_size)) {
|
|
||||||
coalesce_attrs[0] = LFSR_ATTR(pos,
|
|
||||||
SHRUB(INLINED),
|
|
||||||
+weight,
|
|
||||||
DATA(lfsr_data_fromcat(datas, 3)));
|
|
||||||
} else if (lfsr_data_size(&datas[0])
|
|
||||||
+ lfsr_data_size(&datas[1])
|
|
||||||
// make sure to never write null siblings, even when
|
|
||||||
// buffer > cache size
|
|
||||||
<= lfs_max32(lfs->cfg->coalesce_size, file->buffer_size)) {
|
|
||||||
coalesce_attrs[0] = LFSR_ATTR(pos,
|
|
||||||
SHRUB(INLINED),
|
|
||||||
+lfsr_data_size(&datas[0])
|
|
||||||
+ lfsr_data_size(&datas[1]),
|
|
||||||
DATA(lfsr_data_fromcat(datas, 2)));
|
|
||||||
coalesce_attrs[1] = LFSR_ATTR(pos
|
|
||||||
+ lfsr_data_size(&datas[0])
|
|
||||||
+ lfsr_data_size(&datas[1]),
|
|
||||||
SHRUB(INLINED),
|
|
||||||
+weight
|
|
||||||
- lfsr_data_size(&datas[0])
|
|
||||||
- lfsr_data_size(&datas[1]),
|
|
||||||
DATA(datas[2]));
|
|
||||||
} else {
|
|
||||||
coalesce_attrs[0] = LFSR_ATTR(pos,
|
|
||||||
SHRUB(INLINED),
|
|
||||||
+lfsr_data_size(&datas[0]),
|
|
||||||
DATA(datas[0]));
|
|
||||||
if (lfsr_data_size(&datas[1])
|
|
||||||
+ lfsr_data_size(&datas[2])
|
|
||||||
// make sure to never write null siblings, even when
|
|
||||||
// buffer > cache size
|
|
||||||
<= lfs_max32(lfs->cfg->coalesce_size, file->buffer_size)) {
|
|
||||||
coalesce_attrs[1] = LFSR_ATTR(pos + lfsr_data_size(&datas[0]),
|
|
||||||
SHRUB(INLINED),
|
|
||||||
+weight - lfsr_data_size(&datas[0]),
|
|
||||||
DATA(lfsr_data_fromcat(datas + 1, 2)));
|
|
||||||
} else {
|
|
||||||
coalesce_attrs[1] = LFSR_ATTR(pos + lfsr_data_size(&datas[0]),
|
|
||||||
SHRUB(INLINED),
|
|
||||||
lfsr_data_size(&datas[1]),
|
|
||||||
DATA(datas[1]));
|
|
||||||
coalesce_attrs[2] = LFSR_ATTR(pos
|
|
||||||
+ lfsr_data_size(&datas[0])
|
|
||||||
+ lfsr_data_size(&datas[1]),
|
|
||||||
SHRUB(INLINED),
|
|
||||||
+weight
|
|
||||||
- lfsr_data_size(&datas[0])
|
|
||||||
- lfsr_data_size(&datas[1]),
|
|
||||||
DATA(datas[2]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit our attributes
|
// commit our attributes
|
||||||
int err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
|
int err = lfsr_mdir_commit(lfs, &file->m.mdir, LFSR_ATTRS(
|
||||||
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(file,
|
LFSR_ATTR_(file->m.mdir.mid, SHRUBATTRS, 0, SHRUBATTRS(file,
|
||||||
// adjust a hole?
|
scratch_attrs,
|
||||||
hole_attr,
|
attrs_ - scratch_attrs))));
|
||||||
// remove any data in the way
|
|
||||||
(lfsr_file_hasshrub(file)
|
|
||||||
? LFSR_ATTR(
|
|
||||||
lfs_min32(
|
|
||||||
pos + weight,
|
|
||||||
file->inlined.u.rbyd.weight)-1,
|
|
||||||
RM,
|
|
||||||
-(lfs_min32(
|
|
||||||
pos + weight,
|
|
||||||
file->inlined.u.rbyd.weight)
|
|
||||||
- pos),
|
|
||||||
NULL)
|
|
||||||
: LFSR_ATTR_NOOP),
|
|
||||||
// and then append our data
|
|
||||||
coalesce_attrs[0],
|
|
||||||
coalesce_attrs[1],
|
|
||||||
coalesce_attrs[2]))));
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user