From bc09e29bfd120b39d743c352867ba93771df7e97 Mon Sep 17 00:00:00 2001
From: Alex Vanin <alexey@nspcc.ru>
Date: Wed, 14 Apr 2021 12:05:53 +0300
Subject: [PATCH] [#477] engine: Reuse SplitInfoError fix for `engine.Range`

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
---
 pkg/local_object_storage/engine/range.go | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go
index 1d7c9cf43..32f346e5a 100644
--- a/pkg/local_object_storage/engine/range.go
+++ b/pkg/local_object_storage/engine/range.go
@@ -5,6 +5,7 @@ import (
 
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"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/shard"
 	"go.uber.org/zap"
 )
@@ -68,6 +69,7 @@ func (e *StorageEngine) GetRange(prm *RngPrm) (*RngRes, error) {
 		obj   *object.Object
 		siErr *objectSDK.SplitInfoError
 
+		outSI    *objectSDK.SplitInfo
 		outError = object.ErrNotFound
 	)
 
@@ -81,10 +83,24 @@ func (e *StorageEngine) GetRange(prm *RngPrm) (*RngRes, error) {
 			switch {
 			case errors.Is(err, object.ErrNotFound):
 				return false // ignore, go to next shard
+			case errors.As(err, &siErr):
+				siErr = err.(*objectSDK.SplitInfoError)
+
+				if outSI == nil {
+					outSI = objectSDK.NewSplitInfo()
+				}
+
+				meta.MergeSplitInfo(siErr.SplitInfo(), outSI)
+
+				// stop iterating over shards if SplitInfo structure is complete
+				if outSI.Link() != nil && outSI.LastPart() != nil {
+					return true
+				}
+
+				return false
 			case
 				errors.Is(err, object.ErrAlreadyRemoved),
-				errors.Is(err, object.ErrRangeOutOfBounds),
-				errors.As(err, &siErr):
+				errors.Is(err, object.ErrRangeOutOfBounds):
 				outError = err
 
 				return true // stop, return it back
@@ -105,6 +121,10 @@ func (e *StorageEngine) GetRange(prm *RngPrm) (*RngRes, error) {
 		return true
 	})
 
+	if outSI != nil {
+		return nil, objectSDK.NewSplitInfoError(outSI)
+	}
+
 	if obj == nil {
 		return nil, outError
 	}