func Restore(con *glacier.Connection, db *DB, vault string) (err error) { var wg sync.WaitGroup go handleClose(db) jobs := []string{} kvs := make(chan *KeyValue) go db.Iter(kvs, "archive:", "archive:\xff", 0) errch := make(chan error) go func() { select { case cerr := <-errch: if cerr != nil { panic(cerr) } } }() for kv := range kvs { archive := &glacier.Archive{} if err := json.Unmarshal([]byte(kv.Value), archive); err != nil { return err } var jobId string statusKey := fmt.Sprintf("job:%v", kv.Key) jobId, err = db.Get(statusKey) if err != nil { return err } if jobId == "" { jobId, err = con.InitiateRetrievalJob(vault, archive.ArchiveId, "", "") if err != nil { return err } if err := db.Set(statusKey, jobId); err != nil { return err } log.Printf("Initiated a new job for archive retrieval %v", archive.ArchiveId) } wg.Add(1) go func(archive *glacier.Archive, jobId string) { if err := RestoreArchive(con, vault, jobId, filepath.Base(archive.ArchiveDescription), &wg); err != nil { errch <- err } }(archive, jobId) jobs = append(jobs, jobId) } if len(jobs) == 0 { log.Printf("Error: no archive in local DB, maybe sync is not done yet?") db.Close() os.Exit(1) } log.Printf("Waiting for %v jobs to complete, you can safely CTRL+C and resume this process", len(jobs)) wg.Wait() defer close(errch) log.Printf("Restore done, %v archives restored", len(jobs)) return nil }