frostfs-node/pkg/local_object_storage/metabase/cleanup.go
Leonard Lyubich 590745204c [#237] metabase: Structure parameters and results of all operations
All parameters and resulting values of all metabase operations are
structured in new types. The most popular scenarios for using operations are
moved to auxiliary functions.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2020-12-11 17:19:37 +03:00

94 lines
1.8 KiB
Go

package meta
import (
"strings"
"go.etcd.io/bbolt"
)
// CleanUpPrm groups the parameters of CleanUp operation.
type CleanUpPrm struct{}
// CleanUpRes groups resulting values of CleanUp operation.
type CleanUpRes struct{}
// CleanUp removes empty buckets from metabase.
func (db *DB) CleanUp(prm *CleanUpPrm) (res *CleanUpRes, err error) {
err = db.boltDB.Update(func(tx *bbolt.Tx) error {
return tx.ForEach(func(name []byte, b *bbolt.Bucket) error {
switch {
case isFKBTBucket(name):
cleanUpFKBT(tx, name, b)
case isListBucket(name):
cleanUpListBucket(tx, name, b)
default:
cleanUpUniqueBucket(tx, name, b)
}
return nil
})
})
return
}
func isFKBTBucket(name []byte) bool {
bucketName := string(name)
switch {
case
strings.Contains(bucketName, userAttributePostfix),
strings.Contains(bucketName, ownerPostfix):
return true
default:
return false
}
}
func isListBucket(name []byte) bool {
bucketName := string(name)
switch {
case
strings.Contains(bucketName, payloadHashPostfix),
strings.Contains(bucketName, parentPostfix):
return true
default:
return false
}
}
func cleanUpUniqueBucket(tx *bbolt.Tx, name []byte, b *bbolt.Bucket) {
if b.Stats().KeyN == 0 {
_ = tx.DeleteBucket(name) // ignore error, best effort there
}
}
func cleanUpFKBT(tx *bbolt.Tx, name []byte, b *bbolt.Bucket) {
removedBuckets := 0
remainingBuckets := b.Stats().BucketN - 1
_ = b.ForEach(func(k, _ []byte) error {
fkbtRoot := b.Bucket(k)
if fkbtRoot == nil {
return nil
}
if fkbtRoot.Stats().KeyN == 0 {
err := b.DeleteBucket(k)
if err == nil {
removedBuckets++
}
}
return nil
})
if remainingBuckets == removedBuckets {
_ = tx.DeleteBucket(name) // ignore error, best effort there
}
}
func cleanUpListBucket(tx *bbolt.Tx, name []byte, b *bbolt.Bucket) {
cleanUpUniqueBucket(tx, name, b)
}