node: Set mode to shard's components when open it #967
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,21 +22,16 @@ 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)
|
err = db.Init()
|
||||||
}
|
}
|
||||||
if err == nil && !m.NoMetabase() && !m.ReadOnly() {
|
if err != nil {
|
||||||
err = db.Init()
|
return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.mode = m
|
db.mode = 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)
|
||||||
fyrchik
commented
No when the mode is provided to Open(), do we still need this if? It seems metabase knows to do nothing in Degraded mode. No when the mode is provided to Open(), do we still need this if? It seems metabase knows to do nothing in Degraded mode.
acid-ant
commented
Thanks, simplified this part. Thanks, simplified this part.
|
|||||||
} 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
It is necessary to put this in
New()
? It doesn't accepts such things by design, becausethey are provided in
Open
(wherero bool
parameter can be replaced withm mode.Mode
I guess)No, it is not necessary. But in this case, we need to store
mode
insideOpen
, except whenOpen
executed fromSetMode
.Updated, now
mode
propagated viaOpen
.