//****************************************************************************************************** // IndependentOutputAdapterManagerBase.cs - Gbtc // // Copyright © 2020, 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://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: // ---------------------------------------------------------------------------------------------------- // 02/13/2020 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Data; using System.Text; using System.Threading; using GSF.Data; using GSF.Diagnostics; using GSF.TimeSeries.Data; using GSF.Units.EE; using static GSF.TimeSeries.Adapters.IndependentAdapterManagerExtensions; namespace GSF.TimeSeries.Adapters { /// /// Represents an adapter base class that provides functionality to manage and distribute measurements to a collection of output adapters. /// public abstract class IndependentOutputAdapterManagerBase : OutputAdapterCollection, IIndependentAdapterManager { #region [ Members ] // Fields private bool m_disposed; #endregion #region [ Constructors ] /// /// Creates a new . /// protected IndependentOutputAdapterManagerBase() => this.HandleConstruct(); #endregion #region [ Properties ] /// /// Gets or sets primary keys of input measurements for the . /// [ConnectionStringParameter] [Description("Defines primary keys of input measurements the 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")] [DefaultValue(null)] public override MeasurementKey[] InputMeasurementKeys { get => base.InputMeasurementKeys; set { base.InputMeasurementKeys = value; InputMeasurementKeyTypes = DataSource.GetSignalTypes(value, SourceMeasurementTable); } } /// /// Gets or sets the wait timeout, in milliseconds, that system wait for system configuration reload to complete. /// [ConnectionStringParameter] [Description("Defines the wait timeout, in milliseconds, that system wait for system configuration reload to complete.")] [DefaultValue(DefaultConfigurationReloadWaitTimeout)] public virtual int ConfigurationReloadWaitTimeout { get; set; } = DefaultConfigurationReloadWaitTimeout; /// /// Gets or sets the total number of attempts to wait for system configuration reloads when waiting for configuration updates to be available. /// [ConnectionStringParameter] [Description("Defines the total number of attempts to wait for system configuration reloads when waiting for configuration updates to be available.")] [DefaultValue(DefaultConfigurationReloadWaitAttempts)] public virtual int ConfigurationReloadWaitAttempts { get; set; } = DefaultConfigurationReloadWaitAttempts; /// /// Gets or sets the connection string used for database operations. Leave blank to use local configuration database defined in "systemSettings". /// [ConnectionStringParameter] [Description("Defines the connection string used for database operations. Leave blank to use local configuration database defined in \"systemSettings\".")] [DefaultValue(DefaultDatabaseConnectionString)] public virtual string DatabaseConnectionString { get; set; } /// /// Gets or sets the provider string used for database operations. Defaults to a SQL Server provider string. /// [ConnectionStringParameter] [Description("Defines the provider string used for database operations. Defaults to a SQL Server provider string.")] [DefaultValue(DefaultDatabaseProviderString)] public virtual string DatabaseProviderString { get; set; } /// /// Gets any custom adapter settings to be added to each adapter connection string. Can be used to add /// settings that are custom per adapter. /// public virtual string CustomAdapterSettings { get; } = null; /// /// Gets or sets the source measurement table to use for configuration. /// [ConnectionStringParameter] [Description("Defines the source measurement table to use for configuration.")] [DefaultValue(DefaultSourceMeasurementTable)] public virtual string SourceMeasurementTable { get; set; } = DefaultSourceMeasurementTable; /// /// Gets or sets based data source used to load each . Updates /// to this property will cascade to all adapters in this . /// public override DataSet DataSource { get => base.DataSource; set { if (!this.DataSourceChanged(value)) return; base.DataSource = value; this.HandleUpdateDataSource(); } } /// /// Gets number of input measurement required by each adapter. /// public abstract int PerAdapterInputCount { get; } /// /// Gets or sets the index into the per adapter input measurements to use for target adapter name. /// [ConnectionStringParameter] [Description("Defines the index into the per adapter input measurements to use for target adapter name.")] public virtual int InputMeasurementIndexUsedForName { get; set; } /// /// Gets or sets flag that determines if the adapter /// should be automatically parsed every time /// the is updated without requiring adapter to be reinitialized. Defaults /// to true to allow child adapters to come and go based on updates to system configuration. /// protected virtual bool AutoReparseConnectionString { get; set; } = true; /// /// Gets input measurement 's for each of the , if any. /// public virtual SignalType[] InputMeasurementKeyTypes { get; private set; } /// /// Get adapter index currently being processed. /// public int CurrentAdapterIndex { get; internal set; } /// /// Get adapter output index currently being processed. /// public int CurrentOutputIndex { get; internal set; } /// /// Gets associated device ID for , if any, for measurement generation. /// public virtual int CurrentDeviceID { get; } = 0; /// /// Returns the detailed status of the . /// public override string Status { get { StringBuilder status = new StringBuilder(); status.Append(this.HandleStatus()); status.Append(base.Status); return status.ToString(); } } #endregion #region [ Methods ] /// /// Releases the unmanaged resources used by the object and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (m_disposed) return; try { if (!disposing) return; this.HandleDispose(); } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } /// /// Initializes the . /// public override void Initialize() => this.HandleInitialize(); /// /// Validates that an even number of inputs are provided for specified . /// protected void ValidateEvenInputCount() => this.HandleValidateEvenInputCount(); /// /// Parses connection string. Derived classes should override for custom connection string parsing. /// public virtual void ParseConnectionString() => this.HandleParseConnectionString(); /// /// Notifies derived classes that configuration has been reloaded /// public virtual void ConfigurationReloaded() { } /// /// Recalculates routing tables. /// public virtual void RecalculateRoutingTables() => this.HandleRecalculateRoutingTables(); /// /// Queues a collection of measurements for processing to each connected to this . /// /// Measurements to queue for processing. public override void QueueMeasurementsForProcessing(IEnumerable measurements) => this.HandleQueueMeasurementsForProcessing(measurements); /// /// Gets a short one-line status of this . /// /// Maximum number of available characters for display. /// A short one-line summary of the current status of the . public override string GetShortStatus(int maxLength) => this.HandleGetShortStatus(maxLength); /// /// Enumerates child adapters. /// [AdapterCommand("Enumerates child adapters.")] public virtual void EnumerateAdapters() => this.HandleEnumerateAdapters(); /// /// Gets subscriber information for specified client connection. /// /// Enumerated index for child adapter. /// Status for adapter with specified . [AdapterCommand("Gets subscriber information for specified client connection.")] public virtual string GetAdapterStatus(int adapterIndex) => this.HandleGetAdapterStatus(adapterIndex); /// /// Gets configured database connection. /// /// New ADO data connection based on configured settings. public AdoDataConnection GetConfiguredConnection() => this.HandleGetConfiguredConnection(); #endregion #region [ IIndependentAdapterManager Implementation ] // The following properties are not used by output adapters. An IOutputAdapter implementation does not define // output measurements nor is any output automatically reentrant into time-series framework. string IIndependentAdapterManager.PointTagTemplate { get; set; } = DefaultPointTagTemplate; string IIndependentAdapterManager.AlternateTagTemplate { get; set; } = DefaultAlternateTagTemplate; string IIndependentAdapterManager.SignalReferenceTemplate { get; set; } = DefaultSignalReferenceTemplate; string IIndependentAdapterManager.DescriptionTemplate { get; set; } = DefaultDescriptionTemplate; string IIndependentAdapterManager.ParentDeviceAcronymTemplate { get; set; } = DefaultParentDeviceAcronymTemplate; SignalType IIndependentAdapterManager.SignalType { get; set; } = (SignalType)Enum.Parse(typeof(SignalType), DefaultSignalType); SignalType[] IIndependentAdapterManager.SignalTypes { get; } = null; ReadOnlyCollection IIndependentAdapterManager.PerAdapterOutputNames { get; } = null; SignalType[] IIndependentAdapterManager.OutputMeasurementTypes { get; } = null; string IIndependentAdapterManager.TargetHistorianAcronym { get; set; } = DefaultTargetHistorianAcronym; RoutingTables IIndependentAdapterManager.RoutingTables { get; set; } string IIndependentAdapterManager.OriginalDataMember { get; set; } uint IIndependentAdapterManager.AdapterIDCounter { get; set; } ManualResetEventSlim IIndependentAdapterManager.ConfigurationReloadedWaitHandle { get; set; } bool IIndependentAdapterManager.AutoReparseConnectionString { get => AutoReparseConnectionString; set => AutoReparseConnectionString = value; } void IIndependentAdapterManager.OnConfigurationChanged() => OnConfigurationChanged(); void IIndependentAdapterManager.OnInputMeasurementKeysUpdated() => OnInputMeasurementKeysUpdated(); void IIndependentAdapterManager.OnStatusMessage(MessageLevel level, string status, string eventName, MessageFlags flags) => OnStatusMessage(level, status, eventName, flags); void IIndependentAdapterManager.OnProcessException(MessageLevel level, Exception exception, string eventName, MessageFlags flags) => OnProcessException(level, exception, eventName, flags); #endregion } }