FetchRemainingBlocks attempts to complete the target file by downloading any missing blocks using the supplied HTTPRequester. It uses the URLs specified in the zsync control file. progressCallback, if supplied, will be called: - at the start of downloading from each source, - at the end of downloadi
(client HTTPRequester, referer string, progressCallback func(url string, event FetchEvent, err error))
| 44 | // - at the end of downloading from each source with err=io.EOF on no error, or |
| 45 | // otherwise with the error encountered. |
| 46 | func (zs *Syncer) FetchRemainingBlocks(client HTTPRequester, referer string, progressCallback func(url string, event FetchEvent, err error)) (httpBytesDownloaded int64, err error) { |
| 47 | if len(zs.urls) == 0 { |
| 48 | return httpBytesDownloaded, fmt.Errorf("no download URLs known") |
| 49 | } |
| 50 | |
| 51 | failed := make([]bool, len(zs.urls)) |
| 52 | remaining := len(zs.urls) |
| 53 | |
| 54 | for zs.Status() != CompleteData && remaining > 0 { |
| 55 | try := rand.Intn(len(zs.urls)) |
| 56 | if failed[try] { |
| 57 | continue |
| 58 | } |
| 59 | |
| 60 | url := zs.urls[try] |
| 61 | if progressCallback != nil { |
| 62 | progressCallback(url, FetchStarted, nil) |
| 63 | } |
| 64 | var fetched int64 |
| 65 | fetched, err = zs.fetchRemainingBlocksFromURL(client, url, referer) |
| 66 | if err != nil { |
| 67 | failed[try] = true |
| 68 | remaining-- |
| 69 | } |
| 70 | httpBytesDownloaded += fetched |
| 71 | if progressCallback != nil { |
| 72 | progressCallback(zs.urls[try], FetchEnded, err) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | if zs.Status() != CompleteData { |
| 77 | err = fmt.Errorf("could not complete download; most recent error was: %w", err) |
| 78 | } |
| 79 | return |
| 80 | } |
| 81 | |
| 82 | func (zs *Syncer) fetchRemainingBlocksFromURL(client HTTPRequester, rawURL, referer string) (int64, error) { |
| 83 | u, err := url.Parse(rawURL) |