package shard import ( "context" "path/filepath" "testing" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) type epochState struct { Value uint64 } func (s epochState) CurrentEpoch() uint64 { return s.Value } func newShard(t testing.TB, enableWriteCache bool) *Shard { sh := newCustomShard(t, t.TempDir(), enableWriteCache, writecacheconfig.Options{Type: writecacheconfig.TypeBBolt}, nil, nil) t.Cleanup(func() { releaseShard(sh, t) }) return sh } func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts writecacheconfig.Options, bsOpts []blobstor.Option, metaOptions []meta.Option) *Shard { var sh *Shard if enableWriteCache { rootPath = filepath.Join(rootPath, "wc") switch wcOpts.Type { case writecacheconfig.TypeBBolt: wcOpts.BBoltOptions = append( []writecachebbolt.Option{writecachebbolt.WithPath(filepath.Join(rootPath, "wcache"))}, wcOpts.BBoltOptions...) case writecacheconfig.TypeBadger: wcOpts.BadgerOptions = append( []writecachebadger.Option{writecachebadger.WithPath(filepath.Join(rootPath, "wcache"))}, wcOpts.BadgerOptions...) } } else { rootPath = filepath.Join(rootPath, "nowc") } if bsOpts == nil { bsOpts = []blobstor.Option{ blobstor.WithLogger(test.NewLogger(t, true)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( blobovniczatree.WithLogger(test.NewLogger(t, true)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), Policy: func(_ *objectSDK.Object, data []byte) bool { return len(data) <= 1<<20 }, }, { Storage: fstree.New( fstree.WithPath(filepath.Join(rootPath, "blob"))), }, }), } } opts := []Option{ WithID(NewIDFromBytes([]byte{})), WithLogger(test.NewLogger(t, true)), WithBlobStorOptions(bsOpts...), WithMetaBaseOptions( append([]meta.Option{ meta.WithPath(filepath.Join(rootPath, "meta")), meta.WithEpochState(epochState{})}, metaOptions...)..., ), WithPiloramaOptions(pilorama.WithPath(filepath.Join(rootPath, "pilorama"))), WithWriteCache(enableWriteCache), WithWriteCacheOptions(wcOpts), WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { sh.HandleDeletedLocks(addresses) }), WithExpiredLocksCallback(func(ctx context.Context, epoch uint64, a []oid.Address) { sh.HandleExpiredLocks(ctx, epoch, a) }), WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool { pool, err := ants.NewPool(sz) require.NoError(t, err) return pool }), WithGCRemoverSleepInterval(100 * time.Millisecond), } sh = New(opts...) require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) return sh } func releaseShard(s *Shard, t testing.TB) { require.NoError(t, s.Close()) }