/// <summary>
        /// Required Files Agent
        /// </summary>
        public ScheduleAndFilesAgent()
        {
            int limit = (ApplicationSettings.Default.MaxConcurrentDownloads <= 0) ? 1 : ApplicationSettings.Default.MaxConcurrentDownloads;

            _fileDownloadLimit = new Semaphore(limit, limit);
            _requiredFiles     = new RequiredFiles();
        }
Exemple #2
0
 public void Clear()
 {
     RequiredFiles.Clear();
     OptionalFiles.Clear();
     BlackListFiles.Clear();
     WhiteListFiles.Clear();
     PartList.Clear();
 }
        /// <summary>
        /// Run Thread
        /// </summary>
        public void Run()
        {
            Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Thread Started"), LogType.Info.ToString());

            while (!_forceStop)
            {
                lock (_locker)
                {
                    try
                    {
                        // If we are restarting, reset
                        _manualReset.Reset();

                        // Only do something if enabled
                        if (!ApplicationSettings.Default.EnableExpiredFileDeletion)
                        {
                            return;
                        }

                        // Get required files from disk
                        _requiredFiles = RequiredFiles.LoadFromDisk();

                        // Build a list of files in the library
                        DirectoryInfo directory = new DirectoryInfo(ApplicationSettings.Default.LibraryPath);

                        // Check each one and see if it is in required files
                        foreach (FileInfo fileInfo in directory.GetFiles())
                        {
                            // Delete files that were accessed over N days ago
                            try
                            {
                                RequiredFile file = _requiredFiles.GetRequiredFile(fileInfo.Name);
                            }
                            catch
                            {
                                // Not a required file
                                if (fileInfo.LastAccessTime < DateTime.Now.AddDays(ApplicationSettings.Default.LibraryAgentInterval * -1))
                                {
                                    Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Deleting old file: " + fileInfo.Name), LogType.Info.ToString());
                                    File.Delete(fileInfo.FullName);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // Log this message, but dont abort the thread
                        Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString());
                    }
                }

                // Sleep this thread for 5 minutes
                _manualReset.WaitOne(900 * 1000);
            }

            Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Thread Stopped"), LogType.Info.ToString());
        }
Exemple #4
0
        private IEnumerable <IPyStatement> ConvertRequestedToCode()
        {
            var result = new List <IPyStatement>();

            foreach (var item in RequiredFiles.Distinct())
            {
                var req = new PyImportStatement(item.RelativeModulePath, item.Alias);
                result.Add(req);
            }

            return(result.ToArray());
        }
        /// <summary>
        /// Gets the files that were necessary to compile this file
        /// </summary>
        private void ComputeReferencedFiles(Encoding enc, string currentDirectory)
        {
            if (string.IsNullOrEmpty(CompilationFileIdLogFilePath))
            {
                return;
            }

            if (File.Exists(CompilationFileIdLogFilePath))
            {
                RequiredFiles = UoeUtilities.GetReferencedFilesFromFileIdLog(CompilationFileIdLogFilePath, enc, currentDirectory);

                RequiredFiles.RemoveWhere(f =>
                                          f.PathEquals(CompiledFilePath) ||
                                          f.EndsWith(".r", StringComparison.OrdinalIgnoreCase) ||
                                          f.EndsWith(".pl", StringComparison.OrdinalIgnoreCase) ||
                                          !String.IsNullOrEmpty(CompilationXrefFilePath) && f.PathEquals(CompilationXrefFilePath));
            }
        }
Exemple #6
0
        private bool checkFiles()
        {
            if (!RequiredFiles.All(file => System.IO.File.Exists(System.IO.Path.Combine(pathBox.Text, file))))
            {
                pathBox.Background = new SolidColorBrush(Color.FromRgb(255, 220, 220));
                CanGoNext          = false;
            }
            else
            {
                pathBox.Background = new SolidColorBrush(Color.FromRgb(220, 255, 220));
                CreateShortcuts    = shortcutsCheckBox.IsChecked.GetValueOrDefault(false);
                Path      = pathBox.Text;
                CanGoNext = true;
            }

            MainWindow.Instance.RevalidateButtons();
            return(CanGoNext);
        }
Exemple #7
0
        private bool IsProperFolder()
        {
            if (!Directory.Exists(SelectedPath))
            {
                return(false);
            }
            if (RequiredFiles == null || !RequiredFiles.Any())
            {
                return(true);
            }

            try
            {
                // steam / gog path selected
                var steamPath = Path.Combine(SelectedPath, "DARKLAND");
                if (Directory.Exists(steamPath))
                {
                    SelectedPath = steamPath;
                }

                var filesInDirectory = (
                    from f in Directory.EnumerateFiles(SelectedPath, "*")
                    where f != null && RequiredFiles.Contains(Path.GetFileName(f).ToLower())
                    select f.ToLower()).Distinct().ToList();

                if (filesInDirectory.Count == RequiredFiles.Count())
                {
                    var realPath = Path.GetDirectoryName(filesInDirectory.First());
                    if (SelectedPath != realPath)
                    {
                        SelectedPath = realPath;
                    }

                    return(true);
                }

                return(false);
            }
            catch (Exception)
            {
                return(false);
            }
        }
Exemple #8
0
        private IEnumerable <IPhpStatement> ConvertRequestedToCode()
        {
            var result         = new List <IPhpStatement>();
            var alreadyDefined = new List <string>();
            var style          = new PhpEmitStyle();

            foreach (var item in RequiredFiles.Distinct())
            {
                var code = item.GetPhpCode(style); //rozróżniam je po wygenerowanym kodzie
                if (alreadyDefined.Contains(code))
                {
                    continue;
                }
                alreadyDefined.Add(code);
                var req = new PhpMethodCallExpression("require_once", item);
                result.Add(new PhpExpressionStatement(req));
            }

            return(result.ToArray());
        }
Exemple #9
0
        /// <summary>
        /// Run Thread
        /// </summary>
        public void Run()
        {
            Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Thread Started"), LogType.Info.ToString());

            while (!_forceStop)
            {
                lock (_locker)
                {
                    try
                    {
                        // If we are restarting, reset
                        _manualReset.Reset();

                        // Only do something if enabled
                        if (!ApplicationSettings.Default.EnableExpiredFileDeletion)
                        {
                            Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Expired File Deletion Disabled"), LogType.Audit.ToString());
                            return;
                        }

                        // Test Date
                        DateTime testDate = DateTime.Now.AddDays(ApplicationSettings.Default.LibraryAgentInterval * -1);

                        // Get required files from disk
                        _requiredFiles = RequiredFiles.LoadFromDisk();

                        Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Number of required files = " + _requiredFiles.RequiredFileList.Count), LogType.Audit.ToString());

                        // Build a list of files in the library
                        DirectoryInfo directory = new DirectoryInfo(ApplicationSettings.Default.LibraryPath);

                        // Check each one and see if it is in required files
                        foreach (FileInfo fileInfo in directory.GetFiles())
                        {
                            // Never delete certain system files
                            // Also do not delete log/stat files as they are managed by their respective agents
                            if (_persistentFiles.Contains(fileInfo.Name) ||
                                fileInfo.Name.Contains(ApplicationSettings.Default.LogLocation) ||
                                fileInfo.Name.Contains(ApplicationSettings.Default.StatsLogFile)
                                )
                            {
                                continue;
                            }

                            // Delete files that were accessed over N days ago
                            try
                            {
                                RequiredFile file = _requiredFiles.GetRequiredFile(fileInfo.Name);
                            }
                            catch
                            {
                                // It is a bad idea to log in here - it can cause a build up of log files.
                                //Debug.WriteLine(new LogMessage("LibraryAgent - Run", fileInfo.Name + " is not in Required Files, testing last accessed date [" + fileInfo.LastAccessTime + "] is earlier than " + testDate), LogType.Audit.ToString());

                                // Not a required file
                                if (fileInfo.LastAccessTime < testDate)
                                {
                                    Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Deleting old file: " + fileInfo.Name), LogType.Info.ToString());
                                    File.Delete(fileInfo.FullName);

                                    // Is this a HTZ file?
                                    if (fileInfo.Extension.ToLower() == ".htz")
                                    {
                                        // Also delete the extracted version of this file
                                        string pathToPackageFolder = Path.Combine(ApplicationSettings.Default.LibraryPath, "package_" + fileInfo.Name.Replace(fileInfo.Extension, ""));

                                        if (Directory.Exists(pathToPackageFolder))
                                        {
                                            Directory.Delete(pathToPackageFolder, true);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // Log this message, but dont abort the thread
                        Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString());
                    }
                }

                // Sleep this thread for 15 minutes
                _manualReset.WaitOne(2700 * 1000);
            }

            Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Thread Stopped"), LogType.Info.ToString());
        }
 /// <summary>
 /// Required Files Agent
 /// </summary>
 public RequiredFilesAgent()
 {
     _fileDownloadLimit = new Semaphore(ApplicationSettings.Default.MaxConcurrentDownloads, ApplicationSettings.Default.MaxConcurrentDownloads);
     _requiredFiles     = new RequiredFiles();
 }
        /// <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());
        }
Exemple #12
0
        /// <summary>
        /// Run Thread
        /// </summary>
        public void Run()
        {
            Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Thread Started"), LogType.Info.ToString());

            while (!_forceStop)
            {
                lock (_locker)
                {
                    try
                    {
                        // If we are restarting, reset
                        _manualReset.Reset();

                        // Only do something if enabled
                        if (!ApplicationSettings.Default.EnableExpiredFileDeletion)
                            return;

                        // Get required files from disk
                        _requiredFiles = RequiredFiles.LoadFromDisk();

                        // Build a list of files in the library
                        DirectoryInfo directory = new DirectoryInfo(ApplicationSettings.Default.LibraryPath);
                        
                        // Check each one and see if it is in required files
                        foreach (FileInfo fileInfo in directory.GetFiles())
                        {
                            // Never delete certain system files
                            if (_persistentFiles.Contains(fileInfo.Name))
                                continue;

                            // Delete files that were accessed over N days ago
                            try
                            {
                                RequiredFile file = _requiredFiles.GetRequiredFile(fileInfo.Name);
                            }
                            catch
                            {
                                // Not a required file
                                if (fileInfo.LastAccessTime < DateTime.Now.AddDays(ApplicationSettings.Default.LibraryAgentInterval * -1))
                                {
                                    Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Deleting old file: " + fileInfo.Name), LogType.Info.ToString());
                                    File.Delete(fileInfo.FullName);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // Log this message, but dont abort the thread
                        Trace.WriteLine(new LogMessage("LibraryAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString());
                    }
                }

                // Sleep this thread for 5 minutes
                _manualReset.WaitOne(900 * 1000);
            }

            Trace.WriteLine(new LogMessage("LibraryAgent - 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.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>
 /// Required Files Agent
 /// </summary>
 public RequiredFilesAgent()
 {
     _fileDownloadLimit = new Semaphore(ApplicationSettings.Default.MaxConcurrentDownloads, ApplicationSettings.Default.MaxConcurrentDownloads);
     _requiredFiles = new RequiredFiles();
 }
        /// <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());
        }