Exemplo n.º 1
0
        private static ArchiveFile OpenArchiveFile(string fileName)
        {
            Console.WriteLine("Inside OpenArchiveFile function..");

            string m_archiveLocation = FilePath.GetDirectoryName(fileName);

            //string m_archiveLocation = "C:\\Program Files\\openPDC\\Archive\\";
            Console.WriteLine("This is the m_archiveLocation: {0}", m_archiveLocation);
            string instance = fileName.Substring(0, fileName.LastIndexOf('_'));
            ArchiveFile file = new ArchiveFile();
            file.FileName = fileName;
            file.FileAccessMode = FileAccess.Read;

            file.StateFile = new StateFile();
            file.StateFile.FileAccessMode = FileAccess.Read;
            file.StateFile.FileName = string.Format("{0}_startup.dat", instance);

            file.IntercomFile = new IntercomFile();
            file.IntercomFile.FileAccessMode = FileAccess.Read;
            file.IntercomFile.FileName = string.Format("{0}scratch.dat", m_archiveLocation);

            file.MetadataFile = new MetadataFile();
            file.MetadataFile.FileAccessMode = FileAccess.Read;
            file.MetadataFile.FileName = string.Format("{0}_dbase.dat", instance);
            file.MetadataFile.LoadOnOpen = true;

            Console.WriteLine("OpenArchiveFile has finished");
            file.Open();
            return file;
        }
Exemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ArchiveDataBlock"/> class. 
 /// </summary>
 /// <param name="parent">An <see cref="ArchiveFile"/> object.</param>
 /// <param name="index">0-based index of the <see cref="ArchiveDataBlock"/>.</param>
 /// <param name="historianID">Historian identifier whose <see cref="ArchiveData"/> is stored in the <see cref="ArchiveDataBlock"/>.</param>
 /// <param name="reset">true if the <see cref="ArchiveDataBlock"/> is to be <see cref="Reset()"/>; otherwise false.</param>
 internal ArchiveDataBlock(ArchiveFile parent, int index, int historianID, bool reset)
 {
     m_parent = parent;
     m_index = index;
     m_historianID = historianID;
     m_writeCursor = Location;
     m_lastActivityTime = DateTime.Now;
     if (reset)
         Reset();                                        // Clear existing data.
     else
         foreach (ArchiveData dataPoint in Read()) { }   // Read existing data.
 }
Exemplo n.º 3
0
        private TimeTag m_searchEndTime;    // <=|

        #endregion

        #region [ Constructors ]

        /// <summary>
        /// Initializes a new instance of the <see cref="ArchiveFileAllocationTable"/> class.
        /// </summary>
        /// <param name="parent">An <see cref="ArchiveFile"/> object.</param>
        internal ArchiveFileAllocationTable(ArchiveFile parent)
        {
            m_parent = parent;
            m_dataBlockPointers = new List<ArchiveDataBlockPointer>();

            if (m_parent.FileData.Length == 0)
            {
                // File is brand new.
                m_fileStartTime = TimeTag.MinValue;
                m_fileEndTime = TimeTag.MinValue;
                m_dataBlockSize = m_parent.DataBlockSize;
                m_dataBlockCount = ArchiveFile.MaximumDataBlocks(m_parent.FileSize, m_parent.DataBlockSize);

                for (int i = 0; i < m_dataBlockCount; i++)
                {
                    m_dataBlockPointers.Add(new ArchiveDataBlockPointer(m_parent, i));
                }
            }
            else
            {
                // File was created previously.
                byte[] fixedFatData = new byte[FixedBinaryLength];
                m_parent.FileData.Seek(-fixedFatData.Length, SeekOrigin.End);
                m_parent.FileData.Read(fixedFatData, 0, fixedFatData.Length);
                FileStartTime = new TimeTag(EndianOrder.LittleEndian.ToDouble(fixedFatData, 0));
                FileEndTime = new TimeTag(EndianOrder.LittleEndian.ToDouble(fixedFatData, 8));
                DataPointsReceived = EndianOrder.LittleEndian.ToInt32(fixedFatData, 16);
                DataPointsArchived = EndianOrder.LittleEndian.ToInt32(fixedFatData, 20);
                DataBlockSize = EndianOrder.LittleEndian.ToInt32(fixedFatData, 24);
                DataBlockCount = EndianOrder.LittleEndian.ToInt32(fixedFatData, 28);

                byte[] variableFatData = new byte[m_dataBlockCount * ArchiveDataBlockPointer.ByteCount];
                m_parent.FileData.Seek(-(variableFatData.Length + FixedBinaryLength), SeekOrigin.End);
                m_parent.FileData.Read(variableFatData, 0, variableFatData.Length);
                for (int i = 0; i < m_dataBlockCount; i++)
                {
                    m_dataBlockPointers.Add(new ArchiveDataBlockPointer(m_parent, i, variableFatData, i * ArchiveDataBlockPointer.ByteCount, variableFatData.Length));
                }
            }
        }
