//******************************************************************************************************
// DataPointScanner.cs - Gbtc
//
// Copyright © 2014, 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/22/2014 - Stephen C. Wills
// Extracted from the TimeSortedDataPointScanner (now the TimeSortedArchiveFileScanner).
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
namespace GSF.Historian.Files
{
///
/// Scans an archive file for a given signal's data points over a given time range.
///
internal class DataPointScanner
{
#region [ Members ]
// Fields
private readonly List m_dataBlocks;
private readonly TimeTag m_startTime;
private readonly TimeTag m_endTime;
private readonly int m_historianID;
private readonly bool m_includeStartTime;
private readonly EventHandler> m_dataReadExceptionHandler;
#endregion
#region [ Constructors ]
///
/// Creates a new instance.
///
/// for the file to be scanned.
/// Historian ID to scan for.
/// Desired start time.
/// Desired end time.
/// True to include data points equal to the start time; false to exclude.
/// Read exception handler.
public DataPointScanner(ArchiveFileAllocationTable dataBlockAllocationTable, int historianID, TimeTag startTime, TimeTag endTime, bool includeStartTime, EventHandler> dataReadExceptionHandler)
{
// Find all data blocks for desired point over given time range
m_dataBlocks = dataBlockAllocationTable.FindDataBlocks(historianID, startTime, endTime, false);
m_startTime = startTime;
m_endTime = endTime;
m_historianID = historianID;
m_includeStartTime = includeStartTime;
m_dataReadExceptionHandler = dataReadExceptionHandler;
}
#endregion
#region [ Properties ]
///
/// Gets the historian ID associated with this .
///
public int HistorianID
{
get
{
return m_historianID;
}
}
#endregion
#region [ Methods ]
///
/// Reads all s from the s.
///
/// Each read from the s.
public IEnumerable Read()
{
int count = m_dataBlocks.Count;
int index = 0;
Func includeDataPoint;
if (m_includeStartTime)
includeDataPoint = dataPoint => (dataPoint.Time.CompareTo(m_startTime) >= 0 && dataPoint.Time.CompareTo(m_endTime) <= 0);
else
includeDataPoint = dataPoint => (dataPoint.Time.CompareTo(m_startTime) > 0 && dataPoint.Time.CompareTo(m_endTime) <= 0);
// Loop through each data block
foreach (ArchiveDataBlock dataBlock in m_dataBlocks)
{
// Attach to data read exception event for the data block
dataBlock.DataReadException += m_dataReadExceptionHandler;
// Pre-read all data points in this block
List dataPoints = new List();
if (index == 0 || index == count - 1)
{
// Read data through first and last data blocks validating time range
foreach (IDataPoint dataPoint in dataBlock.Read())
{
if (includeDataPoint(dataPoint))
dataPoints.Add(dataPoint);
}
}
else
{
// Read all of the data from the rest of the data blocks
foreach (IDataPoint dataPoint in dataBlock.Read())
{
dataPoints.Add(dataPoint);
}
}
// Detach from data read exception event for the data block
dataBlock.DataReadException -= m_dataReadExceptionHandler;
foreach (IDataPoint dataPoint in dataPoints)
{
yield return dataPoint;
}
index++;
}
}
#endregion
}
}