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 } type shardOptions struct { rootPath string dontRelease bool wcOpts writecacheconfig.Options bsOpts []blobstor.Option metaOptions []meta.Option additionalShardOptions []Option } func newShard(t testing.TB, enableWriteCache bool) *Shard { return newCustomShard(t, enableWriteCache, shardOptions{}) } func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard { if o.rootPath == "" { o.rootPath = t.TempDir() } if enableWriteCache && o.wcOpts.Type == 0 { o.wcOpts.Type = writecacheconfig.TypeBBolt } var sh *Shard if enableWriteCache { o.rootPath = filepath.Join(o.rootPath, "wc") switch o.wcOpts.Type { case writecacheconfig.TypeBBolt: o.wcOpts.BBoltOptions = append( []writecachebbolt.Option{writecachebbolt.WithPath(filepath.Join(o.rootPath, "wcache"))}, o.wcOpts.BBoltOptions...) case writecacheconfig.TypeBadger: o.wcOpts.BadgerOptions = append( []writecachebadger.Option{writecachebadger.WithPath(filepath.Join(o.rootPath, "wcache"))}, o.wcOpts.BadgerOptions...) } } else { o.rootPath = filepath.Join(o.rootPath, "nowc") } if o.bsOpts == nil { o.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(o.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(o.rootPath, "blob"))), }, }), } } opts := []Option{ WithID(NewIDFromBytes([]byte{})), WithLogger(test.NewLogger(t, true)), WithBlobStorOptions(o.bsOpts...), WithMetaBaseOptions( append([]meta.Option{ meta.WithPath(filepath.Join(o.rootPath, "meta")), meta.WithEpochState(epochState{})}, o.metaOptions...)..., ), WithPiloramaOptions(pilorama.WithPath(filepath.Join(o.rootPath, "pilorama"))), WithWriteCache(enableWriteCache), WithWriteCacheOptions(o.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), } opts = append(opts, o.additionalShardOptions...) sh = New(opts...) require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) if !o.dontRelease { t.Cleanup(func() { releaseShard(sh, t) }) } return sh } func releaseShard(s *Shard, t testing.TB) { require.NoError(t, s.Close()) }