1273 lines · 52.8 KB · C#
RawDownload
//******************************************************************************************************//  ActionAdapterBase.cs - Gbtc////  Copyright © 2012, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  09/02/2010 - J. Ritchie Carroll//       Generated original version of source code.//  02/08/2011 - J. Ritchie Carroll//       Added invokable ExamineQueueState method to analyze real-time concentrator frame queue state.//  12/20/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Diagnostics.CodeAnalysis;using System.Linq;using System.Text;using System.Threading;using GSF.Annotations;using GSF.Diagnostics; namespace GSF.TimeSeries.Adapters{    /// <summary>    /// Represents the base class for action adapters.    /// </summary>    /// <remarks>    /// This base class acts as a measurement concentrator which time aligns all incoming measurements for proper processing.    /// Derived classes are expected to override <see cref="ConcentratorBase.PublishFrame"/> to handle time aligned measurements    /// and call <see cref="OnNewMeasurements"/> for any new measurements that may get created.    /// </remarks>    [SuppressMessage("SonarQube.Methods", "S1206", Justification = "Class life-cycle is controlled through library.")]    public abstract class ActionAdapterBase : ConcentratorBase, IActionAdapter    {        #region [ Members ]         // Events         /// <summary>        /// Provides status messages to consumer.        /// </summary>        /// <remarks>        /// <see cref="EventArgs{T}.Argument"/> is new status message.        /// </remarks>        public event EventHandler<EventArgs<string>> StatusMessage;         /// <summary>        /// Event is raised when <see cref="InputMeasurementKeys"/> are updated.        /// </summary>        public event EventHandler InputMeasurementKeysUpdated;         /// <summary>        /// Event is raised when <see cref="OutputMeasurements"/> are updated.        /// </summary>        public event EventHandler OutputMeasurementsUpdated;         /// <summary>        /// Event is raised when adapter is aware of a configuration change.        /// </summary>        public event EventHandler ConfigurationChanged;         /// <summary>        /// Provides new measurements from action adapter.        /// </summary>        /// <remarks>        /// <see cref="EventArgs{T}.Argument"/> is a collection of new measurements for host to process.        /// </remarks>        public event EventHandler<EventArgs<ICollection<IMeasurement>>> NewMeasurements;         // Fields        private string m_name;        private uint m_id;        private string m_connectionString;        private Dictionary<string, string> m_settings;        private DataSet m_dataSource;        private int m_initializationTimeout;        private bool m_autoStart;        private bool m_respectInputDemands;        private bool m_respectOutputDemands;        private MeasurementKey[] m_inputMeasurementKeys;        private IMeasurement[] m_outputMeasurements;        private MeasurementKey[] m_requestedInputMeasurementKeys;        private MeasurementKey[] m_requestedOutputMeasurementKeys;        private List<string> m_inputSourceIDs;        private List<string> m_outputSourceIDs;        private int m_minimumMeasurementsToUse;        private DateTime m_startTimeConstraint;        private DateTime m_stopTimeConstraint;        private int m_hashCode;        private bool m_initialized;        private bool m_disposed;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new <see cref="ActionAdapterBase"/>.        /// </summary>        protected ActionAdapterBase()        {            m_name = this.GetType().Name;            Log.InitialStackMessages = Log.InitialStackMessages.Union("AdapterName", m_name);            m_settings = new Dictionary<string, string>();            m_startTimeConstraint = DateTime.MinValue;            m_stopTimeConstraint = DateTime.MaxValue;            GenHashCode();             // Set incoming measurements to none by default            m_inputMeasurementKeys = new MeasurementKey[0];             // For most implementations millisecond resolution will be sufficient            base.TimeResolution = Ticks.PerMillisecond;        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets name of the action adapter.        /// </summary>        public virtual string Name        {            get            {                return m_name;            }            set            {                m_name = value;                Log.InitialStackMessages = Log.InitialStackMessages.Union("AdapterName", m_name);                GenHashCode();            }        }         /// <summary>        /// Gets or sets numeric ID associated with this action adapter.        /// </summary>        public virtual uint ID        {            get            {                return m_id;            }            set            {                m_id = value;                GenHashCode();            }        }         /// <summary>        /// Gets or sets key/value pair connection information specific to action adapter.        /// </summary>        /// <remarks>        /// <para>        /// Example connection string using manually defined measurements:<br/>        /// <c>framesPerSecond=30; lagTime=1.0; leadTime=0.5; minimumMeasurementsToUse=-1;        /// useLocalClockAsRealTime=true; allowSortsByArrival=false;</c><br/>        /// <c>inputMeasurementKeys={P1:1245;P1:1247;P2:1335};</c><br/>        /// <c>outputMeasurements={P3:1345,60.0,1.0;P3:1346;P3:1347}</c><br/>        /// When defined manually, elements in key:<br/>        /// * inputMeasurementKeys are defined as "ArchiveSource:PointID"<br/>        /// * outputMeasurements are defined as "ArchiveSource:PointID,Adder,Multiplier", the adder and multiplier are optional        /// defaulting to 0.0 and 1.0 respectively.        /// <br/>        /// </para>        /// <para>        /// Example connection string using measurements defined in a <see cref="DataSource"/> table:<br/>        /// <c>framesPerSecond=30; lagTime=1.0; leadTime=0.5; minimumMeasurementsToUse=-1;        /// useLocalClockAsRealTime=true; allowSortsByArrival=false;</c><br/>        /// <c>inputMeasurementKeys={FILTER ActiveMeasurements WHERE Company='GSF' AND SignalType='FREQ' ORDER BY ID};</c><br/>        /// <c>outputMeasurements={FILTER ActiveMeasurements WHERE SignalType IN ('IPHA','VPHA') AND Phase='+'}</c><br/>        /// <br/>        /// Basic filtering syntax is as follows:<br/>        /// <br/>        ///     {FILTER &lt;TableName&gt; WHERE &lt;Expression&gt; [ORDER BY &lt;SortField&gt;]}<br/>        /// <br/>        /// Source tables are expected to have at least the following fields:<br/>        /// <list type="table">        ///     <listheader>        ///         <term>Name</term>        ///         <term>Type</term>        ///         <description>Description.</description>        ///     </listheader>        ///     <item>        ///         <term>ID</term>        ///         <term>NVARCHAR</term>        ///         <description>Measurement key formatted as: ArchiveSource:PointID.</description>        ///     </item>        ///     <item>        ///         <term>PointTag</term>        ///         <term>NVARCHAR</term>        ///         <description>Point tag of measurement.</description>        ///     </item>        ///     <item>        ///         <term>Adder</term>        ///         <term>FLOAT</term>        ///         <description>Adder to apply to value, if any (default to 0.0).</description>        ///     </item>        ///     <item>        ///         <term>Multiplier</term>        ///         <term>FLOAT</term>        ///         <description>Multiplier to apply to value, if any (default to 1.0).</description>        ///     </item>        /// </list>        /// </para>        /// <para>        /// Note that framesPerSecond, lagTime and leadTime are required parameters, all other parameters are optional.        /// </para>        /// </remarks>        public virtual string ConnectionString        {            get            {                return m_connectionString;            }            set            {                m_connectionString = value;                 // Pre-parse settings upon connection string assignment                if (string.IsNullOrWhiteSpace(m_connectionString))                    m_settings = new Dictionary<string, string>();                else                    m_settings = m_connectionString.ParseKeyValuePairs();            }        }         /// <summary>        /// Gets connection info for adapter, if any.        /// </summary>        /// <remarks>        /// For example, this could return IP or host name of source connection.        /// </remarks>        public virtual string ConnectionInfo => null;         /// <summary>        /// Gets or sets <see cref="DataSet"/> based data source available to this <see cref="ActionAdapterBase"/>.        /// </summary>        public virtual DataSet DataSource        {            get            {                return m_dataSource;            }            set            {                m_dataSource = value;            }        }         /// <summary>        /// Gets or sets maximum time system will wait during <see cref="Start"/> for initialization.        /// </summary>        /// <remarks>        /// Set to <see cref="Timeout.Infinite"/> to wait indefinitely.        /// </remarks>        public virtual int InitializationTimeout        {            get            {                return m_initializationTimeout;            }            set            {                m_initializationTimeout = value;            }        }         /// <summary>        /// Gets or sets flag indicating if adapter should automatically start or otherwise connect on demand.        /// </summary>        public virtual bool AutoStart        {            get            {                return m_autoStart;            }            set            {                m_autoStart = value;            }        }         /// <summary>        /// Gets or sets flag indicating if action adapter should respect auto-start requests based on input demands.        /// </summary>        /// <remarks>        /// Action adapters are in the curious position of being able to both consume and produce points, as such the user needs to be able to control how their        /// adapter will behave concerning routing demands when the adapter is setup to connect on demand. In the case of respecting auto-start input demands,        /// as an example, this would be <c>false</c> for an action adapter that calculated measurement, but <c>true</c> for an action adapter used to archive inputs.        /// </remarks>        public virtual bool RespectInputDemands        {            get            {                return m_respectInputDemands;            }            set            {                m_respectInputDemands = value;            }        }         /// <summary>        /// Gets or sets flag indicating if action adapter should respect auto-start requests based on output demands.        /// </summary>        /// <remarks>        /// Action adapters are in the curious position of being able to both consume and produce points, as such the user needs to be able to control how their        /// adapter will behave concerning routing demands when the adapter is setup to connect on demand. In the case of respecting auto-start output demands,        /// as an example, this would be <c>true</c> for an action adapter that calculated measurement, but <c>false</c> for an action adapter used to archive inputs.        /// </remarks>        public virtual bool RespectOutputDemands        {            get            {                return m_respectOutputDemands;            }            set            {                m_respectOutputDemands = value;            }        }         /// <summary>        /// Gets or sets the number of frames per second.        /// </summary>        /// <remarks>        /// Valid frame rates for a <see cref="ConcentratorBase"/> are greater than 0 frames per second.        /// </remarks>        [ConnectionStringParameter,        Description("Defines the number of frames per second expected by the adapter.")]        public new int FramesPerSecond        {            get            {                return base.FramesPerSecond;            }            set            {                base.FramesPerSecond = value;            }        }         /// <summary>        /// Gets or sets the allowed past time deviation tolerance, in seconds (can be sub-second).        /// </summary>        /// <remarks>        /// <para>Defines the time sensitivity to past measurement timestamps.</para>        /// <para>The number of seconds allowed before assuming a measurement timestamp is too old.</para>        /// <para>This becomes the amount of delay introduced by the concentrator to allow time for data to flow into the system.</para>        /// </remarks>        /// <exception cref="ArgumentOutOfRangeException">LagTime must be greater than zero, but it can be less than one.</exception>        [ConnectionStringParameter,        Description("Defines the allowed past time deviation tolerance, in seconds (can be sub-second).")]        public new double LagTime        {            get            {                return base.LagTime;            }            set            {                base.LagTime = value;            }        }         /// <summary>        /// Gets or sets the allowed future time deviation tolerance, in seconds (can be sub-second).        /// </summary>        /// <remarks>        /// <para>Defines the time sensitivity to future measurement timestamps.</para>        /// <para>The number of seconds allowed before assuming a measurement timestamp is too advanced.</para>        /// <para>This becomes the tolerated +/- accuracy of the local clock to real-time.</para>        /// </remarks>        /// <exception cref="ArgumentOutOfRangeException">LeadTime must be greater than zero, but it can be less than one.</exception>        [ConnectionStringParameter,        Description("Defines the allowed future time deviation tolerance, in seconds (can be sub-second).")]        public new double LeadTime        {            get            {                return base.LeadTime;            }            set            {                base.LeadTime = value;            }        }         /// <summary>        /// Gets or sets primary keys of input measurements the action adapter expects.        /// </summary>        /// <remarks>        /// If your adapter needs to receive all measurements, you must explicitly set InputMeasurementKeys to null.        /// </remarks>        [ConnectionStringParameter,        DefaultValue(null),        Description("Defines primary keys of input measurements the action adapter expects; can be one of a filter expression, measurement key, point tag or Guid."),        CustomConfigurationEditor("GSF.TimeSeries.UI.WPF.dll", "GSF.TimeSeries.UI.Editors.MeasurementEditor")]        public virtual MeasurementKey[] InputMeasurementKeys        {            get            {                return m_inputMeasurementKeys;            }            set            {                if (m_inputMeasurementKeys == value)                    return;                 if ((object)m_inputMeasurementKeys != null && (object)value != null)                {                    if (new HashSet<MeasurementKey>(m_inputMeasurementKeys).SetEquals(value))                        return;                }                 m_inputMeasurementKeys = value;                 // The input measurements typically define the "expected measurements" of the action adapter, so                // we use the number of these items to define the expected measurement count                ExpectedMeasurements = (object)m_inputMeasurementKeys != null ? m_inputMeasurementKeys.Length : 0;                 OnInputMeasurementKeysUpdated();            }        }         /// <summary>        /// Gets or sets output measurements that the action adapter will produce, if any.        /// </summary>        [ConnectionStringParameter,        DefaultValue(null),        Description("Defines primary keys of output measurements the action adapter expects; can be one of a filter expression, measurement key, point tag or Guid."),        CustomConfigurationEditor("GSF.TimeSeries.UI.WPF.dll", "GSF.TimeSeries.UI.Editors.MeasurementEditor")]        public virtual IMeasurement[] OutputMeasurements        {            get            {                return m_outputMeasurements;            }            set            {                m_outputMeasurements = value;                OnOutputMeasurementsUpdated();            }        }         /// <summary>        /// Gets or sets <see cref="MeasurementKey.Source"/> values used to filter input measurement keys.        /// </summary>        /// <remarks>        /// This allows an adapter to associate itself with entire collections of measurements based on the source of the measurement keys.        /// Set to <c>null</c> apply no filter.        /// </remarks>        public virtual string[] InputSourceIDs        {            get            {                if ((object)m_inputSourceIDs == null)                    return null;                 return m_inputSourceIDs.ToArray();            }            set            {                if ((object)value == null)                {                    m_inputSourceIDs = null;                }                else                {                    m_inputSourceIDs = new List<string>(value);                    m_inputSourceIDs.Sort();                }                 // Filter measurements to list of specified source IDs                AdapterBase.LoadInputSourceIDs(this);            }        }         /// <summary>

Lines 1–500 of 1273.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t