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..99fb8ae1c 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -16,6 +16,30 @@ 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. +// +// The list of locked objects should be unique. Panics if the list is empty. +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,7 +48,11 @@ 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) { + idCnr := prm.cnt + locker := prm.lock + locked := prm.locked + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Lock", trace.WithAttributes( attribute.String("container_id", idCnr.EncodeToString()), @@ -34,7 +62,7 @@ func (e *StorageEngine) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, l defer span.End() defer elapsed("Lock", e.metrics.AddMethodDuration)() - return e.execIfNotBlocked(func() error { + return LockRes{}, e.execIfNotBlocked(func() error { return e.lock(ctx, idCnr, locker, 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))