using System; using System.Collections.Generic; using System.ComponentModel; using System.Data.OleDb; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Windows.Forms; using ScoutBase.Core; using System.Data.SQLite; namespace ScoutBase.CAT { public class CATUpdaterStartOptions { public string Name; public BACKGROUNDUPDATERSTARTOPTIONS Options; } // Background worker for rig definitions update [DefaultPropertyAttribute("Name")] public class CATUpdater : BackgroundWorker { CATUpdaterStartOptions StartOptions; // Temp directory to save downloaded files string TmpDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Application.CompanyName, Application.ProductName, "Tmp", "RigData").TrimEnd(Path.DirectorySeparatorChar); // File extension string FileExtension = ".ini"; public CATUpdater() : base() { this.WorkerReportsProgress = true; this.WorkerSupportsCancellation = true; // create temp directory if not exists if (!Directory.Exists(TmpDirectory)) Directory.CreateDirectory(TmpDirectory); } private DOWNLOADFILESTATUS GetUpdateFromURL(string url, string zipfilename) { AutoDecompressionWebClient cl = new AutoDecompressionWebClient(); DOWNLOADFILESTATUS status = cl.DownloadFileIfNewer(url, zipfilename, true, true); return status; } private bool ReadRigsFromURL(string url, string zipfilename) { try { DOWNLOADFILESTATUS status = GetUpdateFromURL(url, zipfilename); if (((status & DOWNLOADFILESTATUS.ERROR) > 0) && ((status & DOWNLOADFILESTATUS.NOTFOUND) > 0)) { this.ReportProgress(-1, "Error while downloading and extracting " + zipfilename); return false; } else if (((status & DOWNLOADFILESTATUS.NEWER) > 0) || ((status & DOWNLOADFILESTATUS.NOTNEWER) > 0)) { var dir = new DirectoryInfo(TmpDirectory); FileInfo[] files = dir.GetFiles("*" + FileExtension); foreach (FileInfo file in files) { string oldfilename = Path.Combine(RigData.Database.DefaultDatabaseDirectory(), file.Name); try { if (!File.Exists(oldfilename)) { // file does not exist --> simply copy over File.Copy(file.FullName, oldfilename); } else if (new FileInfo(oldfilename).LastWriteTimeUtc < file.LastWriteTimeUtc) { // file exists but is older --> delete old file and copy over File.Delete(oldfilename); File.Copy(file.FullName, oldfilename); } if (this.CancellationPending) return false; // reduce CPU load Thread.Sleep(1); } catch (Exception ex) { this.ReportProgress(-1, "Error while checking " + oldfilename); return false; } } return true; } } catch (Exception ex) { // Error loading database this.ReportProgress(-1, "[" + url + "]: " + ex.ToString()); } return false; } protected override void OnDoWork(DoWorkEventArgs e) { StartOptions = (CATUpdaterStartOptions)e.Argument; this.ReportProgress(0, StartOptions.Name + " started."); // name the thread for debugging if (String.IsNullOrEmpty(Thread.CurrentThread.Name)) Thread.CurrentThread.Name = nameof(CATUpdater); // create directories if not exist try { if (!Directory.Exists(TmpDirectory)) Directory.CreateDirectory(TmpDirectory); if (!Directory.Exists(RigData.Database.DefaultDatabaseDirectory())) Directory.CreateDirectory(RigData.Database.DefaultDatabaseDirectory()); } catch (Exception ex) { this.ReportProgress(-1, "Error while creating directories: " + ex.ToString()); } this.ReportProgress(0, "Updating rig definitions..."); // get update interval int interval = (int)Properties.Settings.Default.Database_BackgroundUpdate_Period * 60; do { try { // check if any kind of update is enabled if ((StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE) || (StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY)) { // reset database status this.ReportProgress(1, System.Data.SQLite.DATABASESTATUS.UNDEFINED); Stopwatch st = new Stopwatch(); st.Start(); // clear temporary files try { SupportFunctions.DeleteFilesFromDirectory(TmpDirectory, new string[] { "*.tmp", "*.PendingOverwrite" }); } catch (Exception ex) { this.ReportProgress(-1, ex.ToString()); } // update rig database this.ReportProgress(1, System.Data.SQLite.DATABASESTATUS.UPDATING); this.ReportProgress(0, "Updating rig definitions from web database..."); // get update from url if (ReadRigsFromURL(Properties.Settings.Default.Rigs_UpdateURL + "rigs.zip", Path.Combine(TmpDirectory, "rigs.zip"))) { st.Stop(); this.ReportProgress(1, System.Data.SQLite.DATABASESTATUS.UPTODATE); this.ReportProgress(0, " Rig database update completed: " + st.Elapsed.ToString(@"hh\:mm\:ss")); } else { st.Stop(); this.ReportProgress(1, System.Data.SQLite.DATABASESTATUS.ERROR); this.ReportProgress(0, " Rig database update completed with errors: " + st.Elapsed.ToString(@"hh\:mm\:ss")); } if (this.CancellationPending) break; // sleep once to get all messages to main thread Thread.Sleep(1000); // sleep when running periodically if (StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY) { int i = 0; while (!this.CancellationPending && (i < interval)) { Thread.Sleep(1000); i++; } } } } catch (Exception ex) { this.ReportProgress(-1, ex.ToString()); } } while (!this.CancellationPending && (StartOptions.Options == BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY)); if (this.CancellationPending) this.ReportProgress(0, "Cancelled."); else this.ReportProgress(0, "Finished."); } } }