909 lines · 41.5 KB · C#
RawDownload
//******************************************************************************************************//  IaonSession.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://  ----------------------------------------------------------------------------------------------------//  08/23/2011 - J. Ritchie Carroll//       Generated original version of source code.//  12/20/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Data;using System.Linq;using System.Text;using GSF.Annotations;using GSF.Collections;using GSF.Configuration;using GSF.Diagnostics;using System.Collections.Generic; // ReSharper disable InconsistentlySynchronizedFieldnamespace GSF.TimeSeries.Adapters{    /// <summary>    /// Represents a new Input, Action, Output interface session.    /// </summary>    public class IaonSession : IProvideStatus, IDisposable    {        #region [ Members ]         // Events         /// <summary>        /// Provides status messages to consumer.        /// </summary>        /// <remarks>        /// <see cref="EventArgs{T1,T2}.Argument1"/> is the new status message.<br/>        /// <see cref="EventArgs{T1,T2}.Argument2"/> is the message <see cref="UpdateType"/>.        /// </remarks>        public event EventHandler<EventArgs<string, UpdateType>> StatusMessage;         /// <summary>        /// Event is raised when there is an exception encountered while processing.        /// </summary>        /// <remarks>        /// <see cref="EventArgs{T}.Argument"/> is the exception that was thrown.        /// </remarks>        public event EventHandler<EventArgs<Exception>> ProcessException;         /// <summary>        /// Event is raised when <see cref="IAdapter.InputMeasurementKeys"/> are updated.        /// </summary>        public event EventHandler InputMeasurementKeysUpdated;         /// <summary>        /// Event is raised when <see cref="IAdapter.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>        /// Event is raised every five seconds allowing consumer to track current number of unpublished seconds of data in the queue.        /// </summary>        /// <remarks>        /// <see cref="EventArgs{T}.Argument"/> is the total number of unpublished seconds of data.        /// </remarks>        public event EventHandler<EventArgs<int>> UnpublishedSamples;         /// <summary>        /// Event is raised every five seconds allowing host to track total number of unprocessed measurements.        /// </summary>        /// <remarks>        /// <para>        /// Each <see cref="IOutputAdapter"/> implementation reports its current queue size of unprocessed        /// measurements so that if queue size reaches an unhealthy threshold, host can take evasive action.        /// </para>        /// <para>        /// <see cref="EventArgs{T}.Argument"/> is total number of unprocessed measurements.        /// </para>        /// </remarks>        public event EventHandler<EventArgs<int>> UnprocessedMeasurements;         /// <summary>        /// Indicates to the host that processing for one of the input adapters has completed.        /// </summary>        /// <remarks>        /// This event is expected to only be raised when an input adapter has been designed to process        /// a finite amount of data, e.g., reading a historical range of data during temporal processing.        /// </remarks>        public event EventHandler ProcessingComplete;         /// <summary>        /// Event is raised when this <see cref="AdapterCollectionBase{T}"/> is disposed or an <see cref="IAdapter"/> in the collection is disposed.        /// </summary>        public event EventHandler Disposed;         // Fields        private Guid m_nodeID;        private RoutingTables m_routingTables;        private AllAdaptersCollection m_allAdapters;        private FilterAdapterCollection m_filterAdapters;        private InputAdapterCollection m_inputAdapters;        private ActionAdapterCollection m_actionAdapters;        private OutputAdapterCollection m_outputAdapters;        private MeasurementKey[] m_inputMeasurementKeysRestriction;        private readonly int m_measurementWarningThreshold;        private readonly int m_measurementDumpingThreshold;        private readonly int m_defaultSampleSizeWarningThreshold;        private string m_name;        private bool m_disposed;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new <see cref="IaonSession"/>.        /// </summary>        public IaonSession()        {            ConfigurationFile configFile = ConfigurationFile.Current;             // Initialize system settings            CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"];             systemSettings.Add("NodeID", Guid.NewGuid().ToString(), "Unique Node ID");            m_nodeID = systemSettings["NodeID"].ValueAs<Guid>();             // Initialize threshold settings            CategorizedSettingsElementCollection thresholdSettings = configFile.Settings["thresholdSettings"];             thresholdSettings.Add("MeasurementWarningThreshold", "100000", "Number of unarchived measurements allowed in any output adapter queue before displaying a warning message");            thresholdSettings.Add("MeasurementDumpingThreshold", "500000", "Number of unarchived measurements allowed in any output adapter queue before taking evasive action and dumping data");            thresholdSettings.Add("DefaultSampleSizeWarningThreshold", "10", "Default number of unpublished samples (in seconds) allowed in any action adapter queue before displaying a warning message");             m_measurementWarningThreshold = thresholdSettings["MeasurementWarningThreshold"].ValueAsInt32();            m_measurementDumpingThreshold = thresholdSettings["MeasurementDumpingThreshold"].ValueAsInt32();            m_defaultSampleSizeWarningThreshold = thresholdSettings["DefaultSampleSizeWarningThreshold"].ValueAsInt32();             using (Logger.AppendStackMessages("HostAdapter","IaonSession"))            {                // Create a new set of routing tables                switch (OptimizationOptions.DefaultRoutingMethod)                {                    case OptimizationOptions.RoutingMethod.HighLatencyLowCpu:                        m_routingTables = new RoutingTables(new RouteMappingHighLatencyLowCpu());                        break;                    default:                        m_routingTables = new RoutingTables();                        break;                }            }            m_routingTables.StatusMessage += m_routingTables_StatusMessage;            m_routingTables.ProcessException += m_routingTables_ProcessException;             // Create a collection to manage all input, action and output adapter collections as a unit            m_allAdapters = new AllAdaptersCollection();             // Attach to common adapter events            m_allAdapters.StatusMessage += StatusMessageHandler;            m_allAdapters.ProcessException += ProcessExceptionHandler;            m_allAdapters.InputMeasurementKeysUpdated += InputMeasurementKeysUpdatedHandler;            m_allAdapters.OutputMeasurementsUpdated += OutputMeasurementsUpdatedHandler;            m_allAdapters.ConfigurationChanged += ConfigurationChangedHandler;            m_allAdapters.Disposed += DisposedHandler;             // Create filter adapters collection            m_filterAdapters = new FilterAdapterCollection();             // Create input adapters collection            m_inputAdapters = new InputAdapterCollection();            m_inputAdapters.NewMeasurements += NewMeasurementsHandler;            m_inputAdapters.ProcessingComplete += ProcessingCompleteHandler;             // Create action adapters collection            m_actionAdapters = new ActionAdapterCollection();            m_actionAdapters.NewMeasurements += NewMeasurementsHandler;            m_actionAdapters.UnpublishedSamples += UnpublishedSamplesHandler;            m_actionAdapters.RequestTemporalSupport += RequestTemporalSupportHandler;             // Create output adapters collection            m_outputAdapters = new OutputAdapterCollection();            m_outputAdapters.UnprocessedMeasurements += UnprocessedMeasurementsHandler;             // Associate adapter collections with routing tables            m_routingTables.InputAdapters = m_inputAdapters;            m_routingTables.ActionAdapters = m_actionAdapters;            m_routingTables.OutputAdapters = m_outputAdapters;             // We group these adapters such that they are initialized in the following order: output, filter, input, action.            // This is done so that the archival capabilities will be setup before we start receiving input and the input            // data will be flowing before any actions get established for the input - at least generally.            m_allAdapters.Add(m_outputAdapters);            m_allAdapters.Add(m_filterAdapters);            m_allAdapters.Add(m_inputAdapters);            m_allAdapters.Add(m_actionAdapters);        }         /// <summary>        /// Releases the unmanaged resources before the <see cref="IaonSession"/> object is reclaimed by <see cref="GC"/>.        /// </summary>        ~IaonSession() => Dispose(false);         #endregion         #region [ Properties ]         /// <summary>        /// Gets the all adapters collection for this <see cref="IaonSession"/>.        /// </summary>        public virtual AllAdaptersCollection AllAdapters => m_allAdapters;         /// <summary>        /// Gets the filter adapter collection for this <see cref="IaonSession"/>.        /// </summary>        public virtual FilterAdapterCollection FilterAdapters => m_filterAdapters;         /// <summary>        /// Gets the input adapter collection for this <see cref="IaonSession"/>.        /// </summary>        public virtual InputAdapterCollection InputAdapters => m_inputAdapters;         /// <summary>        /// Gets the action adapter collection for this <see cref="IaonSession"/>.        /// </summary>        public virtual ActionAdapterCollection ActionAdapters => m_actionAdapters;         /// <summary>        /// Gets the output adapter collection for this <see cref="IaonSession"/>.        /// </summary>        public virtual OutputAdapterCollection OutputAdapters => m_outputAdapters;         /// <summary>        /// Gets the routing tables for this <see cref="IaonSession"/>.        /// </summary>        public virtual RoutingTables RoutingTables => m_routingTables;         /// <summary>        /// Gets or sets a routing table restriction for a collection of input measurement keys.        /// </summary>        public virtual MeasurementKey[] InputMeasurementKeysRestriction        {            get => m_inputMeasurementKeysRestriction;            set => m_inputMeasurementKeysRestriction = value;        }         /// <summary>        /// Gets or sets the configuration <see cref="DataSet"/> for this <see cref="IaonSession"/>.        /// </summary>        public virtual DataSet DataSource        {            get => m_allAdapters.DataSource;            set => m_allAdapters.DataSource = value;        }         /// <summary>        /// Gets or sets the <see cref="Guid"/> node ID  for this <see cref="IaonSession"/>.        /// </summary>        public virtual Guid NodeID        {            get => m_nodeID;            set => m_nodeID = value;        }         /// <summary>        /// Gets name assigned to this <see cref="IaonSession"/>, if any.        /// </summary>        public virtual string Name        {            get => m_name.ToNonNullString();            set => m_name = value;        }         /// <summary>        /// Gets the combined status of the adapters in this <see cref="IaonSession"/>.        /// </summary>        public virtual string Status        {            get            {                StringBuilder status = new StringBuilder();                 status.AppendLine();                status.AppendLine(">> Filter Adapters:");                status.AppendLine();                 if (!(m_filterAdapters is null))                    status.AppendLine(m_filterAdapters.Status);                 status.AppendLine();                status.AppendLine(">> Input Adapters:");                status.AppendLine();                 if (!(m_inputAdapters is null))                    status.AppendLine(m_inputAdapters.Status);                 status.AppendLine();                status.AppendLine(">> Action Adapters:");                status.AppendLine();                 if (!(m_actionAdapters is null))                    status.AppendLine(m_actionAdapters.Status);                 status.AppendLine();                status.AppendLine(">> Output Adapters:");                status.AppendLine();                 if (!(m_outputAdapters is null))                    status.AppendLine(m_outputAdapters.Status);                 return status.ToString();            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Releases all the resources used by the <see cref="IaonSession"/> object.        /// </summary>        public void Dispose()        {            Dispose(true);            GC.SuppressFinalize(this);        }         /// <summary>        /// Releases the unmanaged resources used by the <see cref="IaonSession"/> 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)                return;                        try            {                if (!disposing)                    return;                 DataSet dataSource = DataSource;                 // Dispose filter adapters collection                if (!(m_filterAdapters is null))                {                    m_filterAdapters.Stop();                    m_filterAdapters.Dispose();                }                m_filterAdapters = null;                 // Dispose input adapters collection                if (!(m_inputAdapters is null))                {                    m_inputAdapters.Stop();                    m_inputAdapters.NewMeasurements -= NewMeasurementsHandler;                    m_inputAdapters.ProcessingComplete -= ProcessingCompleteHandler;                    m_inputAdapters.Dispose();                }                m_inputAdapters = null;                 // Dispose action adapters collection                if (!(m_actionAdapters is null))                {                    m_actionAdapters.Stop();                    m_actionAdapters.NewMeasurements -= NewMeasurementsHandler;                    m_actionAdapters.UnpublishedSamples -= UnpublishedSamplesHandler;                    m_actionAdapters.RequestTemporalSupport -= RequestTemporalSupportHandler;                    m_actionAdapters.Dispose();                }                m_actionAdapters = null;                 // Dispose output adapters collection                if (!(m_outputAdapters is null))                {                    m_outputAdapters.Stop();                    m_outputAdapters.UnprocessedMeasurements -= UnprocessedMeasurementsHandler;                    m_outputAdapters.Dispose();                }                m_outputAdapters = null;                 // Dispose all adapters collection                if (!(m_allAdapters is null))                {                    m_allAdapters.StatusMessage -= StatusMessageHandler;                    m_allAdapters.ProcessException -= ProcessExceptionHandler;                    m_allAdapters.InputMeasurementKeysUpdated -= InputMeasurementKeysUpdatedHandler;                    m_allAdapters.OutputMeasurementsUpdated -= OutputMeasurementsUpdatedHandler;                    m_allAdapters.ConfigurationChanged -= ConfigurationChangedHandler;                    m_allAdapters.Disposed -= DisposedHandler;                    m_allAdapters.Dispose();                }                m_allAdapters = null;                 // Dispose of routing tables                if (!(m_routingTables is null))                {                    m_routingTables.StatusMessage -= m_routingTables_StatusMessage;                    m_routingTables.ProcessException -= m_routingTables_ProcessException;                    m_routingTables.Dispose();                }                m_routingTables = null;                 dataSource?.Dispose();            }            finally            {                m_disposed = true; // Prevent duplicate dispose.                Disposed?.Invoke(this, EventArgs.Empty);            }        }         /// <summary>        /// Initialize and start adapters.        /// </summary>        /// <param name="autoStart">Sets flag that determines if adapters should be automatically started.</param>        public virtual void Initialize(bool autoStart = true)        {            // Initialize all adapters            m_allAdapters.Initialize();             // Start all adapters if they            // haven't started already            if (autoStart)                m_allAdapters.Start();        }         /// <summary>        /// Gets flag that determines if temporal processing is supported in this <see cref="IaonSession"/>.        /// </summary>        /// <param name="collection">Name of collection over which to check support (e.g., "InputAdapters"); or <c>null</c> for all collections.</param>        /// <returns>Flag that determines if temporal processing is supported in this <see cref="IaonSession"/>.</returns>        public virtual bool TemporalProcessingSupportExists(string collection = null)        {            try            {                DataTable temporalSupport = m_allAdapters?.DataSource?.Tables["TemporalSupport"];                 if (temporalSupport is null)                    return false;                 if (string.IsNullOrWhiteSpace(collection))                    return temporalSupport.Rows.Count > 0;                 return temporalSupport.Select($"Source = '{collection}'").Length > 0;            }            catch (Exception ex)            {                Logger.SwallowException(ex, "Ignored Exception", "Failures are non-catastrophic and should only result in false.");                return false;            }        }         /// <summary>        /// Gets derived name of specified object.        /// </summary>        /// <param name="sender">Sending object from which to derive name.</param>        /// <returns>Derived name of specified object.</returns>        public virtual string GetDerivedName(object sender)        {            string name = null;             switch (sender)            {                case IProvideStatus statusProvider:                    name = statusProvider.Name;                    break;                case string nameValue:                    name = nameValue;                    break;            }             if (string.IsNullOrWhiteSpace(name))                name = sender.GetType().Name;             if (!string.IsNullOrWhiteSpace(m_name))                name += "#" + m_name;             return name;        } 

Lines 1–500 of 909.

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