@@ -67,7 +67,7 @@ func uploadBin(ctx *cli.Context) error {
67
67
return cli .Exit (fmt .Sprintf ("failed to get current block height from RPC: %v" , err ), 1 )
68
68
}
69
69
fmt .Fprintln (ctx .App .Writer , "Chain block height:" , currentBlockHeight )
70
- i , buf , err := searchIndexFile (ctx , p , containerID , acc .PrivateKey (), signer , indexFileSize , attr , indexAttrKey , maxParallelSearches , maxRetries , debug )
70
+ i , buf , err := searchIndexFile (ctx , p , containerID , acc .PrivateKey (), indexFileSize , attr , indexAttrKey , maxParallelSearches , maxRetries , debug )
71
71
if err != nil {
72
72
return cli .Exit (fmt .Errorf ("failed to find objects: %w" , err ), 1 )
73
73
}
@@ -227,33 +227,44 @@ func uploadBlocksAndIndexFiles(ctx *cli.Context, p pool.Pool, rpc *rpcclient.Cli
227
227
}
228
228
229
229
// searchIndexFile returns the ID and buffer for the next index file to be uploaded.
230
- func searchIndexFile (ctx * cli.Context , p pool.Pool , containerID cid.ID , privKeys * keys.PrivateKey , signer user. Signer , indexFileSize uint , blockAttributeKey , attributeKey string , maxParallelSearches , maxRetries uint , debug bool ) (uint , []byte , error ) {
230
+ func searchIndexFile (ctx * cli.Context , p pool.Pool , containerID cid.ID , privKeys * keys.PrivateKey , indexFileSize uint , blockAttributeKey , attributeKey string , maxParallelSearches , maxRetries uint , debug bool ) (uint , []byte , error ) {
231
231
var (
232
232
// buf is used to store OIDs of the uploaded blocks.
233
233
buf = make ([]byte , indexFileSize * oid .Size )
234
234
doneCh = make (chan struct {})
235
235
errCh = make (chan error )
236
236
237
- existingIndexCount = uint ( 0 )
237
+ existingIndexCount = 0
238
238
filters = object .NewSearchFilters ()
239
239
)
240
240
go func () {
241
241
defer close (doneCh )
242
242
// Search for existing index files.
243
+ filters .AddFilter (attributeKey , fmt .Sprintf ("%d" , existingIndexCount ), object .MatchNumGE )
243
244
filters .AddFilter ("IndexSize" , fmt .Sprintf ("%d" , indexFileSize ), object .MatchStringEqual )
244
- for i := 0 ; ; i ++ {
245
- indexIDs := searchObjects (ctx .Context , p , containerID , privKeys , attributeKey , uint (i ), uint (i + 1 ), 1 , maxRetries , debug , errCh , filters )
246
- resOIDs := make ([]oid.ID , 0 , 1 )
247
- for id := range indexIDs {
248
- resOIDs = append (resOIDs , id )
249
- }
250
- if len (resOIDs ) == 0 {
251
- break
245
+
246
+ var indexObsj []client.SearchResultItem
247
+ err := retry (func () error {
248
+ var errBlockSearch error
249
+ indexObsj , errBlockSearch = neofs .ObjectSearch (ctx .Context , & p , privKeys , containerID .String (), filters , []string {attributeKey })
250
+ return errBlockSearch
251
+ }, maxRetries , debug )
252
+ if err != nil {
253
+ select {
254
+ case errCh <- fmt .Errorf ("failed to search for index file: %w" , err ):
255
+ default :
252
256
}
253
- if len (resOIDs ) > 1 {
254
- fmt .Fprintf (ctx .App .Writer , "WARN: %d duplicated index files with index %d found: %s\n " , len (resOIDs ), i , resOIDs )
257
+ return
258
+ }
259
+ if len (indexObsj ) != 0 {
260
+ existingIndexCount , err = strconv .Atoi (indexObsj [len (indexObsj )- 1 ].Attributes [0 ])
261
+ if err != nil {
262
+ select {
263
+ case errCh <- fmt .Errorf ("failed to parse index file ID: %w" , err ):
264
+ default :
265
+ }
266
+ return
255
267
}
256
- existingIndexCount ++
257
268
}
258
269
fmt .Fprintf (ctx .App .Writer , "Current index files count: %d\n " , existingIndexCount )
259
270
@@ -263,64 +274,51 @@ func searchIndexFile(ctx *cli.Context, p pool.Pool, containerID cid.ID, privKeys
263
274
// It prevents duplicates.
264
275
processedIndices sync.Map
265
276
wg sync.WaitGroup
266
- oidCh = make (chan oid. ID , 2 * maxParallelSearches )
277
+ objCh = make (chan client. SearchResultItem , 2 * maxParallelSearches )
267
278
)
268
279
wg .Add (int (maxParallelSearches ))
269
280
for range maxParallelSearches {
270
281
go func () {
271
282
defer wg .Done ()
272
- for id := range oidCh {
273
- var obj * object.Object
274
- errRetr := retry (func () error {
275
- var errGet error
276
- obj , errGet = p .ObjectHead (ctx .Context , containerID , id , signer , client.PrmObjectHead {})
277
- return errGet
278
- }, maxRetries , debug )
279
- if errRetr != nil {
280
- select {
281
- case errCh <- fmt .Errorf ("failed to fetch object %s: %w" , id .String (), errRetr ):
282
- default :
283
- }
284
- return
285
- }
286
- blockIndex , err := getBlockIndex (obj , blockAttributeKey )
283
+ for obj := range objCh {
284
+ blockIndex , err := strconv .Atoi (obj .Attributes [0 ])
287
285
if err != nil {
288
286
select {
289
- case errCh <- fmt .Errorf ("failed to get block index from object %s: %w" , id .String (), err ):
287
+ case errCh <- fmt .Errorf ("failed to get block index from object %s: %w" , obj . ID .String (), err ):
290
288
default :
291
289
}
292
290
return
293
291
}
294
292
pos := uint (blockIndex ) % indexFileSize
295
293
if _ , ok := processedIndices .LoadOrStore (pos , blockIndex ); ! ok {
296
- copy (buf [pos * oid .Size :], id [:])
294
+ copy (buf [pos * oid .Size :], obj . ID [:])
297
295
}
298
296
}
299
297
}()
300
298
}
301
299
302
300
// Search for blocks within the index file range.
303
- objIDs := searchObjects (ctx .Context , p , containerID , privKeys , blockAttributeKey , existingIndexCount * indexFileSize , (existingIndexCount + 1 )* indexFileSize , maxParallelSearches , maxRetries , debug , errCh )
304
- for id := range objIDs {
305
- oidCh <- id
301
+ blkObjs := searchObjects (ctx .Context , p , containerID , privKeys , blockAttributeKey , uint ( existingIndexCount ) * indexFileSize , uint (existingIndexCount + 1 )* indexFileSize , maxParallelSearches , maxRetries , debug , errCh )
302
+ for id := range blkObjs {
303
+ objCh <- id
306
304
}
307
- close (oidCh )
305
+ close (objCh )
308
306
wg .Wait ()
309
307
}()
310
308
311
309
select {
312
310
case err := <- errCh :
313
- return existingIndexCount , nil , err
311
+ return uint ( existingIndexCount ) , nil , err
314
312
case <- doneCh :
315
- return existingIndexCount , buf , nil
313
+ return uint ( existingIndexCount ) , buf , nil
316
314
}
317
315
}
318
316
319
317
// searchObjects searches in parallel for objects with attribute GE startIndex and LT
320
318
// endIndex. It returns a buffered channel of resulting object IDs and closes it once
321
319
// OID search is finished. Errors are sent to errCh in a non-blocking way.
322
- func searchObjects (ctx context.Context , p pool.Pool , containerID cid.ID , privKeys * keys.PrivateKey , blockAttributeKey string , startIndex , endIndex , maxParallelSearches , maxRetries uint , debug bool , errCh chan error , additionalFilters ... object.SearchFilters ) chan oid. ID {
323
- var res = make (chan oid. ID , 2 * neofs .DefaultSearchBatchSize )
320
+ func searchObjects (ctx context.Context , p pool.Pool , containerID cid.ID , privKeys * keys.PrivateKey , blockAttributeKey string , startIndex , endIndex , maxParallelSearches , maxRetries uint , debug bool , errCh chan error , additionalFilters ... object.SearchFilters ) chan client. SearchResultItem {
321
+ var res = make (chan client. SearchResultItem , 2 * neofs .DefaultSearchBatchSize )
324
322
go func () {
325
323
var wg sync.WaitGroup
326
324
defer close (res )
@@ -341,23 +339,21 @@ func searchObjects(ctx context.Context, p pool.Pool, containerID cid.ID, privKey
341
339
go func (start , end uint ) {
342
340
defer wg .Done ()
343
341
344
- prm := client.PrmObjectSearch {}
345
342
filters := object .NewSearchFilters ()
346
- if len (additionalFilters ) != 0 {
347
- filters = additionalFilters [0 ]
348
- }
349
343
if end == start + 1 {
350
344
filters .AddFilter (blockAttributeKey , fmt .Sprintf ("%d" , start ), object .MatchStringEqual )
351
345
} else {
352
346
filters .AddFilter (blockAttributeKey , fmt .Sprintf ("%d" , start ), object .MatchNumGE )
353
347
filters .AddFilter (blockAttributeKey , fmt .Sprintf ("%d" , end ), object .MatchNumLT )
354
348
}
355
- prm .SetFilters (filters )
349
+ if len (additionalFilters ) != 0 {
350
+ filters = additionalFilters [0 ]
351
+ }
356
352
357
- var objIDs []oid. ID
353
+ var objIDs []client. SearchResultItem
358
354
err := retry (func () error {
359
355
var errBlockSearch error
360
- objIDs , errBlockSearch = neofs .ObjectSearch (ctx , & p , privKeys , containerID .String (), prm )
356
+ objIDs , errBlockSearch = neofs .ObjectSearch (ctx , & p , privKeys , containerID .String (), filters , [] string { blockAttributeKey } )
361
357
return errBlockSearch
362
358
}, maxRetries , debug )
363
359
if err != nil {
@@ -410,20 +406,6 @@ func uploadObj(ctx context.Context, p pool.Pool, signer user.Signer, containerID
410
406
return resOID , nil
411
407
}
412
408
413
- func getBlockIndex (header * object.Object , attribute string ) (int , error ) {
414
- for _ , attr := range header .UserAttributes () {
415
- if attr .Key () == attribute {
416
- value := attr .Value ()
417
- blockIndex , err := strconv .Atoi (value )
418
- if err != nil {
419
- return - 1 , fmt .Errorf ("attribute %s has invalid value: %s, error: %w" , attribute , value , err )
420
- }
421
- return blockIndex , nil
422
- }
423
- }
424
- return - 1 , fmt .Errorf ("attribute %s not found" , attribute )
425
- }
426
-
427
409
// getContainer gets container by ID and checks its magic.
428
410
func getContainer (ctx * cli.Context , p pool.Pool , expectedMagic string , maxRetries uint , debug bool ) (cid.ID , error ) {
429
411
var (
0 commit comments