frostfs-node/pkg/local_object_storage/metabase/containers.go
Alex Vanin 41578001e4 [#337] metabase: Keep container size estimation
Storage nodes keep container size estimation so they
can announce this info and hope for some basic income
settlements. This is also useful for monitoring.

Container size does not include non regular or inhumed
object sizes.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
2021-01-29 11:04:30 +03:00

102 lines
2 KiB
Go

package meta
import (
"encoding/binary"
"strings"
"github.com/nspcc-dev/neofs-api-go/pkg/container"
"go.etcd.io/bbolt"
)
func (db *DB) Containers() (list []*container.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) ([]*container.ID, error) {
result := make([]*container.ID, 0)
err := tx.ForEach(func(name []byte, _ *bbolt.Bucket) error {
id, err := parseContainerID(name)
if err != nil {
return err
}
if id != nil {
result = append(result, id)
}
return nil
})
return result, err
}
func (db *DB) ContainerSize(id *container.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 *container.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) (*container.ID, error) {
strName := string(name)
if strings.Contains(strName, invalidBase58String) {
return nil, nil
}
id := container.NewID()
return id, id.Parse(strName)
}
func parseContainerSize(v []byte) uint64 {
if len(v) == 0 {
return 0
}
return binary.LittleEndian.Uint64(v)
}
func changeContainerSize(tx *bbolt.Tx, id *container.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)
}