/// <summary> /// Run Thread /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { if (ApplicationSettings.Default.InDownloadWindow) { try { // If we are restarting, reset _manualReset.Reset(); int filesToDownload = _requiredFiles.FilesDownloading; // If we are currently downloading something, we have to wait if (filesToDownload > 0) { _clientInfoForm.RequiredFilesStatus = string.Format("Waiting: {0} Active Downloads", filesToDownload.ToString()); Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Currently Downloading Files, skipping collect"), LogType.Info.ToString()); } else { _clientInfoForm.RequiredFilesStatus = "Running: Requesting connection to Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.R23SignageClient_xmds_xmds; xmds.UseDefaultCredentials = false; // Get required files from XMDS string requiredFilesXml = xmds.RequiredFiles(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; _clientInfoForm.RequiredFilesStatus = "Running: Data received from Xibo Server"; // Load the XML file RF call XmlDocument xml = new XmlDocument(); xml.LoadXml(requiredFilesXml); // Create a required files object and set it to contain the RF returned this tick _requiredFiles = new RequiredFiles(); _requiredFiles.CurrentCacheManager = _cacheManager; _requiredFiles.RequiredFilesXml = xml; // List of Threads to start // TODO: Track these threads so that we can abort them if the application closes List<Thread> threadsToStart = new List<Thread>(); // Required files now contains a list of files to download (this will be updated by the various worker threads) foreach (RequiredFile fileToDownload in _requiredFiles.RequiredFileList) { // Skip downloaded files if (fileToDownload.Complete) continue; // Spawn a thread to download this file. FileAgent fileAgent = new FileAgent(); fileAgent.FileDownloadLimit = _fileDownloadLimit; fileAgent.HardwareKey = _hardwareKey; fileAgent.RequiredFiles = _requiredFiles; fileAgent.RequiredFileId = fileToDownload.Id; fileAgent.RequiredFileType = fileToDownload.FileType; fileAgent.OnComplete += new FileAgent.OnCompleteDelegate(fileAgent_OnComplete); fileAgent.OnPartComplete += new FileAgent.OnPartCompleteDelegate(fileAgent_OnPartComplete); // Create the thread and add it to the list of threads to start Thread thread = new Thread(new ThreadStart(fileAgent.Run)); thread.Name = "FileAgent_" + fileToDownload.FileType + "_Id_" + fileToDownload.Id.ToString(); threadsToStart.Add(thread); } // Start the threads after we have built them all - otherwise they will modify the collection we // are iterating over. foreach (Thread thread in threadsToStart) thread.Start(); // Report what we are doing back to MediaInventory _requiredFiles.ReportInventory(); // Write Required Files _requiredFiles.WriteRequiredFiles(); // Write the Cache Manager to Disk _cacheManager.WriteCacheManager(); // Report the storage usage reportStorage(); // Set the status on the client info screen if (threadsToStart.Count == 0) _clientInfoForm.RequiredFilesStatus = "Sleeping (inside download window)"; else _clientInfoForm.RequiredFilesStatus = string.Format("{0} files to download", threadsToStart.Count.ToString()); _clientInfoForm.UpdateRequiredFiles(RequiredFilesString()); } } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "WebException in Run: " + webEx.Message), LogType.Error.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + ex.Message; } } else { _clientInfoForm.RequiredFilesStatus = string.Format("Outside Download Window {0} - {1}", ApplicationSettings.Default.DownloadStartWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture), ApplicationSettings.Default.DownloadEndWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture)); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Run Thread /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { if (ApplicationSettings.Default.InDownloadWindow) { try { // If we are restarting, reset _manualReset.Reset(); int filesToDownload = _requiredFiles.FilesDownloading; // If we are currently downloading something, we have to wait if (filesToDownload > 0) { _clientInfoForm.RequiredFilesStatus = string.Format("Waiting: {0} Active Downloads", filesToDownload.ToString()); Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Currently Downloading Files, skipping collect"), LogType.Audit.ToString()); } else { _clientInfoForm.RequiredFilesStatus = "Running: Requesting connection to Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = false; // Get required files from XMDS string requiredFilesXml = xmds.RequiredFiles(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; _clientInfoForm.RequiredFilesStatus = "Running: Data received from Xibo Server"; // Load the XML file RF call XmlDocument xml = new XmlDocument(); xml.LoadXml(requiredFilesXml); // Create a required files object and set it to contain the RF returned this tick _requiredFiles = new RequiredFiles(); _requiredFiles.CurrentCacheManager = _cacheManager; _requiredFiles.RequiredFilesXml = xml; // List of Threads to start // TODO: Track these threads so that we can abort them if the application closes List <Thread> threadsToStart = new List <Thread>(); // Required files now contains a list of files to download (this will be updated by the various worker threads) foreach (RequiredFile fileToDownload in _requiredFiles.RequiredFileList) { // Skip downloaded files if (fileToDownload.Complete) { continue; } // Spawn a thread to download this file. FileAgent fileAgent = new FileAgent(); fileAgent.FileDownloadLimit = _fileDownloadLimit; fileAgent.HardwareKey = _hardwareKey; fileAgent.RequiredFiles = _requiredFiles; fileAgent.RequiredFileId = fileToDownload.Id; fileAgent.RequiredFileType = fileToDownload.FileType; fileAgent.OnComplete += new FileAgent.OnCompleteDelegate(fileAgent_OnComplete); fileAgent.OnPartComplete += new FileAgent.OnPartCompleteDelegate(fileAgent_OnPartComplete); // Create the thread and add it to the list of threads to start Thread thread = new Thread(new ThreadStart(fileAgent.Run)); thread.Name = "FileAgent_" + fileToDownload.FileType + "_Id_" + fileToDownload.Id.ToString(); threadsToStart.Add(thread); } // Start the threads after we have built them all - otherwise they will modify the collection we // are iterating over. foreach (Thread thread in threadsToStart) { thread.Start(); } // Report what we are doing back to MediaInventory _requiredFiles.ReportInventory(); // Write Required Files _requiredFiles.WriteRequiredFiles(); // Write the Cache Manager to Disk _cacheManager.WriteCacheManager(); // Report the storage usage reportStorage(); // Set the status on the client info screen if (threadsToStart.Count == 0) { _clientInfoForm.RequiredFilesStatus = "Sleeping (inside download window)"; } else { _clientInfoForm.RequiredFilesStatus = string.Format("{0} files to download", threadsToStart.Count.ToString()); } _clientInfoForm.UpdateRequiredFiles(RequiredFilesString()); } } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + ex.Message; } } else { _clientInfoForm.RequiredFilesStatus = string.Format("Outside Download Window {0} - {1}", ApplicationSettings.Default.DownloadStartWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture), ApplicationSettings.Default.DownloadEndWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture)); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Run Thread /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Started"), LogType.Info.ToString()); int retryAfterSeconds = 0; while (!_forceStop) { // If we are restarting, reset _manualReset.Reset(); // Reset backOff retryAfterSeconds = 0; lock (_locker) { // Run the schedule Agent thread scheduleAgent(); if (ApplicationSettings.Default.InDownloadWindow) { try { int filesToDownload = _requiredFiles.FilesDownloading; // If we are currently downloading something, we have to wait if (filesToDownload > 0) { ClientInfo.Instance.RequiredFilesStatus = string.Format("Waiting: {0} Active Downloads", filesToDownload.ToString()); Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Currently Downloading Files, skipping collect"), LogType.Audit.ToString()); } else if (!ShouldCheckRf()) { ClientInfo.Instance.RequiredFilesStatus = "Sleeping: last check was not required."; } else { ClientInfo.Instance.RequiredFilesStatus = "Running: Requesting connection to Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=requiredFiles"; xmds.UseDefaultCredentials = false; // Get required files from XMDS string requiredFilesXml = xmds.RequiredFiles(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; ClientInfo.Instance.RequiredFilesStatus = "Running: Data received from Xibo Server"; // Calculate and store a CRC32 _lastCheckRf = Crc32Algorithm.Compute(Encoding.UTF8.GetBytes(requiredFilesXml)).ToString(); // Load the XML file RF call XmlDocument xml = new XmlDocument(); xml.LoadXml(requiredFilesXml); // Create a required files object and set it to contain the RF returned this tick _requiredFiles = new RequiredFiles(); _requiredFiles.RequiredFilesXml = xml; // List of Threads to start // TODO: Track these threads so that we can abort them if the application closes List <Thread> threadsToStart = new List <Thread>(); // Track available disk space. long freeSpace = ClientInfo.Instance.GetDriveFreeSpace(); // Required files now contains a list of files to download (this will be updated by the various worker threads) foreach (RequiredFile fileToDownload in _requiredFiles.RequiredFileList) { // Skip downloaded files if (fileToDownload.Complete) { continue; } // Can we fit the file on the drive? if (freeSpace != -1) { if (fileToDownload.Size > freeSpace) { Trace.WriteLine(new LogMessage("RequiredFilesAgent", "Run: Not enough free space on disk"), LogType.Error.ToString()); continue; } // Decrement this file from the free space freeSpace -= (long)fileToDownload.Size; } // Spawn a thread to download this file. FileAgent fileAgent = new FileAgent(); fileAgent.FileDownloadLimit = _fileDownloadLimit; fileAgent.HardwareKey = _hardwareKey; fileAgent.RequiredFiles = _requiredFiles; fileAgent.RequiredFileId = fileToDownload.Id; fileAgent.RequiredFileType = fileToDownload.FileType; fileAgent.OnComplete += new FileAgent.OnCompleteDelegate(fileAgent_OnComplete); fileAgent.OnPartComplete += new FileAgent.OnPartCompleteDelegate(fileAgent_OnPartComplete); // Create the thread and add it to the list of threads to start Thread thread = new Thread(new ThreadStart(fileAgent.Run)); thread.Name = "FileAgent_" + fileToDownload.FileType + "_Id_" + fileToDownload.Id.ToString(); threadsToStart.Add(thread); } // Start the threads after we have built them all - otherwise they will modify the collection we // are iterating over. foreach (Thread thread in threadsToStart) { thread.Start(); } // Report what we are doing back to MediaInventory _requiredFiles.ReportInventory(); // Write Required Files _requiredFiles.WriteRequiredFiles(); // Write the Cache Manager to Disk CacheManager.Instance.WriteCacheManager(); // Set the status on the client info screen if (threadsToStart.Count == 0) { ClientInfo.Instance.RequiredFilesStatus = "Sleeping (inside download window)"; // Raise an event to say we've completed OnFullyProvisioned?.Invoke(); } else { ClientInfo.Instance.RequiredFilesStatus = string.Format("{0} files to download", threadsToStart.Count.ToString()); } ClientInfo.Instance.UpdateRequiredFiles(RequiredFilesString()); } } } catch (WebException webEx) when(webEx.Response is HttpWebResponse httpWebResponse && (int)httpWebResponse.StatusCode == 429) { // Get the header for how long we ought to wait retryAfterSeconds = webEx.Response.Headers["Retry-After"] != null?int.Parse(webEx.Response.Headers["Retry-After"]) : 120; // Log it. Trace.WriteLine(new LogMessage("RequiredFilesAgent", "Run: 429 received, waiting for " + retryAfterSeconds + " seconds."), LogType.Info.ToString()); } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); ClientInfo.Instance.RequiredFilesStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); ClientInfo.Instance.RequiredFilesStatus = "Error: " + ex.Message; } } else { ClientInfo.Instance.RequiredFilesStatus = string.Format("Outside Download Window {0} - {1}", ApplicationSettings.Default.DownloadStartWindowTime.ToString(), ApplicationSettings.Default.DownloadEndWindowTime.ToString()); } } if (retryAfterSeconds > 0) { // Sleep this thread until we've fulfilled our try after _manualReset.WaitOne(retryAfterSeconds * 1000); } else { // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } } Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }