Really revamped flushbuffer, now leveraging overwriting grow tags
I had completely forgotten about overwriting grow tags, that is tags that both change the attr's weight while also changing the tag itself.
This commit is contained in:
@@ -8368,50 +8368,40 @@ 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 scratch_attrs[5];
|
lfsr_attr_t scratch_attrs[4];
|
||||||
lfsr_attr_t *attrs_ = scratch_attrs;
|
lfsr_attr_t *attrs_ = scratch_attrs;
|
||||||
|
|
||||||
lfs_off_t pos = file->buffer_pos;
|
|
||||||
lfs_off_t weight = 0;
|
|
||||||
lfsr_data_t scratch_datas[3];
|
|
||||||
lfsr_data_t *datas_ = scratch_datas;
|
|
||||||
|
|
||||||
// have inlined data?
|
// have inlined data?
|
||||||
if (!lfsr_file_hasshrub(file)) {
|
if (!lfsr_file_hasshrub(file)) {
|
||||||
// need a hole?
|
// left data? this may create a hole
|
||||||
if (file->buffer_pos > lfsr_data_size(&file->inlined.u.data)) {
|
if (file->buffer_pos > 0) {
|
||||||
*attrs_++ = LFSR_ATTR(0,
|
*attrs_++ = LFSR_ATTR(0,
|
||||||
SHRUB(INLINED), +file->buffer_pos, DATA(
|
SHRUB(INLINED), +file->buffer_pos, DISK(
|
||||||
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.block,
|
||||||
file->inlined.u.data.u.disk.off,
|
file->inlined.u.data.u.disk.off,
|
||||||
left_size);
|
lfs_min32(
|
||||||
|
lfsr_data_size(&file->inlined.u.data),
|
||||||
|
file->buffer_pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffer data?
|
// append our buffer
|
||||||
*datas_++ = LFSR_DATA_BUF(file->buffer, file->buffer_size);
|
*attrs_++ = LFSR_ATTR(file->buffer_pos,
|
||||||
weight += file->buffer_size;
|
SHRUB(INLINED), +file->buffer_size, BUF(
|
||||||
|
file->buffer, file->buffer_size));
|
||||||
|
|
||||||
// right data?
|
// right data?
|
||||||
if (lfsr_data_size(&file->inlined.u.data)
|
if (lfsr_data_size(&file->inlined.u.data)
|
||||||
> file->buffer_pos + file->buffer_size) {
|
> file->buffer_pos + file->buffer_size) {
|
||||||
lfs_size_t right_size
|
*attrs_++ = LFSR_ATTR(file->buffer_pos + file->buffer_size,
|
||||||
= lfsr_data_size(&file->inlined.u.data)
|
SHRUB(INLINED), +lfsr_data_size(&file->inlined.u.data)
|
||||||
- (file->buffer_pos + file->buffer_size);
|
- (file->buffer_pos + file->buffer_size),
|
||||||
weight += right_size;
|
DISK(
|
||||||
*datas_++ = LFSR_DATA_DISK(
|
|
||||||
file->inlined.u.data.u.disk.block,
|
file->inlined.u.data.u.disk.block,
|
||||||
file->inlined.u.data.u.disk.off
|
file->inlined.u.data.u.disk.off
|
||||||
+ lfsr_data_size(&file->inlined.u.data)
|
+ (file->buffer_pos + file->buffer_size),
|
||||||
- right_size,
|
lfsr_data_size(&file->inlined.u.data)
|
||||||
right_size);
|
- (file->buffer_pos + file->buffer_size)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// have a shrub?
|
// have a shrub?
|
||||||
@@ -8421,6 +8411,7 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
LFS_ASSERT(file->inlined.u.rbyd.weight > 0);
|
LFS_ASSERT(file->inlined.u.rbyd.weight > 0);
|
||||||
|
|
||||||
// left sibling?
|
// left sibling?
|
||||||
|
lfs_soff_t left_overlap = 0;
|
||||||
if (file->buffer_pos > 0) {
|
if (file->buffer_pos > 0) {
|
||||||
lfsr_srid_t left_rid;
|
lfsr_srid_t left_rid;
|
||||||
lfsr_tag_t left_tag;
|
lfsr_tag_t left_tag;
|
||||||
@@ -8437,41 +8428,38 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
LFS_ASSERT(left_tag == LFSR_TAG_SHRUB(INLINED));
|
LFS_ASSERT(left_tag == LFSR_TAG_SHRUB(INLINED));
|
||||||
|
|
||||||
// need to grow/shrink a hole?
|
// this can be negative!
|
||||||
if (file->buffer_pos != (lfs_off_t)left_rid+1
|
left_overlap = (left_rid+1) - file->buffer_pos;
|
||||||
|
|
||||||
|
// can we get away with a simple grow attr? this may
|
||||||
|
// create a hole
|
||||||
|
if (left_overlap != 0
|
||||||
&& file->buffer_pos
|
&& file->buffer_pos
|
||||||
>= left_rid-(left_weight-1)
|
>= left_rid-(left_weight-1)
|
||||||
+ lfsr_data_size(&left_data)) {
|
+ lfsr_data_size(&left_data)) {
|
||||||
*attrs_++ = LFSR_ATTR(left_rid,
|
*attrs_++ = LFSR_ATTR(left_rid, GROW, -left_overlap, NULL);
|
||||||
GROW, +file->buffer_pos - (left_rid+1), NULL);
|
|
||||||
|
|
||||||
// left data?
|
// need to carve out left data?
|
||||||
} else if (file->buffer_pos
|
} else if (left_overlap > 0) {
|
||||||
< left_rid-(left_weight-1)
|
*attrs_++ = LFSR_ATTR(left_rid,
|
||||||
+ lfsr_data_size(&left_data)) {
|
GROW(SHRUB(INLINED)), -left_overlap,
|
||||||
lfs_size_t left_size
|
DISK(
|
||||||
= file->buffer_pos
|
|
||||||
- (left_rid-(left_weight-1));
|
|
||||||
pos = left_rid-(left_weight-1);
|
|
||||||
weight += left_size;
|
|
||||||
*datas_++ = LFSR_DATA_DISK(
|
|
||||||
left_data.u.disk.block,
|
left_data.u.disk.block,
|
||||||
left_data.u.disk.off,
|
left_data.u.disk.off,
|
||||||
left_size);
|
lfsr_data_size(&left_data) - left_overlap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffer data?
|
|
||||||
*datas_++ = LFSR_DATA_BUF(file->buffer, file->buffer_size);
|
|
||||||
weight += file->buffer_size;
|
|
||||||
|
|
||||||
// right sibling?
|
// right sibling?
|
||||||
|
//
|
||||||
|
// this gets messy, keep in mind right sibling can be the same
|
||||||
|
// attr as the left sibling
|
||||||
|
lfsr_rid_t right_weight = 0;
|
||||||
|
lfsr_data_t right_data = LFSR_DATA_NULL;
|
||||||
if (file->buffer_pos + file->buffer_size
|
if (file->buffer_pos + file->buffer_size
|
||||||
< (lfs_off_t)file->inlined.u.rbyd.weight) {
|
< (lfs_off_t)file->inlined.u.rbyd.weight) {
|
||||||
lfsr_srid_t right_rid;
|
lfsr_srid_t right_rid;
|
||||||
lfsr_tag_t right_tag;
|
lfsr_tag_t right_tag;
|
||||||
lfsr_rid_t right_weight;
|
|
||||||
lfsr_data_t right_data;
|
|
||||||
int err = lfsr_rbyd_lookupnext(lfs, &file->inlined.u.rbyd,
|
int err = lfsr_rbyd_lookupnext(lfs, &file->inlined.u.rbyd,
|
||||||
file->buffer_pos + file->buffer_size, 0,
|
file->buffer_pos + file->buffer_size, 0,
|
||||||
&right_rid, &right_tag, &right_weight, &right_data);
|
&right_rid, &right_tag, &right_weight, &right_data);
|
||||||
@@ -8481,50 +8469,51 @@ static int lfsr_file_flushbuffer(lfs_t *lfs, lfsr_file_t *file) {
|
|||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
LFS_ASSERT(right_tag == LFSR_TAG_SHRUB(INLINED));
|
LFS_ASSERT(right_tag == LFSR_TAG_SHRUB(INLINED));
|
||||||
|
|
||||||
// right data?
|
lfs_soff_t right_overlap
|
||||||
if (right_rid-(right_weight-1) + lfsr_data_size(&right_data)
|
= file->buffer_pos + file->buffer_size
|
||||||
> file->buffer_pos + file->buffer_size) {
|
- (right_rid-(right_weight-1));
|
||||||
lfs_size_t right_size
|
|
||||||
= (right_rid-(right_weight-1)
|
// need to carve out right data?
|
||||||
+ lfsr_data_size(&right_data))
|
if (right_overlap > 0) {
|
||||||
- (file->buffer_pos + file->buffer_size);
|
right_data = LFSR_DATA_DISK(
|
||||||
*datas_++ = LFSR_DATA_DISK(
|
|
||||||
right_data.u.disk.block,
|
right_data.u.disk.block,
|
||||||
right_data.u.disk.off
|
right_data.u.disk.off + right_overlap,
|
||||||
+ lfsr_data_size(&right_data)
|
lfsr_data_size(&right_data) - lfs_min32(
|
||||||
- right_size,
|
right_overlap,
|
||||||
right_size);
|
lfsr_data_size(&right_data)));
|
||||||
|
right_weight -= right_overlap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to bring over a hole?
|
// remove any data we're overwriting, note we need to account for
|
||||||
weight += right_rid+1 - (file->buffer_pos + file->buffer_size);
|
// left_sibling changes
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we remove any data we're overwriting
|
|
||||||
*attrs_++ = LFSR_ATTR(
|
*attrs_++ = LFSR_ATTR(
|
||||||
lfs_min32(
|
lfs_min32(
|
||||||
pos + weight,
|
file->buffer_pos + file->buffer_size
|
||||||
|
+ right_weight - left_overlap,
|
||||||
file->inlined.u.rbyd.weight)-1,
|
file->inlined.u.rbyd.weight)-1,
|
||||||
RM,
|
RM,
|
||||||
-(lfs_min32(
|
-(lfs_min32(
|
||||||
pos + weight,
|
file->buffer_pos + file->buffer_size
|
||||||
|
+ right_weight - left_overlap,
|
||||||
file->inlined.u.rbyd.weight)
|
file->inlined.u.rbyd.weight)
|
||||||
- pos),
|
- file->buffer_pos),
|
||||||
NULL);
|
NULL);
|
||||||
}
|
|
||||||
|
|
||||||
// compile our data references into attributes
|
if (lfsr_data_size(&right_data) == 0) {
|
||||||
const lfsr_data_t *datas = scratch_datas;
|
// append our buffer with any remaining weight
|
||||||
lfs_size_t data_count = datas_ - scratch_datas;
|
*attrs_++ = LFSR_ATTR(file->buffer_pos,
|
||||||
for (lfs_size_t i = 0; i < data_count; i++) {
|
SHRUB(INLINED), +file->buffer_size + right_weight, BUF(
|
||||||
*attrs_++ = LFSR_ATTR(pos,
|
file->buffer, file->buffer_size));
|
||||||
// include the remaining weight if we are the last data
|
} else {
|
||||||
SHRUB(INLINED), +(i == data_count-1
|
// append our buffer
|
||||||
? weight
|
*attrs_++ = LFSR_ATTR(file->buffer_pos,
|
||||||
: lfsr_data_size(&datas[i])),
|
SHRUB(INLINED), +file->buffer_size, BUF(
|
||||||
DATA(datas[i]));
|
file->buffer, file->buffer_size));
|
||||||
pos += lfsr_data_size(&datas[i]);
|
// and any right data
|
||||||
weight -= lfsr_data_size(&datas[i]);
|
*attrs_++ = LFSR_ATTR(file->buffer_pos + file->buffer_size,
|
||||||
|
SHRUB(INLINED), +right_weight, DATA(right_data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// commit our attributes
|
// commit our attributes
|
||||||
|
|||||||
Reference in New Issue
Block a user