/// <summary> /// Constructs a new instance of the <see cref="InputAdapterBase"/>. /// </summary> protected InputAdapterBase() { m_connectionOperation = new LongSynchronizedOperation(AttemptConnectionOperation) { IsBackground = true }; m_connectionTimer = Common.TimerScheduler.CreateTimer(2000); m_connectionTimer.Elapsed += m_connectionTimer_Elapsed; m_connectionTimer.AutoReset = false; m_connectionTimer.Enabled = false; }
private void StartMeasurementCounter() { long now = DateTime.UtcNow.Ticks; DataSet dataSource; DataTable measurementTable; IConfigurationFrame configurationFrame; int measurementsPerFrame; if (!m_receivedConfigFrame) { // If this is the first time we've received the configuration frame, // we'll use it to calculate expected measurements per second for each device dataSource = DataSource; if ((object)dataSource != null && dataSource.Tables.Contains("ActiveMeasurements")) { measurementTable = dataSource.Tables["ActiveMeasurements"]; configurationFrame = m_frameParser.ConfigurationFrame; foreach (DeviceStatisticsHelper<ConfigurationCell> statisticsHelper in StatisticsHelpers) { measurementsPerFrame = measurementTable.Select($"SignalReference LIKE '{statisticsHelper.Device.IDLabel}-%' AND SignalType <> 'FLAG' AND SignalType <> 'STAT'").Length; statisticsHelper.ExpectedMeasurementsPerSecond = configurationFrame.FrameRate * measurementsPerFrame; statisticsHelper.Reset(now); } } } if ((object)m_measurementCounter == null) { // Create the timer if it doesn't already exist m_measurementCounter = CommonPhasorServices.TimerScheduler.CreateTimer(1000); m_measurementCounter.Elapsed += m_measurementCounter_Elapsed; } // Start the measurement counter timer // to start gathering statistics m_measurementCounter.Start(); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="DataGapRecoverer"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if ((object)m_dataGapRecoveryCompleted != null) { // Signal any waiting threads m_abnormalTermination = true; m_dataGapRecoveryCompleted.Set(); m_dataGapRecoveryCompleted.Dispose(); } if ((object)m_dataStreamMonitor != null) { m_dataStreamMonitor.Elapsed -= DataStreamMonitor_Elapsed; m_dataStreamMonitor.Dispose(); m_dataStreamMonitor = null; } if ((object)m_dataGapLogProcessor != null) { m_dataGapLogProcessor.Dispose(); m_dataGapLogProcessor = null; } if ((object)m_dataGapLog != null) { m_dataGapLog.ProcessException -= Common_ProcessException; m_dataGapLog.Dispose(); m_dataGapLog = null; } if ((object)m_temporalSubscription != null) { m_temporalSubscription.StatusMessage -= Common_StatusMessage; m_temporalSubscription.ProcessException -= Common_ProcessException; m_temporalSubscription.ConnectionEstablished -= TemporalSubscription_ConnectionEstablished; m_temporalSubscription.ConnectionTerminated -= TemporalSubscription_ConnectionTerminated; m_temporalSubscription.NewMeasurements -= TemporalSubscription_NewMeasurements; m_temporalSubscription.ProcessingComplete -= TemporalSubscription_ProcessingComplete; m_temporalSubscription.Dispose(); m_temporalSubscription = null; } } } finally { m_disposed = true; // Prevent duplicate dispose. if ((object)Disposed != null) Disposed(this, EventArgs.Empty); } } }
/// <summary> /// Releases the unmanaged resources used by the <see cref="InputAdapterBase"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if (m_connectionTimer != null) { m_connectionTimer.Elapsed -= m_connectionTimer_Elapsed; m_connectionTimer.Dispose(); } m_connectionTimer = null; } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }
/// <summary> /// Constructs a new instance of the <see cref="OutputAdapterBase"/>. /// </summary> protected OutputAdapterBase() { m_metadataRefreshOperation = new LongSynchronizedOperation(ExecuteMetadataRefresh) { IsBackground = true }; m_measurementQueue = ProcessQueue<IMeasurement>.CreateRealTimeQueue(ProcessMeasurements); m_measurementQueue.ProcessException += m_measurementQueue_ProcessException; m_connectionOperation = new LongSynchronizedOperation(AttemptConnectionOperation) { IsBackground = true }; m_connectionTimer = Common.TimerScheduler.CreateTimer(2000); m_connectionTimer.Elapsed += m_connectionTimer_Elapsed; m_connectionTimer.AutoReset = false; m_connectionTimer.Enabled = false; // We monitor total number of unarchived measurements every 5 seconds - this is a useful statistic to monitor, if // total number of unarchived measurements gets very large, measurement archival could be falling behind m_monitorTimer = Common.TimerScheduler.CreateTimer(5000); m_monitorTimer.Elapsed += m_monitorTimer_Elapsed; m_monitorTimer.AutoReset = true; m_monitorTimer.Enabled = false; }
/// <summary> /// Creates a new <see cref="DataGapRecoverer"/>. /// </summary> public DataGapRecoverer() { Log = Logger.CreatePublisher(GetType(), MessageClass.Framework); Log.InitialStackMessages = Log.InitialStackMessages.Union("ComponentName", GetType().Name); m_dataGapRecoveryCompleted = new ManualResetEventSlim(true); m_recoveryStartDelay = DefaultRecoveryStartDelay; m_minimumRecoverySpan = DefaultMinimumRecoverySpan; m_maximumRecoverySpan = DefaultMaximumRecoverySpan; string loggingPath = FilePath.GetDirectoryName(FilePath.GetAbsolutePath(DataSubscriber.DefaultLoggingPath)); if (Directory.Exists(loggingPath)) m_loggingPath = loggingPath; m_subscriptionInfo = new UnsynchronizedSubscriptionInfo(false); m_subscriptionInfo.FilterExpression = DefaultFilterExpression; m_subscriptionInfo.ProcessingInterval = DefaultRecoveryProcessingInterval; m_subscriptionInfo.UseMillisecondResolution = DefaultUseMillisecondResolution; m_dataStreamMonitor = Common.TimerScheduler.CreateTimer((int)(DefaultDataMonitoringInterval * 1000.0D)); m_dataStreamMonitor.Elapsed += DataStreamMonitor_Elapsed; m_dataStreamMonitor.AutoReset = true; m_dataStreamMonitor.Enabled = false; }
private bool m_disposed; // Disposed flag detects redundant calls to dispose method #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="ConcentratorBase"/>. /// </summary> /// <remarks> /// Concentration will not begin until consumer "Starts" concentrator (i.e., calling <see cref="ConcentratorBase.Start"/> method or setting /// <c><see cref="ConcentratorBase.Enabled"/> = true</c>). /// </remarks> protected ConcentratorBase() { Log = Logger.CreatePublisher(GetType(), MessageClass.Framework); m_usePrecisionTimer = true; m_allowSortsByArrival = true; m_allowPreemptivePublishing = true; m_performTimestampReasonabilityCheck = true; m_processingInterval = -1; m_downsamplingMethod = DownsamplingMethod.LastReceived; m_latestMeasurements = new ImmediateMeasurements(this); m_maximumPublicationTimeout = Timeout.Infinite; // Create a new queue for managing real-time frames m_frameQueue = new FrameQueue(this.CreateNewFrame); // Set minimum timer resolution to one millisecond to improve timer accuracy PrecisionTimer.SetMinimumTimerResolution(1); // Create publication wait handle m_publicationWaitHandle = new AutoResetEvent(false); // Create publication thread m_publicationThread = new Thread(PublishFrames); m_publicationThread.Start(); // This timer monitors the total number of unpublished samples every 5 seconds. This is a useful statistic // to monitor: if total number of unpublished samples exceed lag time, measurement concentration could // be falling behind. m_monitorTimer = Common.TimerScheduler.CreateTimer(5000); m_monitorTimer.AutoReset = true; m_monitorTimer.Elapsed += MonitorUnpublishedSamples; }
/// <summary> /// Releases the unmanaged resources used by the <see cref="DataSubscriber"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { DataLossInterval = 0.0D; CommandChannel = null; DataChannel = null; DisposeLocalConcentrator(); if ((object)m_dataGapRecoverer != null) { m_dataGapRecoverer.RecoveredMeasurements -= m_dataGapRecoverer_RecoveredMeasurements; m_dataGapRecoverer.StatusMessage -= m_dataGapRecoverer_StatusMessage; m_dataGapRecoverer.ProcessException -= m_dataGapRecoverer_ProcessException; m_dataGapRecoverer.Dispose(); m_dataGapRecoverer = null; } if ((object)m_runTimeLog != null) { m_runTimeLog.ProcessException -= m_runTimeLog_ProcessException; m_runTimeLog.Dispose(); m_runTimeLog = null; } if ((object)m_subscribedDevicesTimer != null) { m_subscribedDevicesTimer.Elapsed -= SubscribedDevicesTimer_Elapsed; m_subscribedDevicesTimer.Dispose(); m_subscribedDevicesTimer = null; } } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }
/// <summary> /// Creates a new <see cref="ClientConnection"/> instance. /// </summary> /// <param name="parent">Parent data publisher.</param> /// <param name="clientID">Client ID of associated connection.</param> /// <param name="commandChannel"><see cref="TcpServer"/> command channel used to lookup connection information.</param> public ClientConnection(DataPublisher parent, Guid clientID, IServer commandChannel) { m_parent = parent; m_clientID = clientID; m_commandChannel = commandChannel; m_subscriberID = clientID; m_keyIVs = null; m_cipherIndex = 0; // Setup ping timer m_pingTimer = Common.TimerScheduler.CreateTimer(5000); m_pingTimer.AutoReset = true; m_pingTimer.Elapsed += m_pingTimer_Elapsed; m_pingTimer.Start(); // Setup reconnect timer m_reconnectTimer = Common.TimerScheduler.CreateTimer(1000); m_reconnectTimer.AutoReset = false; m_reconnectTimer.Elapsed += m_reconnectTimer_Elapsed; // Attempt to lookup remote connection identification for logging purposes try { Socket commandChannelSocket = GetCommandChannelSocket(); IPEndPoint remoteEndPoint = null; if ((object)commandChannel != null) remoteEndPoint = commandChannelSocket.RemoteEndPoint as IPEndPoint; if ((object)remoteEndPoint != null) { m_ipAddress = remoteEndPoint.Address; if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6) m_connectionID = "[" + m_ipAddress + "]:" + remoteEndPoint.Port; else m_connectionID = m_ipAddress + ":" + remoteEndPoint.Port; try { IPHostEntry ipHost = Dns.GetHostEntry(remoteEndPoint.Address); if (!string.IsNullOrWhiteSpace(ipHost.HostName)) { m_hostName = ipHost.HostName; m_connectionID = m_hostName + " (" + m_connectionID + ")"; } } // Just ignoring possible DNS lookup failures... catch (ArgumentNullException) { // The hostNameOrAddress parameter is null. } catch (ArgumentOutOfRangeException) { // The length of hostNameOrAddress parameter is greater than 255 characters. } catch (ArgumentException) { // The hostNameOrAddress parameter is an invalid IP address. } catch (SocketException) { // An error was encountered when resolving the hostNameOrAddress parameter. } } } catch { // At worst we'll just use the client GUID for identification m_connectionID = m_subscriberID == Guid.Empty ? clientID.ToString() : m_subscriberID.ToString(); } if (string.IsNullOrWhiteSpace(m_connectionID)) m_connectionID = "unavailable"; if (string.IsNullOrWhiteSpace(m_hostName)) { if ((object)m_ipAddress != null) m_hostName = m_ipAddress.ToString(); else m_hostName = m_connectionID; } if ((object)m_ipAddress == null) m_ipAddress = IPAddress.None; }
/// <summary> /// Releases the unmanaged resources used by the <see cref="ConcentratorBase"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { // Make sure concentrator is stopped Stop(); DetachFromFrameRateTimer(m_framesPerSecond, m_processingInterval); m_publicationThread = null; if ((object)m_publicationWaitHandle != null) { AutoResetEvent publicationWaitHandle = m_publicationWaitHandle; m_publicationWaitHandle = null; publicationWaitHandle.Set(); publicationWaitHandle.Dispose(); } if ((object)m_frameQueue != null) { m_frameQueue.Dispose(); m_frameQueue = null; } if ((object)m_monitorTimer != null) { m_monitorTimer.Elapsed -= MonitorUnpublishedSamples; m_monitorTimer.Dispose(); m_monitorTimer = null; } if ((object)m_latestMeasurements != null) { m_latestMeasurements.Dispose(); m_latestMeasurements = null; } m_lastDiscardedMeasurement = null; // Clear minimum timer resolution. PrecisionTimer.ClearMinimumTimerResolution(1); } } finally { m_disposed = true; // Prevent duplicate dispose. if ((object)Disposed != null) Disposed(this, EventArgs.Empty); } } }
/// <summary> /// Releases the unmanaged resources used by the <see cref="ClientConnection"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if ((object)m_pingTimer != null) { m_pingTimer.Elapsed -= m_pingTimer_Elapsed; m_pingTimer.Dispose(); m_pingTimer = null; } if ((object)m_reconnectTimer != null) { m_reconnectTimer.Elapsed -= m_reconnectTimer_Elapsed; m_reconnectTimer.Dispose(); m_reconnectTimer = null; } DataChannel = null; m_commandChannel = null; m_ipAddress = null; m_subscription = null; m_parent = null; } } finally { m_disposed = true; // Prevent duplicate dispose. } } }
/// <summary> /// Releases the unmanaged resources used by the <see cref="MultiProtocolFrameParser"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> private void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { Stop(); PrecisionInputTimer.Detach(ref m_inputTimer); if ((object)m_rateCalcTimer != null) { m_rateCalcTimer.Elapsed -= m_rateCalcTimer_Elapsed; m_rateCalcTimer.Dispose(); } m_rateCalcTimer = null; // Clear minimum timer resolution. PrecisionTimer.ClearMinimumTimerResolution(1); } } finally { m_disposed = true; // Prevent duplicate dispose. } } }
/// <summary> /// Creates a new <see cref="MultiProtocolFrameParser"/> using the default settings. /// </summary> public MultiProtocolFrameParser() { m_connectionString = "server=127.0.0.1:4712"; m_deviceID = 1; m_bufferSize = DefaultBufferSize; m_maximumConnectionAttempts = DefaultMaximumConnectionAttempts; m_autoStartDataParsingSequence = DefaultAutoStartDataParsingSequence; m_allowedParsingExceptions = DefaultAllowedParsingExceptions; m_parsingExceptionWindow = DefaultParsingExceptionWindow; m_checkSumValidationFrameTypes = CheckSumValidationFrameTypes.AllFrames; m_trustHeaderLength = true; m_keepCommandChannelOpen = true; m_rateCalcTimer = TimerScheduler.CreateTimer(); m_phasorProtocol = PhasorProtocol.IEEEC37_118V1; m_transportProtocol = TransportProtocol.Tcp; // Set default frame rate, this calculates milliseconds for each frame DefinedFrameRate = DefaultDefinedFrameRate; m_rateCalcTimer.Elapsed += m_rateCalcTimer_Elapsed; m_rateCalcTimer.Interval = 5000; m_rateCalcTimer.AutoReset = true; m_rateCalcTimer.Enabled = false; // Set minimum timer resolution to one millisecond to improve timer accuracy PrecisionTimer.SetMinimumTimerResolution(1); }
/// <summary> /// Creates a new <see cref="PhasorMeasurementMapper"/>. /// </summary> public PhasorMeasurementMapper() { // Create a cached signal reference dictionary for generated signal references m_generatedSignalReferenceCache = new ConcurrentDictionary<SignalKind, string[]>(); // Create data stream monitoring timer m_dataStreamMonitor = CommonPhasorServices.TimerScheduler.CreateTimer(); m_dataStreamMonitor.Elapsed += m_dataStreamMonitor_Elapsed; m_dataStreamMonitor.AutoReset = true; m_dataStreamMonitor.Enabled = false; m_undefinedDevices = new ConcurrentDictionary<string, long>(); m_configurationOperationLock = new object(); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="UnsynchronizedClientSubscription"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { m_parent = null; // Dispose base time rotation timer if ((object)m_baseTimeRotationTimer != null) { m_baseTimeRotationTimer.Dispose(); m_baseTimeRotationTimer = null; } // Dispose Iaon session this.DisposeTemporalSession(ref m_iaonSession); } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }
/// <summary> /// Releases the unmanaged resources used by the <see cref="PhasorMeasurementMapper"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { // Detach from frame parser events and set reference to null FrameParser = null; if ((object)m_dataStreamMonitor != null) { m_dataStreamMonitor.Elapsed -= m_dataStreamMonitor_Elapsed; m_dataStreamMonitor.Dispose(); m_dataStreamMonitor = null; } if ((object)m_measurementCounter != null) { m_measurementCounter.Elapsed -= m_measurementCounter_Elapsed; m_measurementCounter.Dispose(); m_measurementCounter = null; } if ((object)m_definedDevices != null) { // Unregister each existing device from the statistics engine foreach (ConfigurationCell device in DefinedDevices) { StatisticsEngine.Unregister(device); } } } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }
/// <summary> /// Initializes <see cref="UnsynchronizedClientSubscription"/>. /// </summary> public override void Initialize() { MeasurementKey[] inputMeasurementKeys; string setting; if (Settings.TryGetValue("inputMeasurementKeys", out setting)) { // IMPORTANT: The allowSelect argument of ParseInputMeasurementKeys must be null // in order to prevent SQL injection via the subscription filter expression inputMeasurementKeys = ParseInputMeasurementKeys(DataSource, false, setting); m_requestedInputFilter = setting; // IMPORTANT: We need to remove the setting before calling base.Initialize() // or else we will still be subject to SQL injection Settings.Remove("inputMeasurementKeys"); } else { inputMeasurementKeys = new MeasurementKey[0]; m_requestedInputFilter = null; } base.Initialize(); // Set the InputMeasurementKeys property after calling base.Initialize() // so that the base class does not overwrite our setting InputMeasurementKeys = inputMeasurementKeys; if (Settings.TryGetValue("publishInterval", out setting)) m_publishInterval = int.Parse(setting); else m_publishInterval = -1; if (Settings.TryGetValue("includeTime", out setting)) m_includeTime = setting.ParseBoolean(); else m_includeTime = true; if (Settings.TryGetValue("useMillisecondResolution", out setting)) m_useMillisecondResolution = setting.ParseBoolean(); else m_useMillisecondResolution = false; if (Settings.TryGetValue("requestNaNValueFilter", out setting)) m_isNaNFiltered = m_parent.AllowNaNValueFilter && setting.ParseBoolean(); else m_isNaNFiltered = false; if (Settings.TryGetValue("bufferBlockRetransmissionTimeout", out setting)) m_bufferBlockRetransmissionTimeout = double.Parse(setting); else m_bufferBlockRetransmissionTimeout = 5.0D; if (m_parent.UseBaseTimeOffsets && m_includeTime) { m_baseTimeRotationTimer = Common.TimerScheduler.CreateTimer(m_useMillisecondResolution ? 60000 : 420000); m_baseTimeRotationTimer.AutoReset = true; m_baseTimeRotationTimer.Elapsed += BaseTimeRotationTimer_Elapsed; } m_bufferBlockRetransmissionTimer = Common.TimerScheduler.CreateTimer((int)(m_bufferBlockRetransmissionTimeout * 1000.0D)); m_bufferBlockRetransmissionTimer.AutoReset = false; m_bufferBlockRetransmissionTimer.Elapsed += BufferBlockRetransmissionTimer_Elapsed; // Handle temporal session initialization if (this.TemporalConstraintIsDefined()) m_iaonSession = this.CreateTemporalSession(); }
/// <summary> /// Attempts to connect to this <see cref="DataSubscriber"/>. /// </summary> protected override void AttemptConnection() { long now = m_useLocalClockAsRealTime ? DateTime.UtcNow.Ticks : 0L; List<DeviceStatisticsHelper<SubscribedDevice>> statisticsHelpers = m_statisticsHelpers; m_registerStatisticsOperation.RunOnceAsync(); m_expectedBufferBlockSequenceNumber = 0u; m_commandChannelConnectionAttempts = 0; m_dataChannelConnectionAttempts = 0; m_authenticated = m_securityMode == SecurityMode.TLS; m_subscribed = false; m_keyIVs = null; m_totalBytesReceived = 0L; m_monitoredBytesReceived = 0L; m_lastBytesReceived = 0; m_commandChannel.ConnectAsync(); if (m_useLocalClockAsRealTime && (object)m_subscribedDevicesTimer == null) { m_subscribedDevicesTimer = Common.TimerScheduler.CreateTimer(1000); m_subscribedDevicesTimer.Elapsed += SubscribedDevicesTimer_Elapsed; } if ((object)statisticsHelpers != null) { m_realTime = 0L; m_lastStatisticsHelperUpdate = 0L; foreach (DeviceStatisticsHelper<SubscribedDevice> statisticsHelper in statisticsHelpers) statisticsHelper.Reset(now); } if (m_useLocalClockAsRealTime) m_subscribedDevicesTimer.Start(); }
/// <summary> /// Releases the unmanaged resources used by the <see cref="OutputAdapterBase"/> object and optionally releases the managed resources. /// </summary> /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if (m_connectionTimer != null) { m_connectionTimer.Elapsed -= m_connectionTimer_Elapsed; m_connectionTimer.Dispose(); } m_connectionTimer = null; if (m_monitorTimer != null) { m_monitorTimer.Elapsed -= m_monitorTimer_Elapsed; m_monitorTimer.Dispose(); } m_monitorTimer = null; if (m_measurementQueue != null) { m_measurementQueue.ProcessException -= m_measurementQueue_ProcessException; m_measurementQueue.Dispose(); } m_measurementQueue = null; } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } }