diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 45ddeec8..808a78d2 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -776,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), } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index d4fedb14..80d064c8 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -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 diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 0154fe2c..aeac854f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -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...))) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index d0503f23..d1118565 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -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