Exemple #1
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();
        }
Exemple #2
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);
            }
        }
Exemple #3
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;
        }
Exemple #4
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();
                    }
                }
            }
        }
Exemple #5
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;
        }
Exemple #6
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;
        }
Exemple #7
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;
        }
Exemple #8
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;
                }
            }
        }