diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index d3b4f9cc5..8dcb1fcac 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" "github.com/nspcc-dev/neofs-sdk-go/object" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "go.etcd.io/bbolt" @@ -69,6 +70,9 @@ const inhumeGCMarkValue = "GCMARK" var errBreakBucketForEach = errors.New("bucket ForEach break") // Inhume marks objects as removed but not removes it from metabase. +// +// Allows inhuming non-locked objects only. Returns apistatus.ObjectLocked +// if at least one object is locked. func (db *DB) Inhume(prm *InhumePrm) (res *InhumeRes, err error) { err = db.boltDB.Update(func(tx *bbolt.Tx) error { graveyard, err := tx.CreateBucketIfNotExists(graveyardBucketName) @@ -96,6 +100,11 @@ func (db *DB) Inhume(prm *InhumePrm) (res *InhumeRes, err error) { } for i := range prm.target { + // prevent locked objects to be inhumed + if objectLocked(tx, *prm.target[i].ContainerID(), *prm.target[i].ObjectID()) { + return apistatus.ObjectLocked{} + } + obj, err := db.get(tx, prm.target[i], false, true) // if object is stored and it is regular object then update bucket diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index 9e07228f8..e297cdbe6 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -6,6 +6,10 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" + objecttest "github.com/nspcc-dev/neofs-sdk-go/object/address/test" + oid "github.com/nspcc-dev/neofs-sdk-go/object/id" + oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) @@ -84,3 +88,20 @@ func TestInhumeTombOnTomb(t *testing.T) { require.NoError(t, err) require.False(t, res.Exists()) } + +func TestInhumeLocked(t *testing.T) { + db := newDB(t) + + locked := *objecttest.Address() + + err := db.Lock(*locked.ContainerID(), *oidtest.ID(), []oid.ID{*locked.ObjectID()}) + require.NoError(t, err) + + var prm meta.InhumePrm + prm.WithAddresses(&locked) + + _, err = db.Inhume(&prm) + + var e apistatus.ObjectLocked + require.ErrorAs(t, err, &e) +}