3336 lines · 153.8 KB · C#
RawDownload
//******************************************************************************************************//  ServiceHostBase.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/20/2010 - J. Ritchie Carroll//       Generated original version of source code.//  01/30/2011 - Pinal C. Patel//       Updated to subscribe to new ProcessException event of MultiDestinationExporter class.//  04/21/2011 - Timothy M. Yardley / Erich A. Heine (UIUC)//       Implemented an optional, but enabled by default, non-broadcast method of directly routed//       measurement distribution as a system performance optimization.//  12/20/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Diagnostics;using System.Globalization;using System.IO;using System.Linq;using System.Reflection;using System.Runtime;using System.Security;using System.Security.Cryptography.X509Certificates;using System.ServiceProcess;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Xml;using GSF.Collections;using GSF.Communication;using GSF.Configuration;using GSF.Console;using GSF.Data;using GSF.IO;using GSF.Net.Security;using GSF.Reflection;using GSF.Security;using GSF.ServiceProcess;using GSF.Threading;using GSF.TimeSeries.Adapters;using GSF.TimeSeries.Configuration;using GSF.TimeSeries.Reports;using GSF.Units; namespace GSF.TimeSeries{    #region [ Enumerations ]     /// <summary>    /// Configuration data source type enumeration.    /// </summary>    public enum ConfigurationType    {        /// <summary>        /// Configuration source is a database.        /// </summary>        Database,        /// <summary>        /// Configuration source is a web-service.        /// </summary>        WebService,        /// <summary>        /// Configuration source is a binary file.        /// </summary>        BinaryFile,        /// <summary>        /// Configuration source is a XML file.        /// </summary>        XmlFile    }     #endregion     /// <summary>    /// Represents the time-series framework service host.    /// </summary>    public partial class ServiceHostBase : ServiceBase    {        #region [ Members ]         // Constants        private const int DefaultMinThreadPoolSize = 25;        private const int DefaultMaxThreadPoolSize = 2048;        private const int DefaultConfigurationBackups = 5;         internal event EventHandler<EventArgs<Guid, string, UpdateType>> UpdatedStatus;        internal event EventHandler<EventArgs<Exception>> LoggedException;         // Fields        private IaonSession m_iaonSession;        private string m_nodeIDQueryString;        private ConfigurationType m_configurationType;        private IConfigurationLoader m_configurationLoader;        private BinaryFileConfigurationLoader m_binaryCacheConfigurationLoader;        private XMLConfigurationLoader m_xmlCacheConfigurationLoader;        private string m_cachedXmlConfigurationFile;        private string m_cachedBinaryConfigurationFile;        private int m_configurationBackups;        private bool m_uniqueAdapterIDs;        private bool m_allowRemoteRestart;        private bool m_preferCachedConfiguration;        private MultipleDestinationExporter m_healthExporter;        private MultipleDestinationExporter m_statusExporter;        private ReportingProcessCollection m_reportingProcesses;        private ProcessQueue<Tuple<string, Action<bool>>> m_reloadConfigQueue;        private LongSynchronizedOperation m_configurationCacheOperation;        private volatile DataSet m_latestConfiguration;        private RunTimeLog m_runTimeLog;         private ServiceHelper m_serviceHelper;        private ServerBase m_remotingServer;         private bool m_disposed;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new <see cref="ServiceHostBase"/>.        /// </summary>        public ServiceHostBase()        {            InitializeComponent();            ServiceName = "IaonHost";        }         /// <summary>        /// Creates a new <see cref="ServiceHostBase"/> from specified parameters.        /// </summary>        /// <param name="container">Service host <see cref="IContainer"/>.</param>        public ServiceHostBase(IContainer container)            : this()        {            if (container != null)                container.Add(this);        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets the related remote console application name.        /// </summary>        protected virtual string ConsoleApplicationName        {            get            {                return ServiceName + "Console.exe";            }        }         /// <summary>        /// Gets access to the <see cref="GSF.ServiceProcess.ServiceHelper"/>.        /// </summary>        protected ServiceHelper ServiceHelper        {            get            {                return m_serviceHelper;            }        }         /// <summary>        /// Gets reference to the <see cref="TcpServer"/> based remoting server.        /// </summary>        protected ServerBase RemotingServer        {            get            {                return m_remotingServer;            }        }         /// <summary>        /// Gets reference to the <see cref="AllAdaptersCollection"/>.        /// </summary>        protected AllAdaptersCollection AllAdapters        {            get            {                return m_iaonSession.AllAdapters;            }        }         /// <summary>        /// Gets reference to the <see cref="InputAdapterCollection"/>.        /// </summary>        protected InputAdapterCollection InputAdapters        {            get            {                return m_iaonSession.InputAdapters;            }        }         /// <summary>        /// Gets reference to the <see cref="ActionAdapterCollection"/>.        /// </summary>        protected ActionAdapterCollection ActionAdapters        {            get            {                return m_iaonSession.ActionAdapters;            }        }         /// <summary>        /// Gets reference to the <see cref="OutputAdapterCollection"/>.        /// </summary>        protected OutputAdapterCollection OutputAdapters        {            get            {                return m_iaonSession.OutputAdapters;            }        }         /// <summary>        /// Gets the current node ID.        /// </summary>        protected Guid NodeID        {            get            {                return m_iaonSession.NodeID;            }        }         /// <summary>        /// Gets the current node ID formatted for use in a SQL query string based on <see cref="ServiceHostBase.ConfigurationType"/>.        /// </summary>        protected string NodeIDQueryString        {            get            {                return m_nodeIDQueryString;            }        }         /// <summary>        /// Gets the currently loaded system configuration <see cref="DataSet"/>.        /// </summary>        protected DataSet DataSource        {            get            {                return m_iaonSession.DataSource;            }        }         /// <summary>        /// Gets the defined system <see cref="GSF.TimeSeries.ConfigurationType"/>.        /// </summary>        protected ConfigurationType ConfigurationType        {            get            {                return m_configurationType;            }        }         #endregion         #region [ Methods ]         #region [ Service Event Handlers ]         /// <summary>        /// Event handler for service starting operations.        /// </summary>        /// <param name="sender">Event source.</param>        /// <param name="e">Event arguments containing command line arguments passed into service at startup.</param>        /// <remarks>        /// Time-series framework uses this handler to load settings from configuration file as service is starting.        /// </remarks>        protected virtual void ServiceStartingHandler(object sender, EventArgs<string[]> e)        {            // Define a run-time log            m_runTimeLog = new RunTimeLog();            m_runTimeLog.FileName = "RunTimeLog.txt";            m_runTimeLog.ProcessException += ProcessExceptionHandler;            m_runTimeLog.Initialize();             // Initialize Iaon session            m_iaonSession = new IaonSession();            m_iaonSession.StatusMessage += StatusMessageHandler;            m_iaonSession.ProcessException += ProcessExceptionHandler;            m_iaonSession.ConfigurationChanged += ConfigurationChangedHandler;             // Create a handler for unobserved task exceptions            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;             // Make sure default service settings exist            ConfigurationFile configFile = ConfigurationFile.Current;            string cachePath = string.Format("{0}{1}ConfigurationCache{1}", FilePath.GetAbsolutePath(""), Path.DirectorySeparatorChar);             // System settings            CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"];            systemSettings.Add("ConfigurationType", "Database", "Specifies type of configuration: Database, WebService, BinaryFile or XmlFile");            systemSettings.Add("ConnectionString", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=IaonHost.mdb", "Configuration database connection string");            systemSettings.Add("DataProviderString", "AssemblyName={System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089};ConnectionType=System.Data.OleDb.OleDbConnection;AdapterType=System.Data.OleDb.OleDbDataAdapter", "Configuration database ADO.NET data provider assembly type creation string");            systemSettings.Add("ConfigurationCachePath", cachePath, "Defines the path used to cache serialized configurations");            systemSettings.Add("CachedConfigurationFile", "SystemConfiguration.xml", "File name for last known good system configuration (only cached for a Database or WebService connection)");            systemSettings.Add("UniqueAdaptersIDs", "True", "Set to true if all runtime adapter ID's will be unique to allow for easier adapter specification");            systemSettings.Add("ProcessPriority", "High", "Sets desired process priority: Normal, AboveNormal, High, RealTime");            systemSettings.Add("AllowRemoteRestart", "True", "Controls ability to remotely restart the host service.");            systemSettings.Add("MinThreadPoolWorkerThreads", DefaultMinThreadPoolSize, "Defines the minimum number of allowed thread pool worker threads.");            systemSettings.Add("MaxThreadPoolWorkerThreads", DefaultMaxThreadPoolSize, "Defines the maximum number of allowed thread pool worker threads.");            systemSettings.Add("MinThreadPoolIOPortThreads", DefaultMinThreadPoolSize, "Defines the minimum number of allowed thread pool I/O completion port threads (used by socket layer).");            systemSettings.Add("MaxThreadPoolIOPortThreads", DefaultMaxThreadPoolSize, "Defines the maximum number of allowed thread pool I/O completion port threads (used by socket layer).");            systemSettings.Add("ConfigurationBackups", DefaultConfigurationBackups, "Defines the total number of older backup configurations to maintain.");            systemSettings.Add("PreferCachedConfiguration", "False", "Set to true to try the cached configuration first, before loading database configuration - typically used when cache is updated by external process.");            systemSettings.Add("LocalCertificate", string.Format("{0}.cer", ServiceName), "Path to the local certificate used by this server for authentication.");            systemSettings.Add("RemoteCertificatesPath", @"Certs\Remotes", "Path to the directory where remote certificates are stored.");            systemSettings.Add("DefaultCulture", "en-US", "Default culture to use for language, country/region and calendar formats.");             // Example connection settings            CategorizedSettingsElementCollection exampleSettings = configFile.Settings["exampleConnectionSettings"];            exampleSettings.Add("SqlServer.ConnectionString", "Data Source=serverName; Initial Catalog=databaseName; User ID=userName; Password=password", "Example SQL Server database connection string");            exampleSettings.Add("SqlServer.DataProviderString", "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.SqlClient.SqlConnection; AdapterType=System.Data.SqlClient.SqlDataAdapter", "Example SQL Server database .NET provider string");            exampleSettings.Add("MySQL.ConnectionString", "Server=serverName;Database=databaseName; Uid=root; Pwd=password; allow user variables = true;", "Example MySQL database connection string");            exampleSettings.Add("MySQL.DataProviderString", "AssemblyName={MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d}; ConnectionType=MySql.Data.MySqlClient.MySqlConnection; AdapterType=MySql.Data.MySqlClient.MySqlDataAdapter", "Example MySQL database .NET provider string");            exampleSettings.Add("Oracle.ConnectionString", "Data Source=tnsName; User ID=schemaUserName; Password=schemaPassword", "Example Oracle database connection string");            exampleSettings.Add("Oracle.DataProviderString", "AssemblyName={Oracle.DataAccess, Version=2.112.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342}; ConnectionType=Oracle.DataAccess.Client.OracleConnection; AdapterType=Oracle.DataAccess.Client.OracleDataAdapter", "Example Oracle database .NET provider string");            exampleSettings.Add("SQLite.ConnectionString", "Data Source=databaseName.db; Version=3; Foreign Keys=True; FailIfMissing=True", "Example SQLite database connection string");            exampleSettings.Add("SQLite.DataProviderString", "AssemblyName={System.Data.SQLite, Version=1.0.99.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139}; ConnectionType=System.Data.SQLite.SQLiteConnection; AdapterType=System.Data.SQLite.SQLiteDataAdapter", "Example SQLite database .NET provider string");            exampleSettings.Add("OleDB.ConnectionString", "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=databaseName.mdb", "Example Microsoft Access (via OleDb) database connection string");            exampleSettings.Add("OleDB.DataProviderString", "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.OleDb.OleDbConnection; AdapterType=System.Data.OleDb.OleDbDataAdapter", "Example OleDb database .NET provider string");            exampleSettings.Add("Odbc.ConnectionString", "Driver={SQL Server Native Client 10.0}; Server=serverName; Database=databaseName; Uid=userName; Pwd=password;", "Example ODBC database connection string");            exampleSettings.Add("Odbc.DataProviderString", "AssemblyName={System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089}; ConnectionType=System.Data.Odbc.OdbcConnection; AdapterType=System.Data.Odbc.OdbcDataAdapter", "Example ODBC database .NET provider string");            exampleSettings.Add("WebService.ConnectionString", "http://localhost/ConfigSource/SystemConfiguration.xml", "Example web service connection string");            exampleSettings.Add("XmlFile.ConnectionString", "SystemConfiguration.xml", "Example XML configuration file connection string");             // Attempt to set default culture            try            {                string defaultCulture = systemSettings["DefaultCulture"].ValueAs("en-US");                CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CreateSpecificCulture(defaultCulture);     // Defaults for date formatting, etc.                CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.CreateSpecificCulture(defaultCulture);   // Culture for resource strings, etc.            }            catch (Exception ex)            {                DisplayStatusMessage("Failed to set default culture due to exception, defaulting to \"{1}\": {0}", UpdateType.Alarm, ex.Message, CultureInfo.CurrentCulture.Name.ToNonNullNorEmptyString("Undetermined"));                LogException(ex);            }             // Retrieve configuration cache directory as defined in the config file            cachePath = FilePath.GetAbsolutePath(systemSettings["ConfigurationCachePath"].Value);             // Make sure configuration cache directory exists            try            {                if (!Directory.Exists(cachePath))                    Directory.CreateDirectory(cachePath);            }            catch (Exception ex)            {                DisplayStatusMessage("Failed to create configuration cache directory due to exception: {0}", UpdateType.Alarm, ex.Message);                LogException(ex);            }             try            {                Directory.SetCurrentDirectory(FilePath.GetAbsolutePath(""));            }            catch (Exception ex)            {                DisplayStatusMessage("Failed to set current directory to execution path due to exception: {0}", UpdateType.Alarm, ex.Message);                LogException(ex);            }             // Initialize system settings            m_configurationType = systemSettings["ConfigurationType"].ValueAs<ConfigurationType>();            m_cachedXmlConfigurationFile = FilePath.AddPathSuffix(cachePath) + systemSettings["CachedConfigurationFile"].Value;            m_cachedBinaryConfigurationFile = FilePath.AddPathSuffix(cachePath) + FilePath.GetFileNameWithoutExtension(m_cachedXmlConfigurationFile) + ".bin";            m_configurationBackups = systemSettings["ConfigurationBackups"].ValueAs(DefaultConfigurationBackups);            m_uniqueAdapterIDs = systemSettings["UniqueAdaptersIDs"].ValueAsBoolean(true);            m_allowRemoteRestart = systemSettings["AllowRemoteRestart"].ValueAsBoolean(true);            m_preferCachedConfiguration = systemSettings["PreferCachedConfiguration"].ValueAsBoolean(false);             m_reloadConfigQueue = ProcessQueue<Tuple<string, Action<bool>>>.CreateSynchronousQueue(ExecuteReloadConfig, 500.0D, Timeout.Infinite, false, false);            m_reloadConfigQueue.ProcessException += m_iaonSession.ProcessExceptionHandler;             m_configurationCacheOperation = new LongSynchronizedOperation(ExecuteConfigurationCache)            {                IsBackground = true            };             // Setup default thread pool size            try            {                ThreadPool.SetMinThreads(systemSettings["MinThreadPoolWorkerThreads"].ValueAs(DefaultMinThreadPoolSize), systemSettings["MinThreadPoolIOPortThreads"].ValueAs(DefaultMinThreadPoolSize));                ThreadPool.SetMaxThreads(systemSettings["MaxThreadPoolWorkerThreads"].ValueAs(DefaultMaxThreadPoolSize), systemSettings["MaxThreadPoolIOPortThreads"].ValueAs(DefaultMaxThreadPoolSize));            }            catch (Exception ex)            {                DisplayStatusMessage("Failed to set desired thread pool size due to exception: {0}", UpdateType.Alarm, ex.Message);                LogException(ex);            }             // Define guid with query string delimiters according to database needs            if (string.IsNullOrWhiteSpace(m_nodeIDQueryString))                m_nodeIDQueryString = "'" + m_iaonSession.NodeID + "'";             // Set up the configuration loader            switch (m_configurationType)            {                case ConfigurationType.Database:                    m_configurationLoader = new DatabaseConfigurationLoader                    {                        ConnectionString = systemSettings["ConnectionString"].Value,                        DataProviderString = systemSettings["DataProviderString"].Value,                        NodeIDQueryString = m_nodeIDQueryString                    };                     break;                 case ConfigurationType.WebService:                    m_configurationLoader = new WebServiceConfigurationLoader                    {                        URI = systemSettings["ConnectionString"].Value                    };                     break;                 case ConfigurationType.BinaryFile:                    m_configurationLoader = new BinaryFileConfigurationLoader                    {                        FilePath = systemSettings["ConnectionString"].Value                    };                     break;                 case ConfigurationType.XmlFile:                    m_configurationLoader = new XMLConfigurationLoader                    {                        FilePath = systemSettings["ConnectionString"].Value                    };                     break;            }             m_binaryCacheConfigurationLoader = new BinaryFileConfigurationLoader            {                FilePath = m_cachedBinaryConfigurationFile            };             m_xmlCacheConfigurationLoader = new XMLConfigurationLoader            {                FilePath = m_cachedXmlConfigurationFile            };             m_configurationLoader.StatusMessage += (o, args) => DisplayStatusMessage(args.Argument, UpdateType.Information);            m_binaryCacheConfigurationLoader.StatusMessage += (o, args) => DisplayStatusMessage(args.Argument, UpdateType.Information);            m_xmlCacheConfigurationLoader.StatusMessage += (o, args) => DisplayStatusMessage(args.Argument, UpdateType.Information);             m_configurationLoader.ProcessException += ConfigurationLoader_ProcessException;            m_binaryCacheConfigurationLoader.ProcessException += ConfigurationLoader_ProcessException;            m_xmlCacheConfigurationLoader.ProcessException += ConfigurationLoader_ProcessException;             m_reloadConfigQueue.Start(); #if !MONO            try            {                // Attempt to assign desired process priority. Note that process will require SeIncreaseBasePriorityPrivilege or                 // Administrative privileges to make this change                Process.GetCurrentProcess().PriorityClass = systemSettings["ProcessPriority"].ValueAs<ProcessPriorityClass>();            }            catch (Exception ex)            {                LogException(ex);            }#endif        }         /// <summary>        /// Event handler for service started operation.        /// </summary>

Lines 1–500 of 3336.

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