311 lines · 13.9 KB · C#
RawDownload
//******************************************************************************************************//  ConfigurationFrame.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://  ----------------------------------------------------------------------------------------------------//  05/05/2009 - J. Ritchie Carroll//       Generated original version of source code.//  09/15/2009 - Stephen C. Wills//       Added new header and license agreement.//  12/20/2011 - J. Ritchie Carroll//       Updated configuration caching algorithm to create multiple backup configurations.//  12/17/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.IO;using System.Linq;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters;using System.Runtime.Serialization.Formatters.Soap;using GSF.Collections;using GSF.Configuration;using GSF.IO;using GSF.IO.Checksums;using GSF.Threading; namespace GSF.PhasorProtocols.Anonymous{    /// <summary>    /// Represents a protocol independent implementation of a <see cref="IConfigurationFrame"/> that can be sent or received.    /// </summary>    [Serializable]    public class ConfigurationFrame : ConfigurationFrameBase    {        #region [ Constructors ]         /// <summary>        /// Creates a new <see cref="ConfigurationFrame"/> from specified parameters.        /// </summary>        /// <param name="idCode">The ID code of this <see cref="ConfigurationFrame"/>.</param>        /// <param name="timestamp">The exact timestamp, in <see cref="Ticks"/>, of the data represented by this <see cref="ConfigurationFrame"/>.</param>        /// <param name="frameRate">The defined frame rate of this <see cref="ConfigurationFrame"/>.</param>        public ConfigurationFrame(ushort idCode, Ticks timestamp, ushort frameRate)            : base(idCode, new ConfigurationCellCollection(), timestamp, frameRate)        {        }         /// <summary>        /// Creates a new <see cref="ConfigurationFrame"/> from serialization parameters.        /// </summary>        /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param>        /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param>        protected ConfigurationFrame(SerializationInfo info, StreamingContext context)            : base(info, context)        {        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets reference to the <see cref="ConfigurationCellCollection"/> for this <see cref="ConfigurationFrame"/>.        /// </summary>        public new ConfigurationCellCollection Cells => base.Cells as ConfigurationCellCollection;         /// <summary>        /// Gets or sets name of this configuration frame as assigned or useful in an end-use context.        /// </summary>        public virtual string Name { get; set; }         #endregion         #region [ Methods ]         /// <summary>        /// Calculates checksum of given <paramref name="buffer"/>.        /// </summary>        /// <param name="buffer">Buffer image over which to calculate checksum.</param>        /// <param name="offset">Start index into <paramref name="buffer"/> to calculate checksum.</param>        /// <param name="length">Length of data within <paramref name="buffer"/> to calculate checksum.</param>        /// <returns>Checksum over specified portion of <paramref name="buffer"/>.</returns>        protected override ushort CalculateChecksum(byte[] buffer, int offset, int length)        {            // Just returning calculated CRC-CCITT over given buffer as a default CRC            return buffer.CrcCCITTChecksum(offset, length);        }         #endregion         #region [ Static ]         // Static Fields        private static readonly ProcessQueue<Tuple<IConfigurationFrame, Action<Exception>, string>> s_configurationCacheQueue;        private static string s_configurationCachePath;        private static int s_configurationBackups;         // Static Constructor        static ConfigurationFrame()        {            s_configurationBackups = -1;            s_configurationCacheQueue = ProcessQueue<Tuple<IConfigurationFrame, Action<Exception>, string>>.CreateRealTimeQueue(CacheConfigurationFile);            s_configurationCacheQueue.SynchronizedOperationType = SynchronizedOperationType.LongBackground;            s_configurationCacheQueue.Start();        }         // Static Properties         /// <summary>        /// Gets the path for storing serialized phasor protocol configurations.        /// </summary>        public static string ConfigurationCachePath        {            get            {                // This property will not change during system life-cycle so we cache if for future use                if (string.IsNullOrEmpty(s_configurationCachePath))                {                    // Define default configuration cache directory relative to path of host application                    s_configurationCachePath = string.Format("{0}{1}ConfigurationCache{1}", FilePath.GetAbsolutePath(""), Path.DirectorySeparatorChar);                     // Make sure configuration cache path setting exists within system settings section of config file                    ConfigurationFile configFile = ConfigurationFile.Current;                    CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"];                    systemSettings.Add("ConfigurationCachePath", s_configurationCachePath, "Defines the path used to cache serialized phasor protocol configurations");                     // Retrieve configuration cache directory as defined in the config file                    s_configurationCachePath = FilePath.AddPathSuffix(systemSettings["ConfigurationCachePath"].Value);                     // Make sure configuration cache directory exists                    if (!Directory.Exists(s_configurationCachePath))                        Directory.CreateDirectory(s_configurationCachePath);                }                 return s_configurationCachePath;            }        }         /// <summary>        /// Gets total number of configuration backups to keep when storing serialized phasor protocol configurations.        /// </summary>        public static int ConfigurationBackups        {            get            {                if (s_configurationBackups == -1)                {                    const int DefaultConfigurationBackups = 5;                     // Make sure configuration backups setting exists within system settings section of config file                    ConfigurationFile configFile = ConfigurationFile.Current;                    CategorizedSettingsElementCollection systemSettings = configFile.Settings["systemSettings"];                    systemSettings.Add("ConfigurationBackups", DefaultConfigurationBackups, "Defines the total number of older backup configurations to maintain.");                     // Retrieve configuration backups value as defined in the config file                    s_configurationBackups = systemSettings["ConfigurationBackups"].ValueAs(DefaultConfigurationBackups);                }                 return s_configurationBackups;            }        }         // Static Methods         /// <summary>        /// Serializes configuration frame to cache folder on an independent thread for later use (if needed).        /// </summary>        /// <param name="configurationFrame">Reference to <see cref="IConfigurationFrame"/>.</param>        /// <param name="exceptionHandler"><see cref="Action{T}"/> delegate to handle process exceptions.</param>        /// <param name="configurationName"><see cref="string"/> representing the configuration name.</param>        public static void Cache(IConfigurationFrame configurationFrame, Action<Exception> exceptionHandler, string configurationName)        {            Tuple<IConfigurationFrame, Action<Exception>, string> cacheState = new(configurationFrame, exceptionHandler, configurationName);            s_configurationCacheQueue.Add(cacheState);        }         // Cache configuration file        private static void CacheConfigurationFile(Tuple<IConfigurationFrame, Action<Exception>, string> args)        {            if (args is null)                return;             FileStream configFile = null;            IConfigurationFrame configurationFrame = args.Item1;            Action<Exception> exceptionHandler = args.Item2;            string configurationName = args.Item3;            string configurationCacheFileName = GetConfigurationCacheFileName(configurationName);             try            {                // Create multiple backup configurations, if requested                for (int i = ConfigurationBackups; i > 0; i--)                {                    string origConfigFile = $"{configurationCacheFileName}.backup{(i == 1 ? "" : (i - 1).ToString())}";                     if (File.Exists(origConfigFile))                    {                        string nextConfigFile = $"{configurationCacheFileName}.backup{i}";                         if (File.Exists(nextConfigFile))                            File.Delete(nextConfigFile);                         File.Move(origConfigFile, nextConfigFile);                    }                }            }            catch (Exception ex)            {                exceptionHandler(new InvalidOperationException($"Failed to create extra backup serialized configuration frames due to exception: {ex.Message}"));            }             try            {                if (ConfigurationBackups > 0)                {                    // Back up current configuration file, if any                    if (File.Exists(configurationCacheFileName))                    {                        string backupConfigFile = $"{configurationCacheFileName}.backup";                         if (File.Exists(backupConfigFile))                            File.Delete(backupConfigFile);                         File.Move(configurationCacheFileName, backupConfigFile);                    }                }            }            catch (Exception ex)            {                exceptionHandler(new InvalidOperationException($"Failed to backup last serialized configuration frame due to exception: {ex.Message}"));            }             try            {                // Serialize configuration frame to a file                SoapFormatter xmlSerializer = new()                {                    AssemblyFormat = FormatterAssemblyStyle.Simple,                    TypeFormat = FormatterTypeStyle.TypesWhenNeeded                };                 configFile = File.Create(configurationCacheFileName);                xmlSerializer.Serialize(configFile, configurationFrame);            }            catch (Exception ex)            {                exceptionHandler(new InvalidOperationException($"Failed to serialize configuration frame: {ex.Message}", ex));            }            finally            {                configFile?.Close();            }        }         /// <summary>        /// Gets the file name with path of the specified <paramref name="configurationName"/>.        /// </summary>        /// <param name="configurationName">Name of the configuration to get file name for.</param>        /// <returns>File name with path of the specified <paramref name="configurationName"/>.</returns>        public static string GetConfigurationCacheFileName(string configurationName)        {            return $"{ConfigurationCachePath}{configurationName.ReplaceCharacters('_', c => Path.GetInvalidFileNameChars().Contains(c))}.configuration.xml";        }         /// <summary>        /// Deletes the cached configuration, if defined.        /// </summary>        /// <param name="configurationName">Name of the configuration to delete.</param>        public static void DeleteCachedConfiguration(string configurationName)        {            string configFileName = GetConfigurationCacheFileName(configurationName);             if (File.Exists(configFileName))                File.Delete(configFileName);        }         /// <summary>        /// Deserializes cached configuration, if available.        /// </summary>        /// <param name="configurationName">Name of the configuration to get file name for.</param>        /// <param name="fromCache">Set to True retrieve from cache, False to retrieve from specified file name in <paramref name="configurationName"/></param>        /// <returns>Cached configuration frame, or null if not available.</returns>        public static IConfigurationFrame GetCachedConfiguration(string configurationName, bool fromCache)        {            IConfigurationFrame configFrame = null;            string configFileName = fromCache ? GetConfigurationCacheFileName(configurationName) : configurationName;             if (File.Exists(configFileName))                configFrame = Common.DeserializeConfigurationFrame(configFileName);             return configFrame;        }         #endregion    }}

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