[#199] Create metabase instance as storage engine component

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2020-11-30 16:10:05 +03:00
parent 8a293c76ed
commit 9d4fba923c
4 changed files with 87 additions and 23 deletions

View file

@ -0,0 +1,42 @@
package meta
import (
"fmt"
"os"
"path"
"go.etcd.io/bbolt"
"go.uber.org/zap"
)
// Open boltDB instance for metabase.
func (db *DB) Open() error {
err := os.MkdirAll(path.Dir(db.info.Path), db.info.Permission)
if err != nil {
return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err)
}
db.log.Debug("created directory for Metabase", zap.String("path", db.info.Path))
db.boltDB, err = bbolt.Open(db.info.Path, db.info.Permission, db.boltOptions)
if err != nil {
return fmt.Errorf("can't open boltDB database: %w", err)
}
db.log.Debug("opened boltDB instance for Metabase")
return nil
}
// Init initializes metabase, however metabase doesn't need extra preparations,
// so it implemented to satisfy interface of storage engine components.
func (db *DB) Init() error {
db.log.Debug("Metabase has been initialized")
return nil
}
// Close closes boltDB instance.
func (db *DB) Close() error {
return db.boltDB.Close()
}

View file

@ -3,6 +3,7 @@ package meta
import ( import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"os"
"strconv" "strconv"
"github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/object"
@ -14,30 +15,36 @@ import (
// DB represents local metabase of storage node. // DB represents local metabase of storage node.
type DB struct { type DB struct {
info Info
*cfg *cfg
matchers map[object.SearchMatchType]func(string, []byte, string) bool matchers map[object.SearchMatchType]func(string, []byte, string) bool
boltDB *bbolt.DB
} }
// Option is an option of DB constructor. // Option is an option of DB constructor.
type Option func(*cfg) type Option func(*cfg)
type cfg struct { type cfg struct {
boltDB *bbolt.DB boltOptions *bbolt.Options // optional
info Info
log *logger.Logger log *logger.Logger
} }
func defaultCfg() *cfg { func defaultCfg() *cfg {
return &cfg{ return &cfg{
info: Info{
Permission: os.ModePerm, // 0777
},
log: zap.L(), log: zap.L(),
} }
} }
// NewDB creates, initializes and returns DB instance. // New creates and returns new Metabase instance.
func NewDB(opts ...Option) *DB { func New(opts ...Option) *DB {
c := defaultCfg() c := defaultCfg()
for i := range opts { for i := range opts {
@ -45,9 +52,6 @@ func NewDB(opts ...Option) *DB {
} }
return &DB{ return &DB{
info: Info{
Path: c.boltDB.Path(),
},
cfg: c, cfg: c,
matchers: map[object.SearchMatchType]func(string, []byte, string) bool{ matchers: map[object.SearchMatchType]func(string, []byte, string) bool{
object.MatchUnknown: unknownMatcher, object.MatchUnknown: unknownMatcher,
@ -56,10 +60,6 @@ func NewDB(opts ...Option) *DB {
} }
} }
func (db *DB) Close() error {
return db.boltDB.Close()
}
func stringEqualMatcher(key string, objVal []byte, filterVal string) bool { func stringEqualMatcher(key string, objVal []byte, filterVal string) bool {
switch key { switch key {
default: default:
@ -100,16 +100,31 @@ func bucketKeyHelper(hdr string, val string) []byte {
} }
} }
// 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. // WithLogger returns option to set logger of DB.
func WithLogger(l *logger.Logger) Option { func WithLogger(l *logger.Logger) Option {
return func(c *cfg) { return func(c *cfg) {
c.log = l c.log = l
} }
} }
// WithBoltDBOptions returns option to specify BoltDB options.
func WithBoltDBOptions(opts *bbolt.Options) Option {
return func(c *cfg) {
c.boltOptions = opts
}
}
// WithPath returns option to set system path to Metabase.
func WithPath(path string) Option {
return func(c *cfg) {
c.info.Path = path
}
}
// WithPermissions returns option to specify permission bits
// of Metabase system path.
func WithPermissions(perm os.FileMode) Option {
return func(c *cfg) {
c.info.Permission = perm
}
}

View file

@ -15,7 +15,6 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/util/test" "github.com/nspcc-dev/neofs-node/pkg/util/test"
"github.com/nspcc-dev/tzhash/tz" "github.com/nspcc-dev/tzhash/tz"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.etcd.io/bbolt"
) )
func testSelect(t *testing.T, db *meta.DB, fs objectSDK.SearchFilters, exp ...*objectSDK.Address) { func testSelect(t *testing.T, db *meta.DB, fs objectSDK.SearchFilters, exp ...*objectSDK.Address) {
@ -51,10 +50,11 @@ func testOID() *objectSDK.ID {
func newDB(t testing.TB) *meta.DB { func newDB(t testing.TB) *meta.DB {
path := t.Name() path := t.Name()
bdb, err := bbolt.Open(path, 0600, nil) bdb := meta.New(meta.WithPath(path), meta.WithPermissions(0600))
require.NoError(t, err)
return meta.NewDB(meta.FromBoltDB(bdb)) require.NoError(t, bdb.Open())
return bdb
} }
func releaseDB(db *meta.DB) { func releaseDB(db *meta.DB) {

View file

@ -1,9 +1,16 @@
package meta package meta
import (
"os"
)
// Info groups the information about DB. // Info groups the information about DB.
type Info struct { type Info struct {
// Full path to the metabase. // Full path to the metabase.
Path string Path string
// Permission of database file.
Permission os.FileMode
} }
// DumpInfo returns information about the DB. // DumpInfo returns information about the DB.