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:
Christopher Haster
2023-09-24 16:33:03 -05:00
parent c2d33a1843
commit 0724b9a8c4
+78 -89
View File
@@ -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)); file->inlined.u.data.u.disk.block,
file->inlined.u.data.u.disk.off,
// left data? lfs_min32(
} else if (file->buffer_pos > 0) { lfsr_data_size(&file->inlined.u.data),
lfs_size_t left_size = file->buffer_pos; 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? // 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 + (file->buffer_pos + file->buffer_size),
+ lfsr_data_size(&file->inlined.u.data) lfsr_data_size(&file->inlined.u.data)
- right_size, - (file->buffer_pos + file->buffer_size)));
right_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_data.u.disk.block,
- (left_rid-(left_weight-1)); left_data.u.disk.off,
pos = left_rid-(left_weight-1); lfsr_data_size(&left_data) - left_overlap));
weight += left_size;
*datas_++ = LFSR_DATA_DISK(
left_data.u.disk.block,
left_data.u.disk.off,
left_size);
} }
} }
// 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)
+ lfsr_data_size(&right_data))
- (file->buffer_pos + file->buffer_size);
*datas_++ = LFSR_DATA_DISK(
right_data.u.disk.block,
right_data.u.disk.off
+ lfsr_data_size(&right_data)
- right_size,
right_size);
}
// need to bring over a hole? // need to carve out right data?
weight += right_rid+1 - (file->buffer_pos + file->buffer_size); if (right_overlap > 0) {
right_data = LFSR_DATA_DISK(
right_data.u.disk.block,
right_data.u.disk.off + right_overlap,
lfsr_data_size(&right_data) - lfs_min32(
right_overlap,
lfsr_data_size(&right_data)));
right_weight -= right_overlap;
}
} }
// make sure we remove any data we're overwriting // remove any data we're overwriting, note we need to account for
// left_sibling changes
*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