diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go new file mode 100644 index 00000000..6febe589 --- /dev/null +++ b/pkg/local_object_storage/engine/exists.go @@ -0,0 +1,81 @@ +package engine + +import ( + "errors" + + objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object" + "github.com/nspcc-dev/neofs-node/pkg/core/object" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard" + "go.uber.org/zap" +) + +// ExistsPrm groups the parameters of Exists operation. +type ExistsPrm struct { + addr *objectSDK.Address +} + +// ExistsRes groups resulting values of Exists operation. +type ExistsRes struct { + ex bool +} + +// WithAddress is an Exists option to set object checked for existence. +func (p *ExistsPrm) WithAddress(addr *objectSDK.Address) *ExistsPrm { + if p != nil { + p.addr = addr + } + + return p +} + +// Exists returns the fact that the object is in the storage engine. +func (p *ExistsRes) Exists() bool { + return p.ex +} + +// Exists checks if object is presented in storage engine +// +// Returns any error encountered that does not allow to +// unambiguously determine the presence of an object. +func (e *StorageEngine) Exists(prm *ExistsPrm) (*ExistsRes, error) { + exists, err := e.exists(prm.addr) + + return &ExistsRes{ + ex: exists, + }, err +} + +func (e *StorageEngine) exists(addr *objectSDK.Address) (bool, error) { + shPrm := new(shard.ExistsPrm).WithAddress(addr) + alreadyRemoved := false + exists := false + + e.iterateOverSortedShards(addr, func(_ int, sh *shard.Shard) (stop bool) { + res, err := sh.Exists(shPrm) + if err != nil { + if errors.Is(err, object.ErrAlreadyRemoved) { + alreadyRemoved = true + + return true + } + + // TODO: smth wrong with shard, need to be processed + e.log.Warn("could not check existence of object in shard", + zap.Stringer("shard", sh.ID()), + zap.String("error", err.Error()), + ) + } + + if res != nil && !exists { + exists = res.Exists() + } + + return false + }) + + if alreadyRemoved { + return false, object.ErrAlreadyRemoved + } + + return exists, nil +} diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 55d212aa..2d5b0926 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -34,27 +34,14 @@ func (p *PutPrm) WithObject(obj *object.Object) *PutPrm { // Returns any error encountered that // did not allow to completely save the object. func (e *StorageEngine) Put(prm *PutPrm) (*PutRes, error) { - alreadyRemoved := false // first check if object has not been marked as removed + _, err := e.exists(prm.obj.Address()) // todo: make this check parallel + if err != nil { + return nil, err + } existPrm := new(shard.ExistsPrm) existPrm.WithAddress(prm.obj.Address()) - // todo: make this check parallel - e.iterateOverUnsortedShards(func(s *shard.Shard) (stop bool) { - _, err := s.Exists(existPrm) - if err != nil && errors.Is(err, object.ErrAlreadyRemoved) { - alreadyRemoved = true - - return true - } - - return false - }) - - if alreadyRemoved { - return nil, object.ErrAlreadyRemoved - } - finished := false e.iterateOverSortedShards(prm.obj.Address(), func(ind int, s *shard.Shard) (stop bool) { @@ -96,11 +83,10 @@ func (e *StorageEngine) Put(prm *PutPrm) (*PutRes, error) { } finished = true + return true }) - var err error = nil - if !finished { err = errPutShard }