frostfs-node/pkg/local_object_storage/metabase/v2/cleanup.go
Alex Vanin 74d44beb99 [#199] Add CleanUp method to remove empty buckets from metabase
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2020-12-11 17:19:37 +03:00

85 lines
1.6 KiB
Go

package meta
import (
"strings"
"go.etcd.io/bbolt"
)
func (db *DB) CleanUp() error {
return 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
})
})
}
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)
}