From 70ffdf3478cd2763fa5bf2ac5bcb847def82d610 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 17 Mar 2022 11:03:58 +0300 Subject: [PATCH] [#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 --- pkg/core/object/errors.go | 7 -- pkg/innerring/rpc.go | 8 +- pkg/innerring/settlement.go | 3 + .../blobovnicza/blobovnicza_test.go | 31 +++++--- .../blobovnicza/delete.go | 8 +- .../blobovnicza/errors.go | 13 ++++ pkg/local_object_storage/blobovnicza/get.go | 8 +- .../blobstor/blobovnicza.go | 44 +++++++---- .../blobstor/blobovnicza_test.go | 6 +- .../blobstor/delete_big.go | 8 +- .../blobstor/delete_small.go | 2 +- pkg/local_object_storage/blobstor/get_big.go | 8 +- .../blobstor/get_range_big.go | 6 +- .../blobstor/get_range_small.go | 1 + .../blobstor/get_small.go | 2 + pkg/local_object_storage/engine/exists.go | 10 +-- pkg/local_object_storage/engine/get.go | 15 ++-- pkg/local_object_storage/engine/head.go | 14 ++-- pkg/local_object_storage/engine/inhume.go | 3 +- pkg/local_object_storage/engine/put.go | 2 + pkg/local_object_storage/engine/range.go | 15 ++-- .../metabase/control_test.go | 10 ++- pkg/local_object_storage/metabase/delete.go | 3 +- pkg/local_object_storage/metabase/errors.go | 13 ++++ pkg/local_object_storage/metabase/exists.go | 14 +++- pkg/local_object_storage/metabase/get.go | 29 ++++++-- pkg/local_object_storage/metabase/get_test.go | 5 +- .../metabase/inhume_test.go | 9 +-- pkg/local_object_storage/metabase/put.go | 4 + pkg/local_object_storage/shard/control.go | 3 +- .../shard/control_test.go | 7 +- pkg/local_object_storage/shard/delete.go | 6 +- pkg/local_object_storage/shard/delete_test.go | 5 +- pkg/local_object_storage/shard/errors.go | 19 +++++ pkg/local_object_storage/shard/exists.go | 2 + pkg/local_object_storage/shard/get.go | 11 ++- pkg/local_object_storage/shard/get_test.go | 4 +- pkg/local_object_storage/shard/head.go | 8 +- pkg/local_object_storage/shard/head_test.go | 4 +- pkg/local_object_storage/shard/inhume_test.go | 3 +- pkg/local_object_storage/shard/range.go | 2 + pkg/local_object_storage/writecache/delete.go | 8 +- pkg/local_object_storage/writecache/errors.go | 13 ++++ pkg/local_object_storage/writecache/get.go | 16 +++- .../writecache/storage.go | 6 +- pkg/services/object/get/get_test.go | 73 ++++++++++--------- pkg/services/object/get/local.go | 6 +- pkg/services/object/get/remote.go | 11 ++- pkg/services/object/internal/client/client.go | 18 ++--- 49 files changed, 348 insertions(+), 178 deletions(-) create mode 100644 pkg/local_object_storage/blobovnicza/errors.go create mode 100644 pkg/local_object_storage/metabase/errors.go create mode 100644 pkg/local_object_storage/shard/errors.go create mode 100644 pkg/local_object_storage/writecache/errors.go diff --git a/pkg/core/object/errors.go b/pkg/core/object/errors.go index b1ba11e1..d1a69e5c 100644 --- a/pkg/core/object/errors.go +++ b/pkg/core/object/errors.go @@ -2,13 +2,6 @@ package object 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 // payload of an object. 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") diff --git a/pkg/innerring/rpc.go b/pkg/innerring/rpc.go index b553ab08..8c2ddca3 100644 --- a/pkg/innerring/rpc.go +++ b/pkg/innerring/rpc.go @@ -7,12 +7,12 @@ import ( "time" 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" 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/services/audit" "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/object" 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. // 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) { sgAddress := new(addressSDK.Address) sgAddress.SetContainerID(task.ContainerID()) @@ -115,7 +117,9 @@ func (c *ClientCache) getSG(ctx context.Context, addr *addressSDK.Address, nm *n 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. diff --git a/pkg/innerring/settlement.go b/pkg/innerring/settlement.go index c4338d72..c317ec57 100644 --- a/pkg/innerring/settlement.go +++ b/pkg/innerring/settlement.go @@ -167,6 +167,9 @@ func (s settlementDeps) ContainerNodes(e uint64, cid *cid.ID) ([]common.NodeInfo 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) { cn, nm, err := s.buildContainer(0, addr.ContainerID()) if err != nil { diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index 5f79a2e0..c4c36ee0 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -8,7 +8,6 @@ import ( "os" "testing" - "github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/util/logger/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" @@ -34,7 +33,7 @@ func testAddress() *addressSDK.Address { 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 data := make([]byte, sz) @@ -45,26 +44,34 @@ func testPutGet(t *testing.T, blz *Blobovnicza, sz uint64, expPut, expGet error) pPut.SetAddress(addr) pPut.SetMarshaledObject(data) _, 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 } - testGet(t, blz, addr, data, expGet) + testGet(t, blz, addr, data, assertErrGet) 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.SetAddress(addr) // try to read object from Blobovnicza 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()) } } @@ -94,7 +101,7 @@ func TestBlobovnicza(t *testing.T) { require.NoError(t, blz.Init()) // try to read non-existent address - testGet(t, blz, testAddress(), nil, object.ErrNotFound) + testGet(t, blz, testAddress(), nil, IsErrNotFound) filled := uint64(15 * 1 << 10) @@ -109,7 +116,7 @@ func TestBlobovnicza(t *testing.T) { require.NoError(t, err) // should return 404 - testGet(t, blz, addr, nil, object.ErrNotFound) + testGet(t, blz, addr, nil, IsErrNotFound) // fill Blobovnicza fully for ; filled < sizeLim; filled += objSizeLim { @@ -117,7 +124,9 @@ func TestBlobovnicza(t *testing.T) { } // 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()) } diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index b498b818..e3a5eb0d 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -1,7 +1,7 @@ package blobovnicza 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" "go.etcd.io/bbolt" "go.uber.org/zap" @@ -26,7 +26,7 @@ func (p *DeletePrm) SetAddress(addr *addressSDK.Address) { // Returns any error encountered that // 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. func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) { @@ -65,7 +65,9 @@ func (b *Blobovnicza) Delete(prm *DeletePrm) (*DeleteRes, error) { }) if err == nil && !removed { - err = object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } return nil, err diff --git a/pkg/local_object_storage/blobovnicza/errors.go b/pkg/local_object_storage/blobovnicza/errors.go new file mode 100644 index 00000000..1d749b26 --- /dev/null +++ b/pkg/local_object_storage/blobovnicza/errors.go @@ -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)) +} diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 3b40495e..84dcb628 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -1,7 +1,7 @@ package blobovnicza 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" "go.etcd.io/bbolt" "go.uber.org/zap" @@ -32,7 +32,7 @@ func (p *GetRes) Object() []byte { // Returns any error encountered that // 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. func (b *Blobovnicza) Get(prm *GetPrm) (*GetRes, error) { var ( @@ -60,7 +60,9 @@ func (b *Blobovnicza) Get(prm *GetPrm) (*GetRes, error) { } if data == nil { - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } return &GetRes{ diff --git a/pkg/local_object_storage/blobstor/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovnicza.go index 82b6a76e..af4b4705 100644 --- a/pkg/local_object_storage/blobstor/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovnicza.go @@ -13,6 +13,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza" 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" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "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) if err != nil { - if !errors.Is(err, object.ErrNotFound) { + if !blobovnicza.IsErrNotFound(err) { b.log.Debug("could not get object from level", zap.String("level", p), zap.String("error", err.Error()), @@ -240,7 +241,9 @@ func (b *blobovniczas) get(prm *GetSmallPrm) (res *GetSmallRes, err error) { if err == nil && res == nil { // not found in any blobovnicza - err = object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } return @@ -273,7 +276,7 @@ func (b *blobovniczas) delete(prm *DeleteSmallPrm) (res *DeleteSmallRes, err err res, err = b.deleteObjectFromLevel(bPrm, p, !ok, prm) if err != nil { - if !errors.Is(err, object.ErrNotFound) { + if !blobovnicza.IsErrNotFound(err) { b.log.Debug("could not remove object from level", zap.String("level", p), zap.String("error", err.Error()), @@ -293,7 +296,9 @@ func (b *blobovniczas) delete(prm *DeleteSmallPrm) (res *DeleteSmallRes, err err if err == nil && res == nil { // not found in any blobovnicza - err = object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } return @@ -323,7 +328,7 @@ func (b *blobovniczas) getRange(prm *GetRangeSmallPrm) (res *GetRangeSmallRes, e res, err = b.getRangeFromLevel(prm, p, !ok) if err != nil { 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", zap.String("level", p), zap.String("error", err.Error()), @@ -342,7 +347,9 @@ func (b *blobovniczas) getRange(prm *GetRangeSmallPrm) (res *GetRangeSmallRes, e if err == nil && res == nil { // not found in any blobovnicza - err = object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } return @@ -365,7 +372,7 @@ func (b *blobovniczas) deleteObjectFromLevel(prm *blobovnicza.DeletePrm, blzPath if ok { if res, err := b.deleteObject(v.(*blobovnicza.Blobovnicza), prm, dp); err == nil { return res, err - } else if !errors.Is(err, object.ErrNotFound) { + } else if !blobovnicza.IsErrNotFound(err) { log.Debug("could not remove object from opened blobovnicza", zap.String("error", err.Error()), ) @@ -383,7 +390,7 @@ func (b *blobovniczas) deleteObjectFromLevel(prm *blobovnicza.DeletePrm, blzPath if ok && tryActive { if res, err := b.deleteObject(active.blz, prm, dp); err == nil { return res, err - } else if !errors.Is(err, object.ErrNotFound) { + } else if !blobovnicza.IsErrNotFound(err) { log.Debug("could not remove object from active blobovnicza", zap.String("error", err.Error()), ) @@ -397,7 +404,9 @@ func (b *blobovniczas) deleteObjectFromLevel(prm *blobovnicza.DeletePrm, blzPath // and it's pointless to open them). if u64FromHexString(filepath.Base(blzPath)) > active.ind { log.Debug("index is too big") - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } // open blobovnicza (cached inside) @@ -426,7 +435,7 @@ func (b *blobovniczas) getObjectFromLevel(prm *blobovnicza.GetPrm, blzPath strin if ok { if res, err := b.getObject(v.(*blobovnicza.Blobovnicza), prm); err == nil { return res, err - } else if !errors.Is(err, object.ErrNotFound) { + } else if !blobovnicza.IsErrNotFound(err) { log.Debug("could not read object from opened blobovnicza", zap.String("error", err.Error()), ) @@ -445,7 +454,7 @@ func (b *blobovniczas) getObjectFromLevel(prm *blobovnicza.GetPrm, blzPath strin if ok && tryActive { if res, err := b.getObject(active.blz, prm); err == nil { return res, err - } else if !errors.Is(err, object.ErrNotFound) { + } else if !blobovnicza.IsErrNotFound(err) { log.Debug("could not get object from active blobovnicza", 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). if u64FromHexString(filepath.Base(blzPath)) > active.ind { log.Debug("index is too big") - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } // open blobovnicza (cached inside) @@ -492,7 +503,7 @@ func (b *blobovniczas) getRangeFromLevel(prm *GetRangeSmallPrm, blzPath string, errors.Is(err, object.ErrRangeOutOfBounds): return res, err default: - if !errors.Is(err, object.ErrNotFound) { + if !blobovnicza.IsErrNotFound(err) { log.Debug("could not read payload range from opened blobovnicza", zap.String("error", err.Error()), ) @@ -516,7 +527,7 @@ func (b *blobovniczas) getRangeFromLevel(prm *GetRangeSmallPrm, blzPath string, errors.Is(err, object.ErrRangeOutOfBounds): return res, err default: - if !errors.Is(err, object.ErrNotFound) { + if !blobovnicza.IsErrNotFound(err) { log.Debug("could not read payload range from active blobovnicza", zap.String("error", err.Error()), ) @@ -531,7 +542,10 @@ func (b *blobovniczas) getRangeFromLevel(prm *GetRangeSmallPrm, blzPath string, // and it's pointless to open them). if u64FromHexString(filepath.Base(blzPath)) > active.ind { log.Debug("index is too big") - return nil, object.ErrNotFound + + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } // open blobovnicza (cached inside) diff --git a/pkg/local_object_storage/blobstor/blobovnicza_test.go b/pkg/local_object_storage/blobstor/blobovnicza_test.go index 958d91b9..81f66580 100644 --- a/pkg/local_object_storage/blobstor/blobovnicza_test.go +++ b/pkg/local_object_storage/blobstor/blobovnicza_test.go @@ -2,13 +2,13 @@ package blobstor import ( "crypto/sha256" - "errors" "math/rand" "os" "testing" "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" @@ -153,9 +153,9 @@ func TestBlobovniczas(t *testing.T) { gPrm.SetAddress(addrList[i]) _, err = b.get(gPrm) - require.True(t, errors.Is(err, object.ErrNotFound)) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) _, err = b.delete(dPrm) - require.True(t, errors.Is(err, object.ErrNotFound)) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) } } diff --git a/pkg/local_object_storage/blobstor/delete_big.go b/pkg/local_object_storage/blobstor/delete_big.go index c7abec66..83fa8a8c 100644 --- a/pkg/local_object_storage/blobstor/delete_big.go +++ b/pkg/local_object_storage/blobstor/delete_big.go @@ -3,9 +3,9 @@ package blobstor import ( "errors" - "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" ) // DeleteBigPrm groups the parameters of DeleteBig operation. @@ -21,11 +21,13 @@ type DeleteBigRes struct{} // Returns any error encountered that did not allow // 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) { err := b.fsTree.Delete(prm.addr) if errors.Is(err, fstree.ErrFileNotFound) { - err = object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + err = errNotFound } if err == nil { diff --git a/pkg/local_object_storage/blobstor/delete_small.go b/pkg/local_object_storage/blobstor/delete_small.go index a0585868..e43f41e8 100644 --- a/pkg/local_object_storage/blobstor/delete_small.go +++ b/pkg/local_object_storage/blobstor/delete_small.go @@ -17,7 +17,7 @@ type DeleteSmallRes struct{} // Returns any error encountered that did not allow // 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) { return b.blobovniczas.delete(prm) } diff --git a/pkg/local_object_storage/blobstor/get_big.go b/pkg/local_object_storage/blobstor/get_big.go index 8fa962db..8403924a 100644 --- a/pkg/local_object_storage/blobstor/get_big.go +++ b/pkg/local_object_storage/blobstor/get_big.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" ) @@ -24,14 +24,16 @@ type GetBigRes struct { // Returns any error encountered that // 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. func (b *BlobStor) GetBig(prm *GetBigPrm) (*GetBigRes, error) { // get compressed object data data, err := b.fsTree.Get(prm.addr) if err != nil { 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) diff --git a/pkg/local_object_storage/blobstor/get_range_big.go b/pkg/local_object_storage/blobstor/get_range_big.go index 761e103f..d2450928 100644 --- a/pkg/local_object_storage/blobstor/get_range_big.go +++ b/pkg/local_object_storage/blobstor/get_range_big.go @@ -6,6 +6,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" ) @@ -26,12 +27,15 @@ type GetRangeBigRes struct { // did not allow to completely read the object payload range. // // 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) { // get compressed object data data, err := b.fsTree.Get(prm.addr) if err != nil { 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) diff --git a/pkg/local_object_storage/blobstor/get_range_small.go b/pkg/local_object_storage/blobstor/get_range_small.go index 7fe4c0da..1baa8c31 100644 --- a/pkg/local_object_storage/blobstor/get_range_small.go +++ b/pkg/local_object_storage/blobstor/get_range_small.go @@ -21,6 +21,7 @@ type GetRangeSmallRes struct { // did not allow to completely read the object payload range. // // 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) { return b.blobovniczas.getRange(prm) } diff --git a/pkg/local_object_storage/blobstor/get_small.go b/pkg/local_object_storage/blobstor/get_small.go index 7ff5d89e..d2caec5f 100644 --- a/pkg/local_object_storage/blobstor/get_small.go +++ b/pkg/local_object_storage/blobstor/get_small.go @@ -18,6 +18,8 @@ type GetSmallRes struct { // // Returns any error encountered that // 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) { return b.blobovniczas.get(prm) } diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index 584d55a0..b149c98f 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -1,10 +1,8 @@ package engine import ( - "errors" - - "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" ) @@ -16,7 +14,7 @@ func (e *StorageEngine) exists(addr *addressSDK.Address) (bool, error) { e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { res, err := sh.Exists(shPrm) if err != nil { - if errors.Is(err, object.ErrAlreadyRemoved) { + if shard.IsErrRemoved(err) { alreadyRemoved = true return true @@ -33,7 +31,9 @@ func (e *StorageEngine) exists(addr *addressSDK.Address) (bool, error) { }) if alreadyRemoved { - return false, object.ErrAlreadyRemoved + var errRemoved apistatus.ObjectAlreadyRemoved + + return false, errRemoved } return exists, nil diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 3bf6afeb..7edda40c 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -3,9 +3,9 @@ package engine 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/util" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "go.uber.org/zap" @@ -42,7 +42,8 @@ func (r *GetRes) Object() *objectSDK.Object { // Returns any error encountered that // 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). 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 siErr *objectSDK.SplitInfoError + errNotFound apistatus.ObjectNotFound + outSI *objectSDK.SplitInfo - outError = object.ErrNotFound + outError error = errNotFound shardWithMeta hashedShard metaError error @@ -81,7 +84,7 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) { metaError = err } switch { - case errors.Is(err, object.ErrNotFound): + case shard.IsErrNotFound(err): return false // ignore, go to next shard case errors.As(err, &siErr): siErr = err.(*objectSDK.SplitInfoError) @@ -98,7 +101,7 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) { } return false - case errors.Is(err, object.ErrAlreadyRemoved): + case shard.IsErrRemoved(err): outError = err return true // stop, return it back @@ -118,7 +121,7 @@ func (e *StorageEngine) get(prm *GetPrm) (*GetRes, error) { } if obj == nil { - if shardWithMeta.Shard == nil || !errors.Is(outError, object.ErrNotFound) { + if shardWithMeta.Shard == nil || !shard.IsErrNotFound(outError) { return nil, outError } diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index 26c0dd1b..eb898a7c 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -3,9 +3,9 @@ package engine 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/util" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" 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 // did not allow to completely read the object header. // -// Returns object.ErrNotFound if requested object is missing in local storage. -// Returns object.ErrAlreadyRemoved if requested object was inhumed. +// Returns apistatus.ObjectNotFound if requested object is missing in local storage. +// Returns apistatus.ObjectAlreadyRemoved if requested object was inhumed. // // Returns an error if executions are blocked (see BlockExecution). 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 siErr *objectSDK.SplitInfoError + errNotFound apistatus.ObjectNotFound + outSI *objectSDK.SplitInfo - outError = object.ErrNotFound + outError error = errNotFound ) shPrm := new(shard.HeadPrm). @@ -89,7 +91,7 @@ func (e *StorageEngine) head(prm *HeadPrm) (*HeadRes, error) { res, err := sh.Head(shPrm) if err != nil { switch { - case errors.Is(err, object.ErrNotFound): + case shard.IsErrNotFound(err): return false // ignore, go to next shard case errors.As(err, &siErr): siErr = err.(*objectSDK.SplitInfoError) @@ -106,7 +108,7 @@ func (e *StorageEngine) head(prm *HeadPrm) (*HeadRes, error) { } return false - case errors.Is(err, object.ErrAlreadyRemoved): + case shard.IsErrRemoved(err): outError = err return true // stop, return it back diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 94c68909..39c29aac 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -4,7 +4,6 @@ import ( "context" "errors" - "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" @@ -116,7 +115,7 @@ func (e *StorageEngine) inhumeAddr(addr *addressSDK.Address, prm *shard.InhumePr WithAddress(addr), ) if err != nil { - if errors.Is(err, object.ErrAlreadyRemoved) { + if shard.IsErrRemoved(err) { // inhumed once - no need to be inhumed again status = 2 return true diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 2f986a4d..a1597b5e 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -36,6 +36,8 @@ func (p *PutPrm) WithObject(obj *objectSDK.Object) *PutPrm { // did not allow to completely save the object. // // 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) { err = e.execIfNotBlocked(func() error { res, err = e.put(prm) diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index e3e1860f..a5d1deb7 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -6,6 +6,7 @@ import ( "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/util" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "go.uber.org/zap" @@ -58,8 +59,8 @@ func (r *RngRes) Object() *objectSDK.Object { // Returns any error encountered that // did not allow to completely read the object part. // -// Returns ErrNotFound if requested object is missing in local storage. -// Returns ErrAlreadyRemoved if requested object is inhumed. +// Returns apistatus.ObjectNotFound if requested object is missing in local storage. +// Returns apistatus.ObjectAlreadyRemoved if requested object is inhumed. // Returns ErrRangeOutOfBounds if requested object range is out of bounds. // // Returns an error if executions are blocked (see BlockExecution). @@ -81,8 +82,10 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) { obj *objectSDK.Object siErr *objectSDK.SplitInfoError + errNotFound apistatus.ObjectNotFound + outSI *objectSDK.SplitInfo - outError = object.ErrNotFound + outError error = errNotFound shardWithMeta hashedShard metaError error @@ -100,7 +103,7 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) { metaError = err } switch { - case errors.Is(err, object.ErrNotFound): + case shard.IsErrNotFound(err): return false // ignore, go to next shard case errors.As(err, &siErr): siErr = err.(*objectSDK.SplitInfoError) @@ -118,7 +121,7 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) { return false case - errors.Is(err, object.ErrAlreadyRemoved), + shard.IsErrRemoved(err), errors.Is(err, object.ErrRangeOutOfBounds): outError = err @@ -139,7 +142,7 @@ func (e *StorageEngine) getRange(prm *RngPrm) (*RngRes, error) { } if obj == nil { - if shardWithMeta.Shard == nil || !errors.Is(outError, object.ErrNotFound) { + if shardWithMeta.Shard == nil || !shard.IsErrNotFound(outError) { return nil, outError } diff --git a/pkg/local_object_storage/metabase/control_test.go b/pkg/local_object_storage/metabase/control_test.go index a479233e..4f69d9f8 100644 --- a/pkg/local_object_storage/metabase/control_test.go +++ b/pkg/local_object_storage/metabase/control_test.go @@ -20,9 +20,13 @@ func TestReset(t *testing.T) { 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) - require.ErrorIs(t, err, expErr) + if assertErr != nil { + require.True(t, assertErr(err)) + } else { + require.NoError(t, err) + } require.Equal(t, expExists, exists) } @@ -36,7 +40,7 @@ func TestReset(t *testing.T) { require.NoError(t, err) assertExists(addr, true, nil) - assertExists(addrToInhume, false, object.ErrAlreadyRemoved) + assertExists(addrToInhume, false, meta.IsErrRemoved) err = db.Reset() require.NoError(t, err) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 2fea0c21..4f8fd1aa 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -7,6 +7,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" 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" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "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 obj, err := db.get(tx, addr, false, true) if err != nil { - if errors.Is(err, object.ErrNotFound) { + if errors.As(err, new(apistatus.ObjectNotFound)) { return nil } diff --git a/pkg/local_object_storage/metabase/errors.go b/pkg/local_object_storage/metabase/errors.go new file mode 100644 index 00000000..927cbf83 --- /dev/null +++ b/pkg/local_object_storage/metabase/errors.go @@ -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)) +} diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index ab7d4870..2642f1bc 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -5,7 +5,7 @@ import ( "errors" "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" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" 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. +// +// See DB.Exists docs. func Exists(db *DB, addr *addressSDK.Address) (bool, error) { r, err := db.Exists(new(ExistsPrm).WithAddress(addr)) 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 // 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) { res = new(ExistsRes) @@ -66,9 +70,13 @@ func (db *DB) exists(tx *bbolt.Tx, addr *addressSDK.Address) (exists bool, err e // check graveyard first switch inGraveyard(tx, addr) { case 1: - return false, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return false, errNotFound case 2: - return false, object.ErrAlreadyRemoved + var errRemoved apistatus.ObjectAlreadyRemoved + + return false, errRemoved } objKey := objectKey(addr.ObjectID()) diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 6f18c206..f4374836 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -3,7 +3,7 @@ package meta import ( "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" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" 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. +// +// 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) { res = new(GetRes) @@ -89,9 +92,13 @@ func (db *DB) get(tx *bbolt.Tx, addr *addressSDK.Address, checkGraveyard, raw bo if checkGraveyard { switch inGraveyard(tx, addr) { case 1: - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound 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)) if parentBucket == nil { - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } 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 - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } // 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() if par == nil { // this should never happen though - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } return par, nil @@ -179,5 +192,7 @@ func getSplitInfoError(tx *bbolt.Tx, cid *cid.ID, key []byte) error { return objectSDK.NewSplitInfoError(splitInfo) } - return object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return errNotFound } diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index f72ec12b..a14cda55 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -6,6 +6,7 @@ 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" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/stretchr/testify/require" @@ -112,12 +113,12 @@ func TestDB_Get(t *testing.T) { require.NoError(t, meta.Inhume(db, obj, ts)) _, err := meta.Get(db, obj) - require.ErrorIs(t, err, object.ErrAlreadyRemoved) + require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved)) obj = generateAddress() require.NoError(t, meta.Inhume(db, obj, nil)) _, err = meta.Get(db, obj) - require.ErrorIs(t, err, object.ErrNotFound) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) }) } diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index e297cdbe..eb5ccaa2 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -1,7 +1,6 @@ package meta_test import ( - "errors" "testing" "github.com/nspcc-dev/neofs-node/pkg/core/object" @@ -28,10 +27,10 @@ func TestDB_Inhume(t *testing.T) { require.NoError(t, err) _, 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)) - require.EqualError(t, err, object.ErrAlreadyRemoved.Error()) + require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved)) } func TestInhumeTombOnTomb(t *testing.T) { @@ -56,7 +55,7 @@ func TestInhumeTombOnTomb(t *testing.T) { // addr1 should become inhumed {addr1:addr2} _, 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 _, err = db.Inhume(inhumePrm. @@ -73,7 +72,7 @@ func TestInhumeTombOnTomb(t *testing.T) { // addr3 should be inhumed {addr3: addr1} _, 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) _, err = db.Inhume(inhumePrm. diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 1467ed95..9ed48394 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -56,6 +56,8 @@ var ( ) // Put saves the object in DB. +// +// See DB.Put docs. func Put(db *DB, obj *objectSDK.Object, id *blobovnicza.ID) error { _, err := db.Put(new(PutPrm). 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. // 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) { err = db.boltDB.Batch(func(tx *bbolt.Tx) error { return db.put(tx, prm.obj, prm.id, nil) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 732b5aee..1e6f3e44 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -1,7 +1,6 @@ package shard import ( - "errors" "fmt" "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) - if err != nil && !errors.Is(err, object.ErrAlreadyRemoved) { + if err != nil && !meta.IsErrRemoved(err) { return err } diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index d0cad796..27ee7905 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor" 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" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" 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)) if expObj == nil { - require.ErrorIs(t, err, object.ErrNotFound) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) return } @@ -122,9 +123,9 @@ func TestRefillMetabase(t *testing.T) { _, err := sh.Head(headPrm.WithAddress(member)) if exists { - require.ErrorIs(t, err, object.ErrAlreadyRemoved) + require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved)) } else { - require.ErrorIs(t, err, object.ErrNotFound) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) } } } diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 0cef8300..1b4e33b9 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -1,12 +1,10 @@ package shard 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/blobstor" 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" "go.uber.org/zap" ) @@ -46,7 +44,7 @@ func (s *Shard) Delete(prm *DeletePrm) (*DeleteRes, error) { for i := range prm.addr { if s.hasWriteCache() { 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())) } } diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index cb0f5d9d..83149bb5 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" "github.com/stretchr/testify/require" ) @@ -50,7 +51,7 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { require.NoError(t, err) _, 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) { @@ -73,6 +74,6 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { require.NoError(t, err) _, err = sh.Get(getPrm) - require.EqualError(t, err, object.ErrNotFound.Error()) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) }) } diff --git a/pkg/local_object_storage/shard/errors.go b/pkg/local_object_storage/shard/errors.go new file mode 100644 index 00000000..18a29669 --- /dev/null +++ b/pkg/local_object_storage/shard/errors.go @@ -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)) +} diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index d9c03922..b8473352 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -33,6 +33,8 @@ func (p *ExistsRes) Exists() bool { // // Returns any error encountered that does not allow to // 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) { exists, err := s.objectExists(prm.addr) diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 19194f38..bed17a1c 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -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/blobstor" 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" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "go.uber.org/zap" @@ -62,7 +64,8 @@ func (r *GetRes) HasMeta() bool { // Returns any error encountered that // 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) { var big, small storFetcher @@ -112,7 +115,7 @@ func (s *Shard) fetchObjectData(addr *addressSDK.Address, skipMeta bool, big, sm return res, false, nil } - if errors.Is(err, object.ErrNotFound) { + if writecache.IsErrNotFound(err) { s.log.Debug("object is missing in write-cache") } else { 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 { - return nil, false, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, false, errNotFound } blobovniczaID, err := meta.IsSmall(s.metaBase, addr) diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index 0e5ebf24..647c55af 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -110,10 +110,10 @@ func testGet(t *testing.T, sh *shard.Shard, getPrm *shard.GetPrm, hasWriteCache res, err := sh.Get(getPrm) if hasWriteCache { require.Eventually(t, func() bool { - if errors.Is(err, object.ErrNotFound) { + if shard.IsErrNotFound(err) { res, err = sh.Get(getPrm) } - return !errors.Is(err, object.ErrNotFound) + return !shard.IsErrNotFound(err) }, time.Second, time.Millisecond*100) } return res, err diff --git a/pkg/local_object_storage/shard/head.go b/pkg/local_object_storage/shard/head.go index 467f7852..04348e6c 100644 --- a/pkg/local_object_storage/shard/head.go +++ b/pkg/local_object_storage/shard/head.go @@ -1,11 +1,10 @@ package shard import ( - "errors" "fmt" - "github.com/nspcc-dev/neofs-node/pkg/core/object" 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" 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. // // 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) { // 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{ obj: header, }, 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 return nil, fmt.Errorf("could not read header from write-cache: %w", err) } diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index 32ed10d9..fabb4933 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -83,10 +83,10 @@ func testHead(t *testing.T, sh *shard.Shard, headPrm *shard.HeadPrm, hasWriteCac res, err := sh.Head(headPrm) if hasWriteCache { require.Eventually(t, func() bool { - if errors.Is(err, object.ErrNotFound) { + if shard.IsErrNotFound(err) { res, err = sh.Head(headPrm) } - return !errors.Is(err, object.ErrNotFound) + return !shard.IsErrNotFound(err) }, time.Second, time.Millisecond*100) } return res, err diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 00cd0bb6..63f08323 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" "github.com/stretchr/testify/require" ) @@ -49,5 +50,5 @@ func testShardInhume(t *testing.T, hasWriteCache bool) { require.NoError(t, err) _, err = sh.Get(getPrm) - require.EqualError(t, err, object.ErrAlreadyRemoved.Error()) + require.ErrorAs(t, err, new(apistatus.ObjectAlreadyRemoved)) } diff --git a/pkg/local_object_storage/shard/range.go b/pkg/local_object_storage/shard/range.go index 4f322e45..7fa09565 100644 --- a/pkg/local_object_storage/shard/range.go +++ b/pkg/local_object_storage/shard/range.go @@ -69,6 +69,8 @@ func (r *RngRes) HasMeta() bool { // did not allow to completely read the object part. // // 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) { var big, small storFetcher diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index 6ae38d21..e843ebd9 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -3,14 +3,16 @@ package writecache import ( "errors" - "github.com/nspcc-dev/neofs-node/pkg/core/object" "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" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "go.etcd.io/bbolt" ) // Delete removes object from write-cache. +// +// Returns apistatus.ObjectNotFound is object is missing in write-cache. func (c *cache) Delete(addr *addressSDK.Address) error { c.modeMtx.RLock() defer c.modeMtx.RUnlock() @@ -58,7 +60,9 @@ func (c *cache) Delete(addr *addressSDK.Address) error { err := c.fsTree.Delete(addr) if errors.Is(err, fstree.ErrFileNotFound) { - err = object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + err = errNotFound } if err == nil { diff --git a/pkg/local_object_storage/writecache/errors.go b/pkg/local_object_storage/writecache/errors.go new file mode 100644 index 00000000..ef9feea9 --- /dev/null +++ b/pkg/local_object_storage/writecache/errors.go @@ -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)) +} diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go index 531a8432..a3351105 100644 --- a/pkg/local_object_storage/writecache/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -1,13 +1,15 @@ package writecache 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" addressSDK "github.com/nspcc-dev/neofs-sdk-go/object/address" "go.etcd.io/bbolt" ) // 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) { saddr := addr.String() @@ -30,7 +32,9 @@ func (c *cache) Get(addr *addressSDK.Address) (*objectSDK.Object, error) { data, err := c.fsTree.Get(addr) if err != nil { - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } obj := objectSDK.New() @@ -43,6 +47,8 @@ func (c *cache) Get(addr *addressSDK.Address) (*objectSDK.Object, error) { } // 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) { // 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 @@ -61,6 +67,8 @@ func (c *cache) Head(addr *addressSDK.Address) (*objectSDK.Object, error) { // Get fetches object from the underlying database. // 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) { var value []byte 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) if value == nil { - return object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return errNotFound } value = cloneBytes(value) return nil diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index b67e9355..6c855699 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -7,10 +7,10 @@ import ( lru "github.com/hashicorp/golang-lru" "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" storagelog "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/internal/log" "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" "go.etcd.io/bbolt" "go.uber.org/zap" @@ -103,7 +103,9 @@ func (c *cache) deleteFromDB(keys [][]byte) error { for i := range keys { has := b.Get(keys[i]) if has == nil { - return object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return errNotFound } if err := b.Delete(keys[i]); err != nil { return err diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 9608df8f..2bcbef2b 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -15,6 +15,7 @@ import ( "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/util/logger/test" + apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" 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) { v, ok := c.results[exec.address().String()] if !ok { - return nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } if v.err != nil { @@ -131,7 +134,9 @@ func (s *testStorage) get(exec *execCtx) (*objectSDK.Object, error) { ) if _, ok = s.inhumed[sAddr]; ok { - return nil, object.ErrAlreadyRemoved + var errRemoved apistatus.ObjectAlreadyRemoved + + return nil, errRemoved } 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 nil, object.ErrNotFound + var errNotFound apistatus.ObjectNotFound + + return nil, errNotFound } func cutToRange(o *objectSDK.Object, rng *objectSDK.Range) *objectSDK.Object { @@ -309,19 +316,19 @@ func TestGetLocalOnly(t *testing.T) { 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.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -336,20 +343,20 @@ func TestGetLocalOnly(t *testing.T) { 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.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -599,7 +606,7 @@ func TestGetRemoteSmall(t *testing.T) { c1.addResult(addr, nil, errors.New("any error")) c2 := newTestClient() - c2.addResult(addr, nil, object.ErrAlreadyRemoved) + c2.addResult(addr, nil, new(apistatus.ObjectAlreadyRemoved)) svc := newSvc(builder, &testClientCache{ clients: map[string]*testClient{ @@ -612,19 +619,19 @@ func TestGetRemoteSmall(t *testing.T) { p.WithAddress(addr) 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.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -656,19 +663,19 @@ func TestGetRemoteSmall(t *testing.T) { p.WithAddress(addr) 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.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -700,11 +707,11 @@ func TestGetRemoteSmall(t *testing.T) { c1 := newTestClient() c1.addResult(addr, nil, errors.New("any error")) - c1.addResult(splitAddr, nil, object.ErrNotFound) + c1.addResult(splitAddr, nil, apistatus.ObjectNotFound{}) c2 := newTestClient() c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo)) - c2.addResult(splitAddr, nil, object.ErrNotFound) + c2.addResult(splitAddr, nil, apistatus.ObjectNotFound{}) builder := &testPlacementBuilder{ vectors: map[string][]netmap.Nodes{ @@ -726,13 +733,13 @@ func TestGetRemoteSmall(t *testing.T) { p.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -776,7 +783,7 @@ func TestGetRemoteSmall(t *testing.T) { c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo)) c2.addResult(linkAddr, linkingObj, nil) c2.addResult(child1Addr, children[0], nil) - c2.addResult(child2Addr, nil, object.ErrNotFound) + c2.addResult(child2Addr, nil, apistatus.ObjectNotFound{}) builder := &testPlacementBuilder{ vectors: map[string][]netmap.Nodes{ @@ -800,13 +807,13 @@ func TestGetRemoteSmall(t *testing.T) { p.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -913,11 +920,11 @@ func TestGetRemoteSmall(t *testing.T) { c1 := newTestClient() c1.addResult(addr, nil, errors.New("any error")) - c1.addResult(splitAddr, nil, object.ErrNotFound) + c1.addResult(splitAddr, nil, apistatus.ObjectNotFound{}) c2 := newTestClient() c2.addResult(addr, nil, objectSDK.NewSplitInfoError(splitInfo)) - c2.addResult(splitAddr, nil, object.ErrNotFound) + c2.addResult(splitAddr, nil, apistatus.ObjectNotFound{}) builder := &testPlacementBuilder{ vectors: map[string][]netmap.Nodes{ @@ -939,13 +946,13 @@ func TestGetRemoteSmall(t *testing.T) { p.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -1000,19 +1007,19 @@ func TestGetRemoteSmall(t *testing.T) { testHeadVirtual(svc, addr, splitInfo) headSvc := newTestClient() - headSvc.addResult(preRightAddr, nil, object.ErrNotFound) + headSvc.addResult(preRightAddr, nil, apistatus.ObjectNotFound{}) p := newPrm(false, NewSimpleObjectWriter()) p.WithAddress(addr) 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.WithAddress(addr) 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) { @@ -1180,7 +1187,7 @@ func TestGetFromPastEpoch(t *testing.T) { p.WithAddress(addr) err := svc.Get(ctx, p) - require.True(t, errors.Is(err, object.ErrNotFound)) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) commonPrm.SetNetmapLookupDepth(1) @@ -1203,7 +1210,7 @@ func TestGetFromPastEpoch(t *testing.T) { rp.SetRange(r) err = svc.GetRange(ctx, rp) - require.True(t, errors.Is(err, object.ErrNotFound)) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) w = NewSimpleObjectWriter() rp.SetChunkWriter(w) @@ -1220,7 +1227,7 @@ func TestGetFromPastEpoch(t *testing.T) { hp.WithAddress(addr) err = svc.Head(ctx, hp) - require.True(t, errors.Is(err, object.ErrNotFound)) + require.ErrorAs(t, err, new(apistatus.ObjectNotFound)) w = NewSimpleObjectWriter() hp.SetHeaderWriter(w) diff --git a/pkg/services/object/get/local.go b/pkg/services/object/get/local.go index 0e0234c5..5c127b71 100644 --- a/pkg/services/object/get/local.go +++ b/pkg/services/object/get/local.go @@ -4,6 +4,7 @@ import ( "errors" "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" "go.uber.org/zap" ) @@ -14,6 +15,7 @@ func (exec *execCtx) executeLocal() { exec.collectedObject, err = exec.svc.localStorage.get(exec) var errSplitInfo *objectSDK.SplitInfoError + var errRemoved apistatus.ObjectAlreadyRemoved switch { default: @@ -27,9 +29,9 @@ func (exec *execCtx) executeLocal() { exec.status = statusOK exec.err = nil exec.writeCollectedObject() - case errors.Is(err, object.ErrAlreadyRemoved): + case errors.As(err, &errRemoved): exec.status = statusINHUMED - exec.err = object.ErrAlreadyRemoved + exec.err = errRemoved case errors.As(err, &errSplitInfo): exec.status = statusVIRTUAL mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo()) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index 666b3fa4..7279b869 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -5,7 +5,7 @@ import ( "errors" "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" "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) var errSplitInfo *objectSDK.SplitInfoError + var errRemoved *apistatus.ObjectAlreadyRemoved switch { default: + var errNotFound apistatus.ObjectNotFound + exec.status = statusUndefined - exec.err = object.ErrNotFound + exec.err = errNotFound exec.log.Debug("remote call failed", zap.String("error", err.Error()), @@ -35,9 +38,9 @@ func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool exec.err = nil exec.collectedObject = obj exec.writeCollectedObject() - case errors.Is(err, object.ErrAlreadyRemoved): + case errors.As(err, &errRemoved): exec.status = statusINHUMED - exec.err = object.ErrAlreadyRemoved + exec.err = errRemoved case errors.As(err, &errSplitInfo): exec.status = statusVIRTUAL mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo()) diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 494c4733..449ad9c7 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -148,8 +148,8 @@ func (x GetObjectRes) Object() *object.Object { // // Returns any error prevented the operation from completing correctly in error return. // Returns: -// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; -// object.ErrAlreadyRemoved error if requested object is marked to be removed. +// error of type *object.SplitInfoError if object raw flag is set and requested object is virtual; +// error of type *apistatus.ObjectAlreadyRemoved if requested object is marked to be removed. func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { if prm.tokenSession != nil { prm.cliPrm.WithinSession(*prm.tokenSession) @@ -193,8 +193,6 @@ func GetObject(prm GetObjectPrm) (*GetObjectRes, error) { return nil, fmt.Errorf("read payload: %w", err) } - // FIXME: #1158 object.ErrAlreadyRemoved never returns - obj.SetPayload(buf) 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: -// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; -// object.ErrAlreadyRemoved error if requested object is marked to be removed. +// error of type *object.SplitInfoError if object raw flag is set and requested object is virtual; +// error of type *apistatus.ObjectAlreadyRemoved if requested object is marked to be removed. func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { if prm.local { prm.cliPrm.MarkLocal() @@ -272,8 +270,6 @@ func HeadObject(prm HeadObjectPrm) (*HeadObjectRes, error) { return nil, fmt.Errorf("read object header from NeoFS: %w", err) } - // FIXME: #1158 object.ErrAlreadyRemoved never returns - var hdr object.Object 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: -// error of type *object.SplitInfoError if object if raw flag is set and requested object is virtual; -// object.ErrAlreadyRemoved error if requested object is marked to be removed. +// error of type *object.SplitInfoError if object raw flag is set and requested object is virtual; +// error of type *apistatus.ObjectAlreadyRemoved if requested object is marked to be removed. func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { if prm.local { prm.cliPrm.MarkLocal() @@ -368,8 +364,6 @@ func PayloadRange(prm PayloadRangePrm) (*PayloadRangeRes, error) { return nil, fmt.Errorf("read payload: %w", err) } - // FIXME: #1158 object.ErrAlreadyRemoved never returns - return &PayloadRangeRes{ data: data, }, nil