// Run the defined restore operation func (r *RestoreJob) Run(finished chan<- bool) { log.Infof("restoreJob", "running restoreJob: %v", r.ID) log.Debugf("restoreJob", "Restore Job: %v", *r) r.State = "running" r.cancel = make(chan struct{}) r.Start = time.Now().String() r.NotificationQueue = notification.NewQueue(r.Coordinator, r.ID, *keyManager) sigsc := make(chan files.Signature) processed := make(chan int64) go func() { for _, sig := range r.Paramiters.FileSignatures { sigsc <- sig } close(sigsc) }() var wg sync.WaitGroup wg.Add(r.MaxWorkers) for i := 0; i < r.MaxWorkers; i++ { log.Debugf("restoreJob", "Starting Worker: %v", i) go func() { restoreWorker(r.cancel, sigsc, processed, r.Modifications, *r.To, *r.From, r.NotificationQueue.In, r.ID) wg.Done() }() } go func() { wg.Wait() log.Debugf("restoreJob", "All Workers Done") close(processed) }() r.NotificationQueue.Run() for p := range processed { atomic.AddInt64(&r.FilesProccessed, p) } r.State = "finishing notifications" f, _ := json.Marshal(&spec.JobUpdateRequest{spec.Complete}) r.NotificationQueue.Finish(¬ification.Notification{ Endpoint: "/jobs/" + strconv.Itoa(r.ID) + "/complete", Payload: f}) //Wait for the notification queue to be done <-r.NotificationQueue.Finished r.State = "finished" finished <- true }
// Run starts the backup job. // Backups proceed as follows: // It starts a goroutine to walk the JobPaths and return individual files over a channel // It then starts a number of woker goroutines (MaxWorkers) to handle the actual work // Each worker is handed the path channel and feeds off of incoming messages until it is closed // Each worker is also handed a success channel for keeping track of progress // It waits until all workes terminate, then closes the progress channel // It then checks for any queued errors then sends a finished message over the finished channel func (b *BackupJob) Run(finished chan<- bool) { log.Infof("backupJob", "running backupJob: %v", b.ID) log.Debugf("backupJob", "Backup Job: %v", *b) b.State = "running" b.cancel = make(chan struct{}) b.Start = time.Now().String() b.NotificationQueue = notification.NewQueue(b.Coordinator, b.ID, *keyManager) paths, errc := buildBackupFileList(b.cancel, b.Paramiters.Paths) processed := make(chan int64) var wg sync.WaitGroup wg.Add(b.MaxWorkers) for i := 0; i < b.MaxWorkers; i++ { log.Debugf("backupJob", "Starting Worker: %v", i) go func() { backupWorker(b.cancel, paths, processed, b.Modifications, b.Engines, b.NotificationQueue.In, b.ID) wg.Done() }() } go func() { wg.Wait() log.Debugf("backupJob", "All Workers Done") close(processed) }() b.NotificationQueue.Run() for p := range processed { atomic.AddInt64(&b.FilesProccessed, p) } if err := <-errc; err != nil { //send errors to notifier //b.NotificationQueue.In <- map[string]interface{}{"Error": err} } b.State = "finishing notifications" f, _ := json.Marshal(&spec.JobUpdateRequest{spec.Complete}) b.NotificationQueue.Finish(¬ification.Notification{ Endpoint: "/jobs/" + strconv.Itoa(b.ID) + "/complete", Payload: f}) //Wait for the notification queue to be done <-b.NotificationQueue.Finished b.State = "finished" finished <- true }