[#1175] storage engine: Return status error on Inhume of locked object

Make `StorageEngine.Inhume` to forward first encountered
`apistatus.ObjectLocked` error during shard processing.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-02-16 01:24:43 +03:00 committed by LeL
parent 545861d1bc
commit 97b6ec8150

View file

@ -6,6 +6,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
) )
@ -50,6 +51,9 @@ var errInhumeFailure = errors.New("inhume operation failed")
// Inhume calls metabase. Inhume method to mark object as removed. It won't be // Inhume calls metabase. Inhume method to mark object as removed. It won't be
// removed physically from shard until `Delete` operation. // removed physically from shard until `Delete` operation.
// //
// Allows inhuming non-locked objects only. Returns apistatus.ObjectLocked
// if at least one object is locked.
//
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
func (e *StorageEngine) Inhume(prm *InhumePrm) (res *InhumeRes, err error) { func (e *StorageEngine) Inhume(prm *InhumePrm) (res *InhumeRes, err error) {
err = e.execIfNotBlocked(func() error { err = e.execIfNotBlocked(func() error {
@ -74,10 +78,14 @@ func (e *StorageEngine) inhume(prm *InhumePrm) (*InhumeRes, error) {
shPrm.MarkAsGarbage(prm.addrs[i]) shPrm.MarkAsGarbage(prm.addrs[i])
} }
ok := e.inhumeAddr(prm.addrs[i], shPrm, true) switch e.inhumeAddr(prm.addrs[i], shPrm, true) {
if !ok { case 1:
ok = e.inhumeAddr(prm.addrs[i], shPrm, false) return nil, apistatus.ObjectLocked{}
if !ok { case 0:
switch e.inhumeAddr(prm.addrs[i], shPrm, false) {
case 1:
return nil, apistatus.ObjectLocked{}
case 0:
return nil, errInhumeFailure return nil, errInhumeFailure
} }
} }
@ -86,8 +94,13 @@ func (e *StorageEngine) inhume(prm *InhumePrm) (*InhumeRes, error) {
return new(InhumeRes), nil return new(InhumeRes), nil
} }
func (e *StorageEngine) inhumeAddr(addr *addressSDK.Address, prm *shard.InhumePrm, checkExists bool) (ok bool) { // Returns:
// 0 - fail
// 1 - object locked
// 2 - ok
func (e *StorageEngine) inhumeAddr(addr *addressSDK.Address, prm *shard.InhumePrm, checkExists bool) (status uint8) {
root := false root := false
var errLocked apistatus.ObjectLocked
e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) {
defer func() { defer func() {
@ -105,7 +118,7 @@ func (e *StorageEngine) inhumeAddr(addr *addressSDK.Address, prm *shard.InhumePr
if err != nil { if err != nil {
if errors.Is(err, object.ErrAlreadyRemoved) { if errors.Is(err, object.ErrAlreadyRemoved) {
// inhumed once - no need to be inhumed again // inhumed once - no need to be inhumed again
ok = true status = 2
return true return true
} }
@ -124,11 +137,18 @@ func (e *StorageEngine) inhumeAddr(addr *addressSDK.Address, prm *shard.InhumePr
_, err := sh.Inhume(prm) _, err := sh.Inhume(prm)
if err != nil { if err != nil {
e.reportShardError(sh, "could not inhume object in shard", err) e.reportShardError(sh, "could not inhume object in shard", err)
} else {
ok = true if errors.As(err, &errLocked) {
status = 1
return true
}
return false
} }
return err == nil status = 2
return true
}) })
return return