//****************************************************************************************************** // IntercomRecord.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/09/2007 - Pinal C. Patel // Generated original version of code based on DatAWare system specifications by Brian B. Fox, GSF. // 04/17/2009 - Pinal C. Patel // Converted to C#. // 09/15/2009 - Stephen C. Wills // Added new header and license agreement. // 10/11/2010 - Mihir Brahmbhatt // Updated header and license agreement. // 11/30/2011 - J. Ritchie Carroll // Modified to support buffer optimized ISupportBinaryImage. // 12/14/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections.Generic; using GSF.Parsing; namespace GSF.Historian.Files { /// /// Represents a record in the that contains runtime information of a historian. /// /// public class IntercomRecord : ISupportBinaryImage { // ************************************************************************************************** // * Binary Structure * // ************************************************************************************************** // * # Of Bytes Byte Index Data Type Property Name * // * ---------- ---------- ---------- --------------------------------------------------------------* // * 4 0-3 Int32 DataBlocksUsed * // * 4 4-7 Boolean RolloverInProggress * // * 8 8-15 Double LatestDataTime * // * 4 16-19 Int32 LatestDataID * // * 160 20-179 Double(20) SourceLatestDataTime * // ************************************************************************************************** #region [ Members ] // Constants /// /// Specifies the number of bytes in the binary image of . /// public const int FixedLength = 180; // Fields private int m_recordID; private int m_dataBlocksUsed; private bool m_rolloverInProgress; private TimeTag m_latestDataTime; private int m_latestDataID; private readonly List m_sourceLatestDataTime; #endregion #region [ Constructors ] /// /// Initializes a new instance of the class. /// /// ID of the . public IntercomRecord(int recordID) { m_recordID = recordID; m_latestDataTime = TimeTag.MinValue; m_sourceLatestDataTime = new List(); for (int i = 0; i < 20; i++) { m_sourceLatestDataTime.Add(TimeTag.MinValue); } } /// /// Initializes a new instance of the class. /// /// ID of the . /// Binary image to be used for initializing . /// 0-based starting index of initialization data in the . /// Valid number of bytes in from . public IntercomRecord(int recordID, byte[] buffer, int startIndex, int length) : this(recordID) { ParseBinaryImage(buffer, startIndex, length); } #endregion #region [ Properties ] /// /// Gets or sets the number of allocated s in the active . /// /// The value being assigned is not positive or zero. public int DataBlocksUsed { get { lock (this) { return m_dataBlocksUsed; } } set { if (value < 0) throw new ArgumentException("Value must be positive or zero"); lock (this) { m_dataBlocksUsed = value; } } } /// /// Gets or sets a boolean value that indicates whether the active if being rolled-over. /// public bool RolloverInProgress { get { lock (this) { return m_rolloverInProgress; } } set { lock (this) { m_rolloverInProgress = value; } } } /// /// Gets or sets the of latest received by the active . /// public TimeTag LatestDataTime { get { lock (this) { return m_latestDataTime; } } set { lock (this) { m_latestDataTime = value; } } } /// /// Gets or sets the historian identifier of latest received by the active . /// public int LatestDataID { get { lock (this) { return m_latestDataID; } } set { lock (this) { m_latestDataID = value; } } } /// /// Gets a list of s of the latest received from each of the s. /// public IList SourceLatestDataTime { get { lock (this) { return m_sourceLatestDataTime.AsReadOnly(); } } } /// /// Gets the length of the . /// public int BinaryLength { get { return FixedLength; } } #endregion #region [ Methods ] /// /// Initializes from the specified . /// /// Binary image to be used for initializing . /// 0-based starting index of initialization data in the . /// Valid number of bytes in from . /// Number of bytes used from the for initializing . public int ParseBinaryImage(byte[] buffer, int startIndex, int length) { if (length >= FixedLength) { // Binary image has sufficient data. DataBlocksUsed = LittleEndian.ToInt32(buffer, startIndex); RolloverInProgress = LittleEndian.ToBoolean(buffer, startIndex + 4); LatestDataTime = new TimeTag((decimal)LittleEndian.ToDouble(buffer, startIndex + 8)); LatestDataID = LittleEndian.ToInt32(buffer, startIndex + 16); for (int i = 0; i < m_sourceLatestDataTime.Count; i++) { m_sourceLatestDataTime[i] = new TimeTag((decimal)LittleEndian.ToDouble(buffer, startIndex + 20 + (i * 8))); } return FixedLength; } else { // Binary image does not have sufficient data. return 0; } } /// /// Generates binary image of the and copies it into the given buffer, for bytes. /// /// Buffer used to hold generated binary image of the source object. /// 0-based starting index in the to start writing. /// The number of bytes written to the . /// is null. /// /// or is less than 0 -or- /// and will exceed length. /// public virtual int GenerateBinaryImage(byte[] buffer, int startIndex) { int length = BinaryLength; buffer.ValidateParameters(startIndex, length); lock (this) { Buffer.BlockCopy(LittleEndian.GetBytes(m_dataBlocksUsed), 0, buffer, startIndex, 4); Buffer.BlockCopy(LittleEndian.GetBytes(Convert.ToInt32(m_rolloverInProgress)), 0, buffer, startIndex + 4, 4); Buffer.BlockCopy(LittleEndian.GetBytes((double)m_latestDataTime.Value), 0, buffer, startIndex + 8, 8); Buffer.BlockCopy(LittleEndian.GetBytes(m_latestDataID), 0, buffer, startIndex + 16, 4); for (int i = 0; i < m_sourceLatestDataTime.Count; i++) { Buffer.BlockCopy(LittleEndian.GetBytes((double)m_sourceLatestDataTime[i].Value), 0, buffer, startIndex + 20 + (i * 8), 8); } } return length; } #endregion } }