Reworked ftree/bshrub/shrub relationship, staging in ftree now
This is an attempt to simplify things a bit by moving more logic into
the ftree layer, instead of spreading things around between the
bshrub/bsprout functions.
Now, functionality is organized into high-level ftree operations and
low-level shrub/sprout operations, which only care about the inlined
portion of the shrub/sprout. No more lfsr_bshrub_commit/
lfsr_bshrub_commit__ which were mostly unrelated.
This also adds a lfsr_shrub_t type, which, by taking advantage of the
unused write-related rbyd fields to store the shrub estimate, has the
same size as lfsr_rbyd_t, but can still be casted to an rbyd/btree for
use in readonly rbyd/btree functions.
I considered merging shrub/sprout esimate and shrub/sprout compact into
some sort of ftree_estimate/compact, but it's not obvious what the
benefit would be, so leaving that on the table for now.
---
One nice change is our staging copies are now at the ftree level
(ftree.u and ftree.u_, maybe not the best names, but this is what I've
been using for unions where the name doesn't really matter, god I want
unnamed unions). This simplifies staging, and avoids staging issues
where the underlying type changes.
---
A bit unrelated, but necessary to integrate lfsr_ftree_traverse, a
generalized lfsr_tinfo_t type for all traversal functions was added
(adopted from lfsr_traversal_t really). This is a straightforward tagged
union with relevant traversal types.
The benefit of a generalized tinfo type is better chance we can just
pass the tinfo pointer through multiple layers.
Code changes:
code stack
before: 33368 2984
after: 33260 (-0.3%) 3024 (+1.3%)
This commit is contained in:
@@ -375,6 +375,7 @@ typedef struct lfsr_rbyd {
|
||||
uint32_t cksum;
|
||||
} lfsr_rbyd_t;
|
||||
|
||||
// a btree is just the root rbyd
|
||||
typedef lfsr_rbyd_t lfsr_btree_t;
|
||||
|
||||
typedef struct lfsr_mptr {
|
||||
@@ -456,13 +457,6 @@ typedef struct lfsr_data {
|
||||
} u;
|
||||
} lfsr_data_t;
|
||||
|
||||
typedef struct lfsr_bptr {
|
||||
// note data.size lines up with weight in lfsr_btree_t
|
||||
lfsr_data_t data;
|
||||
lfs_size_t cksize;
|
||||
uint32_t cksum;
|
||||
} lfsr_bptr_t;
|
||||
|
||||
// erased-state checksum
|
||||
typedef struct lfsr_ecksum {
|
||||
// size=-1 indicates no ecksum
|
||||
@@ -510,12 +504,12 @@ typedef struct lfs_file {
|
||||
const struct lfs_file_config *cfg;
|
||||
} lfs_file_t;
|
||||
|
||||
// bsprouts must always be associated with an mdir
|
||||
typedef struct lfsr_bsprout {
|
||||
typedef struct lfsr_bptr {
|
||||
// note data.size lines up with weight in lfsr_btree_t
|
||||
lfsr_data_t data;
|
||||
// copy for staging
|
||||
lfsr_data_t data_;
|
||||
} lfsr_bsprout_t;
|
||||
lfs_size_t cksize;
|
||||
uint32_t cksum;
|
||||
} lfsr_bptr_t;
|
||||
|
||||
// a bleaf is just a bptr with all optional attrs
|
||||
typedef struct lfsr_bleaf {
|
||||
@@ -523,29 +517,40 @@ typedef struct lfsr_bleaf {
|
||||
lfsr_ecksum_t becksum;
|
||||
} lfsr_bleaf_t;
|
||||
|
||||
// bshrubs must always be associated with an mdir
|
||||
//
|
||||
// rbyd.block == mdir.blocks[0] => bshrub
|
||||
// rbyd.block != mdir.blocks[0] => btree
|
||||
typedef struct lfsr_bshrub {
|
||||
lfsr_rbyd_t rbyd;
|
||||
// copy for staging
|
||||
lfsr_rbyd_t rbyd_;
|
||||
// a shrub is a secondary trunk in an mdir, we really only need
|
||||
// trunk/weight/block, so we sneak our estimate into some
|
||||
// overlapping fields
|
||||
typedef struct lfsr_shrub {
|
||||
// this all lines up with lfsr_rbyd_t
|
||||
lfsr_srid_t weight;
|
||||
lfs_block_t blocks[2];
|
||||
lfs_size_t trunk;
|
||||
lfs_size_t eoff;
|
||||
// an upper-bound estimate on the on-disk shrub size
|
||||
lfs_size_t estimate;
|
||||
} lfsr_bshrub_t;
|
||||
} lfsr_shrub_t;
|
||||
|
||||
// the lfsr_ftree_t struct is a sort of proto-file
|
||||
typedef struct lfsr_ftree {
|
||||
// ftrees contain both an active tree and staging tree, to allow
|
||||
// staging files during mdir compacts
|
||||
//
|
||||
// navigating this union is a bit tricky, and relies on related
|
||||
// mdir's block:
|
||||
//
|
||||
// sign(size)=1, data.size==0 => bnull
|
||||
// sign(size)=1, data.block==mdir.block => bsprout
|
||||
// sign(size)=1, data.block!=mdir.block => bleaf
|
||||
// sign(size)=0, data.block==mdir.block => bshrub
|
||||
// sign(size)=0, data.block!=mdir.block => btree
|
||||
//
|
||||
union {
|
||||
lfs_soff_t size;
|
||||
lfsr_data_t data;
|
||||
lfsr_bsprout_t bsprout;
|
||||
lfsr_bptr_t bptr;
|
||||
lfsr_data_t bsprout;
|
||||
lfsr_bleaf_t bleaf;
|
||||
lfsr_bshrub_t bshrub;
|
||||
lfsr_shrub_t bshrub;
|
||||
lfsr_btree_t btree;
|
||||
} u;
|
||||
} u, u_;
|
||||
} lfsr_ftree_t;
|
||||
|
||||
typedef struct lfsr_file {
|
||||
|
||||
Reference in New Issue
Block a user