Exemplo n.º 4
0
        private void WriteToHistoricArchiveFile(ArchiveData[] items)
        {
            if (m_buildHistoricFileListThread.IsAlive)
                // Wait until the historic file list has been built.
                m_buildHistoricFileListThread.Join();

            OnHistoricDataWriteStart();

            Dictionary<int, List<ArchiveData>> sortedPointData = new Dictionary<int, List<ArchiveData>>();
            // First we'll seperate all point data by ID.
            for (int i = 0; i < items.Length; i++)
            {
                if (!sortedPointData.ContainsKey(items[i].HistorianID))
                {
                    sortedPointData.Add(items[i].HistorianID, new List<ArchiveData>());
                }

                sortedPointData[items[i].HistorianID].Add(items[i]);
            }

            ProcessProgress<int> historicWriteProgress = new ProcessProgress<int>("HistoricWrite");
            historicWriteProgress.Total = items.Length;
            foreach (int pointID in sortedPointData.Keys)
            {
                // We'll sort the point data for the current point ID by time.
                sortedPointData[pointID].Sort();

                ArchiveFile historicFile = null;
                ArchiveDataBlock historicFileBlock = null;
                try
                {
                    for (int i = 0; i < sortedPointData[pointID].Count; i++)
                    {
                        if (historicFile == null)
                        {
                            // We'll try to find a historic file when the current point data belongs.
                            Info historicFileInfo;
                            m_writeSearchTimeTag = sortedPointData[pointID][i].Time;
                            lock (m_historicArchiveFiles)
                            {
                                historicFileInfo = m_historicArchiveFiles.Find(FindHistoricArchiveFileForWrite);
                            }

                            if (historicFileInfo != null)
                            {
                                // Found a historic file where the data can be written.
                                historicFile = new ArchiveFile();
                                historicFile.FileName = historicFileInfo.FileName;
                                historicFile.StateFile = m_stateFile;
                                historicFile.IntercomFile = m_intercomFile;
                                historicFile.MetadataFile = m_metadataFile;
                                historicFile.Open();
                            }
                        }

                        if (historicFile != null)
                        {
                            if (sortedPointData[pointID][i].Time.CompareTo(historicFile.Fat.FileStartTime) >= 0 && sortedPointData[pointID][i].Time.CompareTo(historicFile.Fat.FileEndTime) <= 0)
                            {
                                // The current point data belongs to the current historic archive file.
                                if (historicFileBlock == null || historicFileBlock.SlotsAvailable == 0)
                                {
                                    // Request a new or previously used data block for point data.
                                    historicFileBlock = historicFile.Fat.RequestDataBlock(pointID, sortedPointData[pointID][i].Time, -1);
                                }
                                historicFileBlock.Write(sortedPointData[pointID][i]);
                                historicFile.Fat.DataPointsReceived++;
                                historicFile.Fat.DataPointsArchived++;
                                if (i == sortedPointData[pointID].Count() - 1)
                                {
                                    // Last piece of data for the point, so we close the currently open file.
                                    historicFile.Save();
                                    historicFile.Dispose();
                                    historicFile = null;
                                    historicFileBlock = null;
                                }

                                historicWriteProgress.Complete++;
                            }
                            else
                            {
                                // The current point data doesn't belong to the current historic archive file, so we have
                                // to write all the point data we have so far for the current historic archive file to it.
                                i--;
                                historicFile.Dispose();
                                historicFile = null;
                                historicFileBlock = null;
                            }
                        }
                    }

                    // Notify of progress per point.
                    historicWriteProgress.ProgressMessage = string.Format("Wrote historic data for point id {0} ({1} of {2}).", pointID, "{0}", "{1}");
                    OnHistoricDataWriteProgress(historicWriteProgress);
                }
                catch (Exception ex)
                {
                    // Free-up used memory.
                    if (historicFile != null)
                    {
                        try
                        {
                            historicFile.Dispose();
                            historicFile = null;
                        }
                        catch
                        {

                        }
                    }

                    // Notify of the exception.
                    OnHistoricDataWriteException(ex);
                }
            }

            OnHistoricDataWriteComplete();
        }
