1798 lines · 68.7 KB · C#
RawDownload
//******************************************************************************************************//  AdapterCollectionBase.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.//  12/20/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.Data;using System.IO;using System.Linq;using System.Reflection;using System.Text;using System.Timers;using GSF.Annotations;using GSF.Collections;using GSF.IO;using GSF.Threading;using GSF.Units;using Timer = System.Timers.Timer; namespace GSF.TimeSeries.Adapters{    /// <summary>    /// Represents a collection of <see cref="IAdapter"/> implementations.    /// </summary>    /// <typeparam name="T">Type of <see cref="IAdapter"/> this collection contains.</typeparam>    [EditorBrowsable(EditorBrowsableState.Never)]    public abstract class AdapterCollectionBase<T> : ListCollection<T>, IAdapterCollection where T : class, IAdapter    {        #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 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="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>        /// 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 string m_name;        private uint m_id;        private bool m_initialized;        private string m_connectionString;        private Dictionary<string, string> m_settings;        private DataSet m_dataSource;        private string m_dataMember;        private int m_initializationTimeout;        private bool m_autoStart;        private IMeasurement[] m_outputMeasurements;        private MeasurementKey[] m_inputMeasurementKeys;        private string[] m_inputSourceIDs;        private string[] m_outputSourceIDs;        private MeasurementKey[] m_requestedInputMeasurementKeys;        private MeasurementKey[] m_requestedOutputMeasurementKeys;        private Ticks m_lastProcessTime;        private Time m_totalProcessTime;        private long m_processedMeasurements;        private DateTime m_startTimeConstraint;        private DateTime m_stopTimeConstraint;        private int m_processingInterval;        private Timer m_monitorTimer;        private bool m_monitorTimerEnabled;        private readonly LogicalThreadScheduler m_lifecycleThreadScheduler;        private readonly Dictionary<uint, LogicalThread> m_lifecycleThreads;        private readonly LogicalThreadLocal<T> m_activeItem;        private bool m_enabled;        private bool m_disposed;         #endregion         #region [ Constructors ]         /// <summary>        /// Constructs a new instance of the <see cref="AdapterCollectionBase{T}"/>.        /// </summary>        protected AdapterCollectionBase()        {            m_name = GetType().Name;            m_settings = new Dictionary<string, string>();            m_startTimeConstraint = DateTime.MinValue;            m_stopTimeConstraint = DateTime.MaxValue;            m_processingInterval = -1;            m_initializationTimeout = AdapterBase.DefaultInitializationTimeout;            m_autoStart = true;             m_monitorTimer = new Timer();            m_monitorTimer.Elapsed += m_monitorTimer_Elapsed;             // We monitor total number of processed measurements every minute            m_monitorTimer.Interval = 60000;            m_monitorTimer.AutoReset = true;            m_monitorTimer.Enabled = false;             m_lifecycleThreadScheduler = new LogicalThreadScheduler();            m_lifecycleThreads = new Dictionary<uint, LogicalThread>();            m_activeItem = new LogicalThreadLocal<T>();             // Even on a single processor system we want a few threads such that if an            // adapter is taking a long time to initialize, other adapters can still be            // initializing in the meanwhile            if (m_lifecycleThreadScheduler.MaxThreadCount < 4)                m_lifecycleThreadScheduler.MaxThreadCount = 4;             m_lifecycleThreadScheduler.UnhandledException += (sender, args) => OnProcessException(args.Argument);        }         /// <summary>        /// Releases the unmanaged resources before the <see cref="AdapterCollectionBase{T}"/> object is reclaimed by <see cref="GC"/>.        /// </summary>        ~AdapterCollectionBase()        {            Dispose(false);        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets the name of this <see cref="AdapterCollectionBase{T}"/>.        /// </summary>        public virtual string Name        {            get            {                return m_name;            }            set            {                m_name = value;            }        }         /// <summary>        /// Gets or sets numeric ID associated with this <see cref="AdapterCollectionBase{T}"/>.        /// </summary>        public virtual uint ID        {            get            {                return m_id;            }            set            {                m_id = value;            }        }         /// <summary>        /// Gets or sets flag indicating if the adapter collection has been initialized successfully.        /// </summary>        public virtual bool Initialized        {            get            {                return m_initialized;            }            set            {                m_initialized = value;            }        }         /// <summary>        /// Gets or sets key/value pair connection information specific to this <see cref="AdapterCollectionBase{T}"/>.        /// </summary>        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 or sets <see cref="DataSet"/> based data source used to load each <see cref="IAdapter"/>.        /// Updates to this property will cascade to all items in this <see cref="AdapterCollectionBase{T}"/>.        /// </summary>        /// <remarks>        /// Table name specified in <see cref="DataMember"/> from <see cref="DataSource"/> is expected        /// to have the following table column names:<br/>        /// ID, AdapterName, AssemblyName, TypeName, ConnectionString<br/>        /// ID column type should be integer based, all other column types are expected to be string based.        /// </remarks>        public virtual DataSet DataSource        {            get            {                return m_dataSource;            }            set            {                m_dataSource = value;                 // Update data source for items in this collection                lock (this)                {                    foreach (T item in this)                    {                        item.DataSource = m_dataSource;                    }                }            }        }         /// <summary>        /// Gets or sets specific data member (e.g., table name) in <see cref="DataSource"/> used to <see cref="Initialize()"/> this <see cref="AdapterCollectionBase{T}"/>.        /// </summary>        /// <remarks>        /// Table name specified in <see cref="DataMember"/> from <see cref="DataSource"/> is expected        /// to have the following table column names:<br/>        /// ID, AdapterName, AssemblyName, TypeName, ConnectionString<br/>        /// ID column type should be integer based, all other column types are expected to be string based.        /// </remarks>        public virtual string DataMember        {            get            {                return m_dataMember;            }            set            {                m_dataMember = value;            }        }         /// <summary>        /// Gets or sets the default adapter time that represents the maximum time system will wait during <see cref="Start()"/> for initialization.        /// </summary>        /// <remarks>        /// Set to <see cref="System.Threading.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 collection should automatically start items when <see cref="AutoInitialize"/> is <c>false</c>.        /// </summary>        public virtual bool AutoStart        {            get            {                return m_autoStart;            }            set            {                m_autoStart = value;            }        }         /// <summary>        /// Gets or sets primary keys of input measurements the <see cref="AdapterCollectionBase{T}"/> expects, if any.        /// </summary>        public virtual MeasurementKey[] InputMeasurementKeys        {            get            {                // If a specific set of input measurement keys has been assigned, use that set                if (m_inputMeasurementKeys != null)                    return m_inputMeasurementKeys;                 List<MeasurementKey> cumulativeKeys = new List<MeasurementKey>();                 // Otherwise return cumulative results of all child adapters                lock (this)                {                    foreach (T adapter in this)                    {                        if ((object)adapter != null)                        {                            MeasurementKey[] inputMeasurementKeys = adapter.InputMeasurementKeys;                             // If any of the children expects all measurements (i.e., null InputMeasurementKeys)                            // then the parent collection must expect all measurements                            if ((object)inputMeasurementKeys == null)                                return null;                             if (inputMeasurementKeys.Length > 0)                                cumulativeKeys.AddRange(inputMeasurementKeys);                        }                    }                }                 return cumulativeKeys.Distinct().ToArray();            }            set            {                m_inputMeasurementKeys = value;                OnInputMeasurementKeysUpdated();            }        }         /// <summary>        /// Gets or sets output measurements that the <see cref="AdapterCollectionBase{T}"/> will produce, if any.        /// </summary>        public virtual IMeasurement[] OutputMeasurements        {            get            {                // If a specific set of output measurements has been assigned, use that set                if (m_outputMeasurements != null)                    return m_outputMeasurements;                 // Otherwise return cumulative results of all child adapters                List<IMeasurement> cumulativeMeasurements = new List<IMeasurement>();                 // Otherwise return cumulative results of all child adapters                lock (this)                {                    foreach (T adapter in this)                    {                        if ((object)adapter != null)                        {                            IMeasurement[] outputMeasurements = adapter.OutputMeasurements;                             if (outputMeasurements != null && outputMeasurements.Length > 0)                                cumulativeMeasurements.AddRange(outputMeasurements);                        }                    }                }                 return cumulativeMeasurements.Distinct().ToArray();            }            set            {                m_outputMeasurements = value;                OnOutputMeasurementsUpdated();            }        }         /// <summary>        /// Gets or sets <see cref="MeasurementKey.Source"/> values used to filter input measurement keys.        /// </summary>        /// <remarks>        /// The collection classes simply track this value if assigned, no automatic action is taken.        /// </remarks>        public virtual string[] InputSourceIDs        {            get            {                return m_inputSourceIDs;            }            set            {                m_inputSourceIDs = value;            }        }         /// <summary>        /// Gets or sets <see cref="MeasurementKey.Source"/> values used to filter output measurements.        /// </summary>        /// <remarks>        /// The collection classes simply track this value if assigned, no automatic action is taken.        /// </remarks>        public virtual string[] OutputSourceIDs        {            get            {                return m_outputSourceIDs;            }            set            {                m_outputSourceIDs = value;            }        }         /// <summary>        /// Gets or sets input measurement keys that are requested by other adapters based on what adapter says it can provide.        /// </summary>        public virtual MeasurementKey[] RequestedInputMeasurementKeys        {            get            {                // If a specific set of input measurement keys has been assigned, use that set                if (m_requestedInputMeasurementKeys != null)                    return m_requestedInputMeasurementKeys;                 // Otherwise return cumulative results of all child adapters                lock (this)                {                    if (typeof(IActionAdapter).IsAssignableFrom(typeof(T)))                        return this.Cast<IActionAdapter>().Where(item => item.RequestedInputMeasurementKeys != null).SelectMany(item => item.RequestedInputMeasurementKeys).Distinct().ToArray();                     if (typeof(IOutputAdapter).IsAssignableFrom(typeof(T)))                        return this.Cast<IOutputAdapter>().Where(item => item.RequestedInputMeasurementKeys != null).SelectMany(item => item.RequestedInputMeasurementKeys).Distinct().ToArray();                }                 return null;            }            set            {                m_requestedInputMeasurementKeys = value;            }        }         /// <summary>        /// Gets or sets output measurement keys that are requested by other adapters based on what adapter says it can provide.        /// </summary>        public virtual MeasurementKey[] RequestedOutputMeasurementKeys        {            get            {                // If a specific set of output measurement keys has been assigned, use that set                if (m_requestedOutputMeasurementKeys != null)                    return m_requestedOutputMeasurementKeys;                 // Otherwise return cumulative results of all child adapters                lock (this)                {                    if (typeof(IActionAdapter).IsAssignableFrom(typeof(T)))                        return this.Cast<IActionAdapter>().Where(item => item.RequestedOutputMeasurementKeys != null).SelectMany(item => item.RequestedOutputMeasurementKeys).Distinct().ToArray();                     if (typeof(IInputAdapter).IsAssignableFrom(typeof(T)))                        return this.Cast<IInputAdapter>().Where(item => item.RequestedOutputMeasurementKeys != null).SelectMany(item => item.RequestedOutputMeasurementKeys).Distinct().ToArray();                }                 return null;            }            set            {                m_requestedOutputMeasurementKeys = value;            }        }         /// <summary>        /// Gets the flag indicating if this adapter collection supports temporal processing.        /// </summary>        /// <remarks>

Lines 1–500 of 1798.

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