[#1247] object: Return NOT_FOUND and ALREADY_REMOVED statuses

Replace `ErrNotFound`/`ErrAlreadyRemoved` error from
`pkg/core/object` package with `ObjectNotFound`/`ObjectAlreadyRemoved`
one from `apistatus` package. These errors are returned by storage
node's server as NeoFS API statuses.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-03-17 11:03:58 +03:00 committed by Alex Vanin
parent f32c9670ad
commit 70ffdf3478
49 changed files with 348 additions and 178 deletions

View file

@ -2,13 +2,6 @@ package object
import "errors" import "errors"
// ErrNotFound is a basic "not found" error returned by
// object read functions.
var ErrNotFound = errors.New("object not found")
// ErrRangeOutOfBounds is a basic error of violation of the boundaries of the // ErrRangeOutOfBounds is a basic error of violation of the boundaries of the
// payload of an object. // payload of an object.
var ErrRangeOutOfBounds = errors.New("payload range is out of bounds") var ErrRangeOutOfBounds = errors.New("payload range is out of bounds")
// ErrAlreadyRemoved returned when object has tombstone in graveyard.
var ErrAlreadyRemoved = errors.New("object already removed")

View file

@ -7,12 +7,12 @@ import (
"time" "time"
clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client" clientcore "github.com/nspcc-dev/neofs-node/pkg/core/client"
coreObject "github.com/nspcc-dev/neofs-node/pkg/core/object"
neofsapiclient "github.com/nspcc-dev/neofs-node/pkg/innerring/internal/client" neofsapiclient "github.com/nspcc-dev/neofs-node/pkg/innerring/internal/client"
auditproc "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/audit" auditproc "github.com/nspcc-dev/neofs-node/pkg/innerring/processors/audit"
"github.com/nspcc-dev/neofs-node/pkg/network/cache" "github.com/nspcc-dev/neofs-node/pkg/network/cache"
"github.com/nspcc-dev/neofs-node/pkg/services/audit" "github.com/nspcc-dev/neofs-node/pkg/services/audit"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement" "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/object" "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"
@ -60,6 +60,8 @@ func (c *ClientCache) Get(info clientcore.NodeInfo) (clientcore.Client, error) {
// GetSG polls the container from audit task to get the object by id. // GetSG polls the container from audit task to get the object by id.
// Returns storage groups structure from received object. // Returns storage groups structure from received object.
//
// Returns apistatus.ObjectNotFound if storage group is missing.
func (c *ClientCache) GetSG(task *audit.Task, id *oidSDK.ID) (*storagegroup.StorageGroup, error) { func (c *ClientCache) GetSG(task *audit.Task, id *oidSDK.ID) (*storagegroup.StorageGroup, error) {
sgAddress := new(addressSDK.Address) sgAddress := new(addressSDK.Address)
sgAddress.SetContainerID(task.ContainerID()) sgAddress.SetContainerID(task.ContainerID())
@ -115,7 +117,9 @@ func (c *ClientCache) getSG(ctx context.Context, addr *addressSDK.Address, nm *n
return sg, nil return sg, nil
} }
return nil, coreObject.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
// GetHeader requests node from the container under audit to return object header by id. // GetHeader requests node from the container under audit to return object header by id.

View file

@ -167,6 +167,9 @@ func (s settlementDeps) ContainerNodes(e uint64, cid *cid.ID) ([]common.NodeInfo
return res, nil return res, nil
} }
// SGInfo returns audit.SGInfo by object address.
//
// Returns apistatus.ObjectNotFound if storage group is missing.
func (s settlementDeps) SGInfo(addr *addressSDK.Address) (audit.SGInfo, error) { func (s settlementDeps) SGInfo(addr *addressSDK.Address) (audit.SGInfo, error) {
cn, nm, err := s.buildContainer(0, addr.ContainerID()) cn, nm, err := s.buildContainer(0, addr.ContainerID())
if err != nil { if err != nil {

View file

@ -8,7 +8,6 @@ import (
"os" "os"
"testing" "testing"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/util/logger/test" "github.com/nspcc-dev/neofs-node/pkg/util/logger/test"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
@ -34,7 +33,7 @@ func testAddress() *addressSDK.Address {
return addr return addr
} }
func testPutGet(t *testing.T, blz *Blobovnicza, sz uint64, expPut, expGet error) *addressSDK.Address { func testPutGet(t *testing.T, blz *Blobovnicza, sz uint64, assertErrPut, assertErrGet func(error) bool) *addressSDK.Address {
// create binary object // create binary object
data := make([]byte, sz) data := make([]byte, sz)
@ -45,26 +44,34 @@ func testPutGet(t *testing.T, blz *Blobovnicza, sz uint64, expPut, expGet error)
pPut.SetAddress(addr) pPut.SetAddress(addr)
pPut.SetMarshaledObject(data) pPut.SetMarshaledObject(data)
_, err := blz.Put(pPut) _, err := blz.Put(pPut)
require.True(t, errors.Is(err, expPut)) if assertErrPut != nil {
require.True(t, assertErrPut(err))
} else {
require.NoError(t, err)
}
if expPut != nil { if assertErrPut != nil {
return nil return nil
} }
testGet(t, blz, addr, data, expGet) testGet(t, blz, addr, data, assertErrGet)
return addr return addr
} }
func testGet(t *testing.T, blz *Blobovnicza, addr *addressSDK.Address, expObj []byte, expErr error) { func testGet(t *testing.T, blz *Blobovnicza, addr *addressSDK.Address, expObj []byte, assertErr func(error) bool) {
pGet := new(GetPrm) pGet := new(GetPrm)
pGet.SetAddress(addr) pGet.SetAddress(addr)
// try to read object from Blobovnicza // try to read object from Blobovnicza
res, err := blz.Get(pGet) res, err := blz.Get(pGet)
require.True(t, errors.Is(err, expErr)) if assertErr != nil {
require.True(t, assertErr(err))
} else {
require.NoError(t, err)
}
if expErr == nil { if assertErr == nil {
require.Equal(t, expObj, res.Object()) require.Equal(t, expObj, res.Object())
} }
} }
@ -94,7 +101,7 @@ func TestBlobovnicza(t *testing.T) {
require.NoError(t, blz.Init()) require.NoError(t, blz.Init())
// try to read non-existent address // try to read non-existent address
testGet(t, blz, testAddress(), nil, object.ErrNotFound) testGet(t, blz, testAddress(), nil, IsErrNotFound)
filled := uint64(15 * 1 << 10) filled := uint64(15 * 1 << 10)
@ -109,7 +116,7 @@ func TestBlobovnicza(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// should return 404 // should return 404
testGet(t, blz, addr, nil, object.ErrNotFound) testGet(t, blz, addr, nil, IsErrNotFound)
// fill Blobovnicza fully // fill Blobovnicza fully
for ; filled < sizeLim; filled += objSizeLim { for ; filled < sizeLim; filled += objSizeLim {
@ -117,7 +124,9 @@ func TestBlobovnicza(t *testing.T) {
} }
// from now objects should not be saved // from now objects should not be saved
testPutGet(t, blz, 1024, ErrFull, nil) testPutGet(t, blz, 1024, func(err error) bool {
return errors.Is(err, ErrFull)
}, nil)
require.NoError(t, blz.Close()) require.NoError(t, blz.Close())
} }

View file

@ -1,7 +1,7 @@
package blobovnicza package blobovnicza
import ( import (
"github.com/nspcc-dev/neofs-node/pkg/core/object" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
"go.uber.org/zap" "go.uber.org/zap"
@ -26,7 +26,7 @@ func (p *DeletePrm) SetAddress(addr *addressSDK.Address) {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely delete the object. // did not allow to completely delete the object.
// //
// Returns ErrNotFound if the object to be deleted is not in blobovnicza. // Returns apistatus.ObjectNotFound if the object to be deleted is not in blobovnicza.
// //
// Should not be called in read-only configuration. // Should not be called in read-only configuration.
func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) { func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) {
@ -65,7 +65,9 @@ func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) {
}) })
if err == nil && !removed { if err == nil && !removed {
err = object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return nil, err return nil, err

View file

@ -0,0 +1,13 @@
package blobovnicza
import (
"errors"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
)
// IsErrNotFound checks if error returned by Blobovnicza Get/Delete method
// corresponds to missing object.
func IsErrNotFound(err error) bool {
return errors.As(err, new(apistatus.ObjectNotFound))
}

View file

@ -1,7 +1,7 @@
package blobovnicza package blobovnicza
import ( import (
"github.com/nspcc-dev/neofs-node/pkg/core/object" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
"go.uber.org/zap" "go.uber.org/zap"
@ -32,7 +32,7 @@ func (p *GetRes) Object() []byte {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object. // did not allow to completely read the object.
// //
// Returns ErrNotFound if requested object is not // Returns apistatus.ObjectNotFound if requested object is not
// presented in Blobovnicza. // presented in Blobovnicza.
func (b *Blobovnicza) Get(prm *GetPrm) (*GetRes, error) { func (b *Blobovnicza) Get(prm *GetPrm) (*GetRes, error) {
var ( var (
@ -60,7 +60,9 @@ func (b *Blobovnicza) Get(prm *GetPrm) (*GetRes, error) {
} }
if data == nil { if data == nil {
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return &GetRes{ return &GetRes{

View file

@ -13,6 +13,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/blobovnicza" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log" storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
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"
"go.uber.org/zap" "go.uber.org/zap"
@ -224,7 +225,7 @@ func (b *blobovniczas) get(prm *GetSmallPrm) (res *GetSmallRes, err error) {
res, err = b.getObjectFromLevel(bPrm, p, !ok) res, err = b.getObjectFromLevel(bPrm, p, !ok)
if err != nil { if err != nil {
if !errors.Is(err, object.ErrNotFound) { if !blobovnicza.IsErrNotFound(err) {
b.log.Debug("could not get object from level", b.log.Debug("could not get object from level",
zap.String("level", p), zap.String("level", p),
zap.String("error", err.Error()), zap.String("error", err.Error()),
@ -240,7 +241,9 @@ func (b *blobovniczas) get(prm *GetSmallPrm) (res *GetSmallRes, err error) {
if err == nil && res == nil { if err == nil && res == nil {
// not found in any blobovnicza // not found in any blobovnicza
err = object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return return
@ -273,7 +276,7 @@ func (b *blobovniczas) delete(prm *DeleteSmallPrm) (res *DeleteSmallRes, err err
res, err = b.deleteObjectFromLevel(bPrm, p, !ok, prm) res, err = b.deleteObjectFromLevel(bPrm, p, !ok, prm)
if err != nil { if err != nil {
if !errors.Is(err, object.ErrNotFound) { if !blobovnicza.IsErrNotFound(err) {
b.log.Debug("could not remove object from level", b.log.Debug("could not remove object from level",
zap.String("level", p), zap.String("level", p),
zap.String("error", err.Error()), zap.String("error", err.Error()),
@ -293,7 +296,9 @@ func (b *blobovniczas) delete(prm *DeleteSmallPrm) (res *DeleteSmallRes, err err
if err == nil && res == nil { if err == nil && res == nil {
// not found in any blobovnicza // not found in any blobovnicza
err = object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return return
@ -323,7 +328,7 @@ func (b *blobovniczas) getRange(prm *GetRangeSmallPrm) (res *GetRangeSmallRes, e
res, err = b.getRangeFromLevel(prm, p, !ok) res, err = b.getRangeFromLevel(prm, p, !ok)
if err != nil { if err != nil {
outOfBounds := errors.Is(err, object.ErrRangeOutOfBounds) outOfBounds := errors.Is(err, object.ErrRangeOutOfBounds)
if !errors.Is(err, object.ErrNotFound) && !outOfBounds { if !blobovnicza.IsErrNotFound(err) && !outOfBounds {
b.log.Debug("could not get object from level", b.log.Debug("could not get object from level",
zap.String("level", p), zap.String("level", p),
zap.String("error", err.Error()), zap.String("error", err.Error()),
@ -342,7 +347,9 @@ func (b *blobovniczas) getRange(prm *GetRangeSmallPrm) (res *GetRangeSmallRes, e
if err == nil && res == nil { if err == nil && res == nil {
// not found in any blobovnicza // not found in any blobovnicza
err = object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return return
@ -365,7 +372,7 @@ func (b *blobovniczas) deleteObjectFromLevel(prm *blobovnicza.DeletePrm, blzPath
if ok { if ok {
if res, err := b.deleteObject(v.(*blobovnicza.Blobovnicza), prm, dp); err == nil { if res, err := b.deleteObject(v.(*blobovnicza.Blobovnicza), prm, dp); err == nil {
return res, err return res, err
} else if !errors.Is(err, object.ErrNotFound) { } else if !blobovnicza.IsErrNotFound(err) {
log.Debug("could not remove object from opened blobovnicza", log.Debug("could not remove object from opened blobovnicza",
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -383,7 +390,7 @@ func (b *blobovniczas) deleteObjectFromLevel(prm *blobovnicza.DeletePrm, blzPath
if ok && tryActive { if ok && tryActive {
if res, err := b.deleteObject(active.blz, prm, dp); err == nil { if res, err := b.deleteObject(active.blz, prm, dp); err == nil {
return res, err return res, err
} else if !errors.Is(err, object.ErrNotFound) { } else if !blobovnicza.IsErrNotFound(err) {
log.Debug("could not remove object from active blobovnicza", log.Debug("could not remove object from active blobovnicza",
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -397,7 +404,9 @@ func (b *blobovniczas) deleteObjectFromLevel(prm *blobovnicza.DeletePrm, blzPath
// and it's pointless to open them). // and it's pointless to open them).
if u64FromHexString(filepath.Base(blzPath)) > active.ind { if u64FromHexString(filepath.Base(blzPath)) > active.ind {
log.Debug("index is too big") log.Debug("index is too big")
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
// open blobovnicza (cached inside) // open blobovnicza (cached inside)
@ -426,7 +435,7 @@ func (b *blobovniczas) getObjectFromLevel(prm *blobovnicza.GetPrm, blzPath strin
if ok { if ok {
if res, err := b.getObject(v.(*blobovnicza.Blobovnicza), prm); err == nil { if res, err := b.getObject(v.(*blobovnicza.Blobovnicza), prm); err == nil {
return res, err return res, err
} else if !errors.Is(err, object.ErrNotFound) { } else if !blobovnicza.IsErrNotFound(err) {
log.Debug("could not read object from opened blobovnicza", log.Debug("could not read object from opened blobovnicza",
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -445,7 +454,7 @@ func (b *blobovniczas) getObjectFromLevel(prm *blobovnicza.GetPrm, blzPath strin
if ok && tryActive { if ok && tryActive {
if res, err := b.getObject(active.blz, prm); err == nil { if res, err := b.getObject(active.blz, prm); err == nil {
return res, err return res, err
} else if !errors.Is(err, object.ErrNotFound) { } else if !blobovnicza.IsErrNotFound(err) {
log.Debug("could not get object from active blobovnicza", log.Debug("could not get object from active blobovnicza",
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -459,7 +468,9 @@ func (b *blobovniczas) getObjectFromLevel(prm *blobovnicza.GetPrm, blzPath strin
// and it's pointless to open them). // and it's pointless to open them).
if u64FromHexString(filepath.Base(blzPath)) > active.ind { if u64FromHexString(filepath.Base(blzPath)) > active.ind {
log.Debug("index is too big") log.Debug("index is too big")
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
// open blobovnicza (cached inside) // open blobovnicza (cached inside)
@ -492,7 +503,7 @@ func (b *blobovniczas) getRangeFromLevel(prm *GetRangeSmallPrm, blzPath string,
errors.Is(err, object.ErrRangeOutOfBounds): errors.Is(err, object.ErrRangeOutOfBounds):
return res, err return res, err
default: default:
if !errors.Is(err, object.ErrNotFound) { if !blobovnicza.IsErrNotFound(err) {
log.Debug("could not read payload range from opened blobovnicza", log.Debug("could not read payload range from opened blobovnicza",
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -516,7 +527,7 @@ func (b *blobovniczas) getRangeFromLevel(prm *GetRangeSmallPrm, blzPath string,
errors.Is(err, object.ErrRangeOutOfBounds): errors.Is(err, object.ErrRangeOutOfBounds):
return res, err return res, err
default: default:
if !errors.Is(err, object.ErrNotFound) { if !blobovnicza.IsErrNotFound(err) {
log.Debug("could not read payload range from active blobovnicza", log.Debug("could not read payload range from active blobovnicza",
zap.String("error", err.Error()), zap.String("error", err.Error()),
) )
@ -531,7 +542,10 @@ func (b *blobovniczas) getRangeFromLevel(prm *GetRangeSmallPrm, blzPath string,
// and it's pointless to open them). // and it's pointless to open them).
if u64FromHexString(filepath.Base(blzPath)) > active.ind { if u64FromHexString(filepath.Base(blzPath)) > active.ind {
log.Debug("index is too big") log.Debug("index is too big")
return nil, object.ErrNotFound
var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
// open blobovnicza (cached inside) // open blobovnicza (cached inside)

View file

@ -2,13 +2,13 @@ package blobstor
import ( import (
"crypto/sha256" "crypto/sha256"
"errors"
"math/rand" "math/rand"
"os" "os"
"testing" "testing"
"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/util/logger/test" "github.com/nspcc-dev/neofs-node/pkg/util/logger/test"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
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"
@ -153,9 +153,9 @@ func TestBlobovniczas(t *testing.T) {
gPrm.SetAddress(addrList[i]) gPrm.SetAddress(addrList[i])
_, err = b.get(gPrm) _, err = b.get(gPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
_, err = b.delete(dPrm) _, err = b.delete(dPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
} }
} }

View file

@ -3,9 +3,9 @@ package blobstor
import ( import (
"errors" "errors"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log" storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
) )
// DeleteBigPrm groups the parameters of DeleteBig operation. // DeleteBigPrm groups the parameters of DeleteBig operation.
@ -21,11 +21,13 @@ type DeleteBigRes struct{}
// Returns any error encountered that did not allow // Returns any error encountered that did not allow
// to completely remove the object. // to completely remove the object.
// //
// Returns ErrNotFound if there is no object to delete. // Returns apistatus.ObjectNotFound if there is no object to delete.
func (b *BlobStor) DeleteBig(prm *DeleteBigPrm) (*DeleteBigRes, error) { func (b *BlobStor) DeleteBig(prm *DeleteBigPrm) (*DeleteBigRes, error) {
err := b.fsTree.Delete(prm.addr) err := b.fsTree.Delete(prm.addr)
if errors.Is(err, fstree.ErrFileNotFound) { if errors.Is(err, fstree.ErrFileNotFound) {
err = object.ErrNotFound var errNotFound apistatus.ObjectNotFound
err = errNotFound
} }
if err == nil { if err == nil {

View file

@ -17,7 +17,7 @@ type DeleteSmallRes struct{}
// Returns any error encountered that did not allow // Returns any error encountered that did not allow
// to completely remove the object. // to completely remove the object.
// //
// Returns ErrObjectNotFound if there is no object to delete. // Returns apistatus.ObjectNotFound if there is no object to delete.
func (b *BlobStor) DeleteSmall(prm *DeleteSmallPrm) (*DeleteSmallRes, error) { func (b *BlobStor) DeleteSmall(prm *DeleteSmallPrm) (*DeleteSmallRes, error) {
return b.blobovniczas.delete(prm) return b.blobovniczas.delete(prm)
} }

View file

@ -4,8 +4,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
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"
) )
@ -24,14 +24,16 @@ type GetBigRes struct {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object. // did not allow to completely read the object.
// //
// Returns ErrNotFound if requested object is not // Returns apistatus.ObjectNotFound if requested object is not
// presented in shallow dir. // presented in shallow dir.
func (b *BlobStor) GetBig(prm *GetBigPrm) (*GetBigRes, error) { func (b *BlobStor) GetBig(prm *GetBigPrm) (*GetBigRes, error) {
// get compressed object data // get compressed object data
data, err := b.fsTree.Get(prm.addr) data, err := b.fsTree.Get(prm.addr)
if err != nil { if err != nil {
if errors.Is(err, fstree.ErrFileNotFound) { if errors.Is(err, fstree.ErrFileNotFound) {
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return nil, fmt.Errorf("could not read object from fs tree: %w", err) return nil, fmt.Errorf("could not read object from fs tree: %w", err)

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/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
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"
) )
@ -26,12 +27,15 @@ type GetRangeBigRes struct {
// did not allow to completely read the object payload range. // did not allow to completely read the object payload range.
// //
// Returns ErrRangeOutOfBounds if requested object range is out of bounds. // Returns ErrRangeOutOfBounds if requested object range is out of bounds.
// Returns apistatus.ObjectNotFound if object is missing.
func (b *BlobStor) GetRangeBig(prm *GetRangeBigPrm) (*GetRangeBigRes, error) { func (b *BlobStor) GetRangeBig(prm *GetRangeBigPrm) (*GetRangeBigRes, error) {
// get compressed object data // get compressed object data
data, err := b.fsTree.Get(prm.addr) data, err := b.fsTree.Get(prm.addr)
if err != nil { if err != nil {
if errors.Is(err, fstree.ErrFileNotFound) { if errors.Is(err, fstree.ErrFileNotFound) {
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return nil, fmt.Errorf("could not read object from fs tree: %w", err) return nil, fmt.Errorf("could not read object from fs tree: %w", err)

View file

@ -21,6 +21,7 @@ type GetRangeSmallRes struct {
// did not allow to completely read the object payload range. // did not allow to completely read the object payload range.
// //
// Returns ErrRangeOutOfBounds if requested object range is out of bounds. // Returns ErrRangeOutOfBounds if requested object range is out of bounds.
// Returns apistatus.ObjectNotFound if requested object is missing in blobovnicza(s).
func (b *BlobStor) GetRangeSmall(prm *GetRangeSmallPrm) (*GetRangeSmallRes, error) { func (b *BlobStor) GetRangeSmall(prm *GetRangeSmallPrm) (*GetRangeSmallRes, error) {
return b.blobovniczas.getRange(prm) return b.blobovniczas.getRange(prm)
} }

View file

@ -18,6 +18,8 @@ type GetSmallRes struct {
// //
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object. // did not allow to completely read the object.
//
// Returns apistatus.ObjectNotFound if requested object is missing in blobovnicza(s).
func (b *BlobStor) GetSmall(prm *GetSmallPrm) (*GetSmallRes, error) { func (b *BlobStor) GetSmall(prm *GetSmallPrm) (*GetSmallRes, error) {
return b.blobovniczas.get(prm) return b.blobovniczas.get(prm)
} }

View file

@ -1,10 +1,8 @@
package engine package engine
import ( import (
"errors"
"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"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
) )
@ -16,7 +14,7 @@ func (e *StorageEngine) exists(addr *addressSDK.Address) (bool, error) {
e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) {
res, err := sh.Exists(shPrm) res, err := sh.Exists(shPrm)
if err != nil { if err != nil {
if errors.Is(err, object.ErrAlreadyRemoved) { if shard.IsErrRemoved(err) {
alreadyRemoved = true alreadyRemoved = true
return true return true
@ -33,7 +31,9 @@ func (e *StorageEngine) exists(addr *addressSDK.Address) (bool, error) {
}) })
if alreadyRemoved { if alreadyRemoved {
return false, object.ErrAlreadyRemoved var errRemoved apistatus.ObjectAlreadyRemoved
return false, errRemoved
} }
return exists, nil return exists, nil

View file

@ -3,9 +3,9 @@ package engine
import ( import (
"errors" "errors"
"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"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
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"
"go.uber.org/zap" "go.uber.org/zap"
@ -42,7 +42,8 @@ func (r *GetRes) Object() *objectSDK.Object {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object part. // did not allow to completely read the object part.
// //
// Returns ErrNotFound if requested object is missing in local storage. // Returns apistatus.ObjectNotFound if requested object is missing in local storage.
// Returns apistatus.ObjectAlreadyRemoved if object has been marked as removed.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
func (e *StorageEngine) Get(prm *GetPrm) (res *GetRes, err error) { func (e *StorageEngine) Get(prm *GetPrm) (res *GetRes, err error) {
@ -63,8 +64,10 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) {
obj *objectSDK.Object obj *objectSDK.Object
siErr *objectSDK.SplitInfoError siErr *objectSDK.SplitInfoError
errNotFound apistatus.ObjectNotFound
outSI *objectSDK.SplitInfo outSI *objectSDK.SplitInfo
outError = object.ErrNotFound outError error = errNotFound
shardWithMeta hashedShard shardWithMeta hashedShard
metaError error metaError error
@ -81,7 +84,7 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) {
metaError = err metaError = err
} }
switch { switch {
case errors.Is(err, object.ErrNotFound): case shard.IsErrNotFound(err):
return false // ignore, go to next shard return false // ignore, go to next shard
case errors.As(err, &siErr): case errors.As(err, &siErr):
siErr = err.(*objectSDK.SplitInfoError) siErr = err.(*objectSDK.SplitInfoError)
@ -98,7 +101,7 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) {
} }
return false return false
case errors.Is(err, object.ErrAlreadyRemoved): case shard.IsErrRemoved(err):
outError = err outError = err
return true // stop, return it back return true // stop, return it back
@ -118,7 +121,7 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) {
} }
if obj == nil { if obj == nil {
if shardWithMeta.Shard == nil || !errors.Is(outError, object.ErrNotFound) { if shardWithMeta.Shard == nil || !shard.IsErrNotFound(outError) {
return nil, outError return nil, outError
} }

View file

@ -3,9 +3,9 @@ package engine
import ( import (
"errors" "errors"
"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"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
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"
) )
@ -55,8 +55,8 @@ func (r *HeadRes) Header() *objectSDK.Object {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object header. // did not allow to completely read the object header.
// //
// Returns object.ErrNotFound if requested object is missing in local storage. // Returns apistatus.ObjectNotFound if requested object is missing in local storage.
// Returns object.ErrAlreadyRemoved if requested object was inhumed. // Returns apistatus.ObjectAlreadyRemoved if requested object was inhumed.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
func (e *StorageEngine) Head(prm *HeadPrm) (res *HeadRes, err error) { func (e *StorageEngine) Head(prm *HeadPrm) (res *HeadRes, err error) {
@ -77,8 +77,10 @@ func (e *StorageEngine) head(prm *HeadPrm) (*HeadRes, error) {
head *objectSDK.Object head *objectSDK.Object
siErr *objectSDK.SplitInfoError siErr *objectSDK.SplitInfoError
errNotFound apistatus.ObjectNotFound
outSI *objectSDK.SplitInfo outSI *objectSDK.SplitInfo
outError = object.ErrNotFound outError error = errNotFound
) )
shPrm := new(shard.HeadPrm). shPrm := new(shard.HeadPrm).
@ -89,7 +91,7 @@ func (e *StorageEngine) head(prm *HeadPrm) (*HeadRes, error) {
res, err := sh.Head(shPrm) res, err := sh.Head(shPrm)
if err != nil { if err != nil {
switch { switch {
case errors.Is(err, object.ErrNotFound): case shard.IsErrNotFound(err):
return false // ignore, go to next shard return false // ignore, go to next shard
case errors.As(err, &siErr): case errors.As(err, &siErr):
siErr = err.(*objectSDK.SplitInfoError) siErr = err.(*objectSDK.SplitInfoError)
@ -106,7 +108,7 @@ func (e *StorageEngine) head(prm *HeadPrm) (*HeadRes, error) {
} }
return false return false
case errors.Is(err, object.ErrAlreadyRemoved): case shard.IsErrRemoved(err):
outError = err outError = err
return true // stop, return it back return true // stop, return it back

View file

@ -4,7 +4,6 @@ import (
"context" "context"
"errors" "errors"
"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" 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"
@ -116,7 +115,7 @@ func (e *StorageEngine) inhumeAddr(addr *addressSDK.Address, prm *shard.InhumePr
WithAddress(addr), WithAddress(addr),
) )
if err != nil { if err != nil {
if errors.Is(err, object.ErrAlreadyRemoved) { if shard.IsErrRemoved(err) {
// inhumed once - no need to be inhumed again // inhumed once - no need to be inhumed again
status = 2 status = 2
return true return true

View file

@ -36,6 +36,8 @@ func (p *PutPrm) WithObject(obj *objectSDK.Object) *PutPrm {
// did not allow to completely save the object. // did not allow to completely save the object.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
//
// Returns apistatus.ObjectAlreadyRemoved if object has been marked as removed.
func (e *StorageEngine) Put(prm *PutPrm) (res *PutRes, err error) { func (e *StorageEngine) Put(prm *PutPrm) (res *PutRes, err error) {
err = e.execIfNotBlocked(func() error { err = e.execIfNotBlocked(func() error {
res, err = e.put(prm) res, err = e.put(prm)

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"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
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"
"go.uber.org/zap" "go.uber.org/zap"
@ -58,8 +59,8 @@ func (r *RngRes) Object() *objectSDK.Object {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object part. // did not allow to completely read the object part.
// //
// Returns ErrNotFound if requested object is missing in local storage. // Returns apistatus.ObjectNotFound if requested object is missing in local storage.
// Returns ErrAlreadyRemoved if requested object is inhumed. // Returns apistatus.ObjectAlreadyRemoved if requested object is inhumed.
// Returns ErrRangeOutOfBounds if requested object range is out of bounds. // Returns ErrRangeOutOfBounds if requested object range is out of bounds.
// //
// Returns an error if executions are blocked (see BlockExecution). // Returns an error if executions are blocked (see BlockExecution).
@ -81,8 +82,10 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) {
obj *objectSDK.Object obj *objectSDK.Object
siErr *objectSDK.SplitInfoError siErr *objectSDK.SplitInfoError
errNotFound apistatus.ObjectNotFound
outSI *objectSDK.SplitInfo outSI *objectSDK.SplitInfo
outError = object.ErrNotFound outError error = errNotFound
shardWithMeta hashedShard shardWithMeta hashedShard
metaError error metaError error
@ -100,7 +103,7 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) {
metaError = err metaError = err
} }
switch { switch {
case errors.Is(err, object.ErrNotFound): case shard.IsErrNotFound(err):
return false // ignore, go to next shard return false // ignore, go to next shard
case errors.As(err, &siErr): case errors.As(err, &siErr):
siErr = err.(*objectSDK.SplitInfoError) siErr = err.(*objectSDK.SplitInfoError)
@ -118,7 +121,7 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) {
return false return false
case case
errors.Is(err, object.ErrAlreadyRemoved), shard.IsErrRemoved(err),
errors.Is(err, object.ErrRangeOutOfBounds): errors.Is(err, object.ErrRangeOutOfBounds):
outError = err outError = err
@ -139,7 +142,7 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) {
} }
if obj == nil { if obj == nil {
if shardWithMeta.Shard == nil || !errors.Is(outError, object.ErrNotFound) { if shardWithMeta.Shard == nil || !shard.IsErrNotFound(outError) {
return nil, outError return nil, outError
} }

View file

@ -20,9 +20,13 @@ func TestReset(t *testing.T) {
addrToInhume := generateAddress() addrToInhume := generateAddress()
assertExists := func(addr *addressSDK.Address, expExists bool, expErr error) { assertExists := func(addr *addressSDK.Address, expExists bool, assertErr func(error) bool) {
exists, err := meta.Exists(db, addr) exists, err := meta.Exists(db, addr)
require.ErrorIs(t, err, expErr) if assertErr != nil {
require.True(t, assertErr(err))
} else {
require.NoError(t, err)
}
require.Equal(t, expExists, exists) require.Equal(t, expExists, exists)
} }
@ -36,7 +40,7 @@ func TestReset(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
assertExists(addr, true, nil) assertExists(addr, true, nil)
assertExists(addrToInhume, false, object.ErrAlreadyRemoved) assertExists(addrToInhume, false, meta.IsErrRemoved)
err = db.Reset() err = db.Reset()
require.NoError(t, err) require.NoError(t, err)

View file

@ -7,6 +7,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/core/object"
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log" storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
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"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
@ -97,7 +98,7 @@ func (db *DB) delete(tx *bbolt.Tx, addr *addressSDK.Address, refCounter referenc
// unmarshal object, work only with physically stored (raw == true) objects // unmarshal object, work only with physically stored (raw == true) objects
obj, err := db.get(tx, addr, false, true) obj, err := db.get(tx, addr, false, true)
if err != nil { if err != nil {
if errors.Is(err, object.ErrNotFound) { if errors.As(err, new(apistatus.ObjectNotFound)) {
return nil return nil
} }

View file

@ -0,0 +1,13 @@
package meta
import (
"errors"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
)
// IsErrRemoved checks if error returned by Shard Exists/Get/Put method
// corresponds to removed object.
func IsErrRemoved(err error) bool {
return errors.As(err, new(apistatus.ObjectAlreadyRemoved))
}

View file

@ -5,7 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/object" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
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"
@ -39,6 +39,8 @@ func (p *ExistsRes) Exists() bool {
} }
// Exists checks if object is presented in DB. // Exists checks if object is presented in DB.
//
// See DB.Exists docs.
func Exists(db *DB, addr *addressSDK.Address) (bool, error) { func Exists(db *DB, addr *addressSDK.Address) (bool, error) {
r, err := db.Exists(new(ExistsPrm).WithAddress(addr)) r, err := db.Exists(new(ExistsPrm).WithAddress(addr))
if err != nil { if err != nil {
@ -50,6 +52,8 @@ func Exists(db *DB, addr *addressSDK.Address) (bool, error) {
// Exists returns ErrAlreadyRemoved if addr was marked as removed. Otherwise it // Exists returns ErrAlreadyRemoved if addr was marked as removed. Otherwise it
// returns true if addr is in primary index or false if it is not. // returns true if addr is in primary index or false if it is not.
//
// Returns apistatus.ObjectAlreadyRemoved if object has been placed in graveyard.
func (db *DB) Exists(prm *ExistsPrm) (res *ExistsRes, err error) { func (db *DB) Exists(prm *ExistsPrm) (res *ExistsRes, err error) {
res = new(ExistsRes) res = new(ExistsRes)
@ -66,9 +70,13 @@ func (db *DB) exists(tx *bbolt.Tx, addr *addressSDK.Address) (exists bool, err e
// check graveyard first // check graveyard first
switch inGraveyard(tx, addr) { switch inGraveyard(tx, addr) {
case 1: case 1:
return false, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return false, errNotFound
case 2: case 2:
return false, object.ErrAlreadyRemoved var errRemoved apistatus.ObjectAlreadyRemoved
return false, errRemoved
} }
objKey := objectKey(addr.ObjectID()) objKey := objectKey(addr.ObjectID())

View file

@ -3,7 +3,7 @@ package meta
import ( import (
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/object" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
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"
@ -69,6 +69,9 @@ func GetRaw(db *DB, addr *addressSDK.Address, raw bool) (*objectSDK.Object, erro
} }
// Get returns object header for specified address. // Get returns object header for specified address.
//
// Returns apistatus.ObjectNotFound if object is missing in DB.
// Returns apistatus.ObjectAlreadyRemoved if object has been placed in graveyard.
func (db *DB) Get(prm *GetPrm) (res *GetRes, err error) { func (db *DB) Get(prm *GetPrm) (res *GetRes, err error) {
res = new(GetRes) res = new(GetRes)
@ -89,9 +92,13 @@ func (db *DB) get(tx *bbolt.Tx, addr *addressSDK.Address, checkGraveyard, raw bo
if checkGraveyard { if checkGraveyard {
switch inGraveyard(tx, addr) { switch inGraveyard(tx, addr) {
case 1: case 1:
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
case 2: case 2:
return nil, object.ErrAlreadyRemoved var errRemoved apistatus.ObjectAlreadyRemoved
return nil, errRemoved
} }
} }
@ -139,7 +146,9 @@ func getVirtualObject(tx *bbolt.Tx, cid *cid.ID, key []byte, raw bool) (*objectS
parentBucket := tx.Bucket(parentBucketName(cid)) parentBucket := tx.Bucket(parentBucketName(cid))
if parentBucket == nil { if parentBucket == nil {
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
relativeLst, err := decodeList(parentBucket.Get(key)) relativeLst, err := decodeList(parentBucket.Get(key))
@ -148,7 +157,9 @@ func getVirtualObject(tx *bbolt.Tx, cid *cid.ID, key []byte, raw bool) (*objectS
} }
if len(relativeLst) == 0 { // this should never happen though if len(relativeLst) == 0 { // this should never happen though
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
// pick last item, for now there is not difference which address to pick // pick last item, for now there is not difference which address to pick
@ -167,7 +178,9 @@ func getVirtualObject(tx *bbolt.Tx, cid *cid.ID, key []byte, raw bool) (*objectS
par := child.Parent() par := child.Parent()
if par == nil { // this should never happen though if par == nil { // this should never happen though
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
return par, nil return par, nil
@ -179,5 +192,7 @@ func getSplitInfoError(tx *bbolt.Tx, cid *cid.ID, key []byte) error {
return objectSDK.NewSplitInfoError(splitInfo) return objectSDK.NewSplitInfoError(splitInfo)
} }
return object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return errNotFound
} }

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"
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -112,12 +113,12 @@ func TestDB_Get(t *testing.T) {
require.NoError(t, meta.Inhume(db, obj, ts)) require.NoError(t, meta.Inhume(db, obj, ts))
_, err := meta.Get(db, obj) _, err := meta.Get(db, obj)
require.ErrorIs(t, err, object.ErrAlreadyRemoved) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
obj = generateAddress() obj = generateAddress()
require.NoError(t, meta.Inhume(db, obj, nil)) require.NoError(t, meta.Inhume(db, obj, nil))
_, err = meta.Get(db, obj) _, err = meta.Get(db, obj)
require.ErrorIs(t, err, object.ErrNotFound) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
} }

View file

@ -1,7 +1,6 @@
package meta_test package meta_test
import ( import (
"errors"
"testing" "testing"
"github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/core/object"
@ -28,10 +27,10 @@ func TestDB_Inhume(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
_, err = meta.Exists(db, object.AddressOf(raw)) _, err = meta.Exists(db, object.AddressOf(raw))
require.EqualError(t, err, object.ErrAlreadyRemoved.Error()) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
_, err = meta.Get(db, object.AddressOf(raw)) _, err = meta.Get(db, object.AddressOf(raw))
require.EqualError(t, err, object.ErrAlreadyRemoved.Error()) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
} }
func TestInhumeTombOnTomb(t *testing.T) { func TestInhumeTombOnTomb(t *testing.T) {
@ -56,7 +55,7 @@ func TestInhumeTombOnTomb(t *testing.T) {
// addr1 should become inhumed {addr1:addr2} // addr1 should become inhumed {addr1:addr2}
_, err = db.Exists(existsPrm.WithAddress(addr1)) _, err = db.Exists(existsPrm.WithAddress(addr1))
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
// try to inhume addr3 via addr1 // try to inhume addr3 via addr1
_, err = db.Inhume(inhumePrm. _, err = db.Inhume(inhumePrm.
@ -73,7 +72,7 @@ func TestInhumeTombOnTomb(t *testing.T) {
// addr3 should be inhumed {addr3: addr1} // addr3 should be inhumed {addr3: addr1}
_, err = db.Exists(existsPrm.WithAddress(addr3)) _, err = db.Exists(existsPrm.WithAddress(addr3))
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
// try to inhume addr1 (which is already a tombstone in graveyard) // try to inhume addr1 (which is already a tombstone in graveyard)
_, err = db.Inhume(inhumePrm. _, err = db.Inhume(inhumePrm.

View file

@ -56,6 +56,8 @@ var (
) )
// Put saves the object in DB. // Put saves the object in DB.
//
// See DB.Put docs.
func Put(db *DB, obj *objectSDK.Object, id *blobovnicza.ID) error { func Put(db *DB, obj *objectSDK.Object, id *blobovnicza.ID) error {
_, err := db.Put(new(PutPrm). _, err := db.Put(new(PutPrm).
WithObject(obj). WithObject(obj).
@ -67,6 +69,8 @@ func Put(db *DB, obj *objectSDK.Object, id *blobovnicza.ID) error {
// Put saves object header in metabase. Object payload expected to be cut. // Put saves object header in metabase. Object payload expected to be cut.
// Big objects have nil blobovniczaID. // Big objects have nil blobovniczaID.
//
// Returns apistatus.ObjectAlreadyRemoved if object has been placed in graveyard.
func (db *DB) Put(prm *PutPrm) (res *PutRes, err error) { func (db *DB) Put(prm *PutPrm) (res *PutRes, err error) {
err = db.boltDB.Batch(func(tx *bbolt.Tx) error { err = db.boltDB.Batch(func(tx *bbolt.Tx) error {
return db.put(tx, prm.obj, prm.id, nil) return db.put(tx, prm.obj, prm.id, nil)

View file

@ -1,7 +1,6 @@
package shard package shard
import ( import (
"errors"
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/core/object"
@ -114,7 +113,7 @@ func (s *Shard) refillMetabase() error {
} }
err := meta.Put(s.metaBase, obj, blzID) err := meta.Put(s.metaBase, obj, blzID)
if err != nil && !errors.Is(err, object.ErrAlreadyRemoved) { if err != nil && !meta.IsErrRemoved(err) {
return err return err
} }

View file

@ -8,6 +8,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/blobstor" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
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"
objecttest "github.com/nspcc-dev/neofs-sdk-go/object/test" objecttest "github.com/nspcc-dev/neofs-sdk-go/object/test"
@ -99,7 +100,7 @@ func TestRefillMetabase(t *testing.T) {
res, err := sh.Head(headPrm.WithAddress(addr)) res, err := sh.Head(headPrm.WithAddress(addr))
if expObj == nil { if expObj == nil {
require.ErrorIs(t, err, object.ErrNotFound) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
return return
} }
@ -122,9 +123,9 @@ func TestRefillMetabase(t *testing.T) {
_, err := sh.Head(headPrm.WithAddress(member)) _, err := sh.Head(headPrm.WithAddress(member))
if exists { if exists {
require.ErrorIs(t, err, object.ErrAlreadyRemoved) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
} else { } else {
require.ErrorIs(t, err, object.ErrNotFound) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
} }
} }
} }

View file

@ -1,12 +1,10 @@
package shard package shard
import ( import (
"errors"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -46,7 +44,7 @@ func (s *Shard) Delete(prm *DeletePrm) (*DeleteRes, error) {
for i := range prm.addr { for i := range prm.addr {
if s.hasWriteCache() { if s.hasWriteCache() {
err := s.writeCache.Delete(prm.addr[i]) err := s.writeCache.Delete(prm.addr[i])
if err != nil && !errors.Is(err, object.ErrNotFound) { if err != nil && !writecache.IsErrNotFound(err) {
s.log.Error("can't delete object from write cache", zap.String("error", err.Error())) s.log.Error("can't delete object from write cache", zap.String("error", err.Error()))
} }
} }

View file

@ -5,6 +5,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"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -50,7 +51,7 @@ func testShardDelete(t *testing.T, hasWriteCache bool) {
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(getPrm)
require.EqualError(t, err, object.ErrNotFound.Error()) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("small object", func(t *testing.T) { t.Run("small object", func(t *testing.T) {
@ -73,6 +74,6 @@ func testShardDelete(t *testing.T, hasWriteCache bool) {
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(getPrm)
require.EqualError(t, err, object.ErrNotFound.Error()) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
} }

View file

@ -0,0 +1,19 @@
package shard
import (
"errors"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
)
// IsErrNotFound checks if error returned by Shard Get/Head/GetRange method
// corresponds to missing object.
func IsErrNotFound(err error) bool {
return errors.As(err, new(apistatus.ObjectNotFound))
}
// IsErrRemoved checks if error returned by Shard Exists/Get/Head/GetRange method
// corresponds to removed object.
func IsErrRemoved(err error) bool {
return errors.As(err, new(apistatus.ObjectAlreadyRemoved))
}

View file

@ -33,6 +33,8 @@ func (p *ExistsRes) Exists() bool {
// //
// Returns any error encountered that does not allow to // Returns any error encountered that does not allow to
// unambiguously determine the presence of an object. // unambiguously determine the presence of an object.
//
// Returns apistatus.ObjectAlreadyRemoved if object has been marked as removed.
func (s *Shard) Exists(prm *ExistsPrm) (*ExistsRes, error) { func (s *Shard) Exists(prm *ExistsPrm) (*ExistsRes, error) {
exists, err := s.objectExists(prm.addr) exists, err := s.objectExists(prm.addr)

View file

@ -8,6 +8,8 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor"
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
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"
"go.uber.org/zap" "go.uber.org/zap"
@ -62,7 +64,8 @@ func (r *GetRes) HasMeta() bool {
// Returns any error encountered that // Returns any error encountered that
// did not allow to completely read the object part. // did not allow to completely read the object part.
// //
// Returns object.ErrNotFound if requested object is missing in shard. // Returns apistatus.ObjectNotFound if requested object is missing in shard.
// Returns apistatus.ObjectAlreadyRemoved if requested object has been marked as removed in shard.
func (s *Shard) Get(prm *GetPrm) (*GetRes, error) { func (s *Shard) Get(prm *GetPrm) (*GetRes, error) {
var big, small storFetcher var big, small storFetcher
@ -112,7 +115,7 @@ func (s *Shard) fetchObjectData(addr *addressSDK.Address, skipMeta bool, big, sm
return res, false, nil return res, false, nil
} }
if errors.Is(err, object.ErrNotFound) { if writecache.IsErrNotFound(err) {
s.log.Debug("object is missing in write-cache") s.log.Debug("object is missing in write-cache")
} else { } else {
s.log.Error("failed to fetch object from write-cache", zap.Error(err)) s.log.Error("failed to fetch object from write-cache", zap.Error(err))
@ -134,7 +137,9 @@ func (s *Shard) fetchObjectData(addr *addressSDK.Address, skipMeta bool, big, sm
} }
if !exists { if !exists {
return nil, false, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, false, errNotFound
} }
blobovniczaID, err := meta.IsSmall(s.metaBase, addr) blobovniczaID, err := meta.IsSmall(s.metaBase, addr)

View file

@ -110,10 +110,10 @@ func testGet(t *testing.T, sh *shard.Shard, getPrm *shard.GetPrm, hasWriteCache
res, err := sh.Get(getPrm) res, err := sh.Get(getPrm)
if hasWriteCache { if hasWriteCache {
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
if errors.Is(err, object.ErrNotFound) { if shard.IsErrNotFound(err) {
res, err = sh.Get(getPrm) res, err = sh.Get(getPrm)
} }
return !errors.Is(err, object.ErrNotFound) return !shard.IsErrNotFound(err)
}, time.Second, time.Millisecond*100) }, time.Second, time.Millisecond*100)
} }
return res, err return res, err

View file

@ -1,11 +1,10 @@
package shard package shard
import ( import (
"errors"
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache"
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"
) )
@ -51,6 +50,9 @@ func (r *HeadRes) Object() *objectSDK.Object {
// Head reads header of the object from the shard. // Head reads header of the object from the shard.
// //
// Returns any error encountered. // Returns any error encountered.
//
// Returns apistatus.ObjectNotFound if object is missing in Shard.
// Returns apistatus.ObjectAlreadyRemoved if requested object has been marked as removed in shard.
func (s *Shard) Head(prm *HeadPrm) (*HeadRes, error) { func (s *Shard) Head(prm *HeadPrm) (*HeadRes, error) {
// object can be saved in write-cache (if enabled) or in metabase // object can be saved in write-cache (if enabled) or in metabase
@ -61,7 +63,7 @@ func (s *Shard) Head(prm *HeadPrm) (*HeadRes, error) {
return &HeadRes{ return &HeadRes{
obj: header, obj: header,
}, nil }, nil
} else if !errors.Is(err, object.ErrNotFound) { } else if !writecache.IsErrNotFound(err) {
// in this case we think that object is presented in write-cache, but corrupted // in this case we think that object is presented in write-cache, but corrupted
return nil, fmt.Errorf("could not read header from write-cache: %w", err) return nil, fmt.Errorf("could not read header from write-cache: %w", err)
} }

View file

@ -83,10 +83,10 @@ func testHead(t *testing.T, sh *shard.Shard, headPrm *shard.HeadPrm, hasWriteCac
res, err := sh.Head(headPrm) res, err := sh.Head(headPrm)
if hasWriteCache { if hasWriteCache {
require.Eventually(t, func() bool { require.Eventually(t, func() bool {
if errors.Is(err, object.ErrNotFound) { if shard.IsErrNotFound(err) {
res, err = sh.Head(headPrm) res, err = sh.Head(headPrm)
} }
return !errors.Is(err, object.ErrNotFound) return !shard.IsErrNotFound(err)
}, time.Second, time.Millisecond*100) }, time.Second, time.Millisecond*100)
} }
return res, err return res, err

View file

@ -5,6 +5,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"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -49,5 +50,5 @@ func testShardInhume(t *testing.T, hasWriteCache bool) {
require.NoError(t, err) require.NoError(t, err)
_, err = sh.Get(getPrm) _, err = sh.Get(getPrm)
require.EqualError(t, err, object.ErrAlreadyRemoved.Error()) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
} }

View file

@ -69,6 +69,8 @@ func (r *RngRes) HasMeta() bool {
// did not allow to completely read the object part. // did not allow to completely read the object part.
// //
// Returns ErrRangeOutOfBounds if requested object range is out of bounds. // Returns ErrRangeOutOfBounds if requested object range is out of bounds.
// Returns apistatus.ObjectNotFound if requested object is missing.
// Returns apistatus.ObjectAlreadyRemoved if requested object has been marked as removed in shard.
func (s *Shard) GetRange(prm *RngPrm) (*RngRes, error) { func (s *Shard) GetRange(prm *RngPrm) (*RngRes, error) {
var big, small storFetcher var big, small storFetcher

View file

@ -3,14 +3,16 @@ package writecache
import ( import (
"errors" "errors"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log" storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
) )
// Delete removes object from write-cache. // Delete removes object from write-cache.
//
// Returns apistatus.ObjectNotFound is object is missing in write-cache.
func (c *cache) Delete(addr *addressSDK.Address) error { func (c *cache) Delete(addr *addressSDK.Address) error {
c.modeMtx.RLock() c.modeMtx.RLock()
defer c.modeMtx.RUnlock() defer c.modeMtx.RUnlock()
@ -58,7 +60,9 @@ func (c *cache) Delete(addr *addressSDK.Address) error {
err := c.fsTree.Delete(addr) err := c.fsTree.Delete(addr)
if errors.Is(err, fstree.ErrFileNotFound) { if errors.Is(err, fstree.ErrFileNotFound) {
err = object.ErrNotFound var errNotFound apistatus.ObjectNotFound
err = errNotFound
} }
if err == nil { if err == nil {

View file

@ -0,0 +1,13 @@
package writecache
import (
"errors"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
)
// IsErrNotFound checks if error returned by Cache Get/Head/Delete method
// corresponds to missing object.
func IsErrNotFound(err error) bool {
return errors.As(err, new(apistatus.ObjectNotFound))
}

View file

@ -1,13 +1,15 @@
package writecache package writecache
import ( import (
"github.com/nspcc-dev/neofs-node/pkg/core/object" 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"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
) )
// Get returns object from write-cache. // Get returns object from write-cache.
//
// Returns apistatus.ObjectNotFound if requested object is missing in write-cache.
func (c *cache) Get(addr *addressSDK.Address) (*objectSDK.Object, error) { func (c *cache) Get(addr *addressSDK.Address) (*objectSDK.Object, error) {
saddr := addr.String() saddr := addr.String()
@ -30,7 +32,9 @@ func (c *cache) Get(addr *addressSDK.Address) (*objectSDK.Object, error) {
data, err := c.fsTree.Get(addr) data, err := c.fsTree.Get(addr)
if err != nil { if err != nil {
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
obj := objectSDK.New() obj := objectSDK.New()
@ -43,6 +47,8 @@ func (c *cache) Get(addr *addressSDK.Address) (*objectSDK.Object, error) {
} }
// Head returns object header from write-cache. // Head returns object header from write-cache.
//
// Returns apistatus.ObjectNotFound if requested object is missing in write-cache.
func (c *cache) Head(addr *addressSDK.Address) (*objectSDK.Object, error) { func (c *cache) Head(addr *addressSDK.Address) (*objectSDK.Object, error) {
// TODO: #1149 easiest to implement solution is presented here, consider more efficient way, e.g.: // TODO: #1149 easiest to implement solution is presented here, consider more efficient way, e.g.:
// - provide header as common object.Object to Put, but marked to prevent correlation with full object // - provide header as common object.Object to Put, but marked to prevent correlation with full object
@ -61,6 +67,8 @@ func (c *cache) Head(addr *addressSDK.Address) (*objectSDK.Object, error) {
// Get fetches object from the underlying database. // Get fetches object from the underlying database.
// Key should be a stringified address. // Key should be a stringified address.
//
// Returns apistatus.ObjectNotFound if requested object is missing in db.
func Get(db *bbolt.DB, key []byte) ([]byte, error) { func Get(db *bbolt.DB, key []byte) ([]byte, error) {
var value []byte var value []byte
err := db.View(func(tx *bbolt.Tx) error { err := db.View(func(tx *bbolt.Tx) error {
@ -70,7 +78,9 @@ func Get(db *bbolt.DB, key []byte) ([]byte, error) {
} }
value = b.Get(key) value = b.Get(key)
if value == nil { if value == nil {
return object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return errNotFound
} }
value = cloneBytes(value) value = cloneBytes(value)
return nil return nil

View file

@ -7,10 +7,10 @@ import (
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
"github.com/hashicorp/golang-lru/simplelru" "github.com/hashicorp/golang-lru/simplelru"
"github.com/nspcc-dev/neofs-node/pkg/core/object"
"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/fstree"
storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log" storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log"
"github.com/nspcc-dev/neofs-node/pkg/util" "github.com/nspcc-dev/neofs-node/pkg/util"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address"
"go.etcd.io/bbolt" "go.etcd.io/bbolt"
"go.uber.org/zap" "go.uber.org/zap"
@ -103,7 +103,9 @@ func (c *cache) deleteFromDB(keys [][]byte) error {
for i := range keys { for i := range keys {
has := b.Get(keys[i]) has := b.Get(keys[i])
if has == nil { if has == nil {
return object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return errNotFound
} }
if err := b.Delete(keys[i]); err != nil { if err := b.Delete(keys[i]); err != nil {
return err return err

View file

@ -15,6 +15,7 @@ import (
"github.com/nspcc-dev/neofs-node/pkg/services/object/util" "github.com/nspcc-dev/neofs-node/pkg/services/object/util"
"github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement" "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/placement"
"github.com/nspcc-dev/neofs-node/pkg/util/logger/test" "github.com/nspcc-dev/neofs-node/pkg/util/logger/test"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
"github.com/nspcc-dev/neofs-sdk-go/container" "github.com/nspcc-dev/neofs-sdk-go/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
@ -106,7 +107,9 @@ func newTestClient() *testClient {
func (c *testClient) getObject(exec *execCtx, _ client.NodeInfo) (*objectSDK.Object, error) { func (c *testClient) getObject(exec *execCtx, _ client.NodeInfo) (*objectSDK.Object, error) {
v, ok := c.results[exec.address().String()] v, ok := c.results[exec.address().String()]
if !ok { if !ok {
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
if v.err != nil { if v.err != nil {
@ -131,7 +134,9 @@ func (s *testStorage) get(exec *execCtx) (*objectSDK.Object, error) {
) )
if _, ok = s.inhumed[sAddr]; ok { if _, ok = s.inhumed[sAddr]; ok {
return nil, object.ErrAlreadyRemoved var errRemoved apistatus.ObjectAlreadyRemoved
return nil, errRemoved
} }
if info, ok := s.virtual[sAddr]; ok { if info, ok := s.virtual[sAddr]; ok {
@ -142,7 +147,9 @@ func (s *testStorage) get(exec *execCtx) (*objectSDK.Object, error) {
return cutToRange(obj, exec.ctxRange()), nil return cutToRange(obj, exec.ctxRange()), nil
} }
return nil, object.ErrNotFound var errNotFound apistatus.ObjectNotFound
return nil, errNotFound
} }
func cutToRange(o *objectSDK.Object, rng *objectSDK.Range) *objectSDK.Object { func cutToRange(o *objectSDK.Object, rng *objectSDK.Range) *objectSDK.Object {
@ -309,19 +316,19 @@ func TestGetLocalOnly(t *testing.T) {
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
rngPrm := newRngPrm(false, nil, 0, 0) rngPrm := newRngPrm(false, nil, 0, 0)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
headPrm := newHeadPrm(false, nil) headPrm := newHeadPrm(false, nil)
headPrm.WithAddress(addr) headPrm.WithAddress(addr)
err = svc.Head(ctx, headPrm) err = svc.Head(ctx, headPrm)
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved))
}) })
t.Run("404", func(t *testing.T) { t.Run("404", func(t *testing.T) {
@ -336,20 +343,20 @@ func TestGetLocalOnly(t *testing.T) {
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
rngPrm := newRngPrm(false, nil, 0, 0) rngPrm := newRngPrm(false, nil, 0, 0)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
headPrm := newHeadPrm(false, nil) headPrm := newHeadPrm(false, nil)
headPrm.WithAddress(addr) headPrm.WithAddress(addr)
err = svc.Head(ctx, headPrm) err = svc.Head(ctx, headPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("VIRTUAL", func(t *testing.T) { t.Run("VIRTUAL", func(t *testing.T) {
@ -599,7 +606,7 @@ func TestGetRemoteSmall(t *testing.T) {
c1.addResult(addr, nil, errors.New("any error")) c1.addResult(addr, nil, errors.New("any error"))
c2 := newTestClient() c2 := newTestClient()
c2.addResult(addr, nil, object.ErrAlreadyRemoved) c2.addResult(addr, nil, new(apistatus.ObjectAlreadyRemoved))
svc := newSvc(builder, &testClientCache{ svc := newSvc(builder, &testClientCache{
clients: map[string]*testClient{ clients: map[string]*testClient{
@ -612,19 +619,19 @@ func TestGetRemoteSmall(t *testing.T) {
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved))
rngPrm := newRngPrm(false, nil, 0, 0) rngPrm := newRngPrm(false, nil, 0, 0)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved))
headPrm := newHeadPrm(false, nil) headPrm := newHeadPrm(false, nil)
headPrm.WithAddress(addr) headPrm.WithAddress(addr)
err = svc.Head(ctx, headPrm) err = svc.Head(ctx, headPrm)
require.True(t, errors.Is(err, object.ErrAlreadyRemoved)) require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved))
}) })
t.Run("404", func(t *testing.T) { t.Run("404", func(t *testing.T) {
@ -656,19 +663,19 @@ func TestGetRemoteSmall(t *testing.T) {
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
rngPrm := newRngPrm(false, nil, 0, 0) rngPrm := newRngPrm(false, nil, 0, 0)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
headPrm := newHeadPrm(false, nil) headPrm := newHeadPrm(false, nil)
headPrm.WithAddress(addr) headPrm.WithAddress(addr)
err = svc.Head(ctx, headPrm) err = svc.Head(ctx, headPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("VIRTUAL", func(t *testing.T) { t.Run("VIRTUAL", func(t *testing.T) {
@ -700,11 +707,11 @@ func TestGetRemoteSmall(t *testing.T) {
c1 := newTestClient() c1 := newTestClient()
c1.addResult(addr, nil, errors.New("any error")) c1.addResult(addr, nil, errors.New("any error"))
c1.addResult(splitAddr, nil, object.ErrNotFound) c1.addResult(splitAddr, nil, apistatus.ObjectNotFound{})
c2 := newTestClient() c2 := newTestClient()
c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo)) c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo))
c2.addResult(splitAddr, nil, object.ErrNotFound) c2.addResult(splitAddr, nil, apistatus.ObjectNotFound{})
builder := &testPlacementBuilder{ builder := &testPlacementBuilder{
vectors: map[string][]netmap.Nodes{ vectors: map[string][]netmap.Nodes{
@ -726,13 +733,13 @@ func TestGetRemoteSmall(t *testing.T) {
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
rngPrm := newRngPrm(false, nil, 0, 0) rngPrm := newRngPrm(false, nil, 0, 0)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("get chain element failure", func(t *testing.T) { t.Run("get chain element failure", func(t *testing.T) {
@ -776,7 +783,7 @@ func TestGetRemoteSmall(t *testing.T) {
c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo)) c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo))
c2.addResult(linkAddr, linkingObj, nil) c2.addResult(linkAddr, linkingObj, nil)
c2.addResult(child1Addr, children[0], nil) c2.addResult(child1Addr, children[0], nil)
c2.addResult(child2Addr, nil, object.ErrNotFound) c2.addResult(child2Addr, nil, apistatus.ObjectNotFound{})
builder := &testPlacementBuilder{ builder := &testPlacementBuilder{
vectors: map[string][]netmap.Nodes{ vectors: map[string][]netmap.Nodes{
@ -800,13 +807,13 @@ func TestGetRemoteSmall(t *testing.T) {
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
rngPrm := newRngPrm(false, NewSimpleObjectWriter(), 0, 1) rngPrm := newRngPrm(false, NewSimpleObjectWriter(), 0, 1)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
@ -913,11 +920,11 @@ func TestGetRemoteSmall(t *testing.T) {
c1 := newTestClient() c1 := newTestClient()
c1.addResult(addr, nil, errors.New("any error")) c1.addResult(addr, nil, errors.New("any error"))
c1.addResult(splitAddr, nil, object.ErrNotFound) c1.addResult(splitAddr, nil, apistatus.ObjectNotFound{})
c2 := newTestClient() c2 := newTestClient()
c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo)) c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo))
c2.addResult(splitAddr, nil, object.ErrNotFound) c2.addResult(splitAddr, nil, apistatus.ObjectNotFound{})
builder := &testPlacementBuilder{ builder := &testPlacementBuilder{
vectors: map[string][]netmap.Nodes{ vectors: map[string][]netmap.Nodes{
@ -939,13 +946,13 @@ func TestGetRemoteSmall(t *testing.T) {
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
rngPrm := newRngPrm(false, nil, 0, 0) rngPrm := newRngPrm(false, nil, 0, 0)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("get chain element failure", func(t *testing.T) { t.Run("get chain element failure", func(t *testing.T) {
@ -1000,19 +1007,19 @@ func TestGetRemoteSmall(t *testing.T) {
testHeadVirtual(svc, addr, splitInfo) testHeadVirtual(svc, addr, splitInfo)
headSvc := newTestClient() headSvc := newTestClient()
headSvc.addResult(preRightAddr, nil, object.ErrNotFound) headSvc.addResult(preRightAddr, nil, apistatus.ObjectNotFound{})
p := newPrm(false, NewSimpleObjectWriter()) p := newPrm(false, NewSimpleObjectWriter())
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
rngPrm := newRngPrm(false, nil, 0, 1) rngPrm := newRngPrm(false, nil, 0, 1)
rngPrm.WithAddress(addr) rngPrm.WithAddress(addr)
err = svc.GetRange(ctx, rngPrm) err = svc.GetRange(ctx, rngPrm)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
}) })
t.Run("OK", func(t *testing.T) { t.Run("OK", func(t *testing.T) {
@ -1180,7 +1187,7 @@ func TestGetFromPastEpoch(t *testing.T) {
p.WithAddress(addr) p.WithAddress(addr)
err := svc.Get(ctx, p) err := svc.Get(ctx, p)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
commonPrm.SetNetmapLookupDepth(1) commonPrm.SetNetmapLookupDepth(1)
@ -1203,7 +1210,7 @@ func TestGetFromPastEpoch(t *testing.T) {
rp.SetRange(r) rp.SetRange(r)
err = svc.GetRange(ctx, rp) err = svc.GetRange(ctx, rp)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
w = NewSimpleObjectWriter() w = NewSimpleObjectWriter()
rp.SetChunkWriter(w) rp.SetChunkWriter(w)
@ -1220,7 +1227,7 @@ func TestGetFromPastEpoch(t *testing.T) {
hp.WithAddress(addr) hp.WithAddress(addr)
err = svc.Head(ctx, hp) err = svc.Head(ctx, hp)
require.True(t, errors.Is(err, object.ErrNotFound)) require.ErrorAs(t, err, new(apistatus.ObjectNotFound))
w = NewSimpleObjectWriter() w = NewSimpleObjectWriter()
hp.SetHeaderWriter(w) hp.SetHeaderWriter(w)

View file

@ -4,6 +4,7 @@ import (
"errors" "errors"
"github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/core/object"
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"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -14,6 +15,7 @@ func (exec *execCtx) executeLocal() {
exec.collectedObject, err = exec.svc.localStorage.get(exec) exec.collectedObject, err = exec.svc.localStorage.get(exec)
var errSplitInfo *objectSDK.SplitInfoError var errSplitInfo *objectSDK.SplitInfoError
var errRemoved apistatus.ObjectAlreadyRemoved
switch { switch {
default: default:
@ -27,9 +29,9 @@ func (exec *execCtx) executeLocal() {
exec.status = statusOK exec.status = statusOK
exec.err = nil exec.err = nil
exec.writeCollectedObject() exec.writeCollectedObject()
case errors.Is(err, object.ErrAlreadyRemoved): case errors.As(err, &errRemoved):
exec.status = statusINHUMED exec.status = statusINHUMED
exec.err = object.ErrAlreadyRemoved exec.err = errRemoved
case errors.As(err, &errSplitInfo): case errors.As(err, &errSplitInfo):
exec.status = statusVIRTUAL exec.status = statusVIRTUAL
mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo()) mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo())

View file

@ -5,7 +5,7 @@ import (
"errors" "errors"
"github.com/nspcc-dev/neofs-node/pkg/core/client" "github.com/nspcc-dev/neofs-node/pkg/core/client"
"github.com/nspcc-dev/neofs-node/pkg/core/object" 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"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -21,11 +21,14 @@ func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool
obj, err := client.getObject(exec, info) obj, err := client.getObject(exec, info)
var errSplitInfo *objectSDK.SplitInfoError var errSplitInfo *objectSDK.SplitInfoError
var errRemoved *apistatus.ObjectAlreadyRemoved
switch { switch {
default: default:
var errNotFound apistatus.ObjectNotFound
exec.status = statusUndefined exec.status = statusUndefined
exec.err = object.ErrNotFound exec.err = errNotFound
exec.log.Debug("remote call failed", exec.log.Debug("remote call failed",
zap.String("error", err.Error()), zap.String("error", err.Error()),
@ -35,9 +38,9 @@ func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool
exec.err = nil exec.err = nil
exec.collectedObject = obj exec.collectedObject = obj
exec.writeCollectedObject() exec.writeCollectedObject()
case errors.Is(err, object.ErrAlreadyRemoved): case errors.As(err, &errRemoved):
exec.status = statusINHUMED exec.status = statusINHUMED
exec.err = object.ErrAlreadyRemoved exec.err = errRemoved
case errors.As(err, &errSplitInfo): case errors.As(err, &errSplitInfo):
exec.status = statusVIRTUAL exec.status = statusVIRTUAL
mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo()) mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo())

View file

@ -148,8 +148,8 @@ func (x GetObjectRes) Object() *object.Object {
// //
// Returns any error prevented the operation from completing correctly in error return. // Returns any error prevented the operation from completing correctly in error return.
// Returns: // Returns:
// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; // error of type *object.SplitInfoError if object raw flag is set and requested object is virtual;
// object.ErrAlreadyRemoved error if requested object is marked to be removed. // error of type *apistatus.ObjectAlreadyRemoved if requested object is marked to be removed.
func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { func GetObject(prm GetObjectPrm) (*GetObjectRes, error) {
if prm.tokenSession != nil { if prm.tokenSession != nil {
prm.cliPrm.WithinSession(*prm.tokenSession) prm.cliPrm.WithinSession(*prm.tokenSession)
@ -193,8 +193,6 @@ func GetObject(prm GetObjectPrm) (*GetObjectRes, error) {
return nil, fmt.Errorf("read payload: %w", err) return nil, fmt.Errorf("read payload: %w", err)
} }
// FIXME: #1158 object.ErrAlreadyRemoved never returns
obj.SetPayload(buf) obj.SetPayload(buf)
return &GetObjectRes{ return &GetObjectRes{
@ -245,8 +243,8 @@ func (x HeadObjectRes) Header() *object.Object {
// //
// Returns any error prevented the operation from completing correctly in error return. // Returns any error prevented the operation from completing correctly in error return.
// Returns: // Returns:
// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; // error of type *object.SplitInfoError if object raw flag is set and requested object is virtual;
// object.ErrAlreadyRemoved error if requested object is marked to be removed. // error of type *apistatus.ObjectAlreadyRemoved if requested object is marked to be removed.
func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) {
if prm.local { if prm.local {
prm.cliPrm.MarkLocal() prm.cliPrm.MarkLocal()
@ -272,8 +270,6 @@ func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) {
return nil, fmt.Errorf("read object header from NeoFS: %w", err) return nil, fmt.Errorf("read object header from NeoFS: %w", err)
} }
// FIXME: #1158 object.ErrAlreadyRemoved never returns
var hdr object.Object var hdr object.Object
if !cliRes.ReadHeader(&hdr) { if !cliRes.ReadHeader(&hdr) {
@ -338,8 +334,8 @@ func (x PayloadRangeRes) PayloadRange() []byte {
// //
// Returns any error prevented the operation from completing correctly in error return. // Returns any error prevented the operation from completing correctly in error return.
// Returns: // Returns:
// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; // error of type *object.SplitInfoError if object raw flag is set and requested object is virtual;
// object.ErrAlreadyRemoved error if requested object is marked to be removed. // error of type *apistatus.ObjectAlreadyRemoved if requested object is marked to be removed.
func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) {
if prm.local { if prm.local {
prm.cliPrm.MarkLocal() prm.cliPrm.MarkLocal()
@ -368,8 +364,6 @@ func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) {
return nil, fmt.Errorf("read payload: %w", err) return nil, fmt.Errorf("read payload: %w", err)
} }
// FIXME: #1158 object.ErrAlreadyRemoved never returns
return &PayloadRangeRes{ return &PayloadRangeRes{
data: data, data: data,
}, nil }, nil