1396 lines · 56.1 KB · C#
RawDownload
//******************************************************************************************************//  ActionAdapterBase.cs - Gbtc////  Copyright © 2010, 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 Eclipse Public License -v 1.0 (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/eclipse-1.0.php////  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.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.Data;using System.Linq;using System.Text;using System.Threading; 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>    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>        /// 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 IAdapterCollection m_parent;        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 bool m_processMeasurementFilter;        private MeasurementKey[] m_inputMeasurementKeys;        private List<MeasurementKey> m_inputMeasurementKeysHash;        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 ManualResetEvent m_initializeWaitHandle;        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;            m_settings = new Dictionary<string, string>();            m_startTimeConstraint = DateTime.MinValue;            m_stopTimeConstraint = DateTime.MaxValue;            GenHashCode();             // Create wait handle to use for adapter initialization            m_initializeWaitHandle = new ManualResetEvent(false);            m_initializationTimeout = AdapterBase.DefaultInitializationTimeout;             // For most implementations millisecond resolution will be sufficient            base.TimeResolution = Ticks.PerMillisecond;        }         #endregion         #region [ Properties ]         /// <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>Multipler 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;                 // Preparse settings upon connection string assignment                if (m_connectionString.IsNullOrWhiteSpace())                    m_settings = new Dictionary<string, string>();                else                    m_settings = m_connectionString.ParseKeyValuePairs();            }        }         /// <summary>        /// Gets a read-only reference to the collection that contains this <see cref="ActionAdapterBase"/>.        /// </summary>        public ReadOnlyCollection<IAdapter> Parent        {            get            {                return new ReadOnlyCollection<IAdapter>(m_parent);            }        }         /// <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 flag that determines if measurements being queued for processing should be tested to see if they are in the <see cref="InputMeasurementKeys"/>.        /// </summary>        public virtual bool ProcessMeasurementFilter        {            get            {                return m_processMeasurementFilter;            }            set            {                m_processMeasurementFilter = 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 subsecond).        /// </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 subsecond).")]        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 subsecond).        /// </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 subsecond).")]        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.")]        public virtual MeasurementKey[] InputMeasurementKeys        {            get            {                return m_inputMeasurementKeys;            }            set            {                m_inputMeasurementKeys = value;                 // Update input key lookup hash table                if (value != null && value.Length > 0)                {                    m_inputMeasurementKeysHash = new List<MeasurementKey>(value);                    m_inputMeasurementKeysHash.Sort();                     // 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 = m_inputMeasurementKeys.Length;                }                else                {                    m_inputMeasurementKeysHash = null;                    ExpectedMeasurements = 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.")]        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 (m_inputSourceIDs == null)                    return null;                 return m_inputSourceIDs.ToArray();            }            set            {                if (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>        /// Gets or sets <see cref="MeasurementKey.Source"/> values used to filter output measurements.        /// </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[] OutputSourceIDs        {            get            {                if (m_outputSourceIDs == null)                    return null;                 return m_outputSourceIDs.ToArray();            }            set            {                if (value == null)                {                    m_outputSourceIDs = null;

Lines 1–500 of 1396.

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