forked from TrueCloudLab/frostfs-node
[#959] node: Set mode to shard's components when open it
Avoid opening database for `metabase` and `cache` in `Degraded` mode. Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
parent
805862f4b7
commit
29812f6683
25 changed files with 219 additions and 74 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal"
|
common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal"
|
||||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
@ -43,7 +44,7 @@ func openMeta(cmd *cobra.Command) *meta.DB {
|
||||||
}),
|
}),
|
||||||
meta.WithEpochState(epochState{}),
|
meta.WithEpochState(epochState{}),
|
||||||
)
|
)
|
||||||
common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(cmd.Context(), true)))
|
common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(cmd.Context(), mode.ReadOnly)))
|
||||||
|
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -51,7 +52,7 @@ func TestCompression(t *testing.T) {
|
||||||
bs := New(
|
bs := New(
|
||||||
WithCompressObjects(compress),
|
WithCompressObjects(compress),
|
||||||
WithStorages(defaultStorages(dir, smallSizeLimit)))
|
WithStorages(defaultStorages(dir, smallSizeLimit)))
|
||||||
require.NoError(t, bs.Open(context.Background(), false))
|
require.NoError(t, bs.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, bs.Init())
|
require.NoError(t, bs.Init())
|
||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
@ -126,7 +127,7 @@ func TestBlobstor_needsCompression(t *testing.T) {
|
||||||
Storage: fstree.New(fstree.WithPath(dir)),
|
Storage: fstree.New(fstree.WithPath(dir)),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
require.NoError(t, bs.Open(context.Background(), false))
|
require.NoError(t, bs.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, bs.Init())
|
require.NoError(t, bs.Init())
|
||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,7 @@ func TestConcurrentPut(t *testing.T) {
|
||||||
|
|
||||||
blobStor := New(
|
blobStor := New(
|
||||||
WithStorages(defaultStorages(dir, smallSizeLimit)))
|
WithStorages(defaultStorages(dir, smallSizeLimit)))
|
||||||
require.NoError(t, blobStor.Open(context.Background(), false))
|
require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, blobStor.Init())
|
require.NoError(t, blobStor.Init())
|
||||||
|
|
||||||
testGet := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) {
|
testGet := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) {
|
||||||
|
@ -268,7 +269,7 @@ func TestConcurrentDelete(t *testing.T) {
|
||||||
|
|
||||||
blobStor := New(
|
blobStor := New(
|
||||||
WithStorages(defaultStorages(dir, smallSizeLimit)))
|
WithStorages(defaultStorages(dir, smallSizeLimit)))
|
||||||
require.NoError(t, blobStor.Open(context.Background(), false))
|
require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, blobStor.Init())
|
require.NoError(t, blobStor.Init())
|
||||||
|
|
||||||
testPut := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) {
|
testPut := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) {
|
||||||
|
|
|
@ -6,13 +6,29 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open opens BlobStor.
|
// Open opens BlobStor.
|
||||||
func (b *BlobStor) Open(ctx context.Context, readOnly bool) error {
|
func (b *BlobStor) Open(ctx context.Context, mode mode.Mode) error {
|
||||||
b.log.Debug(logs.BlobstorOpening)
|
b.log.Debug(logs.BlobstorOpening)
|
||||||
|
|
||||||
|
b.modeMtx.Lock()
|
||||||
|
defer b.modeMtx.Unlock()
|
||||||
|
b.mode = mode
|
||||||
|
|
||||||
|
err := b.openBlobStor(ctx, mode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.metrics.SetMode(mode.ReadOnly())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BlobStor) openBlobStor(ctx context.Context, mode mode.Mode) error {
|
||||||
|
readOnly := mode.ReadOnly()
|
||||||
for i := range b.storage {
|
for i := range b.storage {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
@ -24,7 +40,6 @@ func (b *BlobStor) Open(ctx context.Context, readOnly bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.metrics.SetMode(readOnly)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
|
objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||||
|
@ -20,7 +21,7 @@ func TestExists(t *testing.T) {
|
||||||
|
|
||||||
b := New(WithStorages(storages))
|
b := New(WithStorages(storages))
|
||||||
|
|
||||||
require.NoError(t, b.Open(context.Background(), false))
|
require.NoError(t, b.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, b.Init())
|
require.NoError(t, b.Init())
|
||||||
|
|
||||||
objects := []*objectSDK.Object{
|
objects := []*objectSDK.Object{
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -26,7 +27,7 @@ func TestIterateObjects(t *testing.T) {
|
||||||
defer os.RemoveAll(p)
|
defer os.RemoveAll(p)
|
||||||
|
|
||||||
// open Blobstor
|
// open Blobstor
|
||||||
require.NoError(t, blobStor.Open(context.Background(), false))
|
require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite))
|
||||||
|
|
||||||
// initialize Blobstor
|
// initialize Blobstor
|
||||||
require.NoError(t, blobStor.Init())
|
require.NoError(t, blobStor.Init())
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (b *BlobStor) SetMode(m mode.Mode) error {
|
||||||
|
|
||||||
err := b.Close()
|
err := b.Close()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err = b.Open(context.TODO(), m.ReadOnly()); err == nil {
|
if err = b.openBlobStor(context.TODO(), m); err == nil {
|
||||||
err = b.Init()
|
err = b.Init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
// Component represents single storage component.
|
// Component represents single storage component.
|
||||||
type Component interface {
|
type Component interface {
|
||||||
Open(context.Context, bool) error
|
Open(context.Context, mode.Mode) error
|
||||||
SetMode(mode.Mode) error
|
SetMode(mode.Mode) error
|
||||||
Init() error
|
Init() error
|
||||||
Close() error
|
Close() error
|
||||||
|
@ -58,18 +58,18 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) {
|
||||||
t.Run("RW", func(t *testing.T) {
|
t.Run("RW", func(t *testing.T) {
|
||||||
// Use-case: irrecoverable error on some components, close everything.
|
// Use-case: irrecoverable error on some components, close everything.
|
||||||
s := cons(t)
|
s := cons(t)
|
||||||
require.NoError(t, s.Open(context.Background(), false))
|
require.NoError(t, s.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, s.Close())
|
require.NoError(t, s.Close())
|
||||||
})
|
})
|
||||||
t.Run("RO", func(t *testing.T) {
|
t.Run("RO", func(t *testing.T) {
|
||||||
// Use-case: irrecoverable error on some components, close everything.
|
// Use-case: irrecoverable error on some components, close everything.
|
||||||
// Open in read-only must be done after the db is here.
|
// Open in read-only must be done after the db is here.
|
||||||
s := cons(t)
|
s := cons(t)
|
||||||
require.NoError(t, s.Open(context.Background(), false))
|
require.NoError(t, s.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, s.Init())
|
require.NoError(t, s.Init())
|
||||||
require.NoError(t, s.Close())
|
require.NoError(t, s.Close())
|
||||||
|
|
||||||
require.NoError(t, s.Open(context.Background(), true))
|
require.NoError(t, s.Open(context.Background(), mode.ReadOnly))
|
||||||
require.NoError(t, s.Close())
|
require.NoError(t, s.Close())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) {
|
||||||
func TestCloseTwice(t *testing.T, cons Constructor) {
|
func TestCloseTwice(t *testing.T, cons Constructor) {
|
||||||
// Use-case: move to maintenance mode twice, first time failed.
|
// Use-case: move to maintenance mode twice, first time failed.
|
||||||
s := cons(t)
|
s := cons(t)
|
||||||
require.NoError(t, s.Open(context.Background(), false))
|
require.NoError(t, s.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, s.Init())
|
require.NoError(t, s.Init())
|
||||||
require.NoError(t, s.Close())
|
require.NoError(t, s.Close())
|
||||||
require.NoError(t, s.Close()) // already closed, no-op
|
require.NoError(t, s.Close()) // already closed, no-op
|
||||||
|
@ -90,12 +90,12 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) {
|
||||||
// Use-case: metabase `Init` failed,
|
// Use-case: metabase `Init` failed,
|
||||||
// call `SetMode` on all not-yet-initialized components.
|
// call `SetMode` on all not-yet-initialized components.
|
||||||
s := cons(t)
|
s := cons(t)
|
||||||
require.NoError(t, s.Open(context.Background(), false))
|
require.NoError(t, s.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, s.SetMode(m))
|
require.NoError(t, s.SetMode(m))
|
||||||
|
|
||||||
t.Run("after open in RO", func(t *testing.T) {
|
t.Run("after open in RO", func(t *testing.T) {
|
||||||
require.NoError(t, s.Close())
|
require.NoError(t, s.Close())
|
||||||
require.NoError(t, s.Open(context.Background(), true))
|
require.NoError(t, s.Open(context.Background(), mode.ReadOnly))
|
||||||
require.NoError(t, s.SetMode(m))
|
require.NoError(t, s.SetMode(m))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) {
|
||||||
t.Run("after init", func(t *testing.T) {
|
t.Run("after init", func(t *testing.T) {
|
||||||
s := cons(t)
|
s := cons(t)
|
||||||
// Use-case: notmal node operation.
|
// Use-case: notmal node operation.
|
||||||
require.NoError(t, s.Open(context.Background(), false))
|
require.NoError(t, s.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, s.Init())
|
require.NoError(t, s.Init())
|
||||||
require.NoError(t, s.SetMode(m))
|
require.NoError(t, s.SetMode(m))
|
||||||
require.NoError(t, s.Close())
|
require.NoError(t, s.Close())
|
||||||
|
@ -114,7 +114,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) {
|
||||||
func TestModeTransition(t *testing.T, cons Constructor, from, to mode.Mode) {
|
func TestModeTransition(t *testing.T, cons Constructor, from, to mode.Mode) {
|
||||||
// Use-case: normal node operation.
|
// Use-case: normal node operation.
|
||||||
s := cons(t)
|
s := cons(t)
|
||||||
require.NoError(t, s.Open(context.Background(), false))
|
require.NoError(t, s.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, s.Init())
|
require.NoError(t, s.Init())
|
||||||
require.NoError(t, s.SetMode(from))
|
require.NoError(t, s.SetMode(from))
|
||||||
require.NoError(t, s.SetMode(to))
|
require.NoError(t, s.SetMode(to))
|
||||||
|
|
|
@ -22,7 +22,18 @@ var ErrDegradedMode = logicerr.New("metabase is in a degraded mode")
|
||||||
var ErrReadOnlyMode = logicerr.New("metabase is in a read-only mode")
|
var ErrReadOnlyMode = logicerr.New("metabase is in a read-only mode")
|
||||||
|
|
||||||
// Open boltDB instance for metabase.
|
// Open boltDB instance for metabase.
|
||||||
func (db *DB) Open(_ context.Context, readOnly bool) error {
|
func (db *DB) Open(_ context.Context, mode mode.Mode) error {
|
||||||
|
db.modeMtx.Lock()
|
||||||
|
defer db.modeMtx.Unlock()
|
||||||
|
db.mode = mode
|
||||||
|
|
||||||
|
if mode.NoMetabase() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return db.openDB(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) openDB(mode mode.Mode) error {
|
||||||
err := util.MkdirAllX(filepath.Dir(db.info.Path), db.info.Permission)
|
err := util.MkdirAllX(filepath.Dir(db.info.Path), db.info.Permission)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err)
|
return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err)
|
||||||
|
@ -34,7 +45,7 @@ func (db *DB) Open(_ context.Context, readOnly bool) error {
|
||||||
opts := *bbolt.DefaultOptions
|
opts := *bbolt.DefaultOptions
|
||||||
db.boltOptions = &opts
|
db.boltOptions = &opts
|
||||||
}
|
}
|
||||||
db.boltOptions.ReadOnly = readOnly
|
db.boltOptions.ReadOnly = mode.ReadOnly()
|
||||||
|
|
||||||
return metaerr.Wrap(db.openBolt())
|
return metaerr.Wrap(db.openBolt())
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
||||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
@ -49,7 +50,7 @@ func newDB(t testing.TB, opts ...meta.Option) *meta.DB {
|
||||||
}, opts...)...,
|
}, opts...)...,
|
||||||
)
|
)
|
||||||
|
|
||||||
require.NoError(t, bdb.Open(context.Background(), false))
|
require.NoError(t, bdb.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, bdb.Init())
|
require.NoError(t, bdb.Init())
|
||||||
|
|
||||||
return bdb
|
return bdb
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package meta
|
package meta
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
@ -23,22 +22,17 @@ func (db *DB) SetMode(m mode.Mode) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
if m.NoMetabase() {
|
||||||
switch {
|
|
||||||
case m.NoMetabase():
|
|
||||||
db.boltDB = nil
|
db.boltDB = nil
|
||||||
case m.ReadOnly():
|
} else {
|
||||||
err = db.Open(context.TODO(), true)
|
err := db.openDB(m)
|
||||||
default:
|
if err == nil && !m.ReadOnly() {
|
||||||
err = db.Open(context.TODO(), false)
|
|
||||||
}
|
|
||||||
if err == nil && !m.NoMetabase() && !m.ReadOnly() {
|
|
||||||
err = db.Init()
|
err = db.Init()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err)
|
return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db.mode = m
|
db.mode = m
|
||||||
db.metrics.SetMode(m)
|
db.metrics.SetMode(m)
|
||||||
|
|
37
pkg/local_object_storage/metabase/mode_test.go
Normal file
37
pkg/local_object_storage/metabase/mode_test.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package meta
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type epochStateTest struct{}
|
||||||
|
|
||||||
|
func (s epochStateTest) CurrentEpoch() uint64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
bdb := New([]Option{
|
||||||
|
WithPath(filepath.Join(t.TempDir(), "metabase")),
|
||||||
|
WithPermissions(0o600),
|
||||||
|
WithEpochState(epochStateTest{}),
|
||||||
|
}...)
|
||||||
|
|
||||||
|
require.NoError(t, bdb.Open(context.Background(), mode.DegradedReadOnly))
|
||||||
|
require.Nil(t, bdb.boltDB)
|
||||||
|
require.NoError(t, bdb.Init())
|
||||||
|
require.Nil(t, bdb.boltDB)
|
||||||
|
require.NoError(t, bdb.Close())
|
||||||
|
|
||||||
|
require.NoError(t, bdb.Open(context.Background(), mode.Degraded))
|
||||||
|
require.Nil(t, bdb.boltDB)
|
||||||
|
require.NoError(t, bdb.Init())
|
||||||
|
require.Nil(t, bdb.boltDB)
|
||||||
|
require.NoError(t, bdb.Close())
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
@ -43,13 +44,13 @@ func TestVersion(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Run("simple", func(t *testing.T) {
|
t.Run("simple", func(t *testing.T) {
|
||||||
db := newDB(t)
|
db := newDB(t)
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, db.Init())
|
require.NoError(t, db.Init())
|
||||||
check(t, db)
|
check(t, db)
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
|
|
||||||
t.Run("reopen", func(t *testing.T) {
|
t.Run("reopen", func(t *testing.T) {
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, db.Init())
|
require.NoError(t, db.Init())
|
||||||
check(t, db)
|
check(t, db)
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
|
@ -57,29 +58,29 @@ func TestVersion(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("old data", func(t *testing.T) {
|
t.Run("old data", func(t *testing.T) {
|
||||||
db := newDB(t)
|
db := newDB(t)
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, db.WriteShardID([]byte{1, 2, 3, 4}))
|
require.NoError(t, db.WriteShardID([]byte{1, 2, 3, 4}))
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
|
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, db.Init())
|
require.NoError(t, db.Init())
|
||||||
check(t, db)
|
check(t, db)
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
})
|
})
|
||||||
t.Run("invalid version", func(t *testing.T) {
|
t.Run("invalid version", func(t *testing.T) {
|
||||||
db := newDB(t)
|
db := newDB(t)
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error {
|
require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error {
|
||||||
return updateVersion(tx, version+1)
|
return updateVersion(tx, version+1)
|
||||||
}))
|
}))
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
|
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.Error(t, db.Init())
|
require.Error(t, db.Init())
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
|
|
||||||
t.Run("reset", func(t *testing.T) {
|
t.Run("reset", func(t *testing.T) {
|
||||||
require.NoError(t, db.Open(context.Background(), false))
|
require.NoError(t, db.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, db.Reset())
|
require.NoError(t, db.Reset())
|
||||||
check(t, db)
|
check(t, db)
|
||||||
require.NoError(t, db.Close())
|
require.NoError(t, db.Close())
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +27,7 @@ func BenchmarkCreate(b *testing.B) {
|
||||||
f := NewBoltForest(
|
f := NewBoltForest(
|
||||||
WithPath(filepath.Join(tmpDir, "test.db")),
|
WithPath(filepath.Join(tmpDir, "test.db")),
|
||||||
WithMaxBatchSize(runtime.GOMAXPROCS(0)))
|
WithMaxBatchSize(runtime.GOMAXPROCS(0)))
|
||||||
require.NoError(b, f.Open(context.Background(), false))
|
require.NoError(b, f.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(b, f.Init())
|
require.NoError(b, f.Init())
|
||||||
defer func() { require.NoError(b, f.Close()) }()
|
defer func() { require.NoError(b, f.Close()) }()
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (t *boltForest) SetMode(m mode.Mode) error {
|
||||||
|
|
||||||
err := t.Close()
|
err := t.Close()
|
||||||
if err == nil && !m.NoMetabase() {
|
if err == nil && !m.NoMetabase() {
|
||||||
if err = t.Open(context.TODO(), m.ReadOnly()); err == nil {
|
if err = t.openBolt(m); err == nil {
|
||||||
err = t.Init()
|
err = t.Init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,18 @@ func (t *boltForest) SetMode(m mode.Mode) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *boltForest) Open(_ context.Context, readOnly bool) error {
|
func (t *boltForest) Open(_ context.Context, mode mode.Mode) error {
|
||||||
|
t.modeMtx.Lock()
|
||||||
|
defer t.modeMtx.Unlock()
|
||||||
|
t.mode = mode
|
||||||
|
if mode.NoMetabase() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return t.openBolt(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *boltForest) openBolt(mode mode.Mode) error {
|
||||||
|
readOnly := mode.ReadOnly()
|
||||||
err := util.MkdirAllX(filepath.Dir(t.path), t.perm)
|
err := util.MkdirAllX(filepath.Dir(t.path), t.perm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err))
|
return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err))
|
||||||
|
@ -131,11 +142,7 @@ func (t *boltForest) Open(_ context.Context, readOnly bool) error {
|
||||||
|
|
||||||
t.db.MaxBatchSize = t.maxBatchSize
|
t.db.MaxBatchSize = t.maxBatchSize
|
||||||
t.db.MaxBatchDelay = t.maxBatchDelay
|
t.db.MaxBatchDelay = t.maxBatchDelay
|
||||||
m := mode.ReadWrite
|
t.metrics.SetMode(mode)
|
||||||
if readOnly {
|
|
||||||
m = mode.ReadOnly
|
|
||||||
}
|
|
||||||
t.metrics.SetMode(m)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ func (f *memoryForest) Init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *memoryForest) Open(context.Context, bool) error {
|
func (f *memoryForest) Open(context.Context, mode.Mode) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
|
@ -24,7 +25,7 @@ var providers = []struct {
|
||||||
}{
|
}{
|
||||||
{"inmemory", func(t testing.TB, _ ...Option) ForestStorage {
|
{"inmemory", func(t testing.TB, _ ...Option) ForestStorage {
|
||||||
f := NewMemoryForest()
|
f := NewMemoryForest()
|
||||||
require.NoError(t, f.Open(context.Background(), false))
|
require.NoError(t, f.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, f.Init())
|
require.NoError(t, f.Init())
|
||||||
return f
|
return f
|
||||||
}},
|
}},
|
||||||
|
@ -34,7 +35,7 @@ var providers = []struct {
|
||||||
WithPath(filepath.Join(t.TempDir(), "test.db")),
|
WithPath(filepath.Join(t.TempDir(), "test.db")),
|
||||||
WithMaxBatchSize(1),
|
WithMaxBatchSize(1),
|
||||||
}, opts...)...)
|
}, opts...)...)
|
||||||
require.NoError(t, f.Open(context.Background(), false))
|
require.NoError(t, f.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, f.Init())
|
require.NoError(t, f.Init())
|
||||||
return f
|
return f
|
||||||
}},
|
}},
|
||||||
|
|
|
@ -58,7 +58,7 @@ type ForestStorage interface {
|
||||||
// DumpInfo returns information about the pilorama.
|
// DumpInfo returns information about the pilorama.
|
||||||
DumpInfo() Info
|
DumpInfo() Info
|
||||||
Init() error
|
Init() error
|
||||||
Open(context.Context, bool) error
|
Open(context.Context, mode.Mode) error
|
||||||
Close() error
|
Close() error
|
||||||
SetMode(m mode.Mode) error
|
SetMode(m mode.Mode) error
|
||||||
SetParentID(id string)
|
SetParentID(id string)
|
||||||
|
|
31
pkg/local_object_storage/pilorama/mode_test.go
Normal file
31
pkg/local_object_storage/pilorama/mode_test.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package pilorama
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Mode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
f := NewBoltForest(
|
||||||
|
[]Option{
|
||||||
|
WithPath(filepath.Join(t.TempDir(), "test.db")),
|
||||||
|
WithMaxBatchSize(1),
|
||||||
|
}...)
|
||||||
|
|
||||||
|
require.NoError(t, f.Open(context.Background(), mode.DegradedReadOnly))
|
||||||
|
require.Nil(t, f.(*boltForest).db)
|
||||||
|
require.NoError(t, f.Init())
|
||||||
|
require.Nil(t, f.(*boltForest).db)
|
||||||
|
require.NoError(t, f.Close())
|
||||||
|
|
||||||
|
require.NoError(t, f.Open(context.Background(), mode.Degraded))
|
||||||
|
require.Nil(t, f.(*boltForest).db)
|
||||||
|
require.NoError(t, f.Init())
|
||||||
|
require.Nil(t, f.(*boltForest).db)
|
||||||
|
require.NoError(t, f.Close())
|
||||||
|
}
|
|
@ -43,12 +43,17 @@ func (s *Shard) handleMetabaseFailure(stage string, err error) error {
|
||||||
// Open opens all Shard's components.
|
// Open opens all Shard's components.
|
||||||
func (s *Shard) Open(ctx context.Context) error {
|
func (s *Shard) Open(ctx context.Context) error {
|
||||||
components := []interface {
|
components := []interface {
|
||||||
Open(context.Context, bool) error
|
Open(context.Context, mode.Mode) error
|
||||||
}{
|
}{
|
||||||
s.blobStor, s.metaBase,
|
s.blobStor,
|
||||||
|
}
|
||||||
|
m := s.GetMode()
|
||||||
|
|
||||||
|
if !m.NoMetabase() {
|
||||||
|
components = append(components, s.metaBase)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.hasWriteCache() {
|
if s.hasWriteCache() && !m.NoMetabase() {
|
||||||
components = append(components, s.writeCache)
|
components = append(components, s.writeCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +62,12 @@ func (s *Shard) Open(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, component := range components {
|
for i, component := range components {
|
||||||
if err := component.Open(ctx, false); err != nil {
|
if err := component.Open(ctx, m); err != nil {
|
||||||
if component == s.metaBase {
|
if component == s.metaBase {
|
||||||
// We must first open all other components to avoid
|
// We must first open all other components to avoid
|
||||||
// opening non-existent DB in read-only mode.
|
// opening non-existent DB in read-only mode.
|
||||||
for j := i + 1; j < len(components); j++ {
|
for j := i + 1; j < len(components); j++ {
|
||||||
if err := components[j].Open(ctx, false); err != nil {
|
if err := components[j].Open(ctx, m); err != nil {
|
||||||
// Other components must be opened, fail.
|
// Other components must be opened, fail.
|
||||||
return fmt.Errorf("could not open %T: %w", components[j], err)
|
return fmt.Errorf("could not open %T: %w", components[j], err)
|
||||||
}
|
}
|
||||||
|
@ -97,8 +102,9 @@ func (s *Shard) Init(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var components []initializer
|
var components []initializer
|
||||||
|
m := s.GetMode()
|
||||||
|
|
||||||
if !s.GetMode().NoMetabase() {
|
if !m.NoMetabase() {
|
||||||
var initMetabase initializer
|
var initMetabase initializer
|
||||||
|
|
||||||
if s.NeedRefillMetabase() {
|
if s.NeedRefillMetabase() {
|
||||||
|
@ -114,7 +120,7 @@ func (s *Shard) Init(ctx context.Context) error {
|
||||||
components = []initializer{s.blobStor}
|
components = []initializer{s.blobStor}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.hasWriteCache() {
|
if s.hasWriteCache() && !m.NoMetabase() {
|
||||||
components = append(components, s.writeCache)
|
components = append(components, s.writeCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,11 @@ func (s *Shard) ID() *ID {
|
||||||
|
|
||||||
// UpdateID reads shard ID saved in the metabase and updates it if it is missing.
|
// UpdateID reads shard ID saved in the metabase and updates it if it is missing.
|
||||||
func (s *Shard) UpdateID(ctx context.Context) (err error) {
|
func (s *Shard) UpdateID(ctx context.Context) (err error) {
|
||||||
var metabaseOpened bool
|
|
||||||
var idFromMetabase []byte
|
var idFromMetabase []byte
|
||||||
if err = s.metaBase.Open(ctx, false); err != nil {
|
metabaseOpened := !s.GetMode().NoMetabase()
|
||||||
|
if err = s.metaBase.Open(ctx, s.GetMode()); err != nil {
|
||||||
err = fmt.Errorf("failed to open metabase: %w", err)
|
err = fmt.Errorf("failed to open metabase: %w", err)
|
||||||
} else {
|
metabaseOpened = false
|
||||||
metabaseOpened = true
|
|
||||||
}
|
}
|
||||||
if metabaseOpened {
|
if metabaseOpened {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil"
|
||||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -75,7 +76,7 @@ func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) {
|
func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) {
|
||||||
require.NoError(b, cache.Open(context.Background(), false), "opening")
|
require.NoError(b, cache.Open(context.Background(), mode.ReadWrite), "opening")
|
||||||
require.NoError(b, cache.Init(), "initializing")
|
require.NoError(b, cache.Init(), "initializing")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,8 +95,14 @@ func (c *cache) DumpInfo() Info {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open opens and initializes database. Reads object counters from the ObjectCounters instance.
|
// Open opens and initializes database. Reads object counters from the ObjectCounters instance.
|
||||||
func (c *cache) Open(_ context.Context, readOnly bool) error {
|
func (c *cache) Open(_ context.Context, mode mode.Mode) error {
|
||||||
err := c.openStore(readOnly)
|
c.modeMtx.Lock()
|
||||||
|
defer c.modeMtx.Unlock()
|
||||||
|
c.mode = mode
|
||||||
|
if mode.NoMetabase() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := c.openStore(mode.ReadOnly())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return metaerr.Wrap(err)
|
return metaerr.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ func newCache[Option any](
|
||||||
mb := meta.New(
|
mb := meta.New(
|
||||||
meta.WithPath(filepath.Join(dir, "meta")),
|
meta.WithPath(filepath.Join(dir, "meta")),
|
||||||
meta.WithEpochState(dummyEpoch{}))
|
meta.WithEpochState(dummyEpoch{}))
|
||||||
require.NoError(t, mb.Open(context.Background(), false))
|
require.NoError(t, mb.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, mb.Init())
|
require.NoError(t, mb.Init())
|
||||||
|
|
||||||
bs := blobstor.New(blobstor.WithStorages([]blobstor.SubStorage{
|
bs := blobstor.New(blobstor.WithStorages([]blobstor.SubStorage{
|
||||||
|
@ -213,11 +213,11 @@ func newCache[Option any](
|
||||||
fstree.WithDirNameLen(1)),
|
fstree.WithDirNameLen(1)),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
require.NoError(t, bs.Open(context.Background(), false))
|
require.NoError(t, bs.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, bs.Init())
|
require.NoError(t, bs.Init())
|
||||||
|
|
||||||
wc := createCacheFn(t, smallSize, mb, bs, opts...)
|
wc := createCacheFn(t, smallSize, mb, bs, opts...)
|
||||||
require.NoError(t, wc.Open(context.Background(), false))
|
require.NoError(t, wc.Open(context.Background(), mode.ReadWrite))
|
||||||
require.NoError(t, wc.Init())
|
require.NoError(t, wc.Init())
|
||||||
|
|
||||||
// First set mode for metabase and blobstor to prevent background flushes.
|
// First set mode for metabase and blobstor to prevent background flushes.
|
||||||
|
|
30
pkg/local_object_storage/writecache/mode_test.go
Normal file
30
pkg/local_object_storage/writecache/mode_test.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package writecache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
wc := New(
|
||||||
|
WithLogger(test.NewLogger(t)),
|
||||||
|
WithFlushWorkersCount(2),
|
||||||
|
WithPath(t.TempDir()))
|
||||||
|
|
||||||
|
require.NoError(t, wc.Open(context.Background(), mode.DegradedReadOnly))
|
||||||
|
require.Nil(t, wc.(*cache).db)
|
||||||
|
require.NoError(t, wc.Init())
|
||||||
|
require.Nil(t, wc.(*cache).db)
|
||||||
|
require.NoError(t, wc.Close())
|
||||||
|
|
||||||
|
require.NoError(t, wc.Open(context.Background(), mode.Degraded))
|
||||||
|
require.Nil(t, wc.(*cache).db)
|
||||||
|
require.NoError(t, wc.Init())
|
||||||
|
require.Nil(t, wc.(*cache).db)
|
||||||
|
require.NoError(t, wc.Close())
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ type Cache interface {
|
||||||
Seal(context.Context, bool) error
|
Seal(context.Context, bool) error
|
||||||
|
|
||||||
Init() error
|
Init() error
|
||||||
Open(ctx context.Context, readOnly bool) error
|
Open(ctx context.Context, mode mode.Mode) error
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue