func doPrepareSyncURLs(sourceURL string, targetURLs []string, bar barSend, lock countlock.Locker) { for sURLs := range prepareSyncURLs(sourceURL, targetURLs) { if sURLs.Error != nil { // no need to print errors here, any error here // will be printed later during Sync() continue } if !globalQuietFlag { bar.Extend(sURLs.SourceContent.Size) lock.Up() // Let copy routine know that it has to catch up. } } }
func doSyncCmdSession(bar barSend, s *sessionV1) <-chan syncSession { ssCh := make(chan syncSession) // Separate source and target. 'sync' can take only one source. // but any number of targets, even the recursive URLs mixed in-between. sourceURL := s.URLs[0] // first one is source targetURLs := s.URLs[1:] go func(sourceURL string, targetURLs []string, bar barSend, ssCh chan syncSession, s *sessionV1) { defer close(ssCh) go trapSync(ssCh) var lock countlock.Locker if !globalQuietFlag { // Keep progress-bar and copy routines in sync. lock = countlock.New() defer lock.Close() } wg := new(sync.WaitGroup) syncQueue := make(chan bool, int(math.Max(float64(runtime.NumCPU())-1, 1))) defer close(syncQueue) go doPrepareSyncURLs(sourceURL, targetURLs, bar, lock) for sURLs := range prepareSyncURLs(sourceURL, targetURLs) { if sURLs.Error != nil { ssCh <- syncSession{ Error: iodine.New(sURLs.Error, nil), Done: false, } continue } syncQueue <- true wg.Add(1) if !globalQuietFlag { lock.Down() // Do not jump ahead of the progress bar builder above. } go doSyncSession(sURLs, &bar, syncQueue, ssCh, wg, s) } wg.Wait() }(sourceURL, targetURLs, bar, ssCh, s) return ssCh }