From 0b7860100f43bf27b79ad86984811338b07a9263 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 15:46:07 +0300 Subject: [PATCH 1/5] [#1421] metabase: Use `LockPrm` to store Lock operation parameters Refactor `Lock` method to use `LockPrm` and `LockRes` structures to store operation parameters and results, respectively. Signed-off-by: Aleksey Savchuk --- .../metabase/inhume_test.go | 6 ++- .../metabase/iterators_test.go | 9 ++++- pkg/local_object_storage/metabase/lock.go | 40 ++++++++++++++----- .../metabase/lock_test.go | 23 ++++++++--- pkg/local_object_storage/shard/control.go | 7 +++- pkg/local_object_storage/shard/lock.go | 6 ++- .../populate-metabase/internal/populate.go | 6 ++- 7 files changed, 77 insertions(+), 20 deletions(-) diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index 786d10396..7394901ba 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -111,7 +111,11 @@ func TestInhumeLocked(t *testing.T) { locked := oidtest.Address() - err := db.Lock(context.Background(), locked.Container(), oidtest.ID(), []oid.ID{locked.Object()}) + var lockPrm meta.LockPrm + lockPrm.SetContainer(locked.Container()) + lockPrm.SetTarget(oidtest.ID(), locked.Object()) + + _, err := db.Lock(context.Background(), lockPrm) require.NoError(t, err) var prm meta.InhumePrm diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 4c9579965..e6f2c8264 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -35,9 +35,14 @@ func TestDB_IterateExpired(t *testing.T) { expiredLocked := putWithExpiration(t, db, objectSDK.TypeRegular, epoch-1) - require.NoError(t, db.Lock(context.Background(), expiredLocked.Container(), oidtest.ID(), []oid.ID{expiredLocked.Object()})) + var lockPrm meta.LockPrm + lockPrm.SetContainer(expiredLocked.Container()) + lockPrm.SetTarget(oidtest.ID(), expiredLocked.Object()) - err := db.IterateExpired(context.Background(), epoch, func(exp *meta.ExpiredObject) error { + _, err := db.Lock(context.Background(), lockPrm) + require.NoError(t, err) + + err = db.IterateExpired(context.Background(), epoch, func(exp *meta.ExpiredObject) error { if addr, ok := mAlive[exp.Type()]; ok { require.NotEqual(t, addr, exp.Address()) } diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index b930a0141..e003e3594 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -30,13 +30,35 @@ func bucketNameLockers(idCnr cid.ID, key []byte) []byte { return bucketName(idCnr, lockersPrefix, key) } +// LockPrm contains parameters for Lock operation. +type LockPrm struct { + cnt cid.ID + lock oid.ID + locked []oid.ID +} + +// SetContainer sets the container ID for both the lock and locked objects +// since they must belong to the same container. +func (p *LockPrm) SetContainer(cnt cid.ID) { + p.cnt = cnt +} + +// SetTarget sets lock object ID and IDs of objects to be locked. +func (p *LockPrm) SetTarget(lock oid.ID, locked ...oid.ID) { + p.lock = lock + p.locked = locked +} + +// LockPrm contains results for Lock operation. +type LockRes struct{} + // Lock marks objects as locked with another object. All objects are from the // specified container. // // Allows locking regular objects only (otherwise returns apistatus.LockNonRegularObject). // // Locked list should be unique. Panics if it is empty. -func (db *DB) Lock(ctx context.Context, cnr cid.ID, locker oid.ID, locked []oid.ID) error { +func (db *DB) Lock(ctx context.Context, prm LockPrm) (LockRes, error) { var ( startedAt = time.Now() success = false @@ -47,9 +69,9 @@ func (db *DB) Lock(ctx context.Context, cnr cid.ID, locker oid.ID, locked []oid. _, span := tracing.StartSpanFromContext(ctx, "metabase.Lock", trace.WithAttributes( - attribute.String("container_id", cnr.EncodeToString()), - attribute.String("locker", locker.EncodeToString()), - attribute.Int("locked_count", len(locked)), + attribute.String("container_id", prm.cnt.EncodeToString()), + attribute.String("locker", prm.lock.EncodeToString()), + attribute.Int("locked_count", len(prm.locked)), )) defer span.End() @@ -57,18 +79,18 @@ func (db *DB) Lock(ctx context.Context, cnr cid.ID, locker oid.ID, locked []oid. defer db.modeMtx.RUnlock() if db.mode.NoMetabase() { - return ErrDegradedMode + return LockRes{}, ErrDegradedMode } else if db.mode.ReadOnly() { - return ErrReadOnlyMode + return LockRes{}, ErrReadOnlyMode } - if len(locked) == 0 { + if len(prm.locked) == 0 { panic("empty locked list") } - err := db.lockInternal(locked, cnr, locker) + err := db.lockInternal(prm.locked, prm.cnt, prm.lock) success = err == nil - return err + return LockRes{}, err } func (db *DB) lockInternal(locked []oid.ID, cnr cid.ID, locker oid.ID) error { diff --git a/pkg/local_object_storage/metabase/lock_test.go b/pkg/local_object_storage/metabase/lock_test.go index 341ff9ad1..0fcc9d89c 100644 --- a/pkg/local_object_storage/metabase/lock_test.go +++ b/pkg/local_object_storage/metabase/lock_test.go @@ -23,9 +23,12 @@ func TestDB_Lock(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close(context.Background())) }() + var lockPrm meta.LockPrm + lockPrm.SetContainer(cnr) + t.Run("empty locked list", func(t *testing.T) { - require.Panics(t, func() { _ = db.Lock(context.Background(), cnr, oid.ID{}, nil) }) - require.Panics(t, func() { _ = db.Lock(context.Background(), cnr, oid.ID{}, []oid.ID{}) }) + lockPrm.SetTarget(oid.ID{}) + require.Panics(t, func() { _, _ = db.Lock(context.Background(), lockPrm) }) }) t.Run("(ir)regular", func(t *testing.T) { @@ -47,7 +50,8 @@ func TestDB_Lock(t *testing.T) { id, _ := obj.ID() // try to lock it - err = db.Lock(context.Background(), cnr, oidtest.ID(), []oid.ID{id}) + lockPrm.SetTarget(oidtest.ID(), id) + _, err = db.Lock(context.Background(), lockPrm) if typ == objectSDK.TypeRegular { require.NoError(t, err, typ) } else { @@ -198,7 +202,12 @@ func TestDB_Lock_Expired(t *testing.T) { require.ErrorIs(t, err, meta.ErrObjectIsExpired) // lock the obj - require.NoError(t, db.Lock(context.Background(), addr.Container(), oidtest.ID(), []oid.ID{addr.Object()})) + var lockPrm meta.LockPrm + lockPrm.SetContainer(addr.Container()) + lockPrm.SetTarget(oidtest.ID(), addr.Object()) + + _, err = db.Lock(context.Background(), lockPrm) + require.NoError(t, err) // object is expired but locked, thus, must be available _, err = metaGet(db, addr, false) @@ -277,7 +286,11 @@ func putAndLockObj(t *testing.T, db *meta.DB, numOfLockedObjs int) ([]*objectSDK err := putBig(db, lockObj) require.NoError(t, err) - err = db.Lock(context.Background(), cnr, lockID, lockedObjIDs) + var lockPrm meta.LockPrm + lockPrm.SetContainer(cnr) + lockPrm.SetTarget(lockID, lockedObjIDs...) + + _, err = db.Lock(context.Background(), lockPrm) require.NoError(t, err) return lockedObjs, lockObj diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 5a9e26155..3af00834e 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -326,7 +326,12 @@ func (s *Shard) refillLockObject(ctx context.Context, obj *objectSDK.Object) err cnr, _ := obj.ContainerID() id, _ := obj.ID() - err := s.metaBase.Lock(ctx, cnr, id, locked) + + var lockPrm meta.LockPrm + lockPrm.SetContainer(cnr) + lockPrm.SetTarget(id, locked...) + + _, err := s.metaBase.Lock(ctx, lockPrm) if err != nil { return fmt.Errorf("could not lock objects: %w", err) } diff --git a/pkg/local_object_storage/shard/lock.go b/pkg/local_object_storage/shard/lock.go index 31ca16aa1..b41019580 100644 --- a/pkg/local_object_storage/shard/lock.go +++ b/pkg/local_object_storage/shard/lock.go @@ -38,7 +38,11 @@ func (s *Shard) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, locked [] return ErrDegradedMode } - err := s.metaBase.Lock(ctx, idCnr, locker, locked) + var lockPrm meta.LockPrm + lockPrm.SetContainer(idCnr) + lockPrm.SetTarget(locker, locked...) + + _, err := s.metaBase.Lock(ctx, lockPrm) if err != nil { return fmt.Errorf("metabase lock: %w", err) } diff --git a/scripts/populate-metabase/internal/populate.go b/scripts/populate-metabase/internal/populate.go index 4da23a295..f4689ed11 100644 --- a/scripts/populate-metabase/internal/populate.go +++ b/scripts/populate-metabase/internal/populate.go @@ -253,7 +253,11 @@ func PopulateLocked( lockerOID, _ := locker.ID() group.Go(func() error { - if err := db.Lock(ctx, lockerCID, lockerOID, []oid.ID{id}); err != nil { + var lockPrm meta.LockPrm + lockPrm.SetContainer(lockerCID) + lockPrm.SetTarget(lockerOID, id) + + if _, err := db.Lock(ctx, lockPrm); err != nil { return fmt.Errorf("couldn't lock an object: %w", err) } return nil -- 2.45.2 From 0c8f031080f22e45824763ff0a824893aa56a533 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 16:06:18 +0300 Subject: [PATCH 2/5] [#1421] shard: Use `LockPrm` to store Lock operation parameters Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/lock.go | 9 +++- .../shard/control_test.go | 8 +++- pkg/local_object_storage/shard/gc_test.go | 12 +++++- pkg/local_object_storage/shard/lock.go | 42 ++++++++++++++----- pkg/local_object_storage/shard/lock_test.go | 12 +++++- 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 5d43e59df..47974eddd 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -62,6 +62,9 @@ func (e *StorageEngine) lock(ctx context.Context, idCnr cid.ID, locker oid.ID, l // - 1: locking irregular object // - 2: ok func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, locked oid.ID, checkExists bool) (status uint8) { + var lockPrm shard.LockPrm + lockPrm.SetContainer(idCnr) + // code is pretty similar to inhumeAddr, maybe unify? root := false var addrLocked oid.Address @@ -95,7 +98,8 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo } eclocked = append(eclocked, objID) } - err = sh.Lock(ctx, idCnr, locker, eclocked) + lockPrm.SetTarget(locker, eclocked...) + _, err = sh.Lock(ctx, lockPrm) if err != nil { e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) @@ -120,7 +124,8 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo } } - err := sh.Lock(ctx, idCnr, locker, []oid.ID{locked}) + lockPrm.SetTarget(locker, locked) + _, err := sh.Lock(ctx, lockPrm) if err != nil { e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 6d2cd7137..e76fe679f 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -283,7 +283,13 @@ func TestRefillMetabase(t *testing.T) { require.NoError(t, err) lockID, _ := lockObj.ID() - require.NoError(t, sh.Lock(context.Background(), cnrLocked, lockID, locked)) + + var lockPrm LockPrm + lockPrm.SetContainer(cnrLocked) + lockPrm.SetTarget(lockID, locked...) + + _, err = sh.Lock(context.Background(), lockPrm) + require.NoError(t, err) var inhumePrm InhumePrm inhumePrm.SetTarget(object.AddressOf(tombObj), tombMembers...) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index e3670b441..807f8cadd 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -61,7 +61,11 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { _, err := sh.Put(context.Background(), putPrm) require.NoError(t, err) - err = sh.Lock(context.Background(), cnr, lockID, []oid.ID{objID}) + var lockPrm LockPrm + lockPrm.SetContainer(cnr) + lockPrm.SetTarget(lockID, objID) + + _, err = sh.Lock(context.Background(), lockPrm) require.NoError(t, err) putPrm.SetObject(lock) @@ -150,7 +154,11 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { _, err := sh.Put(context.Background(), putPrm) require.NoError(t, err) - err = sh.Lock(context.Background(), cnr, lockID, append(childIDs, parentID, linkID)) + var lockPrm LockPrm + lockPrm.SetContainer(cnr) + lockPrm.SetTarget(lockID, append(childIDs, parentID, linkID)...) + + _, err = sh.Lock(context.Background(), lockPrm) require.NoError(t, err) putPrm.SetObject(lock) diff --git a/pkg/local_object_storage/shard/lock.go b/pkg/local_object_storage/shard/lock.go index b41019580..871b266b2 100644 --- a/pkg/local_object_storage/shard/lock.go +++ b/pkg/local_object_storage/shard/lock.go @@ -12,19 +12,41 @@ import ( "go.opentelemetry.io/otel/trace" ) +// LockPrm contains parameters for Lock operation. +type LockPrm struct { + cnt cid.ID + lock oid.ID + locked []oid.ID +} + +// SetContainer sets the container ID for both the lock and locked objects +// since they must belong to the same container. +func (p *LockPrm) SetContainer(cnt cid.ID) { + p.cnt = cnt +} + +// SetTarget sets lock object ID and IDs of objects to be locked. +func (p *LockPrm) SetTarget(lock oid.ID, locked ...oid.ID) { + p.lock = lock + p.locked = locked +} + +// LockPrm contains results for Lock operation. +type LockRes struct{} + // Lock marks objects as locked with another object. All objects from the // specified container. // // Allows locking regular objects only (otherwise returns apistatus.LockNonRegularObject). // // Locked list should be unique. Panics if it is empty. -func (s *Shard) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, locked []oid.ID) error { +func (s *Shard) Lock(ctx context.Context, prm LockPrm) (LockRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.Lock", trace.WithAttributes( attribute.String("shard_id", s.ID().String()), - attribute.String("container_id", idCnr.EncodeToString()), - attribute.String("locker", locker.EncodeToString()), - attribute.Int("locked_count", len(locked)), + attribute.String("container_id", prm.cnt.EncodeToString()), + attribute.String("locker", prm.lock.EncodeToString()), + attribute.Int("locked_count", len(prm.locked)), )) defer span.End() @@ -33,21 +55,21 @@ func (s *Shard) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, locked [] m := s.info.Mode if m.ReadOnly() { - return ErrReadOnlyMode + return LockRes{}, ErrReadOnlyMode } else if m.NoMetabase() { - return ErrDegradedMode + return LockRes{}, ErrDegradedMode } var lockPrm meta.LockPrm - lockPrm.SetContainer(idCnr) - lockPrm.SetTarget(locker, locked...) + lockPrm.SetContainer(prm.cnt) + lockPrm.SetTarget(prm.lock, prm.locked...) _, err := s.metaBase.Lock(ctx, lockPrm) if err != nil { - return fmt.Errorf("metabase lock: %w", err) + return LockRes{}, fmt.Errorf("metabase lock: %w", err) } - return nil + return LockRes{}, nil } // IsLocked checks object locking relation of the provided object. Not found object is diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 5caf3641f..f19b61c12 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -82,7 +82,11 @@ func TestShard_Lock(t *testing.T) { // lock the object - err = sh.Lock(context.Background(), cnr, lockID, []oid.ID{objID}) + var lockPrm LockPrm + lockPrm.SetContainer(cnr) + lockPrm.SetTarget(lockID, objID) + + _, err = sh.Lock(context.Background(), lockPrm) require.NoError(t, err) putPrm.SetObject(lock) @@ -173,8 +177,12 @@ func TestShard_IsLocked(t *testing.T) { require.False(t, locked) // locked object is locked + var lockPrm LockPrm + lockPrm.SetContainer(cnrID) + lockPrm.SetTarget(lockID, objID) - require.NoError(t, sh.Lock(context.Background(), cnrID, lockID, []oid.ID{objID})) + _, err = sh.Lock(context.Background(), lockPrm) + require.NoError(t, err) locked, err = sh.IsLocked(context.Background(), objectcore.AddressOf(obj)) require.NoError(t, err) -- 2.45.2 From e0f7513625ffc9f201cc0d7eaa75368a465cb836 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 16:18:22 +0300 Subject: [PATCH 3/5] [#1421] engine/test: Add missing error check after locking object Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/lock_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 7bb9e3934..4c239e45b 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -326,11 +326,12 @@ func TestLockExpiredRegularObject(t *testing.T) { require.ErrorAs(t, err, &errNotFound) t.Run("lock expired regular object", func(t *testing.T) { - engine.Lock(context.Background(), + err := engine.Lock(context.Background(), address.Container(), oidtest.ID(), []oid.ID{address.Object()}, ) + require.NoError(t, err) res, err := engine.IsLocked(context.Background(), objectcore.AddressOf(object)) require.NoError(t, err) -- 2.45.2 From edb2bc7b55bca733dd85bc0a72e8a66ecceb65e1 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 16:20:07 +0300 Subject: [PATCH 4/5] [#1421] engine/test: Add missing storage engine close Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume_test.go | 1 + pkg/local_object_storage/engine/lock_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 2d083a58c..763099a35 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -153,6 +153,7 @@ func TestInhumeExpiredRegularObject(t *testing.T) { )...), } }).prepare(t).engine + defer func() { require.NoError(t, engine.Close(context.Background())) }() cnr := cidtest.ID() diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 4c239e45b..76ce919cc 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -306,6 +306,7 @@ func TestLockExpiredRegularObject(t *testing.T) { )...), } }).prepare(t).engine + defer func() { require.NoError(t, engine.Close(context.Background())) }() cnr := cidtest.ID() -- 2.45.2 From fb5c4b0ad3f53da9ff4a76be20a735926ed257ee Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 16:24:44 +0300 Subject: [PATCH 5/5] [#1421] engine: Use `LockPrm` to store Lock operation parameters Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/object.go | 7 +++- pkg/local_object_storage/engine/lock.go | 34 ++++++++++++++++---- pkg/local_object_storage/engine/lock_test.go | 28 +++++++++++----- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 6804aae59..0095b34d2 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -481,7 +481,12 @@ func (e engineWithoutNotifications) Delete(ctx context.Context, tombstone oid.Ad } func (e engineWithoutNotifications) Lock(ctx context.Context, locker oid.Address, toLock []oid.ID) error { - return e.engine.Lock(ctx, locker.Container(), locker.Object(), toLock) + var prm engine.LockPrm + prm.WithContainer(locker.Container()) + prm.WithTarget(locker.Object(), toLock...) + + _, err := e.engine.Lock(ctx, prm) + return err } func (e engineWithoutNotifications) Put(ctx context.Context, o *objectSDK.Object, indexedContainer bool) error { diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 47974eddd..81d05bff3 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -16,6 +16,28 @@ import ( "go.uber.org/zap" ) +// LockPrm contains parameters for Lock operation. +type LockPrm struct { + cnt cid.ID + lock oid.ID + locked []oid.ID +} + +// WithContainer sets the container ID for both the lock and locked objects +// since they must belong to the same container. +func (p *LockPrm) WithContainer(cnt cid.ID) { + p.cnt = cnt +} + +// WithTarget sets lock object ID and IDs of objects to be locked. +func (p *LockPrm) WithTarget(lock oid.ID, locked ...oid.ID) { + p.lock = lock + p.locked = locked +} + +// LockPrm contains results for Lock operation. +type LockRes struct{} + var errLockFailed = errors.New("lock operation failed") // Lock marks objects as locked with another object. All objects from the @@ -24,18 +46,18 @@ var errLockFailed = errors.New("lock operation failed") // Allows locking regular objects only (otherwise returns apistatus.LockNonRegularObject). // // Locked list should be unique. Panics if it is empty. -func (e *StorageEngine) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, locked []oid.ID) error { +func (e *StorageEngine) Lock(ctx context.Context, prm LockPrm) (LockRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Lock", trace.WithAttributes( - attribute.String("container_id", idCnr.EncodeToString()), - attribute.String("locker", locker.EncodeToString()), - attribute.Int("locked_count", len(locked)), + attribute.String("container_id", prm.cnt.EncodeToString()), + attribute.String("locker", prm.lock.EncodeToString()), + attribute.Int("locked_count", len(prm.locked)), )) defer span.End() defer elapsed("Lock", e.metrics.AddMethodDuration)() - return e.execIfNotBlocked(func() error { - return e.lock(ctx, idCnr, locker, locked) + return LockRes{}, e.execIfNotBlocked(func() error { + return e.lock(ctx, prm.cnt, prm.lock, prm.locked) }) } diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 76ce919cc..2388226be 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -106,7 +106,11 @@ func TestLockUserScenario(t *testing.T) { err = Put(context.Background(), e, lockerObj, false) require.NoError(t, err) - err = e.Lock(context.Background(), cnr, lockerID, []oid.ID{id}) + var lockPrm LockPrm + lockPrm.WithContainer(cnr) + lockPrm.WithTarget(lockerID, id) + + _, err = e.Lock(context.Background(), lockPrm) require.NoError(t, err) // 3. @@ -191,7 +195,11 @@ func TestLockExpiration(t *testing.T) { id, _ := obj.ID() idLock, _ := lock.ID() - err = e.Lock(context.Background(), cnr, idLock, []oid.ID{id}) + var lockPrm LockPrm + lockPrm.WithContainer(cnr) + lockPrm.WithTarget(idLock, id) + + _, err = e.Lock(context.Background(), lockPrm) require.NoError(t, err) var inhumePrm InhumePrm @@ -262,7 +270,11 @@ func TestLockForceRemoval(t *testing.T) { id, _ := obj.ID() idLock, _ := lock.ID() - err = e.Lock(context.Background(), cnr, idLock, []oid.ID{id}) + var lockPrm LockPrm + lockPrm.WithContainer(cnr) + lockPrm.WithTarget(idLock, id) + + _, err = e.Lock(context.Background(), lockPrm) require.NoError(t, err) // 3. @@ -327,11 +339,11 @@ func TestLockExpiredRegularObject(t *testing.T) { require.ErrorAs(t, err, &errNotFound) t.Run("lock expired regular object", func(t *testing.T) { - err := engine.Lock(context.Background(), - address.Container(), - oidtest.ID(), - []oid.ID{address.Object()}, - ) + var lockPrm LockPrm + lockPrm.WithContainer(address.Container()) + lockPrm.WithTarget(oidtest.ID(), address.Object()) + + _, err := engine.Lock(context.Background(), lockPrm) require.NoError(t, err) res, err := engine.IsLocked(context.Background(), objectcore.AddressOf(object)) -- 2.45.2