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" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "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 wcOpts []writecache.Option 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() } var sh *Shard if enableWriteCache { o.wcOpts = append( []writecache.Option{writecache.WithPath(filepath.Join(o.rootPath, "wcache"))}, o.wcOpts...) } if o.bsOpts == nil { o.bsOpts = []blobstor.Option{ blobstor.WithLogger(test.NewLogger(t)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( context.Background(), blobovniczatree.WithLogger(test.NewLogger(t)), 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)), 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(context.Background())) require.NoError(t, sh.Init(context.Background())) return sh }