5
5
"io/ioutil"
6
6
"os"
7
7
"path/filepath"
8
- "runtime"
9
8
"strings"
10
9
"sync"
10
+ "sync/atomic"
11
11
12
12
"github.com/sirupsen/logrus"
13
13
"gopkg.in/src-d/go-billy-siva.v4"
@@ -194,6 +194,7 @@ var errInvalidRepoKind = errors.NewKind("invalid repo kind: %d")
194
194
// GetPos retrieves a repository at a given position. If the position is
195
195
// out of bounds it returns io.EOF.
196
196
func (p * RepositoryPool ) GetPos (pos int ) (* Repository , error ) {
197
+
197
198
if pos >= len (p .repositories ) {
198
199
return nil , io .EOF
199
200
}
@@ -225,24 +226,25 @@ func (p *RepositoryPool) GetPos(pos int) (*Repository, error) {
225
226
// RepoIter creates a new Repository iterator
226
227
func (p * RepositoryPool ) RepoIter () (* RepositoryIter , error ) {
227
228
iter := & RepositoryIter {
228
- pos : 0 ,
229
229
pool : p ,
230
230
}
231
+ atomic .StoreInt32 (& iter .pos , 0 )
231
232
232
233
return iter , nil
233
234
}
234
235
235
236
// RepositoryIter iterates over all repositories in the pool
236
237
type RepositoryIter struct {
237
- pos int
238
+ pos int32
238
239
pool * RepositoryPool
239
240
}
240
241
241
242
// Next retrieves the next Repository. It returns io.EOF as error
242
243
// when there are no more Repositories to retrieve.
243
244
func (i * RepositoryIter ) Next () (* Repository , error ) {
244
- r , err := i .pool .GetPos (i .pos )
245
- i .pos ++
245
+ pos := int (atomic .LoadInt32 (& i .pos ))
246
+ r , err := i .pool .GetPos (pos )
247
+ atomic .AddInt32 (& i .pos , 1 )
246
248
247
249
return r , err
248
250
}
@@ -265,19 +267,11 @@ type RowRepoIter interface {
265
267
type rowRepoIter struct {
266
268
mu sync.Mutex
267
269
270
+ currRepoIter RowRepoIter
268
271
repositoryIter * RepositoryIter
269
272
iter RowRepoIter
270
273
session * Session
271
274
ctx * sql.Context
272
-
273
- wg sync.WaitGroup
274
- done chan bool
275
- err error
276
- repos chan * Repository
277
- rows chan sql.Row
278
-
279
- doneMutex sync.Mutex
280
- doneClosed bool
281
275
}
282
276
283
277
// NewRowRepoIter initializes a new repository iterator.
@@ -303,169 +297,71 @@ func NewRowRepoIter(
303
297
}
304
298
305
299
repoIter := rowRepoIter {
300
+ currRepoIter : nil ,
306
301
repositoryIter : rIter ,
307
302
iter : iter ,
308
303
session : s ,
309
304
ctx : ctx ,
310
- done : make (chan bool ),
311
- err : nil ,
312
- repos : make (chan * Repository ),
313
- rows : make (chan sql.Row ),
314
- }
315
-
316
- go repoIter .fillRepoChannel ()
317
-
318
- wNum := runtime .NumCPU ()
319
-
320
- for i := 0 ; i < wNum ; i ++ {
321
- repoIter .wg .Add (1 )
322
-
323
- go repoIter .rowReader (i )
324
305
}
325
306
326
- go func () {
327
- repoIter .wg .Wait ()
328
- close (repoIter .rows )
329
- closeIter (& repoIter )
330
- }()
331
-
332
307
return & repoIter , nil
333
308
}
334
309
335
- func (i * rowRepoIter ) setError (err error ) {
310
+ // Next gets the next row
311
+ func (i * rowRepoIter ) Next () (sql.Row , error ) {
336
312
i .mu .Lock ()
337
313
defer i .mu .Unlock ()
338
314
339
- i .err = err
340
- }
341
-
342
- func closeIter (i * rowRepoIter ) {
343
- i .doneMutex .Lock ()
344
- defer i .doneMutex .Unlock ()
345
-
346
- if ! i .doneClosed {
347
- close (i .done )
348
- i .doneClosed = true
349
- }
350
- }
351
-
352
- func (i * rowRepoIter ) fillRepoChannel () {
353
- defer close (i .repos )
354
-
355
315
for {
356
316
select {
357
- case <- i .done :
358
- return
359
-
360
317
case <- i .ctx .Done ():
361
- closeIter (i )
362
- return
318
+ return nil , ErrSessionCanceled .New ()
363
319
364
320
default :
365
- repo , err := i .repositoryIter .Next ()
366
-
367
- switch err {
368
- case nil :
369
- select {
370
- case <- i .done :
371
- return
321
+ if i .currRepoIter == nil {
322
+ repo , err := i .repositoryIter .Next ()
323
+ if err != nil {
324
+ if err == io .EOF {
325
+ return nil , io .EOF
326
+ }
372
327
373
- case <- i .ctx .Done ():
374
- i .setError (ErrSessionCanceled .New ())
375
- closeIter (i )
376
- return
328
+ if i .session .SkipGitErrors {
329
+ continue
330
+ }
377
331
378
- case i .repos <- repo :
379
- continue
332
+ return nil , err
380
333
}
381
334
382
- case io .EOF :
383
- i .setError (io .EOF )
384
- return
385
-
386
- default :
387
- if ! i .session .SkipGitErrors {
388
- closeIter (i )
389
- i .setError (err )
390
- return
335
+ i .currRepoIter , err = i .iter .NewIterator (repo )
336
+ if err != nil {
337
+ return nil , err
391
338
}
392
339
}
393
- }
394
- }
395
- }
396
340
397
- func (i * rowRepoIter ) rowReader (num int ) {
398
- defer i .wg .Done ()
399
-
400
- for repo := range i .repos {
401
- iter , err := i .iter .NewIterator (repo )
402
- if err != nil {
403
- // guard from possible previous error
404
- select {
405
- case <- i .done :
406
- return
407
- default :
408
- i .setError (err )
409
- closeIter (i )
410
- continue
411
- }
412
- }
413
-
414
- loop:
415
- for {
416
- select {
417
- case <- i .done :
418
- iter .Close ()
419
- return
420
-
421
- case <- i .ctx .Done ():
422
- i .setError (ErrSessionCanceled .New ())
423
- return
424
-
425
- default :
426
- row , err := iter .Next ()
427
- switch err {
428
- case nil :
429
- select {
430
- case <- i .done :
431
- iter .Close ()
432
- return
433
- case i .rows <- row :
434
- }
341
+ row , err := i .currRepoIter .Next ()
342
+ if err != nil {
343
+ if err == io .EOF {
344
+ i .currRepoIter .Close ()
345
+ i .currRepoIter = nil
346
+ continue
347
+ }
435
348
436
- case io .EOF :
437
- iter .Close ()
438
- break loop
439
-
440
- default :
441
- if ! i .session .SkipGitErrors {
442
- iter .Close ()
443
- i .setError (err )
444
- closeIter (i )
445
- return
446
- } else {
447
- break loop
448
- }
349
+ if i .session .SkipGitErrors {
350
+ continue
449
351
}
450
- }
451
- }
452
- }
453
- }
454
352
455
- // Next gets the next row
456
- func (i * rowRepoIter ) Next () (sql.Row , error ) {
457
- row , ok := <- i .rows
458
- if ! ok {
459
- i .mu .Lock ()
460
- defer i .mu .Unlock ()
353
+ return nil , err
354
+ }
461
355
462
- return nil , i .err
356
+ return row , nil
357
+ }
463
358
}
464
-
465
- return row , nil
466
359
}
467
360
468
361
// Close called to close the iterator
469
362
func (i * rowRepoIter ) Close () error {
363
+ if i .currRepoIter != nil {
364
+ i .currRepoIter .Close ()
365
+ }
470
366
return i .iter .Close ()
471
367
}
0 commit comments