Exemplo n.º 5
0
        private Info GetHistoricFileInfo(string fileName)
        {
            Info fileInfo = null;
            try
            {
                if (File.Exists(fileName))
                {
                    // We'll open the file and get relevant information about it.
                    ArchiveFile historicArchiveFile = new ArchiveFile();
                    historicArchiveFile.FileName = fileName;
                    historicArchiveFile.StateFile = m_stateFile;
                    historicArchiveFile.IntercomFile = m_intercomFile;
                    historicArchiveFile.MetadataFile = m_metadataFile;
                    try
                    {
                        historicArchiveFile.Open();
                        fileInfo = new Info();
                        fileInfo.FileName = fileName;
                        fileInfo.StartTimeTag = historicArchiveFile.Fat.FileStartTime;
                        fileInfo.EndTimeTag = historicArchiveFile.Fat.FileEndTime;
                    }
                    catch (Exception)
                    {

                    }
                    finally
                    {
                        historicArchiveFile.Dispose();
                        historicArchiveFile = null;
                    }
                }
                else
                {
                    // We'll resolve to getting the file information from its name only if the file no longer exists
                    // at the location. This will be the case when file is moved to a different location. In this
                    // case the file information we provide is only as good as the file name.
                    string datesString = FilePath.GetFileNameWithoutExtension(fileName).Substring((FilePath.GetFileNameWithoutExtension(m_fileName) + "_").Length);
                    string[] fileStartEndDates = datesString.Split(new string[] { "_to_" }, StringSplitOptions.None);

                    fileInfo = new Info();
                    fileInfo.FileName = fileName;
                    if (fileStartEndDates.Length == 2)
                    {
                        fileInfo.StartTimeTag = new TimeTag(Convert.ToDateTime(fileStartEndDates[0].Replace('!', ':')));
                        fileInfo.EndTimeTag = new TimeTag(Convert.ToDateTime(fileStartEndDates[1].Replace('!', ':')));
                    }
                }
            }
            catch (Exception)
            {

            }

            return fileInfo;
        }
