/// <summary> /// Adds a <see cref="IDownloadSource"/> to this <see cref="IDownloadManager"/>. /// </summary> /// <param name="downloadSource">The <see cref="IDownloadSource"/> to add.</param> /// <returns>True if the <paramref name="downloadSource"/> was added; false if the <paramref name="downloadSource"/> was /// invalid or already in this <see cref="IDownloadManager"/>.</returns> public bool AddSource(IDownloadSource downloadSource) { if (downloadSource == null) { return(false); } if (log.IsDebugEnabled) { log.DebugFormat("Adding DownloadSource: {0}", downloadSource); } lock (_downloadSourcesSync) { if (_downloadSources.Contains(downloadSource)) { if (log.IsDebugEnabled) { log.DebugFormat("DownloadSource `{0}` not added - already in collection.", downloadSource); } return(false); } downloadSource.DownloadFinished += downloadSource_DownloadFinished; downloadSource.DownloadFailed += downloadSource_DownloadFailed; _downloadSources.Add(downloadSource); UpdateMaxAttempts(); } return(true); }
/// <summary> /// Download the official list. /// </summary> /// <param name="source">The download source.</param> public static ToV Download(IDownloadSource source) { string dlsrc = source.Translate("https://launchermeta.mojang.com/mc/game/version_manifest.json"); string tov = Downloader.hclient.GetStringAsync(dlsrc).Result; return(new ToV(tov)); }
public static void Initialize() { CoreMCL = new OneMCL(@".\.minecraft"); Option = new LaunchOptionBase("one-minecraft-launcher"); Config.LoadFromFile(); VersionsList = new ObservableCollection <KMCCC.Launcher.Version>(); RefreshVersionsList(CoreMCL.Core.GetVersions()); AccountTypes.Mojang.Text = "Mojang账号(正版登陆)"; AccountTypes.Offline.Text = "离线模式"; DownloadSourcesList = new List <IDownloadSource>(); var tmp = new OriginalSource(); DownloadSourcesList.Add(tmp); DownloadSourcesList.Add(new BMCLApiSource()); DownloadSource = tmp; foreach (IDownloadSource source in DownloadSourcesList) { if (Equals(source.SourceID, Config.INSTANCE.DownloadSourceId)) { DownloadSource = source; } } }
public IVersion GetVersion(string identifier, IDownloadSource dlsrc) { IEnumerable <string> dlist = Directory.EnumerateDirectories(GameDir); var q = from vd in dlist where vd == identifier select GameDir + vd; return (MojangAPI.Version.Parse( File.ReadAllText( $"{q.First()}/{identifier}.json" ) )); }
public IVersion GetVersion(string identifier, IDownloadSource dlsrc) { var version = from v in (JArray)tov["versions"] where (string)v["id"] == identifier select v["url"]; string vdata = Downloader.hclient.GetStringAsync( dlsrc.Translate((string)version.First()) ) .Result; Util.GenDir($"{GameDir}/versions/{identifier}"); using (FileStream f = File.Open($"{GameDir}/versions/{identifier}/{identifier}.json", FileMode.Create)) using (StreamWriter sw = new StreamWriter(f)) { sw.Write(vdata); } return(Version.Parse(vdata)); }
/// <summary> /// Removes a <see cref="IDownloadSource"/> from this <see cref="IDownloadManager"/>. /// </summary> /// <param name="downloadSource">The <see cref="IDownloadSource"/> to remove.</param> /// <returns>True if the <paramref name="downloadSource"/> was removed; false if the <paramref name="downloadSource"/> was /// invalid or not in this <see cref="IDownloadManager"/>.</returns> public bool RemoveSource(IDownloadSource downloadSource) { // Check for a valid argument if (downloadSource == null) { if (log.IsInfoEnabled) { log.Info("RemoveSource failed since the DownloadSource parameter was null."); } return(false); } // Remove from the _downloadSources list lock (_downloadSourcesSync) { if (!_downloadSources.Remove(downloadSource)) { if (log.IsDebugEnabled) { log.DebugFormat("Could not remove DownloadSource `{0}` - was not in the _downloadSources list.", downloadSource); } return(false); } UpdateMaxAttempts(); } // Remove the event hooks downloadSource.DownloadFinished -= downloadSource_DownloadFinished; downloadSource.DownloadFailed -= downloadSource_DownloadFailed; if (log.IsDebugEnabled) { log.DebugFormat("DownloadSource `{0}` removed from DownloadManager `{1}`.", downloadSource, this); } return(true); }
/// <summary> /// Executes a <see cref="IDownloadSource"/>, which will read the desired files. /// </summary> /// <param name="source">The <see cref="IDownloadSource"/> to use.</param> void ExecuteSource(IDownloadSource source) { if (log.IsDebugEnabled) { log.DebugFormat("Executing download source: {0}", source); } source.DownloadFinished += source_DownloadFinished; source.DownloadFailed += source_DownloadFailed; // Master servers file (master server list) var tempFile = Path.GetTempFileName(); Interlocked.Increment(ref _numBusyMasterServersFile); if (!source.Download(CurrentMasterServersFilePath, tempFile, null)) { Interlocked.Decrement(ref _numBusyMasterServersFile); PathHelper.SafeDeleteTempFile(tempFile); } // Download sources file (file server list) tempFile = Path.GetTempFileName(); Interlocked.Increment(ref _numBusyDownloadSourcesFile); if (!source.Download(CurrentDownloadSourcesFilePath, tempFile, null)) { Interlocked.Decrement(ref _numBusyDownloadSourcesFile); PathHelper.SafeDeleteTempFile(tempFile); } // Version file (contains the current version number) // -or- // VersionFileList file (contains the listing of all the files for the version) tempFile = Path.GetTempFileName(); Interlocked.Increment(ref _numBusyVersionFile); if (!source.Download(_remoteFileToDownload, tempFile, null)) { Interlocked.Decrement(ref _numBusyVersionFile); PathHelper.SafeDeleteTempFile(tempFile); } }
void source_DownloadFailed(IDownloadSource sender, string remoteFile, string localFilePath) { // Handle based on what remote file it was if (remoteFile == CurrentVersionFilePath) { Interlocked.Decrement(ref _numBusyVersionFile); } else if (_readVersion.HasValue && StringComparer.OrdinalIgnoreCase.Equals(PathHelper.GetVersionString(_readVersion.Value) + ".txt", remoteFile)) { Interlocked.Decrement(ref _numBusyVersionFile); } else if (remoteFile == CurrentMasterServersFilePath) { Interlocked.Decrement(ref _numBusyMasterServersFile); } else if (remoteFile == CurrentDownloadSourcesFilePath) { Interlocked.Decrement(ref _numBusyDownloadSourcesFile); } else { const string errmsg = "Unexpected remote file `{0}` downloaded by `{1}`."; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, sender); } Debug.Fail(string.Format(errmsg, remoteFile, sender)); return; } // Delete the temp file PathHelper.SafeDeleteTempFile(localFilePath); CheckIfComplete(); }
public IVersion GetLatest(IDownloadSource dlsrc) => GetVersion((string)tov["latest"]["release"], dlsrc);
/// <summary> /// Handles the <see cref="IDownloadSource.DownloadFinished"/> event for the <see cref="_downloadSources"/>. /// </summary> /// <param name="sender">The sender.</param> /// <param name="remoteFile">The remote file.</param> /// <param name="localFilePath">The local file path.</param> void downloadSource_DownloadFinished(IDownloadSource sender, string remoteFile, string localFilePath) { if (log.IsInfoEnabled) log.InfoFormat("Job `{0}` finished successfully.", remoteFile); // Remove from the failed dictionaries RemoveFromFailedDicts(remoteFile, true); // Remove from failed list lock (_failedDownloadsSync) { _failedDownloads.Remove(remoteFile); } // Remove from the download queue var finished = false; lock (_downloadQueueSync) { var removed = _downloadQueue.Remove(remoteFile); Debug.Assert(removed); if (_downloadQueue.Count == 0) finished = true; } // Add to the finished queue lock (_finishedDownloadsSync) { _finishedDownloads.Add(remoteFile); } var tempPath = GetTempPath(remoteFile); var targetPath = GetTargetPath(remoteFile); // Ensure the target path exists lock (_fileSystemSync) { var dir = Path.GetDirectoryName(targetPath); if (dir != null) { if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); } } // Try to move the file var fileCopied = true; try { lock (_fileSystemSync) { if (log.IsDebugEnabled) log.DebugFormat("Copying file from `{0}` to `{1}`.", tempPath, targetPath); File.Copy(tempPath, targetPath, true); } } catch (Exception ex) { fileCopied = false; const string errmsg = "File copy from `{0}` to `{1}` failed: {2}"; if (log.IsWarnEnabled) log.WarnFormat(errmsg, tempPath, targetPath, ex); Debug.Fail(string.Format(errmsg, tempPath, targetPath, ex)); try { if (FileMoveFailed != null) FileMoveFailed(this, remoteFile, tempPath, targetPath); } catch (NullReferenceException ex2) { Debug.Fail(ex2.ToString()); } } // Delete the old file if (fileCopied) { lock (_fileSystemSync) { try { if (File.Exists(tempPath)) { if (log.IsDebugEnabled) log.DebugFormat("Deleting temporary file: {0}", tempPath); File.Delete(tempPath); } } catch (IOException ex) { const string errmsg = "Failed to delete temporary file `{0}`: {1}"; if (log.IsWarnEnabled) log.WarnFormat(errmsg, tempPath, ex); Debug.Fail(string.Format(errmsg, tempPath, ex)); } } // Notify that the file successfully downloaded and was moved try { if (DownloadFinished != null) DownloadFinished(this, remoteFile, targetPath); } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } // Notify if all jobs have finished if (finished) { try { if (Finished != null) Finished(this); } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } }
public YoutubeVideoDownloadSpecifier(Uri uri, IDownloadSource source, ParameterList parameters) : base(uri, source, parameters) { }
void source_DownloadFinished(IDownloadSource sender, string remoteFile, string localFilePath) { // Handle based on what remote file it was if (remoteFile == CurrentVersionFilePath) { // Version file try { var txt = TryReadAllText(localFilePath); if (txt != null) { // Try to parse and add the version int version; if (!int.TryParse(txt, out version)) { const string errmsg = "Failed to parse version file to integer (remote path: {0}, local path: {1}). Contents: `{2}`"; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, localFilePath, txt); _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, txt)); } else { _masterReadInfo.AddVersion(version); _hasReadVersion = true; } } } catch (Exception ex) { const string errmsg = "Unexpected error while handling version file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyVersionFile); } } else if (_readVersion.HasValue && StringComparer.OrdinalIgnoreCase.Equals(PathHelper.GetVersionString(_readVersion.Value) + ".txt", remoteFile)) { // VersionFileList file try { var txt = TryReadAllText(localFilePath); _masterReadInfo.AddVersionFileListText(txt); } catch (Exception ex) { const string errmsg = "Unexpected error while handling version file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyVersionFile); } } else if (remoteFile == CurrentMasterServersFilePath) { try { // Add the list of master servers var descriptors = DownloadSourceDescriptor.FromDescriptorFile(localFilePath); foreach (var desc in descriptors) { _masterReadInfo.AddMasterServer(desc); } // If any of the added master servers are not in our list, grab from it, too lock (_sourcesSync) { foreach (var desc in descriptors) { var d = desc; if (!_sources.Any(x => x.IsIdenticalTo(d))) { // None of our existing sources match the descriptor, so add it to our list and start // grabbing from that new source try { var newSource = desc.Instantiate(); _sources.Add(newSource); ExecuteSource(newSource); } catch (Exception ex) { const string errmsg = "Failed to instantiate and/or execute downoaded master server using DownloadSourceDescriptor `{0}`. Exception: {1}"; if (log.IsWarnEnabled) log.WarnFormat(errmsg, desc, ex); Debug.Fail(string.Format(errmsg, desc, ex)); } } } } } catch (Exception ex) { const string errmsg = "Unexpected error while handling master servers file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyMasterServersFile); } } else if (remoteFile == CurrentDownloadSourcesFilePath) { try { // Add the list of download sources var descriptors = DownloadSourceDescriptor.FromDescriptorFile(localFilePath); foreach (var desc in descriptors) { _masterReadInfo.AddDownloadSource(desc); } } catch (Exception ex) { const string errmsg = "Unexpected error while handling download sources file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyDownloadSourcesFile); } } else { const string errmsg = "Unexpected remote file `{0}` downloaded by `{1}`."; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, sender); Debug.Fail(string.Format(errmsg, remoteFile, sender)); return; } // Delete the temp file PathHelper.SafeDeleteTempFile(localFilePath); CheckIfComplete(); }
void source_DownloadFailed(IDownloadSource sender, string remoteFile, string localFilePath) { // Handle based on what remote file it was if (remoteFile == CurrentVersionFilePath) Interlocked.Decrement(ref _numBusyVersionFile); else if (_readVersion.HasValue && StringComparer.OrdinalIgnoreCase.Equals(PathHelper.GetVersionString(_readVersion.Value) + ".txt", remoteFile)) Interlocked.Decrement(ref _numBusyVersionFile); else if (remoteFile == CurrentMasterServersFilePath) Interlocked.Decrement(ref _numBusyMasterServersFile); else if (remoteFile == CurrentDownloadSourcesFilePath) Interlocked.Decrement(ref _numBusyDownloadSourcesFile); else { const string errmsg = "Unexpected remote file `{0}` downloaded by `{1}`."; if (log.IsErrorEnabled) log.ErrorFormat(errmsg, remoteFile, sender); Debug.Fail(string.Format(errmsg, remoteFile, sender)); return; } // Delete the temp file PathHelper.SafeDeleteTempFile(localFilePath); CheckIfComplete(); }
/// <summary> /// Executes a <see cref="IDownloadSource"/>, which will read the desired files. /// </summary> /// <param name="source">The <see cref="IDownloadSource"/> to use.</param> void ExecuteSource(IDownloadSource source) { if (log.IsDebugEnabled) log.DebugFormat("Executing download source: {0}", source); source.DownloadFinished += source_DownloadFinished; source.DownloadFailed += source_DownloadFailed; // Master servers file (master server list) var tempFile = Path.GetTempFileName(); Interlocked.Increment(ref _numBusyMasterServersFile); if (!source.Download(CurrentMasterServersFilePath, tempFile, null)) { Interlocked.Decrement(ref _numBusyMasterServersFile); PathHelper.SafeDeleteTempFile(tempFile); } // Download sources file (file server list) tempFile = Path.GetTempFileName(); Interlocked.Increment(ref _numBusyDownloadSourcesFile); if (!source.Download(CurrentDownloadSourcesFilePath, tempFile, null)) { Interlocked.Decrement(ref _numBusyDownloadSourcesFile); PathHelper.SafeDeleteTempFile(tempFile); } // Version file (contains the current version number) // -or- // VersionFileList file (contains the listing of all the files for the version) tempFile = Path.GetTempFileName(); Interlocked.Increment(ref _numBusyVersionFile); if (!source.Download(_remoteFileToDownload, tempFile, null)) { Interlocked.Decrement(ref _numBusyVersionFile); PathHelper.SafeDeleteTempFile(tempFile); } }
/// <summary> /// Handles the <see cref="IDownloadSource.DownloadFinished"/> event for the <see cref="_downloadSources"/>. /// </summary> /// <param name="sender">The sender.</param> /// <param name="remoteFile">The remote file.</param> /// <param name="localFilePath">The local file path.</param> void downloadSource_DownloadFinished(IDownloadSource sender, string remoteFile, string localFilePath) { if (log.IsInfoEnabled) { log.InfoFormat("Job `{0}` finished successfully.", remoteFile); } // Remove from the failed dictionaries RemoveFromFailedDicts(remoteFile, true); // Remove from failed list lock (_failedDownloadsSync) { _failedDownloads.Remove(remoteFile); } // Remove from the download queue var finished = false; lock (_downloadQueueSync) { var removed = _downloadQueue.Remove(remoteFile); Debug.Assert(removed); if (_downloadQueue.Count == 0) { finished = true; } } // Add to the finished queue lock (_finishedDownloadsSync) { _finishedDownloads.Add(remoteFile); } var tempPath = GetTempPath(remoteFile); var targetPath = GetTargetPath(remoteFile); // Ensure the target path exists lock (_fileSystemSync) { var dir = Path.GetDirectoryName(targetPath); if (dir != null) { if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } } // Try to move the file var fileCopied = true; try { lock (_fileSystemSync) { if (log.IsDebugEnabled) { log.DebugFormat("Copying file from `{0}` to `{1}`.", tempPath, targetPath); } File.Copy(tempPath, targetPath, true); } } catch (Exception ex) { fileCopied = false; const string errmsg = "File copy from `{0}` to `{1}` failed: {2}"; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, tempPath, targetPath, ex); } Debug.Fail(string.Format(errmsg, tempPath, targetPath, ex)); try { if (FileMoveFailed != null) { FileMoveFailed(this, remoteFile, tempPath, targetPath); } } catch (NullReferenceException ex2) { Debug.Fail(ex2.ToString()); } } // Delete the old file if (fileCopied) { lock (_fileSystemSync) { try { if (File.Exists(tempPath)) { if (log.IsDebugEnabled) { log.DebugFormat("Deleting temporary file: {0}", tempPath); } File.Delete(tempPath); } } catch (IOException ex) { const string errmsg = "Failed to delete temporary file `{0}`: {1}"; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, tempPath, ex); } Debug.Fail(string.Format(errmsg, tempPath, ex)); } } // Notify that the file successfully downloaded and was moved try { if (DownloadFinished != null) { DownloadFinished(this, remoteFile, targetPath); } } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } // Notify if all jobs have finished if (finished) { try { if (Finished != null) { Finished(this); } } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } }
void source_DownloadFinished(IDownloadSource sender, string remoteFile, string localFilePath) { // Handle based on what remote file it was if (remoteFile == CurrentVersionFilePath) { // Version file try { var txt = TryReadAllText(localFilePath); if (txt != null) { // Try to parse and add the version int version; if (!int.TryParse(txt, out version)) { const string errmsg = "Failed to parse version file to integer (remote path: {0}, local path: {1}). Contents: `{2}`"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, localFilePath, txt); } _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, txt)); } else { _masterReadInfo.AddVersion(version); _hasReadVersion = true; } } } catch (Exception ex) { const string errmsg = "Unexpected error while handling version file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); } _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyVersionFile); } } else if (_readVersion.HasValue && StringComparer.OrdinalIgnoreCase.Equals(PathHelper.GetVersionString(_readVersion.Value) + ".txt", remoteFile)) { // VersionFileList file try { var txt = TryReadAllText(localFilePath); _masterReadInfo.AddVersionFileListText(txt); } catch (Exception ex) { const string errmsg = "Unexpected error while handling version file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); } _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyVersionFile); } } else if (remoteFile == CurrentMasterServersFilePath) { try { // Add the list of master servers var descriptors = DownloadSourceDescriptor.FromDescriptorFile(localFilePath); foreach (var desc in descriptors) { _masterReadInfo.AddMasterServer(desc); } // If any of the added master servers are not in our list, grab from it, too lock (_sourcesSync) { foreach (var desc in descriptors) { var d = desc; if (!_sources.Any(x => x.IsIdenticalTo(d))) { // None of our existing sources match the descriptor, so add it to our list and start // grabbing from that new source try { var newSource = desc.Instantiate(); _sources.Add(newSource); ExecuteSource(newSource); } catch (Exception ex) { const string errmsg = "Failed to instantiate and/or execute downoaded master server using DownloadSourceDescriptor `{0}`. Exception: {1}"; if (log.IsWarnEnabled) { log.WarnFormat(errmsg, desc, ex); } Debug.Fail(string.Format(errmsg, desc, ex)); } } } } } catch (Exception ex) { const string errmsg = "Unexpected error while handling master servers file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); } _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyMasterServersFile); } } else if (remoteFile == CurrentDownloadSourcesFilePath) { try { // Add the list of download sources var descriptors = DownloadSourceDescriptor.FromDescriptorFile(localFilePath); foreach (var desc in descriptors) { _masterReadInfo.AddDownloadSource(desc); } } catch (Exception ex) { const string errmsg = "Unexpected error while handling download sources file (remote path: {0}, local path: {1}). Exception: {2}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, localFilePath, ex); } _masterReadInfo.AppendError(string.Format(errmsg, remoteFile, localFilePath, ex)); } finally { Interlocked.Decrement(ref _numBusyDownloadSourcesFile); } } else { const string errmsg = "Unexpected remote file `{0}` downloaded by `{1}`."; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, remoteFile, sender); } Debug.Fail(string.Format(errmsg, remoteFile, sender)); return; } // Delete the temp file PathHelper.SafeDeleteTempFile(localFilePath); CheckIfComplete(); }
/// <summary> /// Handles the <see cref="IDownloadSource.DownloadFailed"/> event for the <see cref="_downloadSources"/>. /// </summary> /// <param name="sender">The sender.</param> /// <param name="remoteFile">The remote file.</param> /// <param name="localFilePath">The local file path.</param> void downloadSource_DownloadFailed(IDownloadSource sender, string remoteFile, string localFilePath) { var invokeFailed = false; var invokeFinished = false; lock (_downloadFailedDictSync) { // Increment the fail count for this file int fails; if (!_downloadFailedDictCount.TryGetValue(remoteFile, out fails)) { fails = 1; _downloadFailedDictCount.Add(remoteFile, fails); } else _downloadFailedDictCount[remoteFile]++; if (log.IsInfoEnabled) log.InfoFormat("Job `{0}` failed (attempt #{1}; retry? {2})", remoteFile, fails + 1, fails <= MaxAttempts); // Check if the failure has happened too many times and that we should just give up if (fails > MaxAttempts) { RemoveFromFailedDicts(remoteFile, false); lock (_downloadQueueSync) { var removed = _downloadQueue.Remove(remoteFile); Debug.Assert(removed); if (_downloadQueue.Count == 0) invokeFinished = true; } lock (_failedDownloadsSync) { if (!_failedDownloads.Contains(remoteFile)) _failedDownloads.Add(remoteFile); } invokeFailed = true; } else { // Add the downloader that just failed to the list of failed sources List<IDownloadSource> failedSources; if (!_downloadFailedDict.TryGetValue(remoteFile, out failedSources)) { failedSources = new List<IDownloadSource>(); _downloadFailedDict.Add(remoteFile, failedSources); } failedSources.Add(sender); // If every source we have has failed, empty the list so they can all try again. This forces // failed files to rotate through all sources before trying the same one again. var containsAllSources = true; lock (_downloadSourcesSync) { foreach (var src in _downloadSources) { if (!failedSources.Contains(src)) { containsAllSources = false; break; } } } if (containsAllSources) failedSources.Clear(); // Add back to the NotStartedQueue so it can be attempted again lock (_notStartedQueueSync) { Debug.Assert(!_notStartedQueue.Contains(remoteFile), "Why is this item already in the NotStartedQueue?"); _notStartedQueue.Enqueue(remoteFile); } } } // Invoke the DownloadFailed event if needed (done here to prevent invoking while in lock) if (invokeFailed) { try { if (DownloadFailed != null) DownloadFailed(this, remoteFile); } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } // Invoke the DownloadFinished event if needed (done here to prevent invoking while in lock) if (invokeFinished) { try { if (Finished != null) Finished(this); } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } }
/// <summary> /// Adds a <see cref="IDownloadSource"/> to this <see cref="IDownloadManager"/>. /// </summary> /// <param name="downloadSource">The <see cref="IDownloadSource"/> to add.</param> /// <returns>True if the <paramref name="downloadSource"/> was added; false if the <paramref name="downloadSource"/> was /// invalid or already in this <see cref="IDownloadManager"/>.</returns> public bool AddSource(IDownloadSource downloadSource) { if (downloadSource == null) return false; if (log.IsDebugEnabled) log.DebugFormat("Adding DownloadSource: {0}", downloadSource); lock (_downloadSourcesSync) { if (_downloadSources.Contains(downloadSource)) { if (log.IsDebugEnabled) log.DebugFormat("DownloadSource `{0}` not added - already in collection.", downloadSource); return false; } downloadSource.DownloadFinished += downloadSource_DownloadFinished; downloadSource.DownloadFailed += downloadSource_DownloadFailed; _downloadSources.Add(downloadSource); UpdateMaxAttempts(); } return true; }
public IVersion GetLatestSnap(IDownloadSource dlsrc) { throw new NotImplementedException(); }
/// <summary> /// Removes a <see cref="IDownloadSource"/> from this <see cref="IDownloadManager"/>. /// </summary> /// <param name="downloadSource">The <see cref="IDownloadSource"/> to remove.</param> /// <returns>True if the <paramref name="downloadSource"/> was removed; false if the <paramref name="downloadSource"/> was /// invalid or not in this <see cref="IDownloadManager"/>.</returns> public bool RemoveSource(IDownloadSource downloadSource) { // Check for a valid argument if (downloadSource == null) { if (log.IsInfoEnabled) log.Info("RemoveSource failed since the DownloadSource parameter was null."); return false; } // Remove from the _downloadSources list lock (_downloadSourcesSync) { if (!_downloadSources.Remove(downloadSource)) { if (log.IsDebugEnabled) log.DebugFormat("Could not remove DownloadSource `{0}` - was not in the _downloadSources list.", downloadSource); return false; } UpdateMaxAttempts(); } // Remove the event hooks downloadSource.DownloadFinished -= downloadSource_DownloadFinished; downloadSource.DownloadFailed -= downloadSource_DownloadFailed; if (log.IsDebugEnabled) log.DebugFormat("DownloadSource `{0}` removed from DownloadManager `{1}`.", downloadSource, this); return true; }
public IVersion GetLatestSnap(IDownloadSource dlsrc) => GetVersion((string)tov["latest"]["snapshot"], dlsrc);
public void Add(IDownloadSource downloadSource) { DownloadSources.Add(downloadSource); }
/// <summary> /// Handles the <see cref="IDownloadSource.DownloadFailed"/> event for the <see cref="_downloadSources"/>. /// </summary> /// <param name="sender">The sender.</param> /// <param name="remoteFile">The remote file.</param> /// <param name="localFilePath">The local file path.</param> void downloadSource_DownloadFailed(IDownloadSource sender, string remoteFile, string localFilePath) { var invokeFailed = false; var invokeFinished = false; lock (_downloadFailedDictSync) { // Increment the fail count for this file int fails; if (!_downloadFailedDictCount.TryGetValue(remoteFile, out fails)) { fails = 1; _downloadFailedDictCount.Add(remoteFile, fails); } else { _downloadFailedDictCount[remoteFile]++; } if (log.IsInfoEnabled) { log.InfoFormat("Job `{0}` failed (attempt #{1}; retry? {2})", remoteFile, fails + 1, fails <= MaxAttempts); } // Check if the failure has happened too many times and that we should just give up if (fails > MaxAttempts) { RemoveFromFailedDicts(remoteFile, false); lock (_downloadQueueSync) { var removed = _downloadQueue.Remove(remoteFile); Debug.Assert(removed); if (_downloadQueue.Count == 0) { invokeFinished = true; } } lock (_failedDownloadsSync) { if (!_failedDownloads.Contains(remoteFile)) { _failedDownloads.Add(remoteFile); } } invokeFailed = true; } else { // Add the downloader that just failed to the list of failed sources List <IDownloadSource> failedSources; if (!_downloadFailedDict.TryGetValue(remoteFile, out failedSources)) { failedSources = new List <IDownloadSource>(); _downloadFailedDict.Add(remoteFile, failedSources); } failedSources.Add(sender); // If every source we have has failed, empty the list so they can all try again. This forces // failed files to rotate through all sources before trying the same one again. var containsAllSources = true; lock (_downloadSourcesSync) { foreach (var src in _downloadSources) { if (!failedSources.Contains(src)) { containsAllSources = false; break; } } } if (containsAllSources) { failedSources.Clear(); } // Add back to the NotStartedQueue so it can be attempted again lock (_notStartedQueueSync) { Debug.Assert(!_notStartedQueue.Contains(remoteFile), "Why is this item already in the NotStartedQueue?"); _notStartedQueue.Enqueue(remoteFile); } } } // Invoke the DownloadFailed event if needed (done here to prevent invoking while in lock) if (invokeFailed) { try { if (DownloadFailed != null) { DownloadFailed(this, remoteFile); } } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } // Invoke the DownloadFinished event if needed (done here to prevent invoking while in lock) if (invokeFinished) { try { if (Finished != null) { Finished(this); } } catch (NullReferenceException ex) { Debug.Fail(ex.ToString()); } } }