//******************************************************************************************************
// Frame.cs - Gbtc
//
// Copyright © 2010, 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 Eclipse Public License -v 1.0 (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/eclipse-1.0.php
//
// 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.
//
//******************************************************************************************************
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 ConcurrentDictionary m_measurements; // Concurrent dictionary of measurements published by this frame
private IMeasurement m_lastSortedMeasurement; // Last measurement sorted into this frame
#endregion
#region [ Constructors ]
public Frame(Ticks timestamp)
: this(timestamp, -1)
{
}
///
/// Constructs a new given the specified parameters.
///
/// Timestamp, in ticks, for this .
/// Expected number of measurements for the .
public Frame(Ticks timestamp, int expectedMeasurements)
{
m_timestamp = timestamp;
#if UseHighResolutionTime
m_receivedTimestamp = PrecisionTimer.UtcNow.Ticks;
#else
m_receivedTimestamp = DateTime.UtcNow.Ticks;
#endif
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;
#if UseHighResolutionTime
m_receivedTimestamp = PrecisionTimer.UtcNow.Ticks;
#else
m_receivedTimestamp = DateTime.UtcNow.Ticks;
#endif
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
}
}