forked from TrueCloudLab/frostfs-node
107 lines
2.2 KiB
Go
107 lines
2.2 KiB
Go
|
package meta
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"encoding/hex"
|
||
|
"strconv"
|
||
|
|
||
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||
|
"github.com/nspcc-dev/neofs-node/pkg/util/logger"
|
||
|
"go.etcd.io/bbolt"
|
||
|
"go.uber.org/zap"
|
||
|
)
|
||
|
|
||
|
// DB represents local metabase of storage node.
|
||
|
type DB struct {
|
||
|
info Info
|
||
|
|
||
|
*cfg
|
||
|
|
||
|
matchers map[object.SearchMatchType]func(string, []byte, string) bool
|
||
|
}
|
||
|
|
||
|
// Option is an option of DB constructor.
|
||
|
type Option func(*cfg)
|
||
|
|
||
|
type cfg struct {
|
||
|
boltDB *bbolt.DB
|
||
|
|
||
|
log *logger.Logger
|
||
|
}
|
||
|
|
||
|
func defaultCfg() *cfg {
|
||
|
return &cfg{
|
||
|
log: zap.L(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NewDB creates, initializes and returns DB instance.
|
||
|
func NewDB(opts ...Option) *DB {
|
||
|
c := defaultCfg()
|
||
|
|
||
|
for i := range opts {
|
||
|
opts[i](c)
|
||
|
}
|
||
|
|
||
|
return &DB{
|
||
|
info: Info{
|
||
|
Path: c.boltDB.Path(),
|
||
|
},
|
||
|
cfg: c,
|
||
|
matchers: map[object.SearchMatchType]func(string, []byte, string) bool{
|
||
|
object.MatchUnknown: unknownMatcher,
|
||
|
object.MatchStringEqual: stringEqualMatcher,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (db *DB) Close() error {
|
||
|
return db.boltDB.Close()
|
||
|
}
|
||
|
|
||
|
func stringEqualMatcher(key string, objVal []byte, filterVal string) bool {
|
||
|
switch key {
|
||
|
default:
|
||
|
return string(objVal) == filterVal
|
||
|
case v2object.FilterHeaderPayloadHash, v2object.FilterHeaderHomomorphicHash:
|
||
|
return hex.EncodeToString(objVal) == filterVal
|
||
|
case v2object.FilterHeaderCreationEpoch, v2object.FilterHeaderPayloadLength:
|
||
|
return strconv.FormatUint(binary.LittleEndian.Uint64(objVal), 10) == filterVal
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func unknownMatcher(_ string, _ []byte, _ string) bool {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// bucketKeyHelper returns byte representation of val that is used as a key
|
||
|
// in boltDB. Useful for getting filter values from unique and list indexes.
|
||
|
func bucketKeyHelper(hdr string, val string) []byte {
|
||
|
switch hdr {
|
||
|
case v2object.FilterHeaderPayloadHash:
|
||
|
v, err := hex.DecodeString(val)
|
||
|
if err != nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return v
|
||
|
default:
|
||
|
return []byte(val)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// FromBoltDB returns option to construct DB from BoltDB instance.
|
||
|
func FromBoltDB(db *bbolt.DB) Option {
|
||
|
return func(c *cfg) {
|
||
|
c.boltDB = db
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// WithLogger returns option to set logger of DB.
|
||
|
func WithLogger(l *logger.Logger) Option {
|
||
|
return func(c *cfg) {
|
||
|
c.log = l
|
||
|
}
|
||
|
}
|