Allow to customize blobovnicza's leaf width #622
9 changed files with 47 additions and 7 deletions
|
@ -174,6 +174,7 @@ type subStorageCfg struct {
|
|||
// blobovnicza-specific
|
||||
size uint64
|
||||
width uint64
|
||||
leafWidth uint64
|
||||
openedCacheSize int
|
||||
}
|
||||
|
||||
|
@ -288,6 +289,7 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol
|
|||
sCfg.size = sub.Size()
|
||||
sCfg.depth = sub.ShallowDepth()
|
||||
sCfg.width = sub.ShallowWidth()
|
||||
sCfg.leafWidth = sub.LeafWidth()
|
||||
sCfg.openedCacheSize = sub.OpenedCacheSize()
|
||||
case fstree.Type:
|
||||
sub := fstreeconfig.From((*config.Config)(storagesCfg[i]))
|
||||
|
@ -774,6 +776,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage {
|
|||
blobovniczatree.WithBlobovniczaSize(sRead.size),
|
||||
blobovniczatree.WithBlobovniczaShallowDepth(sRead.depth),
|
||||
blobovniczatree.WithBlobovniczaShallowWidth(sRead.width),
|
||||
blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth),
|
||||
blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize),
|
||||
blobovniczatree.WithLogger(c.log),
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ func TestEngineSection(t *testing.T) {
|
|||
require.EqualValues(t, 1, blz.ShallowDepth())
|
||||
require.EqualValues(t, 4, blz.ShallowWidth())
|
||||
require.EqualValues(t, 50, blz.OpenedCacheSize())
|
||||
require.EqualValues(t, 10, blz.LeafWidth())
|
||||
|
||||
require.Equal(t, "tmp/0/blob", ss[1].Path())
|
||||
require.EqualValues(t, 0644, ss[1].Perm())
|
||||
|
@ -142,6 +143,7 @@ func TestEngineSection(t *testing.T) {
|
|||
require.EqualValues(t, 1, blz.ShallowDepth())
|
||||
require.EqualValues(t, 4, blz.ShallowWidth())
|
||||
require.EqualValues(t, 50, blz.OpenedCacheSize())
|
||||
require.EqualValues(t, 10, blz.LeafWidth())
|
||||
|
||||
require.Equal(t, "tmp/1/blob", ss[1].Path())
|
||||
require.EqualValues(t, 0644, ss[1].Perm())
|
||||
|
|
|
@ -102,3 +102,13 @@ func (x *Config) OpenedCacheSize() int {
|
|||
func (x *Config) BoltDB() *boltdbconfig.Config {
|
||||
return (*boltdbconfig.Config)(x)
|
||||
}
|
||||
|
||||
// LeafWidth returns the value of "leaf_width" config parameter.
|
||||
//
|
||||
// Returns 0 if the value is not a positive number.
|
||||
func (x *Config) LeafWidth() uint64 {
|
||||
return config.UintSafe(
|
||||
(*config.Config)(x),
|
||||
"leaf_width",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_SIZE=4194304
|
|||
FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH=1
|
||||
FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4
|
||||
FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50
|
||||
FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10
|
||||
### FSTree config
|
||||
FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE=fstree
|
||||
FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH=tmp/0/blob
|
||||
|
@ -167,6 +168,7 @@ FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_SIZE=4194304
|
|||
FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH=1
|
||||
FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH=4
|
||||
FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50
|
||||
FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_LEAF_WIDTH=10
|
||||
### FSTree config
|
||||
FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE=fstree
|
||||
FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH=tmp/1/blob
|
||||
|
|
|
@ -168,7 +168,8 @@
|
|||
"size": 4194304,
|
||||
"depth": 1,
|
||||
"width": 4,
|
||||
"opened_cache_capacity": 50
|
||||
"opened_cache_capacity": 50,
|
||||
"leaf_width": 10
|
||||
},
|
||||
{
|
||||
"type": "fstree",
|
||||
|
@ -218,7 +219,8 @@
|
|||
"size": 4194304,
|
||||
"depth": 1,
|
||||
"width": 4,
|
||||
"opened_cache_capacity": 50
|
||||
"opened_cache_capacity": 50,
|
||||
"leaf_width": 10
|
||||
},
|
||||
{
|
||||
"type": "fstree",
|
||||
|
|
|
@ -145,6 +145,7 @@ storage:
|
|||
depth: 1 # max depth of object tree storage in key-value DB
|
||||
width: 4 # max width of object tree storage in key-value DB
|
||||
opened_cache_capacity: 50 # maximum number of opened database files
|
||||
leaf_width: 10 # max count of key-value DB on leafs of object tree storage
|
||||
- perm: 0644 # permissions for blobstor files(directories: +x for current user and group)
|
||||
depth: 5 # max depth of object tree storage in FS
|
||||
|
||||
|
|
|
@ -98,6 +98,10 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) {
|
|||
opts[i](&blz.cfg)
|
||||
}
|
||||
|
||||
if blz.blzLeafWidth == 0 {
|
||||
blz.blzLeafWidth = blz.blzShallowWidth
|
||||
}
|
||||
|
||||
cache, err := simplelru.NewLRU[string, *blobovnicza.Blobovnicza](blz.openedCacheSize, func(p string, value *blobovnicza.Blobovnicza) {
|
||||
lvlPath := filepath.Dir(p)
|
||||
if b, ok := blz.active[lvlPath]; ok && b.ind == u64FromHexString(filepath.Base(p)) {
|
||||
|
@ -120,13 +124,17 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) {
|
|||
panic(fmt.Errorf("could not create LRU cache of size %d: %w", blz.openedCacheSize, err))
|
||||
}
|
||||
|
||||
cp := uint64(1)
|
||||
activeMapCapacity := uint64(1)
|
||||
for i := uint64(0); i < blz.blzShallowDepth; i++ {
|
||||
cp *= blz.blzShallowWidth
|
||||
if i+1 == blz.blzShallowDepth {
|
||||
activeMapCapacity *= blz.blzLeafWidth
|
||||
|
||||
} else {
|
||||
activeMapCapacity *= blz.blzShallowWidth
|
||||
}
|
||||
}
|
||||
|
||||
blz.opened = cache
|
||||
blz.active = make(map[string]blobovniczaWithIndex, cp)
|
||||
blz.active = make(map[string]blobovniczaWithIndex, activeMapCapacity)
|
||||
|
||||
return blz
|
||||
}
|
||||
|
@ -161,7 +169,7 @@ func (b *Blobovniczas) updateAndGet(lvlPath string, old *uint64) (blobovniczaWit
|
|||
|
||||
if ok {
|
||||
if old != nil {
|
||||
if active.ind == b.blzShallowWidth-1 {
|
||||
if active.ind == b.blzLeafWidth-1 {
|
||||
return active, logicerr.New("no more Blobovniczas")
|
||||
} else if active.ind != *old {
|
||||
// sort of CAS in order to control concurrent
|
||||
|
|
|
@ -115,7 +115,12 @@ func (b *Blobovniczas) iterateDeepest(ctx context.Context, addr oid.Address, f f
|
|||
|
||||
// iterator over particular level of directories.
|
||||
func (b *Blobovniczas) iterateSorted(ctx context.Context, addr *oid.Address, curPath []string, execDepth uint64, f func([]string) (bool, error)) (bool, error) {
|
||||
indices := indexSlice(b.blzShallowWidth)
|
||||
isLeafLevel := uint64(len(curPath)) == b.blzShallowDepth
|
||||
levelWidth := b.blzShallowWidth
|
||||
if isLeafLevel {
|
||||
levelWidth = b.blzLeafWidth
|
||||
}
|
||||
indices := indexSlice(levelWidth)
|
||||
|
||||
hrw.SortSliceByValue(indices, addressHash(addr, filepath.Join(curPath...)))
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ type cfg struct {
|
|||
openedCacheSize int
|
||||
blzShallowDepth uint64
|
||||
blzShallowWidth uint64
|
||||
blzLeafWidth uint64
|
||||
compression *compression.Config
|
||||
blzOpts []blobovnicza.Option
|
||||
// reportError is the function called when encountering disk errors.
|
||||
|
@ -64,6 +65,12 @@ func WithBlobovniczaShallowWidth(width uint64) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func WithBlobovniczaLeafWidth(w uint64) Option {
|
||||
return func(c *cfg) {
|
||||
c.blzLeafWidth = w
|
||||
}
|
||||
}
|
||||
|
||||
func WithBlobovniczaShallowDepth(depth uint64) Option {
|
||||
return func(c *cfg) {
|
||||
c.blzShallowDepth = depth
|
||||
|
|
Loading…
Add table
Reference in a new issue
It is possible to multiply out of the loop, in this case
if
will be redundant. In this case, condition for iteration will bei < blz.blzShallowDepth-1
Since this is an unsigned data type (uint64), I prefer not to deal with subtraction:)