/// <summary> /// Checks if this <see cref="DownloadSourceDescriptor"/> is identical to another <see cref="DownloadSourceDescriptor"/>. /// </summary> /// <param name="other">The other <see cref="DownloadSourceDescriptor"/>.</param> /// <returns>True if they are identical; otherwise false.</returns> /// <exception cref="ArgumentNullException"><paramref name="other"/> is null.</exception> public bool IsIdenticalTo(DownloadSourceDescriptor other) { if (other == null) { throw new ArgumentNullException("other"); } return(this == other || Type == other.Type || RootPath == other.RootPath); }
/// <summary> /// Checks if this <see cref="IDownloadSource"/> contains the same values as the given <see cref="DownloadSourceDescriptor"/>. /// </summary> /// <param name="descriptor">The <see cref="DownloadSourceDescriptor"/> to compare to.</param> /// <returns>True if they have equal values; otherwise false.</returns> public bool IsIdenticalTo(DownloadSourceDescriptor descriptor) { if (descriptor.Type != DownloadSourceType.Http) { return(false); } if (descriptor.RootPath != RootPath) { return(false); } return(true); }
/// <summary> /// Adds a master server. /// </summary> /// <param name="master">The <see cref="DownloadSourceDescriptor"/>.</param> public void AddMasterServer(DownloadSourceDescriptor master) { if (master == null) { Debug.Fail("master is null."); return; } if (log.IsDebugEnabled) log.DebugFormat("Adding master server `{0}` to MasterServerReadInfo `{1}`.", master, this); lock (_mastersSync) { if (!_masters.Any(master.IsIdenticalTo)) { _masters.Add(master); return; } } }
/// <summary> /// Adds a download source read from a master server. /// </summary> /// <param name="source">The <see cref="DownloadSourceDescriptor"/>.</param> public void AddDownloadSource(DownloadSourceDescriptor source) { if (source == null) { Debug.Fail("source is null."); return; } if (log.IsDebugEnabled) log.DebugFormat("Adding download source `{0}` to MasterServerReadInfo `{1}`.", source, this); lock (_sourcesSync) { if (!_sources.Any(source.IsIdenticalTo)) { _sources.Add(source); return; } } }
/// <summary> /// Adds a master server. /// </summary> /// <param name="master">The <see cref="DownloadSourceDescriptor"/>.</param> public void AddMasterServer(DownloadSourceDescriptor master) { if (master == null) { Debug.Fail("master is null."); return; } if (log.IsDebugEnabled) { log.DebugFormat("Adding master server `{0}` to MasterServerReadInfo `{1}`.", master, this); } lock (_mastersSync) { if (!_masters.Any(master.IsIdenticalTo)) { _masters.Add(master); return; } } }
/// <summary> /// Adds a download source read from a master server. /// </summary> /// <param name="source">The <see cref="DownloadSourceDescriptor"/>.</param> public void AddDownloadSource(DownloadSourceDescriptor source) { if (source == null) { Debug.Fail("source is null."); return; } if (log.IsDebugEnabled) { log.DebugFormat("Adding download source `{0}` to MasterServerReadInfo `{1}`.", source, this); } lock (_sourcesSync) { if (!_sources.Any(source.IsIdenticalTo)) { _sources.Add(source); return; } } }
/// <summary> /// Checks if this <see cref="IDownloadSource"/> contains the same values as the given <see cref="DownloadSourceDescriptor"/>. /// </summary> /// <param name="descriptor">The <see cref="DownloadSourceDescriptor"/> to compare to.</param> /// <returns>True if they have equal values; otherwise false.</returns> public bool IsIdenticalTo(DownloadSourceDescriptor descriptor) { if (descriptor.Type != DownloadSourceType.Http) return false; if (descriptor.RootPath != RootPath) return false; return true; }
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> /// The worker method for the reader threads. /// </summary> /// <param name="o">The arguments.</param> void ReadThreadWorker(object o) { var stateObj = (ThreadWorkerArgs)o; var callback = stateObj.Callback; var userState = stateObj.UserState; var readVersion = stateObj.Version; if (log.IsDebugEnabled) { log.DebugFormat("Running MasterServerReader worker. UserState: {0}. ReadVersion: {1}. Callback: {2}", userState, readVersion.HasValue ? readVersion.Value.ToString() : "[NULL]", callback); } var info = new MasterServerReadInfo(); if (readVersion.HasValue) { info.AddVersion(readVersion.Value); } // Create the master server readers from the file IEnumerable <DownloadSourceDescriptor> descriptors; lock (_ioSync) { descriptors = DownloadSourceDescriptor.FromDescriptorFile(LocalMasterServerListPath); } // Ensure we have descriptors if (descriptors.Count() == 0) { const string errmsg = "No DownloadSourceDescriptors could be found."; if (log.IsErrorEnabled) { log.Error(errmsg); } info.AppendError(errmsg); callback(this, info, userState); return; } // Create the source instances var sources = new List <IDownloadSource>(); foreach (var desc in descriptors) { try { var src = desc.Instantiate(); sources.Add(src); } catch (Exception ex) { const string errmsg = "Failed to instantiate DownloadSourceDescriptor `{0}`: {1}"; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg, desc, ex); } info.AppendError(string.Format(errmsg, desc, ex)); } } // Ensure we have at least one source if (sources.Count == 0) { const string errmsg = "All DownloadSourceDescriptors failed to be instantiated - no servers available to use."; if (log.IsErrorEnabled) { log.ErrorFormat(errmsg); } info.AppendError(errmsg); callback(this, info, userState); return; } // Start the downloader using (var msd = new MasterServerDownloader(info, sources, readVersion) { DisposeSources = true }) { // This will block until its complete msd.Execute(); } // Save the new information to the files WriteMasterServersFile(info, LocalMasterServerListPath); WriteDownloadSourcesFile(info, LocalDownloadSourceListPath); // Invoke the callback if (callback != null) { callback(this, info, userState); } }
/// <summary> /// Checks if this <see cref="DownloadSourceDescriptor"/> is identical to another <see cref="DownloadSourceDescriptor"/>. /// </summary> /// <param name="other">The other <see cref="DownloadSourceDescriptor"/>.</param> /// <returns>True if they are identical; otherwise false.</returns> /// <exception cref="ArgumentNullException"><paramref name="other"/> is null.</exception> public bool IsIdenticalTo(DownloadSourceDescriptor other) { if (other == null) throw new ArgumentNullException("other"); return this == other || Type == other.Type || RootPath == other.RootPath; }