static void Main(string[] args) { string line; Console.WriteLine("Type HELP for a list of options."); Console.WriteLine(); using (OutageLog log = new OutageLog()) { log.FileName = @"C:\Users\swills\test.txt"; log.LogModified += (sender, arg) => Console.WriteLine("Modified!"); log.Initialize(); while (!(line = Console.ReadLine()).Equals("EXIT", StringComparison.OrdinalIgnoreCase)) { switch (line.ToUpper()) { case "ADD": log.Add(DateTimeOffset.UtcNow.AddSeconds(-1.0D), DateTimeOffset.UtcNow); Console.WriteLine($"Count: {log.Count}"); break; case "REMOVE": log.Remove(log.First()); Console.WriteLine($"Count: {log.Count}"); break; case "DUMP": foreach (Outage outage in log.Outages) { Console.WriteLine($"{outage.Start:yyyy-MM-dd HH:mm:ss.fff};{outage.End:yyyy-MM-dd HH:mm:ss.fff}"); } Console.WriteLine(); break; case "STATUS": Console.WriteLine(log.Status); Console.WriteLine(); break; case "HELP": Console.WriteLine("ADD - Adds a new outage to the log"); Console.WriteLine("REMOVE - Removes the first outage from the log"); Console.WriteLine("DUMP - Displays the contents of the log"); Console.WriteLine("STATUS - Displays detailed status of the log"); Console.WriteLine("EXIT - Exits this application"); Console.WriteLine(); break; } } } }
/// <summary> /// Initializes the <see cref="DataGapRecoverer"/>. /// </summary> public void Initialize() { if (m_disposed) { throw new InvalidOperationException("Data gap recoverer has been disposed. Cannot initialize."); } Dictionary <string, string> settings = m_connectionString.ToNonNullString().ParseKeyValuePairs(); string setting; double timeInterval; int processingInterval; if (settings.TryGetValue("sourceConnectionName", out setting) && !string.IsNullOrWhiteSpace(setting)) { m_sourceConnectionName = setting; } if (settings.TryGetValue("recoveryStartDelay", out setting) && double.TryParse(setting, out timeInterval)) { RecoveryStartDelay = timeInterval; } if (settings.TryGetValue("dataMonitoringInterval", out setting) && double.TryParse(setting, out timeInterval)) { DataMonitoringInterval = timeInterval; } if (settings.TryGetValue("minimumRecoverySpan", out setting) && double.TryParse(setting, out timeInterval)) { MinimumRecoverySpan = timeInterval; } if (settings.TryGetValue("maximumRecoverySpan", out setting) && double.TryParse(setting, out timeInterval)) { MaximumRecoverySpan = timeInterval; } if (settings.TryGetValue("filterExpression", out setting) && !string.IsNullOrWhiteSpace(setting)) { FilterExpression = setting; } if (settings.TryGetValue("recoveryProcessingInterval", out setting) && int.TryParse(setting, out processingInterval)) { RecoveryProcessingInterval = processingInterval; } if (settings.TryGetValue("useMillisecondResolution", out setting)) { UseMillisecondResolution = setting.ParseBoolean(); } if (settings.TryGetValue("startRecoveryBuffer", out setting) && double.TryParse(setting, out timeInterval)) { StartRecoveryBuffer = timeInterval; } if (settings.TryGetValue("endRecoveryBuffer", out setting) && double.TryParse(setting, out timeInterval)) { EndRecoveryBuffer = timeInterval; } // Get logging path, if any has been defined if (settings.TryGetValue("loggingPath", out setting)) { setting = FilePath.GetDirectoryName(FilePath.GetAbsolutePath(setting)); if (Directory.Exists(setting)) { m_loggingPath = setting; } else { OnStatusMessage(MessageLevel.Warning, $"Logging path \"{setting}\" not found, defaulting to \"{FilePath.GetAbsolutePath("")}\"...", "Initialization"); } } if (string.IsNullOrEmpty(m_sourceConnectionName)) { throw new NullReferenceException("Source connection name must defined - it is used to create outage log file name."); } // Setup a new temporal data subscriber that will be used to query historical data m_temporalSubscription = new DataSubscriber(); m_temporalSubscription.Name = m_sourceConnectionName + "!" + GetType().Name; m_temporalSubscription.DataSource = m_dataSource; m_temporalSubscription.ConnectionString = $"{m_connectionString};BypassStatistics=true"; m_temporalSubscription.StatusMessage += Common_StatusMessage; m_temporalSubscription.ProcessException += Common_ProcessException; m_temporalSubscription.ConnectionEstablished += TemporalSubscription_ConnectionEstablished; m_temporalSubscription.ConnectionTerminated += TemporalSubscription_ConnectionTerminated; m_temporalSubscription.ProcessingComplete += TemporalSubscription_ProcessingComplete; m_temporalSubscription.NewMeasurements += TemporalSubscription_NewMeasurements; m_temporalSubscription.Initialize(); // Setup data gap outage log to persist unprocessed outages between class life-cycles m_dataGapLog = new OutageLog(); m_dataGapLog.FileName = GetLoggingPath(m_sourceConnectionName + "_OutageLog.txt"); m_dataGapLog.ProcessException += Common_ProcessException; m_dataGapLog.Initialize(); // Setup data gap processor to process items one at a time, a 5-second minimum period is established between each gap processing m_dataGapLogProcessor = new OutageLogProcessor(m_dataGapLog, ProcessDataGap, CanProcessDataGap, ex => OnProcessException(MessageLevel.Warning, ex), GSF.Common.Max(5000, (int)(m_recoveryStartDelay * 1000.0D))); }
/// <summary> /// Initializes the <see cref="DataGapRecoverer"/>. /// </summary> public void Initialize() { if (m_disposed) throw new InvalidOperationException("Data gap recoverer has been disposed. Cannot initialize."); Dictionary<string, string> settings = m_connectionString.ToNonNullString().ParseKeyValuePairs(); string setting; double timeInterval; int processingInterval; if (settings.TryGetValue("sourceConnectionName", out setting) && !string.IsNullOrWhiteSpace(setting)) m_sourceConnectionName = setting; if (settings.TryGetValue("recoveryStartDelay", out setting) && double.TryParse(setting, out timeInterval)) RecoveryStartDelay = timeInterval; if (settings.TryGetValue("dataMonitoringInterval", out setting) && double.TryParse(setting, out timeInterval)) DataMonitoringInterval = timeInterval; if (settings.TryGetValue("minimumRecoverySpan", out setting) && double.TryParse(setting, out timeInterval)) MinimumRecoverySpan = timeInterval; if (settings.TryGetValue("maximumRecoverySpan", out setting) && double.TryParse(setting, out timeInterval)) MaximumRecoverySpan = timeInterval; if (settings.TryGetValue("filterExpression", out setting) && !string.IsNullOrWhiteSpace(setting)) FilterExpression = setting; if (settings.TryGetValue("recoveryProcessingInterval", out setting) && int.TryParse(setting, out processingInterval)) RecoveryProcessingInterval = processingInterval; if (settings.TryGetValue("useMillisecondResolution", out setting)) UseMillisecondResolution = setting.ParseBoolean(); // Get logging path, if any has been defined if (settings.TryGetValue("loggingPath", out setting)) { setting = FilePath.GetDirectoryName(FilePath.GetAbsolutePath(setting)); if (Directory.Exists(setting)) m_loggingPath = setting; else OnStatusMessage("WARNING: Logging path \"{0}\" not found, defaulting to \"{1}\"...", setting, FilePath.GetAbsolutePath("")); } if (string.IsNullOrEmpty(m_sourceConnectionName)) throw new NullReferenceException("Source connection name must defined - it is used to create outage log file name."); // Setup a new temporal data subscriber that will be used to query historical data m_temporalSubscription = new DataSubscriber(); m_temporalSubscription.Name = m_sourceConnectionName + "!" + GetType().Name; m_temporalSubscription.DataSource = m_dataSource; m_temporalSubscription.ConnectionString = m_connectionString; m_temporalSubscription.StatusMessage += Common_StatusMessage; m_temporalSubscription.ProcessException += Common_ProcessException; m_temporalSubscription.ConnectionEstablished += TemporalSubscription_ConnectionEstablished; m_temporalSubscription.ConnectionTerminated += TemporalSubscription_ConnectionTerminated; m_temporalSubscription.ProcessingComplete += TemporalSubscription_ProcessingComplete; m_temporalSubscription.NewMeasurements += TemporalSubscription_NewMeasurements; m_temporalSubscription.Initialize(); // Setup data gap outage log to persist unprocessed outages between class life-cycles m_dataGapLog = new OutageLog(); m_dataGapLog.FileName = GetLoggingPath(m_sourceConnectionName + "_OutageLog.txt"); m_dataGapLog.ProcessException += Common_ProcessException; m_dataGapLog.Initialize(); // Setup data gap processor to process items one at a time, a 5-second minimum period is established between each gap processing m_dataGapLogProcessor = new OutageLogProcessor(m_dataGapLog, ProcessDataGap, CanProcessDataGap, OnProcessException, GSF.Common.Max(5000, (int)(m_recoveryStartDelay * SI.Milli))); }
/// <summary> /// Initializes the <see cref="DataGapRecoverer"/>. /// </summary> public void Initialize() { if (m_disposed) { throw new InvalidOperationException("Data gap recoverer has been disposed. Cannot initialize."); } Dictionary <string, string> settings = m_connectionString.ToNonNullString().ParseKeyValuePairs(); string setting; double timeInterval; int processingInterval; if (settings.TryGetValue("sourceConnectionName", out setting) && !string.IsNullOrWhiteSpace(setting)) { m_sourceConnectionName = setting; } if (settings.TryGetValue("recoveryStartDelay", out setting) && double.TryParse(setting, out timeInterval)) { RecoveryStartDelay = timeInterval; } if (settings.TryGetValue("dataMonitoringInterval", out setting) && double.TryParse(setting, out timeInterval)) { DataMonitoringInterval = timeInterval; } if (settings.TryGetValue("minimumRecoverySpan", out setting) && double.TryParse(setting, out timeInterval)) { MinimumRecoverySpan = timeInterval; } if (settings.TryGetValue("maximumRecoverySpan", out setting) && double.TryParse(setting, out timeInterval)) { MaximumRecoverySpan = timeInterval; } if (settings.TryGetValue("filterExpression", out setting) && !string.IsNullOrWhiteSpace(setting)) { FilterExpression = setting; } if (settings.TryGetValue("recoveryProcessingInterval", out setting) && int.TryParse(setting, out processingInterval)) { RecoveryProcessingInterval = processingInterval; } if (settings.TryGetValue("useMillisecondResolution", out setting)) { UseMillisecondResolution = setting.ParseBoolean(); } if (string.IsNullOrEmpty(m_sourceConnectionName)) { throw new NullReferenceException("Source connection name must defined - it is used to create outage log file name."); } // Setup a new temporal data subscriber that will be used to query historical data m_temporalSubscription = new DataSubscriber(); m_temporalSubscription.Name = m_sourceConnectionName + "!" + GetType().Name; m_temporalSubscription.DataSource = m_dataSource; m_temporalSubscription.ConnectionString = m_connectionString; m_temporalSubscription.StatusMessage += Common_StatusMessage; m_temporalSubscription.ProcessException += Common_ProcessException; m_temporalSubscription.ConnectionEstablished += TemporalSubscription_ConnectionEstablished; m_temporalSubscription.ConnectionTerminated += TemporalSubscription_ConnectionTerminated; m_temporalSubscription.ProcessingComplete += TemporalSubscription_ProcessingComplete; m_temporalSubscription.NewMeasurements += TemporalSubscription_NewMeasurements; m_temporalSubscription.Initialize(); // Setup data gap outage log to persist unprocessed outages between class life-cycles m_dataGapLog = new OutageLog(); m_dataGapLog.FileName = m_sourceConnectionName + "_OutageLog.txt"; m_dataGapLog.ProcessException += Common_ProcessException; m_dataGapLog.Initialize(); // Setup data gap processor to process items one at a time, a 5-second minimum period is established between each gap processing m_dataGapLogProcessor = new OutageLogProcessor(m_dataGapLog, ProcessDataGap, CanProcessDataGap, OnProcessException, GSF.Common.Max(5000, (int)(m_recoveryStartDelay * SI.Milli))); }