forked from TrueCloudLab/frostfs-node
[#1094] blobovnicza: calculate size in Init
properly
If pre-existing blobovnicza is initialized, it's size should be updated even if all buckets are in place. Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
418b553920
commit
651adf46c6
3 changed files with 19 additions and 43 deletions
|
@ -1,7 +1,6 @@
|
||||||
package blobovnicza
|
package blobovnicza
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
|
@ -49,32 +48,34 @@ func (b *Blobovnicza) Init() error {
|
||||||
zap.Uint64("storage size limit", b.fullSizeLimit),
|
zap.Uint64("storage size limit", b.fullSizeLimit),
|
||||||
)
|
)
|
||||||
|
|
||||||
return b.boltDB.Update(func(tx *bbolt.Tx) error {
|
if size := b.filled.Load(); size != 0 {
|
||||||
|
b.log.Debug("already initialized", zap.Uint64("size", size))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var size uint64
|
||||||
|
|
||||||
|
err := b.boltDB.Update(func(tx *bbolt.Tx) error {
|
||||||
return b.iterateBucketKeys(func(lower, upper uint64, key []byte) (bool, error) {
|
return b.iterateBucketKeys(func(lower, upper uint64, key []byte) (bool, error) {
|
||||||
// create size range bucket
|
// create size range bucket
|
||||||
|
|
||||||
|
rangeStr := stringifyBounds(lower, upper)
|
||||||
b.log.Debug("creating bucket for size range",
|
b.log.Debug("creating bucket for size range",
|
||||||
zap.String("range", stringifyBounds(lower, upper)),
|
zap.String("range", rangeStr))
|
||||||
)
|
|
||||||
|
|
||||||
_, err := tx.CreateBucket(key)
|
|
||||||
if errors.Is(err, bbolt.ErrBucketExists) {
|
|
||||||
// => "smallest" bucket exists => already initialized => do nothing
|
|
||||||
// TODO: consider separate bucket structure allocation step
|
|
||||||
// and state initialization/activation
|
|
||||||
|
|
||||||
b.log.Debug("bucket already exists, initializing state")
|
|
||||||
|
|
||||||
return true, b.syncFullnessCounter(tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
buck, err := tx.CreateBucketIfNotExists(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("(%T) could not create bucket for bounds [%d:%d]: %w",
|
return false, fmt.Errorf("(%T) could not create bucket for bounds %s: %w",
|
||||||
b, lower, upper, err)
|
b, rangeStr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size += uint64(buck.Stats().KeyN) * (upper + lower) / 2
|
||||||
return false, nil
|
return false, nil
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
b.filled.Store(size)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close releases all internal database resources.
|
// Close releases all internal database resources.
|
||||||
|
|
|
@ -33,9 +33,7 @@ func (b *Blobovnicza) iterateBounds(f func(uint64, uint64) (bool, error)) error
|
||||||
for upper := firstBucketBound; upper <= max(objLimitBound, firstBucketBound); upper *= 2 {
|
for upper := firstBucketBound; upper <= max(objLimitBound, firstBucketBound); upper *= 2 {
|
||||||
var lower uint64
|
var lower uint64
|
||||||
|
|
||||||
if upper == firstBucketBound {
|
if upper != firstBucketBound {
|
||||||
lower = 0
|
|
||||||
} else {
|
|
||||||
lower = upper/2 + 1
|
lower = upper/2 + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"go.etcd.io/bbolt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const firstBucketBound = uint64(32 * 1 << 10) // 32KB
|
const firstBucketBound = uint64(32 * 1 << 10) // 32KB
|
||||||
|
@ -51,24 +49,3 @@ func (b *Blobovnicza) decSize(sz uint64) {
|
||||||
func (b *Blobovnicza) full() bool {
|
func (b *Blobovnicza) full() bool {
|
||||||
return b.filled.Load() >= b.fullSizeLimit
|
return b.filled.Load() >= b.fullSizeLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Blobovnicza) syncFullnessCounter(tx *bbolt.Tx) error {
|
|
||||||
sz := uint64(0)
|
|
||||||
|
|
||||||
if err := b.iterateBucketKeys(func(lower, upper uint64, key []byte) (bool, error) {
|
|
||||||
buck := tx.Bucket(key)
|
|
||||||
if buck == nil {
|
|
||||||
return false, fmt.Errorf("bucket not found %s", stringifyBounds(lower, upper))
|
|
||||||
}
|
|
||||||
|
|
||||||
sz += uint64(buck.Stats().KeyN) * (upper + lower) / 2
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b.filled.Store(sz)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue