/// <summary> /// See interface docs. /// </summary> /// <param name="parameters"></param> public void Startup(PluginStartupParameters parameters) { Singleton = this; var options = OptionsStorage.Load(this); _HtmlLocaliser = Factory.Resolve <IHtmlLocaliser>(); _HtmlLocaliser.Initialise(); _HtmlLocaliser.AddResourceStrings(typeof(DatabaseEditorStrings)); BaseStationDatabase = Factory.ResolveSingleton <IAutoConfigBaseStationDatabase>().Database; BaseStationDatabase.WriteSupportEnabled = true; _WebSiteExtender = Factory.Resolve <IWebSiteExtender>(); _WebSiteExtender.Enabled = false; _WebSiteExtender.WebRootSubFolder = "Web"; _WebSiteExtender.InjectContent = @"<script src=""script-DatabaseEditor/inject.js"" type=""text/javascript"">"; _WebSiteExtender.InjectMapPages(); _WebSiteExtender.InjectReportPages(); _WebSiteExtender.Initialise(parameters); _WebSiteExtender.ProtectFolder(ProtectedFolder); parameters.WebSite.HtmlLoadedFromFile += WebSite_HtmlLoadedFromFile; var redirection = Factory.ResolveSingleton <IRedirectionConfiguration>(); redirection.AddRedirection("/DatabaseEditor", "/DatabaseEditor/index.html", RedirectionContext.Any); redirection.AddRedirection("/DatabaseEditor/", "/DatabaseEditor/index.html", RedirectionContext.Any); ApplyOptions(options); }
/// <summary> /// See interface docs. /// </summary> public void Initialise() { Database = Factory.Resolve <IBaseStationDatabase>(); LoadConfiguration(); Factory.ResolveSingleton <IConfigurationStorage>().ConfigurationChanged += ConfigurationStorage_ConfigurationChanged; }
public void TestInitialise() { _OriginalClassFactory = Factory.TakeSnapshot(); _RuntimeEnvironment = TestUtilities.CreateMockSingleton<IRuntimeEnvironment>(); _ConfigurationStorage = TestUtilities.CreateMockSingleton<IConfigurationStorage>(); _Configuration = new Configuration(); _ConfigurationStorage.Setup(s => s.Load()).Returns(_Configuration); _CreateDatabaseFileName = Path.Combine(TestContext.TestDeploymentDir, "CreatedDatabase.sqb"); if(File.Exists(_CreateDatabaseFileName)) File.Delete(_CreateDatabaseFileName); _EmptyDatabaseFileName = Path.Combine(TestContext.TestDeploymentDir, "TestCopyBaseStation.sqb"); File.Copy(Path.Combine(TestContext.TestDeploymentDir, "BaseStation.sqb"), _EmptyDatabaseFileName, true); _Database = Factory.Singleton.Resolve<IBaseStationDatabase>(); _Database.FileName = _EmptyDatabaseFileName; _Provider = new Mock<IBaseStationDatabaseProvider>() { DefaultValue = DefaultValue.Mock }.SetupAllProperties(); _Database.Provider = _Provider.Object; _Provider.Setup(p => p.UtcNow).Returns(DateTime.UtcNow); _ConnectionStringBuilder = new SQLiteConnectionStringBuilder() { DataSource = _EmptyDatabaseFileName }; _Criteria = new SearchBaseStationCriteria() { FromDate = DateTime.MinValue, ToDate = DateTime.MaxValue, }; _FileNameChangingEvent = new EventRecorder<EventArgs>(); _FileNameChangedEvent = new EventRecorder<EventArgs>(); }
/// <summary> /// See interface docs. /// </summary> /// <param name="parameters"></param> public void Startup(PluginStartupParameters parameters) { Singleton = this; var options = OptionsStorage.Load(this); _HtmlLocaliser = Factory.Singleton.Resolve <IHtmlLocaliser>(); _HtmlLocaliser.Initialise(); _HtmlLocaliser.AddResourceStrings(typeof(DatabaseEditorStrings)); _BaseStationDatabase = Factory.Singleton.Resolve <IAutoConfigBaseStationDatabase>().Singleton.Database; _BaseStationDatabase.WriteSupportEnabled = true; _WebSiteExtender = Factory.Singleton.Resolve <IWebSiteExtender>(); _WebSiteExtender.Enabled = false; _WebSiteExtender.WebRootSubFolder = "Web"; _WebSiteExtender.InjectContent = @"<script src=""script-DatabaseEditor/inject.js"" type=""text/javascript"">"; _WebSiteExtender.InjectMapPages(); _WebSiteExtender.InjectReportPages(); _WebSiteExtender.PageHandlers.Add(String.Format("/{0}/SingleAircraftSearch.json", ProtectedFolder), SingleAircraftSearch); _WebSiteExtender.PageHandlers.Add(String.Format("/{0}/SingleAircraftSave.json", ProtectedFolder), SingleAircraftSave); _WebSiteExtender.Initialise(parameters); _WebSiteExtender.ProtectFolder(ProtectedFolder); parameters.WebSite.HtmlLoadedFromFile += WebSite_HtmlLoadedFromFile; ApplyOptions(options); }
/// <summary> /// See interface docs. /// </summary> public void Initialise() { Database = Factory.Singleton.Resolve<IBaseStationDatabase>(); LoadConfiguration(); Factory.Singleton.Resolve<IConfigurationStorage>().Singleton.ConfigurationChanged += ConfigurationStorage_ConfigurationChanged; }
/// <summary> /// See interface docs. /// </summary> /// <param name="parameters"></param> public void Startup(PluginStartupParameters parameters) { lock (_SyncLock) { var optionsStorage = new OptionsStorage(); _Options = optionsStorage.Load(this); _Database = Factory.Singleton.Resolve <IAutoConfigBaseStationDatabase>().Singleton.Database; _Database.FileNameChanging += BaseStationDatabase_FileNameChanging; _Database.FileNameChanged += BaseStationDatabase_FileNameChanged; _StandingDataManager = Factory.Singleton.Resolve <IStandingDataManager>().Singleton; _StandingDataManager.LoadCompleted += StandingDataManager_LoadCompleted; StartSession(); // If we process messages on the same thread as IAutoConfigListener raises the message received event on then we // will be running on the same thread as the aircraft list. Our processing can take some time, particularly if many // database writes have to happen simultaneously on startup, so to avoid blocking the update of the aircraft list // we create a background thread and process the messages on that. _BackgroundThreadMessageQueue = new BackgroundThreadQueue <BaseStationMessageEventArgs>("BaseStationDatabaseWriterMessageQueue"); _BackgroundThreadMessageQueue.StartBackgroundThread(MessageQueue_MessageReceived, MessageQueue_ExceptionCaught); var listener = Factory.Singleton.Resolve <IAutoConfigListener>().Singleton.Listener; listener.Port30003MessageReceived += MessageListener_MessageReceived; listener.SourceChanged += MessageListener_SourceChanged; Factory.Singleton.Resolve <IHeartbeatService>().Singleton.SlowTick += Heartbeat_SlowTick; } }
/// <summary> /// Imports flight records. /// </summary> /// <param name="source"></param> /// <param name="dest"></param> private void ProcessFlights(IBaseStationDatabaseSQLite source, IBaseStationDatabase dest) { if (!ImportFlights) { WriteLog("Flight import skipped"); } else if (!ImportSessions || !ImportLocations) { WriteLog("Flight import skipped because session import was skipped"); } else if (!ImportAircraft) { WriteLog("Flight import skipped because aircraft import was skipped"); } else { WriteLog("Importing flight records"); var criteria = new SearchBaseStationCriteria(); var countFlights = source.GetCountOfFlights(new SearchBaseStationCriteria()); var countSource = 0; var countDest = 0; var startRow = 0; var pageSize = 30000; while (startRow < countFlights) { var allSource = source.GetFlights(criteria, startRow, startRow + (pageSize - 1), "DATE", true, null, false); countSource += allSource.Count; var upsertCandidates = new List <BaseStationFlightUpsert>(); var upsertKeys = new HashSet <string>(); foreach (var candidate in allSource) { var key = $"{candidate.AircraftID}-{candidate.StartTime}"; if (!upsertKeys.Contains(key) && _AircraftMap.TryGetValue(candidate.AircraftID, out var aircraftID) && _SessionMap.TryGetValue(candidate.SessionID, out var sessionID)) { upsertCandidates.Add(new BaseStationFlightUpsert(candidate) { AircraftID = aircraftID, SessionID = sessionID, }); upsertKeys.Add(key); } } var upserted = dest.UpsertManyFlights(upsertCandidates); countDest += upserted.Length; startRow += pageSize; } WriteLog($" Imported {countDest:N0} / {countSource:N0} flights"); } }
/// <summary> /// Imports Session records. /// </summary> /// <param name="source"></param> /// <param name="dest"></param> private void ProcessSessions(IBaseStationDatabaseSQLite source, IBaseStationDatabase dest) { _SessionMap.Clear(); if (!ImportSessions) { WriteLog("Session import skipped"); } else if (!ImportLocations) { WriteLog("Session import skipped because location import was skipped"); } else { WriteLog("Importing Session records"); var allSource = source.GetSessions(); var allDest = dest.GetSessions(); foreach (var rec in allSource) { if (_LocationMap.TryGetValue(rec.LocationID, out var destLocationID)) { var sourceID = rec.SessionID; rec.LocationID = destLocationID; var existing = allDest.FirstOrDefault(r => r.SessionID > 0 && r.StartTime == rec.StartTime); if (existing == null) { rec.SessionID = 0; dest.InsertSession(rec); } else { rec.SessionID = existing.SessionID; dest.UpdateSession(rec); } _SessionMap.Add(sourceID, rec.SessionID); } } WriteLog($" Imported {allSource.Count:N0} sessions"); } }
/// <summary> /// See interface docs. /// </summary> /// <param name="parameters"></param> public void Startup(PluginStartupParameters parameters) { Singleton = this; lock (_SyncLock) { var optionsStorage = new OptionsStorage(); _Options = optionsStorage.Load(); _Database = Factory.Singleton.Resolve <IAutoConfigBaseStationDatabase>().Singleton.Database; _Database.FileNameChanging += BaseStationDatabase_FileNameChanging; _Database.FileNameChanged += BaseStationDatabase_FileNameChanged; _StandingDataManager = Factory.Singleton.Resolve <IStandingDataManager>().Singleton; _StandingDataManager.LoadCompleted += StandingDataManager_LoadCompleted; var feedManager = Factory.Singleton.Resolve <IFeedManager>().Singleton; feedManager.FeedsChanged += FeedManager_FeedsChanged; _OnlineLookupCache = Provider.CreateOnlineLookupCache(); _OnlineLookupCache.Database = _Database; _OnlineLookupCache.RefreshOutOfDateAircraft = _Options.RefreshOutOfDateAircraft; _OnlineLookupCache.EnabledChanged += OnlineLookupCache_EnabledChanged; StartSession(); var onlineLookupManager = Factory.Singleton.Resolve <IAircraftOnlineLookupManager>().Singleton; onlineLookupManager.RegisterCache(_OnlineLookupCache, 100, letManagerControlLifetime: false); // If we process messages on the same thread as the listener raises the message received event on then we // will be running on the same thread as the aircraft list. Our processing can take some time, particularly if many // database writes have to happen simultaneously on startup, so to avoid blocking the update of the aircraft list // we create a background thread and process the messages on that. _BackgroundThreadMessageQueue = new BackgroundThreadQueue <BaseStationMessageEventArgs>("BaseStationDatabaseWriterMessageQueue", 200000); _BackgroundThreadMessageQueue.StartBackgroundThread(MessageQueue_MessageReceived, MessageQueue_ExceptionCaught); HookFeed(); _HeartbeatService = Factory.Singleton.Resolve <IHeartbeatService>(); _HeartbeatService.SlowTick += Heartbeat_SlowTick; _HeartbeatService.Start(); } }
/// <summary> /// Imports aircraft records. /// </summary> /// <param name="source"></param> /// <param name="dest"></param> private void ProcessAircraft(IBaseStationDatabaseSQLite source, IBaseStationDatabase dest) { _AircraftMap.Clear(); if (!ImportAircraft) { WriteLog("Aircraft import skipped"); } else { WriteLog("Importing Aircraft records"); var allSource = source.GetAllAircraft().ToDictionary(r => r.AircraftID, r => r); var upsertCandidates = new List <BaseStationAircraftUpsert>(); var upsertKeys = new HashSet <string>(); foreach (var kvp in allSource) { if (!upsertKeys.Contains(kvp.Value.ModeS)) { upsertCandidates.Add(new BaseStationAircraftUpsert(kvp.Value)); upsertKeys.Add(kvp.Value.ModeS); } } upsertKeys.Clear(); var upserted = dest.UpsertManyAircraft(upsertCandidates).ToDictionary(r => r.ModeS, r => r); upsertCandidates.Clear(); foreach (var sourceKvp in allSource) { var sourceID = sourceKvp.Key; if (upserted.TryGetValue(sourceKvp.Value.ModeS, out var rec)) { _AircraftMap.Add(sourceID, rec.AircraftID); } } WriteLog($" Imported {upserted.Count:N0} / {allSource.Count:N0} aircraft"); } }
/// <summary> /// Imports Location records. /// </summary> /// <param name="source"></param> /// <param name="dest"></param> private void ProcessLocations(IBaseStationDatabase source, IBaseStationDatabase dest) { _LocationMap.Clear(); if (!ImportLocations) { WriteLog("Location import skipped"); } else { WriteLog("Importing Location records"); var allSource = source.GetLocations(); var allDest = dest.GetLocations(); foreach (var rec in allSource) { var sourceID = rec.LocationID; var existing = allDest.FirstOrDefault(r => r.LocationID > 0 && String.Equals(r.LocationName, rec.LocationName)); if (existing == null) { rec.LocationID = 0; dest.InsertLocation(rec); } else { rec.LocationID = existing.LocationID; existing.LocationID = -1; dest.UpdateLocation(rec); } _LocationMap.Add(sourceID, rec.LocationID); } WriteLog($" Imported {allSource.Count:N0} locations"); } }
public void TestCleanup() { Factory.RestoreSnapshot(_OriginalClassFactory); if(_Database != null) { _Database.Dispose(); _Database = null; } }
public void BaseStationDatabase_Constructor_Initialises_To_Known_Values_And_Properties_Work() { _Database.Dispose(); _Database = Factory.Singleton.Resolve<IBaseStationDatabase>(); Assert.IsNotNull(_Database.Provider); TestUtilities.TestProperty(_Database, "Provider", _Database.Provider, _Provider.Object); Assert.AreEqual(null, _Database.FileName); Assert.IsFalse(_Database.IsConnected); Assert.IsFalse(_Database.WriteSupportEnabled); }
/// <summary> /// See interface docs. /// </summary> /// <param name="parameters"></param> public void Startup(PluginStartupParameters parameters) { lock(_SyncLock) { var optionsStorage = new OptionsStorage(); _Options = optionsStorage.Load(this); _Database = Factory.Singleton.Resolve<IAutoConfigBaseStationDatabase>().Singleton.Database; _Database.FileNameChanging += BaseStationDatabase_FileNameChanging; _Database.FileNameChanged += BaseStationDatabase_FileNameChanged; _StandingDataManager = Factory.Singleton.Resolve<IStandingDataManager>().Singleton; _StandingDataManager.LoadCompleted += StandingDataManager_LoadCompleted; StartSession(); // If we process messages on the same thread as IAutoConfigListener raises the message received event on then we // will be running on the same thread as the aircraft list. Our processing can take some time, particularly if many // database writes have to happen simultaneously on startup, so to avoid blocking the update of the aircraft list // we create a background thread and process the messages on that. _BackgroundThreadMessageQueue = new BackgroundThreadQueue<BaseStationMessageEventArgs>("BaseStationDatabaseWriterMessageQueue"); _BackgroundThreadMessageQueue.StartBackgroundThread(MessageQueue_MessageReceived, MessageQueue_ExceptionCaught); var listener = Factory.Singleton.Resolve<IAutoConfigListener>().Singleton.Listener; listener.Port30003MessageReceived += MessageListener_MessageReceived; listener.SourceChanged += MessageListener_SourceChanged; Factory.Singleton.Resolve<IHeartbeatService>().Singleton.SlowTick += Heartbeat_SlowTick; } }