frostfs-node/pkg/local_object_storage/metabase/containers.go
Alex Vanin e41aba610d [#945] metabase: Fix containers listing
Container listing should not ignore tombstone and
storage group objects which are not stored in
primary buckets.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2021-10-27 16:10:01 +03:00

104 lines
2.1 KiB
Go

package meta
import (
"encoding/binary"
"strings"
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
"go.etcd.io/bbolt"
)
func (db *DB) Containers() (list []*cid.ID, err error) {
err = db.boltDB.View(func(tx *bbolt.Tx) error {
list, err = db.containers(tx)
return err
})
return list, err
}
func (db *DB) containers(tx *bbolt.Tx) ([]*cid.ID, error) {
result := make([]*cid.ID, 0)
unique := make(map[string]struct{})
err := tx.ForEach(func(name []byte, _ *bbolt.Bucket) error {
id := parseContainerID(name, unique)
if id != nil {
result = append(result, id)
unique[id.String()] = struct{}{}
}
return nil
})
return result, err
}
func (db *DB) ContainerSize(id *cid.ID) (size uint64, err error) {
err = db.boltDB.Update(func(tx *bbolt.Tx) error {
size, err = db.containerSize(tx, id)
return err
})
return size, err
}
func (db *DB) containerSize(tx *bbolt.Tx, id *cid.ID) (uint64, error) {
containerVolume, err := tx.CreateBucketIfNotExists(containerVolumeBucketName)
if err != nil {
return 0, err
}
key := id.ToV2().GetValue()
return parseContainerSize(containerVolume.Get(key)), nil
}
func parseContainerID(name []byte, ignore map[string]struct{}) *cid.ID {
containerID := cid.New()
strContainerID := strings.Split(string(name), invalidBase58String)[0]
if _, ok := ignore[strContainerID]; ok {
return nil
}
if err := containerID.Parse(strContainerID); err != nil {
return nil
}
return containerID
}
func parseContainerSize(v []byte) uint64 {
if len(v) == 0 {
return 0
}
return binary.LittleEndian.Uint64(v)
}
func changeContainerSize(tx *bbolt.Tx, id *cid.ID, delta uint64, increase bool) error {
containerVolume, err := tx.CreateBucketIfNotExists(containerVolumeBucketName)
if err != nil {
return err
}
key := id.ToV2().GetValue()
size := parseContainerSize(containerVolume.Get(key))
if increase {
size += delta
} else if size > delta {
size -= delta
} else {
size = 0
}
buf := make([]byte, 8) // consider using sync.Pool to decrease allocations
binary.LittleEndian.PutUint64(buf, size)
return containerVolume.Put(key, buf)
}