600 lines · 21.9 KB · C#
RawDownload
//******************************************************************************************************//  MetadataFile.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://  ----------------------------------------------------------------------------------------------------//  03/08/2007 - Pinal C. Patel//       Generated original version of source code.//  04/21/2009 - Pinal C. Patel//       Converted to C#.//  09/03/2009 - Pinal C. Patel//       Added Read() overload that takes string as its parameter for performing flexible reads.//  09/15/2009 - Stephen C. Wills//       Added new header and license agreement.//  09/16/2009 - Pinal C. Patel//       Changed the default value for SettingsCategory property to the type name.//  10/11/2010 - Mihir Brahmbhatt//       Updated header and license agreement.//  12/14/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Generic;using System.Configuration;using System.Drawing;using System.IO;using System.Linq;using System.Text;using GSF.Configuration;using GSF.IO; namespace GSF.Historian.Files{    /// <summary>    /// Defines legacy operational modes for the <see cref="MetadataFile"/>.    /// </summary>    public enum MetadataFileLegacyMode    {        /// <summary>        /// Only use new "..._dbase.dat2" format.        /// </summary>        Disabled,        /// <summary>        /// Use new "..._dbase.dat2" format and also maintain a legacy "..._dbase.dat" file.        /// </summary>        Compatible,        /// <summary>        /// Only use legacy "..._dbase.dat" file.        /// </summary>        Enabled    }     /// <summary>    /// Represents a file containing <see cref="MetadataRecord"/>s.    /// </summary>    /// <seealso cref="MetadataRecord"/>    [ToolboxBitmap(typeof(MetadataFile))]    public class MetadataFile : IsamDataFileBase<MetadataRecord>    {        #region [ Members ]         // Nested Types        private class LegacyMetadataFile : IsamDataFileBase<MetadataRecord>        {            #region [ Constructors ]             /// <summary>            /// Creates a new <see cref="LegacyMetadataFile"/>.            /// </summary>            /// <param name="fileName">Legacy file name.</param>            public LegacyMetadataFile(string fileName)            {                FileName = fileName;                FileAccessMode = FileAccess.Write;            }             #endregion             #region [ Methods ]             /// <summary>            /// Gets the binary size of a <see cref="MetadataRecord"/>.            /// </summary>            /// <returns>A 32-bit signed integer.</returns>            protected override int GetRecordSize()            {                return MetadataRecord.FixedLength;            }             /// <summary>            /// Creates a new <see cref="MetadataRecord"/> with the specified <paramref name="recordIndex"/>.            /// </summary>            /// <param name="recordIndex">1-based index of the <see cref="MetadataRecord"/>.</param>            /// <returns>A <see cref="MetadataRecord"/> object.</returns>            protected override MetadataRecord CreateNewRecord(int recordIndex)            {                return new MetadataRecord(recordIndex, MetadataFileLegacyMode.Enabled);            }             #endregion        }         // Fields        private MetadataFileLegacyMode m_legacyMode;        private string m_baseFileName;        private readonly Dictionary<int, MetadataRecord> m_records;         #endregion         #region [ Constructors ]         /// <summary>        /// Initializes a new instance of the <see cref="MetadataFile"/> class.        /// </summary>        public MetadataFile()        {            SettingsCategory = this.GetType().Name;            m_legacyMode = MetadataFileLegacyMode.Disabled;  // Default to only using new file format            m_records = new Dictionary<int, MetadataRecord>();        }         #endregion         #region [ Properties ]         /// <summary>        /// Determines legacy operation mode for the <see cref="MetadataFile"/>.        /// </summary>        public MetadataFileLegacyMode LegacyMode        {            get            {                return m_legacyMode;            }            set            {                if (m_legacyMode != value)                {                    m_legacyMode = value;                     if (m_legacyMode == MetadataFileLegacyMode.Enabled)                        m_records.Clear();                }            }        }         /// <summary>        /// Gets or sets the name of the file.        /// </summary>        /// <remarks>        /// Changing the <see cref="IsamDataFileBase{T}.FileName"/> when the file is open will cause the file to be re-opened.        /// </remarks>        public override string FileName        {            get            {                return base.FileName;            }            set            {                base.FileName = value;                 if ((object)value == null)                {                    m_baseFileName = null;                }                else                {                    if (value.EndsWith("2"))                        m_baseFileName = value.Substring(0, value.Length - 1);                    else                        m_baseFileName = value;                }            }        }         /// <summary>        /// Gets a boolean value that indicates whether the file data on disk is corrupt.        /// </summary>        public override bool IsCorrupt        {            get            {                if (m_legacyMode == MetadataFileLegacyMode.Enabled)                    return base.IsCorrupt;                 return false;            }        }         /// <summary>        /// Gets the number of file records on the disk.        /// </summary>        public override int RecordsOnDisk        {            get            {                if (m_legacyMode == MetadataFileLegacyMode.Enabled)                    return base.RecordsOnDisk;                 // Difficult to calculate with variable length strings, so we just return count in memory                return RecordsInMemory;            }        }         /// <summary>        /// Gets the number of file records loaded in memory.        /// </summary>        public override int RecordsInMemory        {            get            {                if (m_legacyMode == MetadataFileLegacyMode.Enabled)                    return base.RecordsInMemory;                 return m_records.Keys.DefaultIfEmpty(0).Max();            }        }         /// <summary>        /// Gets the descriptive status of the <see cref="MetadataFile"/>.        /// </summary>        public override string Status        {            get            {                StringBuilder status = new StringBuilder();                 status.Append(base.Status);                status.AppendFormat("     Legacy operation mode: {0}", m_legacyMode);                status.AppendLine();                 return status.ToString();            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Saves settings of the file to the config file if the <see cref="IsamDataFileBase{T}.PersistSettings"/> property is set to true.        /// </summary>        /// <exception cref="ConfigurationErrorsException"><see cref="IsamDataFileBase{T}.SettingsCategory"/> has a value of null or empty string.</exception>        public override void SaveSettings()        {            if (PersistSettings)            {                base.SaveSettings();                 // Save settings under the specified category.                ConfigurationFile config = ConfigurationFile.Current;                CategorizedSettingsElementCollection settings = config.Settings[SettingsCategory];                settings["LegacyMode", true].Update(m_legacyMode);                config.Save();            }        }         /// <summary>        /// Loads saved settings of the file from the config file if the <see cref="IsamDataFileBase{T}.PersistSettings"/> property is set to true.        /// </summary>        /// <exception cref="ConfigurationErrorsException"><see cref="IsamDataFileBase{T}.SettingsCategory"/> has a value of null or empty string.</exception>        public override void LoadSettings()        {            if (PersistSettings)            {                base.LoadSettings();                 // Load settings from the specified category.                CategorizedSettingsElementCollection settings = ConfigurationFile.Current.Settings[SettingsCategory];                settings.Add("LegacyMode", m_legacyMode, "Metadata file legacy format mode. Value is one of \"Disabled\", \"Compatible\" or \"Enabled\" where \"Disabled\" means only use new format, \"Compatible\" means use new format and also write a legacy format file for compatibility and \"Enabled\" means only use the legacy format.");                LegacyMode = settings["LegacyMode"].ValueAs(m_legacyMode);                 // Define new file name for non-legacy implementations                if (m_legacyMode != MetadataFileLegacyMode.Enabled && !FileName.EndsWith("2"))                    FileName += "2";                 // By design of the new metadata file format, data is always loaded into memory - regardless of configuration setting                if (m_legacyMode != MetadataFileLegacyMode.Enabled)                    LoadOnOpen = true;            }        }         /// <summary>        /// Reads <see cref="MetadataRecord"/>s that matches the <paramref name="searchPattern"/>.        /// </summary>        /// <param name="searchPattern">Comma or semi-colon delimited list of IDs or text for which the matching <see cref="MetadataRecord"/>s are to be retrieved.</param>        /// <returns>An <see cref="IEnumerable{T}"/> object of <see cref="MetadataRecord"/>.</returns>        public IEnumerable<MetadataRecord> Read(string searchPattern)        {            int id;            foreach (string searchPart in searchPattern.Split(',', ';'))            {                // Iterate through all parts.                if (int.TryParse(searchPattern, out id))                {                    // Exact id is specified.                    yield return Read(id);                }                else                {                    // Text is specified, so search for matches.                    foreach (MetadataRecord record in Read())                    {                        if (record.Name.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0 ||                            record.Synonym1.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0 ||                            record.Synonym2.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0 ||                            record.Synonym3.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0 ||                            record.Description.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0 ||                            record.Remarks.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0 ||                            record.HardwareInfo.IndexOf(searchPart, StringComparison.CurrentCultureIgnoreCase) >= 0)                        {                            yield return record;                        }                    }                }            }        }         /// <summary>        /// Opens the file.        /// </summary>        public override void Open()        {            // Handle special cases for readers            if (!PersistSettings || FileAccessMode == FileAccess.Read)            {                // Need to fall back on using old file format if a new one doesn't exist for historical reads                if (!File.Exists(FileName) && !string.IsNullOrEmpty(m_baseFileName) && File.Exists(m_baseFileName))                    base.FileName = m_baseFileName;                 // Use new file format if a newer one exists                if (m_legacyMode != MetadataFileLegacyMode.Enabled && !FileName.EndsWith("2") && File.Exists(FileName + "2"))                    FileName += "2";                 // Fall back on legacy mode if needed                if (!FileName.EndsWith("2") && File.Exists(FileName))                    m_legacyMode = MetadataFileLegacyMode.Enabled;            }             base.Open();        }         /// <summary>        /// Loads records from disk into memory.        /// </summary>        public override void Load()        {            if (m_legacyMode == MetadataFileLegacyMode.Enabled)            {                base.Load();                return;            }             if (!IsOpen)                throw new InvalidOperationException(string.Format("MetadataFile \"{0}\" is not open", FileName));             // Waits for any pending request to save records before completing.            SaveWaitHandle.Wait();             // Waits for any prior request to load records before completing.            LoadWaitHandle.Wait();            LoadWaitHandle.Reset();             try            {                OnDataLoading();                 lock (FileDataLock)                {                    if (FileData.Length > 0)                    {                        FileData.Seek(0, SeekOrigin.Begin);                        BinaryReader reader = new BinaryReader(FileData);                        int count = reader.ReadInt32();                         for (int i = 0; i < count; i++)                        {                            MetadataRecord record = new MetadataRecord(reader);                            m_records[record.HistorianID] = record;                        }                    }                }                 OnDataLoaded();            }            finally            {                LoadWaitHandle.Set();            }        }         /// <summary>        /// Reads file records from disk if records were not loaded in memory otherwise returns the records in memory.        /// </summary>        /// <returns>Records of the file.</returns>        public override IEnumerable<MetadataRecord> Read()        {            if (m_legacyMode == MetadataFileLegacyMode.Enabled)            {                foreach (MetadataRecord record in base.Read())                {                    yield return record;                }            }             if (!IsOpen)                throw new InvalidOperationException(string.Format("MetadataFile \"{0}\" is not open", FileName));             foreach (MetadataRecord record in m_records.Values)            {                yield return record;            }        }         /// <summary>        /// Reads specified file record from disk if records were not loaded in memory otherwise returns the record in memory.        /// </summary>        /// <param name="recordIndex">1-based index of the record to be read.</param>        /// <returns>Record with the specified ID if it exists; otherwise null.</returns>        public override MetadataRecord Read(int recordIndex)        {            if (m_legacyMode == MetadataFileLegacyMode.Enabled)                return base.Read(recordIndex);             if (!IsOpen)                throw new InvalidOperationException(string.Format("MetadataFile \"{0}\" is not open", FileName));             MetadataRecord record;             if (m_records.TryGetValue(recordIndex, out record))                return record;             // For compatibility with legacy mode, return a blank record if index is less than max            if (recordIndex < m_records.Keys.Max())                return new MetadataRecord(recordIndex, m_legacyMode);             return null;        }         /// <summary>        /// Saves records loaded in memory to disk.        /// </summary>        /// <remarks>        /// <see cref="IsamDataFileBase{T}.Save"/> is equivalent to <see cref="FileStream.Flush()"/> when records are not loaded in memory.        /// </remarks>        public override void Save()        {            if (m_legacyMode == MetadataFileLegacyMode.Enabled)                base.Save();             if (m_legacyMode == MetadataFileLegacyMode.Compatible)                SaveLegacyMetadataFile();             if (m_legacyMode == MetadataFileLegacyMode.Disabled || m_legacyMode == MetadataFileLegacyMode.Compatible)            {                if (!IsOpen)                    throw new InvalidOperationException(string.Format("MetadataFile \"{0}\" is not open", FileName));                 // Waits for any pending request to save records before completing.                SaveWaitHandle.Wait();                 // Waits for any prior request to load records before completing.                LoadWaitHandle.Wait();                SaveWaitHandle.Reset();                 try                {                    OnDataSaving();                     lock (FileDataLock)                    {                        FileData.SetLength(0);                        BinaryWriter writer = new BinaryWriter(FileData);                        writer.Write(m_records.Count);                         foreach (MetadataRecord record in m_records.Values)                        {                            record.WriteImage(writer);                        }                         FileData.Flush();                        File.SetLastWriteTime(FileName, DateTime.Now);                    }                     OnDataSaved();

Lines 1–500 of 600.

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