//****************************************************************************************************** // Frame.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: // ---------------------------------------------------------------------------------------------------- // 09/02/2010 - J. Ritchie Carroll // Generated original version of source code. // 04/14/2011 - J. Ritchie Carroll // Added received and published timestamps for measurements. // 05/11/2011 - J. Ritchie Carroll // Updated to use a concurrent dictionary. // 12/20/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections.Concurrent; using System.Collections.Generic; namespace GSF.TimeSeries { /// /// Implementation of a basic . /// /// /// A frame represents a collection of measurements at a given time. /// public class Frame : IFrame { #region [ Members ] // Fields private Ticks m_timestamp; // Time, represented as 100-nanosecond ticks, of this frame of data private Ticks m_receivedTimestamp; // Time, represented as 100-nanosecond ticks, of frame received (i.e. created) private Ticks m_publishedTimestamp; // Time, represented as 100-nanosecond ticks, of frame published (post process) private bool m_published; // Determines if this frame of data has been published private int m_sortedMeasurements; // Total measurements sorted into this frame private readonly ConcurrentDictionary m_measurements; // Concurrent dictionary of measurements published by this frame private IMeasurement m_lastSortedMeasurement; // Last measurement sorted into this frame #endregion #region [ Constructors ] /// /// Constructs a new given the specified parameters. /// /// Timestamp, in ticks, for this . /// Expected number of measurements for the . public Frame(Ticks timestamp, int expectedMeasurements = -1) { m_timestamp = timestamp; m_receivedTimestamp = DateTime.UtcNow.Ticks; if (expectedMeasurements > 0) m_measurements = new ConcurrentDictionary(s_defaultConcurrencyLevel, expectedMeasurements * 2); else m_measurements = new ConcurrentDictionary(); m_sortedMeasurements = -1; } /// /// Constructs a new given the specified parameters. /// /// Timestamp, in ticks, for this . /// Initial set of measurements to load into the , if any. public Frame(Ticks timestamp, IDictionary measurements) { m_timestamp = timestamp; m_receivedTimestamp = DateTime.UtcNow.Ticks; m_measurements = new ConcurrentDictionary(measurements); m_sortedMeasurements = -1; } #endregion #region [ Properties ] /// /// Keyed measurements in this . /// public ConcurrentDictionary Measurements { get { return m_measurements; } } /// /// Gets or sets published state of this (pre-processing). /// public bool Published { get { return m_published; } set { m_published = value; } } /// /// Gets or sets total number of measurements that have been sorted into this . /// /// /// If this property has not been assigned a value, the property will return measurement count. /// public int SortedMeasurements { get { if (m_sortedMeasurements == -1) return m_measurements.Count; return m_sortedMeasurements; } set { m_sortedMeasurements = value; } } /// /// Gets or sets exact timestamp, in , of the data represented in this . /// /// /// The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. /// public virtual Ticks Timestamp { get { return m_timestamp; } set { m_timestamp = value; } } /// /// Gets or sets exact timestamp, in ticks, of when this was received (i.e., created). /// /// /// In the default implementation, this timestamp will simply be the ticks of of when this class was created. /// The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. /// public Ticks ReceivedTimestamp { get { return m_receivedTimestamp; } set { m_receivedTimestamp = value; } } /// /// Gets or sets exact timestamp, in ticks, of when this was published (post-processing). /// /// /// In the default implementation, setting this property will update all associated . /// The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. /// public Ticks PublishedTimestamp { get { return m_publishedTimestamp; } set { m_publishedTimestamp = value; if (m_measurements != null) { foreach (IMeasurement measurement in m_measurements.Values) { measurement.PublishedTimestamp = m_publishedTimestamp; } } } } /// /// Gets or sets reference to last measurement that was sorted into this . /// public IMeasurement LastSortedMeasurement { get { return m_lastSortedMeasurement; } set { m_lastSortedMeasurement = value; } } #endregion #region [ Methods ] /// /// Create a copy of this and its measurements. /// /// /// The measurement dictionary of this is synclocked during copy. /// /// A cloned . public virtual Frame Clone() { lock (m_measurements) { return new Frame(m_timestamp, m_measurements); } } /// /// Determines whether the specified is equal to the current . /// /// The to compare with the current . /// /// true if the specified is equal to the current ; /// otherwise, false. /// public bool Equals(IFrame other) { return (CompareTo(other) == 0); } /// /// Determines whether the specified is equal to the current . /// /// The to compare with the current . /// /// true if the specified is equal to the current ; /// otherwise, false. /// public override bool Equals(object obj) { IFrame other = obj as IFrame; if ((object)other != null) return Equals(other); return false; } /// /// Compares the with an . /// /// The to compare with the current . /// A 32-bit signed integer that indicates the relative order of the objects being compared. /// This implementation of a basic frame compares itself by timestamp. public int CompareTo(IFrame other) { if ((object)other != null) return m_timestamp.CompareTo(other.Timestamp); return 1; } /// /// Compares the with the specified . /// /// The to compare with the current . /// A 32-bit signed integer that indicates the relative order of the objects being compared. /// is not an . /// This implementation of a basic frame compares itself by timestamp. public int CompareTo(object obj) { IFrame other = obj as IFrame; if ((object)other != null) return CompareTo(other); throw new ArgumentException("Frame can only be compared with other IFrames"); } /// /// Serves as a hash function for the current . /// /// A hash code for the current . /// Hash code based on timestamp of frame. public override int GetHashCode() { return m_timestamp.GetHashCode(); } #endregion #region [ Operators ] /// /// Compares two timestamps for equality. /// /// The left hand operand. /// The right hand operand. /// A representing the result of the operation. public static bool operator ==(Frame frame1, Frame frame2) { if ((object)frame1 != null) return frame1.Equals(frame2); return ((object)frame2 == null); } /// /// Compares two timestamps for inequality. /// /// The left hand operand. /// The right hand operand. /// A representing the result of the operation. public static bool operator !=(Frame frame1, Frame frame2) { if ((object)frame1 != null) return !frame1.Equals(frame2); return ((object)frame2 != null); } /// /// Returns true if left timestamp is greater than right timestamp. /// /// The left hand operand. /// The right hand operand. /// A representing the result of the operation. public static bool operator >(Frame frame1, Frame frame2) { if ((object)frame1 != null) return frame1.CompareTo(frame2) > 0; return false; } /// /// Returns true if left timestamp is greater than or equal to right timestamp. /// /// The left hand operand. /// The right hand operand. /// A representing the result of the operation. public static bool operator >=(Frame frame1, Frame frame2) { if ((object)frame1 != null) return frame1.CompareTo(frame2) >= 0; return ((object)frame2 == null); } /// /// Returns true if left timestamp is less than right timestamp. /// /// The left hand operand. /// The right hand operand. /// A representing the result of the operation. public static bool operator <(Frame frame1, Frame frame2) { if ((object)frame1 != null) return frame1.CompareTo(frame2) < 0; return false; } /// /// Returns true if left timestamp is less than or equal to right timestamp. /// /// The left hand operand. /// The right hand operand. /// A representing the result of the operation. public static bool operator <=(Frame frame1, Frame frame2) { if ((object)frame1 != null) return frame1.CompareTo(frame2) <= 0; return ((object)frame2 == null); } #endregion #region [ Static ] // Static Fields private static readonly int s_defaultConcurrencyLevel = Environment.ProcessorCount * 4; #endregion } }