From 9d4fba923c47d748040770178a5a7ac7fa947935 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Mon, 30 Nov 2020 16:10:05 +0300 Subject: [PATCH] [#199] Create metabase instance as storage engine component Signed-off-by: Alex Vanin --- .../metabase/v2/control.go | 42 +++++++++++++++ pkg/local_object_storage/metabase/v2/db.go | 53 ++++++++++++------- .../metabase/v2/db_test.go | 8 +-- pkg/local_object_storage/metabase/v2/info.go | 7 +++ 4 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 pkg/local_object_storage/metabase/v2/control.go diff --git a/pkg/local_object_storage/metabase/v2/control.go b/pkg/local_object_storage/metabase/v2/control.go new file mode 100644 index 000000000..2e6223884 --- /dev/null +++ b/pkg/local_object_storage/metabase/v2/control.go @@ -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() +} diff --git a/pkg/local_object_storage/metabase/v2/db.go b/pkg/local_object_storage/metabase/v2/db.go index b6589c47d..c55c70f95 100644 --- a/pkg/local_object_storage/metabase/v2/db.go +++ b/pkg/local_object_storage/metabase/v2/db.go @@ -3,6 +3,7 @@ package meta import ( "encoding/binary" "encoding/hex" + "os" "strconv" "github.com/nspcc-dev/neofs-api-go/pkg/object" @@ -14,30 +15,36 @@ import ( // DB represents local metabase of storage node. type DB struct { - info Info - *cfg matchers map[object.SearchMatchType]func(string, []byte, string) bool + + boltDB *bbolt.DB } // Option is an option of DB constructor. type Option func(*cfg) type cfg struct { - boltDB *bbolt.DB + boltOptions *bbolt.Options // optional + + info Info log *logger.Logger } func defaultCfg() *cfg { return &cfg{ + info: Info{ + Permission: os.ModePerm, // 0777 + }, + log: zap.L(), } } -// NewDB creates, initializes and returns DB instance. -func NewDB(opts ...Option) *DB { +// New creates and returns new Metabase instance. +func New(opts ...Option) *DB { c := defaultCfg() for i := range opts { @@ -45,9 +52,6 @@ func NewDB(opts ...Option) *DB { } return &DB{ - info: Info{ - Path: c.boltDB.Path(), - }, cfg: c, matchers: map[object.SearchMatchType]func(string, []byte, string) bool{ 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 { switch key { 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. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { 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 + } +} diff --git a/pkg/local_object_storage/metabase/v2/db_test.go b/pkg/local_object_storage/metabase/v2/db_test.go index 341c5253c..17452aaee 100644 --- a/pkg/local_object_storage/metabase/v2/db_test.go +++ b/pkg/local_object_storage/metabase/v2/db_test.go @@ -15,7 +15,6 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/util/test" "github.com/nspcc-dev/tzhash/tz" "github.com/stretchr/testify/require" - "go.etcd.io/bbolt" ) 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 { path := t.Name() - bdb, err := bbolt.Open(path, 0600, nil) - require.NoError(t, err) + bdb := meta.New(meta.WithPath(path), meta.WithPermissions(0600)) - return meta.NewDB(meta.FromBoltDB(bdb)) + require.NoError(t, bdb.Open()) + + return bdb } func releaseDB(db *meta.DB) { diff --git a/pkg/local_object_storage/metabase/v2/info.go b/pkg/local_object_storage/metabase/v2/info.go index 906e21209..967e9c713 100644 --- a/pkg/local_object_storage/metabase/v2/info.go +++ b/pkg/local_object_storage/metabase/v2/info.go @@ -1,9 +1,16 @@ package meta +import ( + "os" +) + // Info groups the information about DB. type Info struct { // Full path to the metabase. Path string + + // Permission of database file. + Permission os.FileMode } // DumpInfo returns information about the DB.