Exemplo n.º 6
0
        private void PrepareForRollover()
        {
            try
            {
                DriveInfo archiveDrive = new DriveInfo(Path.GetPathRoot(m_fileName));
                if (archiveDrive.AvailableFreeSpace < archiveDrive.TotalSize * (1 - ((double)m_fileOffloadThreshold / 100)))
                {
                    // We'll start offloading historic files if we've reached the offload threshold.
                    OffloadHistoricFiles();
                }

                OnRolloverPreparationStart();

                // Opening and closing a new archive file in "standby" mode will create a "standby" archive file.
                ArchiveFile standbyArchiveFile = new ArchiveFile();
                standbyArchiveFile.FileName = StandbyArchiveFileName;
                standbyArchiveFile.FileSize = m_fileSize;
                standbyArchiveFile.DataBlockSize = m_dataBlockSize;
                standbyArchiveFile.StateFile = m_stateFile;
                standbyArchiveFile.IntercomFile = m_intercomFile;
                standbyArchiveFile.MetadataFile = m_metadataFile;
                try
                {
                    standbyArchiveFile.Open();
                }
                catch (Exception)
                {
                    string standbyFileName = standbyArchiveFile.FileName;
                    standbyArchiveFile.Close();
                    // We didn't succeed in creating a "standby" archive file, so we'll delete it if it was created
                    // partially (might happen if there isn't enough disk space or thread is aborted). This is to
                    // ensure that this preparation processes is kicked off again until a valid "standby" archive
                    // file is successfully created.
                    if (File.Exists(standbyFileName))
                    {
                        File.Delete(standbyFileName);
                    }

                    throw; // Rethrow the exception so the appropriate action is taken.
                }
                finally
                {
                    standbyArchiveFile.Dispose();
                }

                OnRolloverPreparationComplete();
            }
            catch (ThreadAbortException)
            {
                // This thread must die now...
            }
            catch (Exception ex)
            {
                OnRolloverPreparationException(ex);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Reads <see cref="ArchiveData"/> points.
        /// </summary>
        /// <param name="historianID">Historian identifier for which <see cref="ArchiveData"/> points are to be retrieved.</param>
        /// <param name="startTime">Start <see cref="TimeTag"/> (in GMT) for the <see cref="ArchiveData"/> points to be retrieved.</param>
        /// <param name="endTime">End <see cref="TimeTag"/> (in GMT) for the <see cref="ArchiveData"/> points to be retrieved.</param>
        /// <returns><see cref="IEnumerable{T}"/> object containing zero or more <see cref="ArchiveData"/> points.</returns>
        public IEnumerable<IDataPoint> ReadData(int historianID, TimeTag startTime, TimeTag endTime)
        {
            // Ensure that the current file is open.
            if (!IsOpen)
                throw new InvalidOperationException(string.Format("\"{0}\" file is not open.", m_fileName));

            // Ensure that the current file is active.
            if (m_fileType != ArchiveFileType.Active)
                throw new InvalidOperationException("Data can only be directly read from files that are Active.");

            // Ensure that the start and end time are valid.
            if (startTime > endTime)
                throw new ArgumentException("End Time preceeds Start Time in the specified timespan.");

            // Yeild to the rollover process if it is in progress.
            m_rolloverWaitHandle.WaitOne();

            List<Info> dataFiles = new List<Info>();
            if (startTime < m_fat.FileStartTime)
            {
                // Data is to be read from historic file(s).
                if (m_buildHistoricFileListThread.IsAlive)
                    m_buildHistoricFileListThread.Join();

                m_readSearchStartTimeTag = startTime;
                m_readSearchEndTimeTag = endTime;
                lock (m_historicArchiveFiles)
                {
                    dataFiles.AddRange(m_historicArchiveFiles.FindAll(FindHistoricArchiveFileForRead));
                }
            }

            if (endTime >= m_fat.FileStartTime)
            {
                // Data is to be read from the active file.
                Info activeFileInfo = new Info();
                activeFileInfo.FileName = m_fileName;
                activeFileInfo.StartTimeTag = m_fat.FileStartTime;
                activeFileInfo.EndTimeTag = m_fat.FileEndTime;
                dataFiles.Add(activeFileInfo);
            }

            // Read data from all qualifying files.
            foreach (Info dataFile in dataFiles)
            {
                ArchiveFile file = new ArchiveFile();
                IList<ArchiveDataBlock> dataBlocks;
                try
                {
                    file.FileName = dataFile.FileName;
                    file.StateFile = m_stateFile;
                    file.IntercomFile = m_intercomFile;
                    file.MetadataFile = m_metadataFile;
                    file.Open();

                    dataBlocks = file.Fat.FindDataBlocks(historianID, startTime, endTime);
                    if (dataBlocks.Count > 0)
                    {
                        // Data block before the first data block matching the search criteria might contain some data 
                        // for the specified search criteria, so look for such a data block and process its data.
                        lock (file.Fat.DataBlockPointers)
                        {
                            for (int i = dataBlocks[0].Index - 1; i >= 0; i--)
                            {
                                if (file.Fat.DataBlockPointers[i].HistorianID == historianID)
                                {
                                    foreach (ArchiveData data in file.Fat.DataBlockPointers[i].DataBlock.Read())
                                    {
                                        if (data.Time >= startTime)
                                            yield return data;
                                    }

                                    break;
                                }
                            }
                        }

                        // Read data from rest of the data blocks and scan the last data block for data matching the
                        // the search criteria as it may contain data beyond the timespan specified in the search.
                        for (int i = 0; i < dataBlocks.Count; i++)
                        {
                            if (i < dataBlocks.Count - 1)
                            {
                                // Read all the data.
                                foreach (ArchiveData data in dataBlocks[i].Read())
                                {
                                    yield return data;
                                }
                            }
                            else
                            {
                                // Scan through the data block.
                                foreach (ArchiveData data in dataBlocks[i].Read())
                                {
                                    if (data.Time <= endTime)
                                        yield return data;
                                    else
                                        yield break;
                                }
                            }
                        }
                    }
                }
                finally
                {
                    if (file.IsOpen)
                    {
                        file.Close();
                    }
                }
            }
        }
Exemplo n.º 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ArchiveDataBlockPointer"/> class.
 /// </summary>
 /// <param name="parent">An <see cref="ArchiveFile"/> object.</param>
 /// <param name="index">0-based index of the <see cref="ArchiveDataBlockPointer"/>.</param>
 /// <param name="binaryImage">Binary image to be used for initializing <see cref="ArchiveDataBlockPointer"/>.</param>
 /// <param name="startIndex">0-based starting index of initialization data in the <paramref name="binaryImage"/>.</param>
 /// <param name="length">Valid number of bytes in <paramref name="binaryImage"/> from <paramref name="startIndex"/>.</param>
 internal ArchiveDataBlockPointer(ArchiveFile parent, int index, byte[] binaryImage, int startIndex, int length)
     : this(parent, index)
 {
     Initialize(binaryImage, startIndex, length);
 }
Exemplo n.º 9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ArchiveDataBlockPointer"/> class.
 /// </summary>
 /// <param name="parent">An <see cref="ArchiveFile"/> object.</param>
 /// <param name="index">0-based index of the <see cref="ArchiveDataBlockPointer"/>.</param>
 internal ArchiveDataBlockPointer(ArchiveFile parent, int index)
 {
     m_parent = parent;
     m_index = index;
     Reset();
 }
Exemplo n.º 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ArchiveDataBlock"/> class. 
        /// </summary>
        /// <param name="parent">An <see cref="ArchiveFile"/> object.</param>
        /// <param name="index">0-based index of the <see cref="ArchiveDataBlock"/>.</param>
        /// <param name="historianID">Historian identifier whose <see cref="ArchiveDataPoint"/> is stored in the <see cref="ArchiveDataBlock"/>.</param>
        /// <param name="reset">true if the <see cref="ArchiveDataBlock"/> is to be <see cref="Reset()"/>; otherwise false.</param>
        /// <param name="preRead">true to pre-read data to locate write cursor.</param>
        internal ArchiveDataBlock(ArchiveFile parent, int index, int historianID, bool reset, bool preRead = true)
        {
            m_parent = parent;
            m_index = index;
            m_historianID = historianID;
            m_readBuffer = new byte[ArchiveDataPoint.FixedLength];
            m_writeCursor = Location;
            m_lastActivityTime = DateTime.Now;

            if (reset)
            {
                // Clear existing data.
                Reset();
            }
            else if (preRead)
            {
                // Scan through existing data to locate write cursor
                foreach (ArchiveDataPoint dataPoint in Read())
                {
                }
            }
        }
Exemplo n.º 11
0
 private void CloseArchiveFile()
 {
     if ((object)m_archiveFile != null)
     {
         m_archiveFile.DataReadException -= file_DataReadException;
         m_archiveFile.HistoricFileListBuildComplete -= file_HistoricFileListBuildComplete;
         m_archiveFile.HistoricFileListBuildException -= file_HistoricFileListBuildException;
         m_archiveFile.HistoricFileListBuildStart -= file_HistoricFileListBuildStart;
         m_archiveFile.HistoricFileListUpdated -= file_HistoricFileListUpdated;
         m_archiveFile.RolloverComplete -= file_RolloverComplete;
         m_archiveFile.RolloverStart -= file_RolloverStart;
         m_archiveFile.Dispose();
     }
     m_archiveFile = null;
 }
Exemplo n.º 12
0
        // Opens an archive file as read-only and returns the ArchiveFile object.
        private ArchiveFile OpenArchiveFile(string fileName)
        {
            const string metadataFileName = "{0}{1}_dbase.dat";
            const string stateFileName = "{0}{1}_startup.dat";
            const string intercomFileName = "{0}scratch.dat";

            string archiveLocation = FilePath.GetDirectoryName(fileName);
            string archiveName = FilePath.GetFileName(fileName);
            string instance = archiveName.Substring(0, archiveName.LastIndexOf('_'));

            ArchiveFile file = new ArchiveFile
            {
                FileName = fileName,
                FileAccessMode = FileAccess.Read,
                MonitorNewArchiveFiles = true,
                PersistSettings = false,
                StateFile = new StateFile
                {
                    FileAccessMode = FileAccess.Read,
                    FileName = string.Format(stateFileName, archiveLocation, instance)
                },
                IntercomFile = new IntercomFile
                {
                    FileAccessMode = FileAccess.Read,
                    FileName = string.Format(intercomFileName, archiveLocation)
                },
                MetadataFile = new MetadataFile
                {
                    FileAccessMode = FileAccess.Read,
                    FileName = string.Format(metadataFileName, archiveLocation, instance),
                    LoadOnOpen = true
                }
            };

            file.DataReadException += file_DataReadException;
            file.HistoricFileListBuildComplete += file_HistoricFileListBuildComplete;
            file.HistoricFileListBuildException += file_HistoricFileListBuildException;
            file.HistoricFileListBuildStart += file_HistoricFileListBuildStart;
            file.HistoricFileListUpdated += file_HistoricFileListUpdated;
            file.RolloverComplete += file_RolloverComplete;
            file.RolloverStart += file_RolloverStart;

            // Initialize the archive file (starts file watchers)
            file.Initialize();

            // Open the active archive file
            file.Open();

            // Start the roll-over watch timer
            m_rolloverWatcher.Start();

            return file;
        }
Exemplo n.º 13
0
 /// <summary>
 /// Opens the <see cref="ArchiveFile"/> for use.
 /// </summary>
 /// <param name="fileName">Archive .D archive file name.</param>
 public void Open(string fileName)
 {
     CloseArchiveFile();
     m_archiveFile = OpenArchiveFile(fileName);
 }
Exemplo n.º 14
0
        private Info GetHistoricFileInfo(string fileName)
        {
            Info fileInfo = null;
            try
            {
                if (File.Exists(fileName))
                {
                    // We'll open the file and get relevant information about it.
                    ArchiveFile historicArchiveFile = new ArchiveFile();
                    historicArchiveFile.FileName = fileName;
                    historicArchiveFile.StateFile = m_stateFile;
                    historicArchiveFile.IntercomFile = m_intercomFile;
                    historicArchiveFile.MetadataFile = m_metadataFile;
                    historicArchiveFile.FileAccessMode = FileAccess.Read;

                    try
                    {
                        historicArchiveFile.Open();
                        fileInfo = new Info();
                        fileInfo.FileName = fileName;
                        fileInfo.StartTimeTag = historicArchiveFile.Fat.FileStartTime;
                        fileInfo.EndTimeTag = historicArchiveFile.Fat.FileEndTime;
                    }
                    catch (Exception ex)
                    {
                        OnHistoricFileListBuildException(new InvalidOperationException(string.Format("Failed to access historic data file \"{0}\" due to exception: {1}", FilePath.GetFileName(fileName), ex.Message), ex));
                    }
                    finally
                    {
                        historicArchiveFile.Dispose();
                    }
                }
                //else
                //{
                //    // We'll resolve to getting the file information from its name only if the file no longer exists
                //    // at the location. This will be the case when file is moved to a different location. In this
                //    // case the file information we provide is only as good as the file name.
                //    string datesString = FilePath.GetFileNameWithoutExtension(fileName).Substring((FilePath.GetFileNameWithoutExtension(m_fileName) + "_").Length);
                //    string[] fileStartEndDates = datesString.Split(new string[] { "_to_" }, StringSplitOptions.None);

                //    fileInfo = new Info();
                //    fileInfo.FileName = fileName;
                //    if (fileStartEndDates.Length == 2)
                //    {
                //        fileInfo.StartTimeTag = new TimeTag(Convert.ToDateTime(fileStartEndDates[0].Replace('!', ':')));
                //        fileInfo.EndTimeTag = new TimeTag(Convert.ToDateTime(fileStartEndDates[1].Replace('!', ':')));
                //    }
                //}
            }
            catch
            {

            }

            return fileInfo;
        }
Exemplo n.º 15
0
        // Read data implementation
        private IEnumerable<IDataPoint> ReadData(IEnumerable<int> historianIDs, TimeTag startTime, TimeTag endTime, int lastHistorianID)
        {
            // Yield to archive rollover process.
            m_rolloverWaitHandle.WaitOne();

            // Ensure that the current file is open.
            if (!IsOpen)
                throw new InvalidOperationException(string.Format("\"{0}\" file is not open", m_fileName));

            // Ensure that the current file is active.
            if (m_fileType != ArchiveFileType.Active)
                throw new InvalidOperationException("Data can only be directly read from files that are Active");

            // Ensure that the start and end time are valid.
            if (startTime.CompareTo(endTime) > 0)
                throw new ArgumentException("End Time preceeds Start Time in the specified timespan");

            List<Info> dataFiles = new List<Info>();
            bool pendingRollover = false;
            bool usingActiveFile = false;

            if (startTime.CompareTo(m_fat.FileStartTime) < 0)
            {
                // Data is to be read from historic file(s) - make sure that the list has been built
                if (m_buildHistoricFileListThread.IsAlive)
                    m_buildHistoricFileListThread.Join();

                lock (m_historicArchiveFiles)
                {
                    dataFiles.AddRange(m_historicArchiveFiles.FindAll(info => FindHistoricArchiveFileForRead(info, startTime, endTime)));
                }
            }

            if (endTime.CompareTo(m_fat.FileStartTime) >= 0)
            {
                // Data is to be read from the active file.
                Info activeFileInfo = new Info();
                activeFileInfo.FileName = m_fileName;
                activeFileInfo.StartTimeTag = m_fat.FileStartTime;
                activeFileInfo.EndTimeTag = m_fat.FileEndTime;
                dataFiles.Add(activeFileInfo);
            }

            // Read data from all qualifying files.
            foreach (Info dataFile in dataFiles)
            {
                ArchiveFile file = null;

                try
                {
                    if (string.Compare(dataFile.FileName, m_fileName, true) == 0)
                    {
                        // Read data from current file.
                        usingActiveFile = true;
                        file = this;

                        // Atomically increment total number of readers for active file
                        Interlocked.Increment(ref m_activeFileReaders);
                    }
                    else
                    {
                        // Read data from historic file.
                        usingActiveFile = false;
                        file = new ArchiveFile();
                        file.FileName = dataFile.FileName;
                        file.StateFile = m_stateFile;
                        file.IntercomFile = m_intercomFile;
                        file.MetadataFile = m_metadataFile;
                        file.FileAccessMode = FileAccess.Read;
                        file.Open();
                    }

                    // Create new time sorted data point scanner for the desired points in this file and given time range
                    TimeSortedDataPointScanner scanner = new TimeSortedDataPointScanner(file.Fat, historianIDs, startTime, endTime, lastHistorianID, (sender, e) => OnDataReadException(e.Argument));

                    // Reset last historian ID to scan from beginning after picking up where left off from roll over
                    lastHistorianID = -1;

                    // Return data points
                    foreach (IDataPoint dataPoint in scanner.Read())
                    {
                        yield return dataPoint;

                        // If a rollover needs to happen, we need to relinquish read lock and close file
                        if (m_rolloverInProgress)
                        {
                            startTime = dataPoint.Time;
                            lastHistorianID = dataPoint.HistorianID;
                            pendingRollover = true;
                            break;
                        }
                    }
                }
                finally
                {
                    if (usingActiveFile)
                    {
                        // Atomically decrement active file reader count to signal in-process code that read is complete or yielded
                        Interlocked.Decrement(ref m_activeFileReaders);
                    }
                    else if ((object)file != null && file.IsOpen)
                    {
                        file.Close();
                    }
                }

                if (pendingRollover)
                    break;
            }

            if (pendingRollover)
            {
                // Recurse into this function with an updated start time and last read point ID so that read can
                // resume right where it left off - recursed function call will wait until rollover is complete
                foreach (IDataPoint dataPoint in ReadData(historianIDs, startTime, endTime, lastHistorianID))
                {
                    yield return dataPoint;
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ArchiveFileAllocationTable"/> class.
        /// </summary>
        /// <param name="parent">An <see cref="ArchiveFile"/> object.</param>
        internal ArchiveFileAllocationTable(ArchiveFile parent)
        {
            m_parent = parent;
            m_dataBlockPointers = new List<ArchiveDataBlockPointer>();
            m_fixedTableRegion = new FixedTableRegion(this);
            m_variableTableRegion = new VariableTableRegion(this);

            if (m_parent.FileData.Length == 0)
            {
                // File is brand new.
                m_fileStartTime = TimeTag.MinValue;
                m_fileEndTime = TimeTag.MinValue;
                m_dataBlockSize = m_parent.DataBlockSize;
                m_dataBlockCount = ArchiveFile.MaximumDataBlocks(m_parent.FileSize, m_parent.DataBlockSize);

                for (int i = 0; i < m_dataBlockCount; i++)
                {
                    m_dataBlockPointers.Add(new ArchiveDataBlockPointer(m_parent, i));
                }
            }
            else
            {
                // Existing file, read table regions:

                // Seek to beginning of fixed table region
                m_parent.FileData.Seek(-m_fixedTableRegion.BinaryLength, SeekOrigin.End);

                // Parse fixed table region
                m_fixedTableRegion.ParseBinaryImageFromStream(m_parent.FileData);

                // Seek to beginning of variable table region (above fixed from bottom of file)
                m_parent.FileData.Seek(-(m_fixedTableRegion.BinaryLength + m_variableTableRegion.BinaryLength), SeekOrigin.End);

                // Parse variable table region
                m_variableTableRegion.ParseBinaryImageFromStream(m_parent.FileData);
            }
        }