Flipped btree encoding to allow variable redund blocks
This should have been done as a part of the earlier tag reencoding work,
since having the block at the end was what allowed us to move the
redund-count out of the tag encoding.
New encoding:
[-- 32-bit csum --]
[-- leb128 weight --]
[-- leb128 trunk --]
[-- leb128 block --]
Note that since our tags have an explicit size, we can store a variable
number of blocks. The plan is to use this to eventually store redundant
copies for error correction:
[-- 32-bit csum --]
[-- leb128 weight --]
[-- leb128 trunk --]
[-- leb128 block --] -.
[-- leb128 block --] +- n redundant blocks
[-- leb128 block --] |
... -'
This does have a significant tradeoff, we need to know the checksum size
to access the btree structure. This doesn't seem like a big deal, but
with the possibility of different checksum types may be an annoying
issue.
Note that FCRC was also flipped for consistency.
This commit is contained in:
@@ -1338,8 +1338,8 @@ typedef struct lfsr_attr {
|
|||||||
|
|
||||||
// fcrc on-disk encoding
|
// fcrc on-disk encoding
|
||||||
typedef struct lfsr_fcrc {
|
typedef struct lfsr_fcrc {
|
||||||
lfs_size_t size;
|
|
||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
|
lfs_size_t size;
|
||||||
} lfsr_fcrc_t;
|
} lfsr_fcrc_t;
|
||||||
|
|
||||||
// 1 leb128 + 1 crc32c => 9 bytes (worst case)
|
// 1 leb128 + 1 crc32c => 9 bytes (worst case)
|
||||||
@@ -1349,28 +1349,29 @@ static lfs_ssize_t lfsr_fcrc_todisk(lfs_t *lfs, const lfsr_fcrc_t *fcrc,
|
|||||||
uint8_t buffer[static LFSR_FCRC_DSIZE]) {
|
uint8_t buffer[static LFSR_FCRC_DSIZE]) {
|
||||||
(void)lfs;
|
(void)lfs;
|
||||||
lfs_ssize_t d = 0;
|
lfs_ssize_t d = 0;
|
||||||
lfs_ssize_t d_ = lfs_toleb128(fcrc->size, &buffer[0], 5);
|
|
||||||
|
lfs_tole32_(fcrc->crc, &buffer[d]);
|
||||||
|
d += 4;
|
||||||
|
|
||||||
|
lfs_ssize_t d_ = lfs_toleb128(fcrc->size, &buffer[d], 5);
|
||||||
if (d_ < 0) {
|
if (d_ < 0) {
|
||||||
return d_;
|
return d_;
|
||||||
}
|
}
|
||||||
d += d_;
|
d += d_;
|
||||||
|
|
||||||
lfs_tole32_(fcrc->crc, &buffer[d]);
|
|
||||||
d += 4;
|
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lfs_ssize_t lfsr_fcrc_fromdisk(lfs_t *lfs, lfsr_fcrc_t *fcrc,
|
static lfs_ssize_t lfsr_fcrc_fromdisk(lfs_t *lfs, lfsr_fcrc_t *fcrc,
|
||||||
lfsr_data_t data) {
|
lfsr_data_t data) {
|
||||||
lfs_ssize_t d = 0;
|
lfs_ssize_t d = 0;
|
||||||
lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &fcrc->size);
|
lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &fcrc->crc);
|
||||||
if (d_ < 0) {
|
if (d_ < 0) {
|
||||||
return d_;
|
return d_;
|
||||||
}
|
}
|
||||||
d += d_;
|
d += d_;
|
||||||
|
|
||||||
d_ = lfsr_data_readle32(lfs, data, d, &fcrc->crc);
|
d_ = lfsr_data_readleb128(lfs, data, d, &fcrc->size);
|
||||||
if (d_ < 0) {
|
if (d_ < 0) {
|
||||||
return d_;
|
return d_;
|
||||||
}
|
}
|
||||||
@@ -2650,7 +2651,7 @@ static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
|
|
||||||
// find the expected fcrc, don't bother avoiding a reread of the
|
// find the expected fcrc, don't bother avoiding a reread of the
|
||||||
// perturb byte, as it should still be in our cache
|
// perturb byte, as it should still be in our cache
|
||||||
lfsr_fcrc_t fcrc = {.size=lfs->cfg->prog_size, .crc=0};
|
lfsr_fcrc_t fcrc = {.crc=0, .size=lfs->cfg->prog_size};
|
||||||
err = lfsr_bd_csum(lfs, rbyd_.block, aligned, lfs->cfg->prog_size,
|
err = lfsr_bd_csum(lfs, rbyd_.block, aligned, lfs->cfg->prog_size,
|
||||||
lfs->cfg->prog_size,
|
lfs->cfg->prog_size,
|
||||||
&fcrc.crc);
|
&fcrc.crc);
|
||||||
@@ -3042,13 +3043,17 @@ static inline lfs_size_t lfsr_btree_setinlined(lfs_size_t weight) {
|
|||||||
|
|
||||||
// branch on-disk encoding
|
// branch on-disk encoding
|
||||||
|
|
||||||
// 3 leb128 + 1 crc32c => 19 bytes (worst case)
|
// 1 crc32c + 3 leb128 => 19 bytes (worst case)
|
||||||
#define LFSR_BRANCH_DSIZE (5+5+5+4)
|
#define LFSR_BRANCH_DSIZE (4+5+5+5)
|
||||||
|
|
||||||
static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
|
static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
|
||||||
uint8_t buffer[static LFSR_BRANCH_DSIZE]) {
|
uint8_t buffer[static LFSR_BRANCH_DSIZE]) {
|
||||||
(void)lfs;
|
(void)lfs;
|
||||||
lfs_ssize_t d = 0;
|
lfs_ssize_t d = 0;
|
||||||
|
|
||||||
|
lfs_tole32_(branch->crc, &buffer[d]);
|
||||||
|
d += 4;
|
||||||
|
|
||||||
lfs_ssize_t d_ = lfs_toleb128(branch->weight, &buffer[d], 5);
|
lfs_ssize_t d_ = lfs_toleb128(branch->weight, &buffer[d], 5);
|
||||||
if (d_ < 0) {
|
if (d_ < 0) {
|
||||||
return d_;
|
return d_;
|
||||||
@@ -3067,9 +3072,6 @@ static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch,
|
|||||||
}
|
}
|
||||||
d += d_;
|
d += d_;
|
||||||
|
|
||||||
lfs_tole32_(branch->crc, &buffer[d]);
|
|
||||||
d += 4;
|
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3080,7 +3082,13 @@ static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch,
|
|||||||
branch->off = 0;
|
branch->off = 0;
|
||||||
|
|
||||||
lfs_ssize_t d = 0;
|
lfs_ssize_t d = 0;
|
||||||
lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &branch->weight);
|
lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &branch->crc);
|
||||||
|
if (d_ < 0) {
|
||||||
|
return d_;
|
||||||
|
}
|
||||||
|
d += d_;
|
||||||
|
|
||||||
|
d_ = lfsr_data_readleb128(lfs, data, d, &branch->weight);
|
||||||
if (d_ < 0) {
|
if (d_ < 0) {
|
||||||
return d_;
|
return d_;
|
||||||
}
|
}
|
||||||
@@ -3098,12 +3106,6 @@ static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch,
|
|||||||
}
|
}
|
||||||
d += d_;
|
d += d_;
|
||||||
|
|
||||||
d_ = lfsr_data_readle32(lfs, data, d, &branch->crc);
|
|
||||||
if (d_ < 0) {
|
|
||||||
return d_;
|
|
||||||
}
|
|
||||||
d += d_;
|
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -93,10 +93,10 @@ def fromtag(data):
|
|||||||
return tag>>15, tag&0x7fff, weight, size, 2+d+d_
|
return tag>>15, tag&0x7fff, weight, size, 2+d+d_
|
||||||
|
|
||||||
def frombtree(data):
|
def frombtree(data):
|
||||||
w, d1 = fromleb128(data)
|
crc = fromle32(data)
|
||||||
trunk, d2 = fromleb128(data[d1:])
|
w, d1 = fromleb128(data[4:])
|
||||||
block, d3 = fromleb128(data[d1+d2:])
|
trunk, d2 = fromleb128(data[4+d1:])
|
||||||
crc = fromle32(data[d1+d2+d3:])
|
block, d3 = fromleb128(data[4+d1+d2:])
|
||||||
return w, trunk, block, crc
|
return w, trunk, block, crc
|
||||||
|
|
||||||
def popc(x):
|
def popc(x):
|
||||||
|
|||||||
+4
-4
@@ -102,10 +102,10 @@ def frommdir(data):
|
|||||||
return blocks
|
return blocks
|
||||||
|
|
||||||
def frombtree(data):
|
def frombtree(data):
|
||||||
w, d1 = fromleb128(data)
|
crc = fromle32(data)
|
||||||
trunk, d2 = fromleb128(data[d1:])
|
w, d1 = fromleb128(data[4:])
|
||||||
block, d3 = fromleb128(data[d1+d2:])
|
trunk, d2 = fromleb128(data[4+d1:])
|
||||||
crc = fromle32(data[d1+d2+d3:])
|
block, d3 = fromleb128(data[4+d1+d2:])
|
||||||
return w, trunk, block, crc
|
return w, trunk, block, crc
|
||||||
|
|
||||||
def popc(x):
|
def popc(x):
|
||||||
|
|||||||
Reference in New Issue
Block a user