@@ -69,19 +69,29 @@ func (s *Service) GetRange(ctx context.Context, prm RangePrm) error {
6969 return s .copyLocalECPartRange (prm .objWriter , prm .addr .Container (), prm .addr .Object (), pi , prm .rng .GetOffset (), prm .rng .GetLength ())
7070 }
7171
72- return s .getRange (ctx , prm , nodeLists , repRules , ecRules )
72+ return s .getRange (ctx , prm , nodeLists , repRules , ecRules , nil )
7373}
7474
75- func (s * Service ) getRange (ctx context.Context , prm RangePrm , nodeLists [][]netmapsdk.NodeInfo , repRules []uint , ecRules []iec.Rule ) error {
75+ func (s * Service ) getRange (ctx context.Context , prm RangePrm , nodeLists [][]netmapsdk.NodeInfo , repRules []uint , ecRules []iec.Rule ,
76+ hashPrm * RangeHashPrm ) error {
7677 if len (repRules ) > 0 { // REP format does not require encoding
77- err := s .get (ctx , prm .commonPrm , withPreSortedContainerNodes (nodeLists [:len (repRules )], repRules ), withPayloadRange (prm .rng )).err
78+ err := s .get (ctx , prm .commonPrm , withPreSortedContainerNodes (nodeLists [:len (repRules )], repRules ), withPayloadRange (prm .rng ), withHash ( hashPrm ) ).err
7879 if len (ecRules ) == 0 || ! errors .Is (err , apistatus .ErrObjectNotFound ) {
7980 return err
8081 }
8182 }
8283
84+ ecNodeLists := nodeLists [len (repRules ):]
85+ if hashPrm != nil && prm .rangeForwarder != nil && ! localNodeInSets (s .neoFSNet , nodeLists ) {
86+ hashes , err := s .proxyHashRequest (ctx , ecNodeLists , prm .rangeForwarder )
87+ if err == nil {
88+ hashPrm .forwardedRangeHashResponse = hashes
89+ }
90+ return err
91+ }
92+
8393 return s .copyECObjectRange (ctx , prm .objWriter , prm .addr .Container (), prm .addr .Object (), prm .common .SessionToken (),
84- ecRules , nodeLists [ len ( repRules ):] , prm .rng .GetOffset (), prm .rng .GetLength ())
94+ ecRules , ecNodeLists , prm .rng .GetOffset (), prm .rng .GetLength ())
8595}
8696
8797func (s * Service ) GetRangeHash (ctx context.Context , prm RangeHashPrm ) (* RangeHashRes , error ) {
@@ -90,10 +100,6 @@ func (s *Service) GetRangeHash(ctx context.Context, prm RangeHashPrm) (*RangeHas
90100 return nil , fmt .Errorf ("get nodes for object: %w" , err )
91101 }
92102
93- if prm .rangeForwarder != nil && ! localNodeInSets (s .neoFSNet , nodeLists ) {
94- return s .proxyHashRequest (ctx , nodeLists , prm .rangeForwarder )
95- }
96-
97103 hashes := make ([][]byte , 0 , len (prm .rngs ))
98104
99105 for _ , rng := range prm .rngs {
@@ -113,10 +119,17 @@ func (s *Service) GetRangeHash(ctx context.Context, prm RangeHashPrm) (*RangeHas
113119 hash : util .NewSaltingWriter (h , prm .salt ),
114120 })
115121
116- if err := s .getRange (ctx , rngPrm , nodeLists , repRules , ecRules ); err != nil {
122+ if err := s .getRange (ctx , rngPrm , nodeLists , repRules , ecRules , & prm ); err != nil {
117123 return nil , err
118124 }
119125
126+ if prm .forwardedRangeHashResponse != nil {
127+ // forwarder request case; no need to collect the other
128+ // parts, the whole response has already been received
129+ hashes = prm .forwardedRangeHashResponse
130+ break
131+ }
132+
120133 hashes = append (hashes , h .Sum (nil ))
121134 }
122135
@@ -125,7 +138,7 @@ func (s *Service) GetRangeHash(ctx context.Context, prm RangeHashPrm) (*RangeHas
125138 }, nil
126139}
127140
128- func (s * Service ) proxyHashRequest (ctx context.Context , sortedNodeLists [][]netmapsdk.NodeInfo , proxyFn RangeRequestForwarder ) (* RangeHashRes , error ) {
141+ func (s * Service ) proxyHashRequest (ctx context.Context , sortedNodeLists [][]netmapsdk.NodeInfo , proxyFn RangeRequestForwarder ) ([][] byte , error ) {
129142 for i := range sortedNodeLists {
130143 for j := range sortedNodeLists [i ] {
131144 conn , node , err := s .conns .(* clientCacheWrapper )._connect (sortedNodeLists [i ][j ])
@@ -138,7 +151,7 @@ func (s *Service) proxyHashRequest(ctx context.Context, sortedNodeLists [][]netm
138151
139152 hashes , err := proxyFn (ctx , node , conn )
140153 if err == nil {
141- return & RangeHashRes { hashes : hashes } , nil
154+ return hashes , nil
142155 }
143156
144157 if errors .Is (err , apistatus .ErrObjectAlreadyRemoved ) || errors .Is (err , apistatus .ErrObjectAccessDenied ) ||
0 commit comments