protected static MultiMirrorFileDownloadSpec GetDlSpec(FileQueueSpec spec,
     KeyValuePair<FileFetchInfo, ITransferStatus> file) {
     var dlSpec = new MultiMirrorFileDownloadSpec(file.Key.FilePath,
         spec.Location.GetChildFileWithName(file.Key.FilePath)) {
         Progress = file.Value,
         Verification = file.Key.OnVerify,
         ExistingFile =
             file.Key.ExistingPath != null ? spec.Location.GetChildFileWithName(file.Key.ExistingPath) : null
     };
     dlSpec.LocalFile.MakeSureParentPathExists();
     return dlSpec;
 }
 public void Download(MultiMirrorFileDownloadSpec spec) {
     spec.Start();
     try {
         while (true) {
             var host = _mirrorStrategy.GetHost();
             if (TryDownload(spec, host))
                 break;
             ResetSpec(spec);
             Thread.Sleep(MillisecondsTimeout);
         }
     } catch (Exception) {
         spec.Fail();
         throw;
     }
 }
 public void Download(MultiMirrorFileDownloadSpec spec, CancellationToken token) {
     spec.Start();
     try {
         while (true) {
             token.ThrowIfCancellationRequested();
             var host = _mirrorStrategy.GetHost();
             if (TryDownload(spec, host))
                 break;
             spec.Progress?.Reset();
             Thread.Sleep(MillisecondsTimeout);
         }
     } catch (Exception) {
         spec.Fail();
         throw;
     }
 }
 public async Task DownloadAsync(MultiMirrorFileDownloadSpec spec) {
     spec.Start();
     try {
         while (true) {
             var host = _mirrorStrategy.GetHost();
             spec.UpdateHost(host);
             if (await TryDownloadAsync(spec, host).ConfigureAwait(false))
                 break;
             ResetSpec(spec);
             await Task.Delay(MillisecondsTimeout).ConfigureAwait(false);
         }
     } catch (Exception) {
         spec.Fail();
         throw;
     }
 }
 bool TryDownload(MultiMirrorFileDownloadSpec spec, Uri host) {
     try {
         TryDownloadFile(spec, host);
         spec.End();
         return true;
     } catch (TransferException) {} catch (VerificationError) {}
     return false;
 }
 private static void ResetSpec(MultiMirrorFileDownloadSpec spec)
     => spec.Progress?.Update(null, spec.Progress.Progress);
 static FileDownloadSpec BuildSpec(MultiMirrorFileDownloadSpec spec, Uri host) => spec.Progress == null
     ? new FileDownloadSpec(spec.GetUri(host), spec.LocalFile) {
         Verification = spec.Verification,
         CancellationToken = spec.CancellationToken,
         ExistingFile = spec.ExistingFile
     }
     : new FileDownloadSpec(spec.GetUri(host), spec.LocalFile, spec.Progress) {
         Verification = spec.Verification,
         CancellationToken = spec.CancellationToken,
         ExistingFile = spec.ExistingFile
     };
 protected async Task TryDownloadFileAsync(MultiMirrorFileDownloadSpec spec, Uri host) {
     try {
         await _downloader.DownloadAsync(BuildSpec(spec, host))
             .ConfigureAwait(false);
     } catch (Exception ex) {
         if (!(ex is IProgramError))
             _mirrorStrategy.Failure(host);
         else
             _mirrorStrategy.ProgramFailure();
         throw;
     }
     _mirrorStrategy.Success(host);
 }
 protected void TryDownloadFile(MultiMirrorFileDownloadSpec spec, Uri host) {
     try {
         _downloader.Download(BuildSpec(spec, host));
     } catch (Exception ex) {
         if (!(ex is IProgramError))
             _mirrorStrategy.Failure(host);
         else
             _mirrorStrategy.ProgramFailure();
         throw;
     }
     _mirrorStrategy.Success(host);
 }
 async Task<bool> TryDownloadAsync(MultiMirrorFileDownloadSpec spec, Uri host) {
     try {
         await TryDownloadFileAsync(spec, host).ConfigureAwait(false);
         spec.End();
         return true;
     } catch (TransferException) {} catch (VerificationError) {}
     return false;
 }