/* * TDAS.File.PersistentChannel.cs * * Copyright © 2009 * Diversified Technical Systems, Inc. * All Rights Reserved */ using System; using System.IO; using System.Linq; using DTS.Common.DAS.Concepts.DAS.Channel; using DTS.Common.Utilities; using DTS.Common.Utilities.DotNetProgrammingConstructs; using DTS.Common.Utilities.IO.MemoryMap; using DTS.Common.Utilities.Logging; namespace DTS.Serialization.TDAS { public partial class File { /// /// Representation of a channel. Changes made to this representation /// are immediately manifest in the associated channel file. /// public partial class PersistentChannel : ExceptionalList, ILargeDataAware, IChannelHeader, IDisposable { /// /// The window into this persistent channel's soul. /// protected FileMapViewArray ViewArray { get => _ViewArray.Value; set => _ViewArray.Value = value; } private readonly Property _ViewArray = new Property( typeof(PersistentChannel).Namespace + ".File.PersistentChannel.ViewArray", null, false ); /// /// Get value indicating whether or not this class has been /// preinitialized from an existing serialization. /// protected bool IsInitializedFromFile { get => _IsInitializedFromFile.Value; private set => _IsInitializedFromFile.Value = value; } private readonly Property _IsInitializedFromFile = new Property( typeof(PersistentChannel).Namespace + ".File.PersistentChannel.IsInitializedFromFile", false, false ); private readonly Property _minADC = new Property( typeof(PersistentChannel).Namespace + ".File.PersistentChannel.MinADC", short.MinValue, false); public short MinADC { get { if (!_minADC.IsInitialized) { ComputeMinMaxADC(); } return _minADC.Value; } } private readonly Property _maxADC = new Property( typeof(PersistentChannel).Namespace + ".File.PersistentChannel.MaxADC", short.MaxValue, false); private static readonly object MyLock = new object(); public short MaxADC { get { if (!_maxADC.IsInitialized) { ComputeMinMaxADC(); } return _maxADC.Value; } } internal void ComputeMinMaxADC() { var min = short.MaxValue; var max = short.MinValue; for (ulong sample = 0; sample < NumberOfSamples; sample++) { min = Math.Min(min, Data[sample]); max = Math.Max(max, Data[sample]); } _minADC.Value = min; _maxADC.Value = max; } /// /// Initialize an instance of this class. /// /// /// /// The filename of the associated channel data file. /// /// /// /// The channel header to be written into the associated channel data file. /// /// public PersistentChannel(string filename, TDASBinaryChannelHeader channelHeader, bool overwriteIfExists) { try { IsInitializedFromFile = System.IO.File.Exists(Filename = filename); IsMemoryMapped = false; if (!IsInitializedFromFile || overwriteIfExists) { if (null == channelHeader) throw new ArgumentNullException("channel header is required to generate new file but none was provided"); //else // this.NumberOfTriggerSamples = channelHeader.NumberOfTriggers; //APILogger.Log("writing 2 ", this.Filename); //using (var mutex = new System.Threading.Mutex(false, Filename.Replace(Path.DirectorySeparatorChar, '_'))) lock (MyLock) { //while (!mutex.WaitOne(50, false)) { System.Threading.Thread.Sleep(5); } //try { using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.OpenOrCreate))) { var fields = Enum.GetValues(typeof(Field)).Cast().ToArray(); // convert to byte[] //var euBA = Encoding.UTF8.GetBytes(channelHeader.EngineeringUnit); //if (euBA.Length % 2 != 0) //{ // var xStr = new string(channelHeader.EngineeringUnit) + ' '; // euBA = Encoding.UTF8.GetBytes(xStr); //} foreach (var field in fields) { switch (field) { case Field.AcquisitionRate: fileWriter.Write(this.channelHeader.AcquisitionRate = channelHeader.AcquisitionRate); _AcquisitionRateInitialized = true; break; case Field.NumberOfPostT0DataPoints: fileWriter.Write(this.channelHeader.NumberOfPostT0DataPoints = channelHeader.NumberOfPostT0DataPoints); _NumberOfPostT0DataPointsInitialized = true; break; case Field.NumberOfPreT0DataPoints: fileWriter.Write(this.channelHeader.NumberOfPreT0DataPoints = channelHeader.NumberOfPreT0DataPoints); _NumberOfPreT0DataPointsInitialized = true; break; case Field.PreZeroLevelInCnts: fileWriter.Write(this.channelHeader.PreZeroLevelInCnts = channelHeader.PreZeroLevelInCnts); _PreZeroLevelInCntsInitialized = true; break; case Field.PreCalLevelInCnts: fileWriter.Write(this.channelHeader.PreCalLevelInCnts = channelHeader.PreCalLevelInCnts); _PreCalLevelInCntsInitialized = true; break; case Field.SignalToNoiseRatioInDb: fileWriter.Write(this.channelHeader.SignalToNoiseRatioInDb = channelHeader.SignalToNoiseRatioInDb); _SignalToNoiseRatioInDbInitialized = true; break; case Field.PostZeroLevelInCnts: fileWriter.Write(this.channelHeader.PostZeroLevelInCnts = channelHeader.PostZeroLevelInCnts); _PostZeroLevelInCntsInitialized = true; break; case Field.PostCalLevelInCnts: fileWriter.Write(this.channelHeader.PostCalLevelInCnts = channelHeader.PostCalLevelInCnts); _PostCalLevelInCntsInitialized = true; break; case Field.DataZeroLevelInCnts: fileWriter.Write(this.channelHeader.DataZeroLevelInCnts = channelHeader.DataZeroLevelInCnts); _DataZeroLevelInCntsInitialized = true; break; case Field.ScaleFactorMVPerCnt: fileWriter.Write(this.channelHeader.ScaleFactorMVPerCnt = channelHeader.ScaleFactorMVPerCnt); _ScaleFactorMVPerCntInitialized = true; break; case Field.ScaleFactorEUPerCnt: fileWriter.Write(this.channelHeader.ScaleFactorEUPerCnt = channelHeader.ScaleFactorEUPerCnt); _ScaleFactorEUPerCntInitialized = true; break; } } } } //finally { mutex.ReleaseMutex(); } } } } catch (System.Exception ex) { throw new Exception("encountered problem constructing " + GetType().FullName, ex); } } // xxx Make this a recursive function, with the terminating condition being a call with the first case, which // returns the offset of "start of file". // public enum Field { AcquisitionRate, //public Double NumberOfPreT0DataPoints, //public Int32 NumberOfPostT0DataPoints, //public Int32 PreZeroLevelInCnts, //public Int32 PreCalLevelInCnts, //public Int32 SignalToNoiseRatioInDb, //public Double PostZeroLevelInCnts, //public Int32 PostCalLevelInCnts, //public Int32 DataZeroLevelInCnts, //public Int32 ScaleFactorMVPerCnt, //public Double ScaleFactorEUPerCnt //public Double } //this is wasteful, we should improve it to use cached results when we've already computed the offset of previous fields rather than //recursively calculating everytime ... however we don't do it much so it's probably low priority private int GetSizeOf(Field field) { switch (field) { case Field.AcquisitionRate: return sizeof(double); case Field.NumberOfPostT0DataPoints: return sizeof(int); case Field.NumberOfPreT0DataPoints: return sizeof(int); case Field.PreZeroLevelInCnts: return sizeof(int); case Field.PreCalLevelInCnts: return sizeof(int); case Field.SignalToNoiseRatioInDb: return sizeof(double); case Field.PostZeroLevelInCnts: return sizeof(int); case Field.PostCalLevelInCnts: return sizeof(int); case Field.DataZeroLevelInCnts: return sizeof(int); case Field.ScaleFactorMVPerCnt: return sizeof(double); case Field.ScaleFactorEUPerCnt: return sizeof(double); } return 0; } /// /// /// public int GetFileOffsetOf(Field field) { try { var offset = 0; if (field == Field.AcquisitionRate) { offset = 0; } else { var previousField = (Field)(((int)field) - 1); offset = GetFileOffsetOf(previousField) + GetSizeOf(previousField); } return offset; } catch (System.Exception ex) { throw new Exception("encountered problem getting file offset for property", ex); } } /// /// Get value indicating whether or not all necessary properties of this /// class have been initialized to make this object useable. /// public bool IsInitialized { get { try { return _AcquisitionRateInitialized && _NumberOfPreT0DataPointsInitialized && _NumberOfPostT0DataPointsInitialized && _PreZeroLevelInCntsInitialized && _PreCalLevelInCntsInitialized && _SignalToNoiseRatioInDbInitialized && _PostZeroLevelInCntsInitialized && _PostCalLevelInCntsInitialized && _DataZeroLevelInCntsInitialized && _ScaleFactorMVPerCntInitialized && _ScaleFactorEUPerCntInitialized ; } catch (System.Exception ex) { throw new Exception("encountered problem determining initialization status", ex); } } } public bool IsDataArraySized => NumberOfSamples < int.MaxValue; /// /// Get/set the number of trigger samples. /// protected int NumberOfTriggerSamples { get; set; } /// /// size of view into memory-mapped file. /// protected int ViewSize { get; set; } private bool _IsViewSizeInitialized = false; /// /// to indicate whether or not a memory mapping has already been /// established for this object. /// protected bool IsMemoryMapped { get; set; } /// /// Get the length of this persistent channel's data. /// public long Length { get { try { if (NumberOfSamples > long.MaxValue) throw new ApplicationException("ulong overflowed while being cast to long"); return (long)NumberOfSamples; } catch (System.Exception ex) { throw new Exception("encountered problem determining total amount of channel data", ex); } } } /// /// Get the data count of this persistent channel's data. /// public new int Count { get { try { if (Length > int.MaxValue) throw new ApplicationException("long overflowed while being cast to int"); return (int)Length; } catch (System.Exception ex) { throw new Exception("encountered problem getting channel data count", ex); } } } /// /// Override long-indexing here. Return a sample of the underlying array. /// /// /// /// The index of the sample being affected. /// /// /// /// The sample at the specified index. /// /// public short this[long i] { get { try { return this[(ulong)i]; } catch (System.Exception ex) { throw new Exception("encountered problem getting long-indexable value at index " + i.ToString(), ex); } } set { try { this[(ulong)i] = value; } catch (System.Exception ex) { throw new Exception("encountered problem setting long-indexable value at index " + i.ToString(), ex); } } } public void UnSet() { lock (MyLock) { _Data.Value = new short[0]; _Data.UnInitialize(); } } // Override indexing operator here, return a sample of the underlying array. public short this[ulong i] { get { //using (var mutex = new System.Threading.Mutex(false, Filename.Replace(Path.DirectorySeparatorChar, '_'))) lock (MyLock) { //while (!mutex.WaitOne(50, false)) { System.Threading.Thread.Sleep(5); } try { ulong offsetSampleDataStart = 8 + 4 + 4 + 4 + 4 + 8 + 4 + 4 + 4 + 8 + 8; // OffsetOfSampleDataStart; if (!_IsViewSizeInitialized) { // // Memory map array object map view paging math seems to be a bit // screwed. If you don't make the page exactly the same size as the // system memory allocation granularity, it will start returning trash // data after the first page fault. // const int StandardPageSize = 65536; if (NumberOfSamples + offsetSampleDataStart > StandardPageSize) { ViewSize = StandardPageSize; } else { // // If the map size exceeds the file size, we'll get strange COM error // codes. // var numberOfDataBytes = NumberOfSamples * 2; if (numberOfDataBytes + offsetSampleDataStart > int.MaxValue) throw new Exception("overflowed view size variable (max value: " + int.MaxValue.ToString() + ") when downcasting number of bytes in test data (" + numberOfDataBytes.ToString() + ")"); ViewSize = (int)(numberOfDataBytes + offsetSampleDataStart); } _IsViewSizeInitialized = true; } // MMBAD: Possible inefficiency. Perhaps either for "debug" build, or find some other way // to verify this outside of the array access. // //if ( !IsInitialized && !IsInitializedFromFile ) // throw new NotInitializedException( "object initialization has not completed" ); //else if ( !IsMemoryMapped ) if (!IsMemoryMapped) { var fileInfo = new FileInfo(Filename); // Make a new mapViewArray for the file with proper offset and // readonly privilages to protect sample integrity. ViewArray = new FileMapViewArray(Path.GetFullPath(Filename), MapAccess.FileMapRead, MapProtection.PageReadOnly, offsetSampleDataStart, (fileInfo.Length), ViewSize); IsMemoryMapped = true; } // MMBAD: possible inefficiency: these values are supposed to be cached, but they may be accessing // disk each time. Can't copy at this level because all channels come through here, but it is // supposed to be getting cached at least. //short a = (short)((ViewArray[(long)(this.OffsetOfSampleDataStart + (2 * i))] & 0xFFFF)); //short b = (short)((ViewArray[(long)(this.OffsetOfSampleDataStart + (2 * i) + 1)] & 0xFFFF) << 8); //rv = a; //rv += b; //if (rv > 20000) //{ // int j = rv; //} var rv = (short)((ViewArray[(long)(offsetSampleDataStart + (2 * i))] & 0xFFFF)); rv += (short)((ViewArray[(long)(offsetSampleDataStart + (2 * i) + 1)] & 0xFFFF) << 8); return rv; } catch (System.Exception ex) { throw new Exception("encountered problem getting short value at index " + i.ToString(), ex); } //finally { mutex.ReleaseMutex(); } } } set { try { throw new NotSupportedException("SliceRaw::File::PersistentChannel::[] Sample Data is READ_ONLY."); } catch (System.Exception ex) { throw new Exception("encountered problem setting short value at index " + i.ToString(), ex); } } } /// /// Get/set the filename of the associated channel data file. /// public string Filename { get => _Filename.Value; private set => _Filename.Value = value; } private readonly Property _Filename = new Property( typeof(PersistentChannel).Namespace + ".File.PreAllocatedChannel.Filename", null, false ); /// /// Get/set data array value. /// public short[] Data { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!IsDataArraySized) throw new DataTooBigForArrayException("Data size (" + Count.ToString() + ") is too large to be safely handled within the application"); if (!_Data.IsInitialized) { // // If we haven't handed out one of these yet, make one up and then hang onto it // to use for subsequent requests to we don't have clones all over the place. // var dataArray = new short[Count]; for (var i = 0; i < dataArray.Length; i++) dataArray[i] = this[i]; _Data.Value = dataArray; } return _Data.Value; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".Data property value", ex); } } set { try { _Data.Value = value; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".Data property value", ex); } } } private readonly Property _Data = new Property( typeof(PersistentChannel).Namespace + ".File.PreAllocatedChannel.Data", null, false ); /// /// Get/set binary writer to be used by data append session. /// private BinaryWriter AppendSessionWriter { get; set; } /// /// Prepare this object for repeated calls to AppendSessionData. /// public void BeginAppendSession() { try { APILogger.Log("beginning append writes ", Filename); AppendSessionWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open)); } catch (System.Exception ex) { throw new Exception("encountered problem beginning data append session", ex); } } /// /// Secure object from repeated calls to AppendSessionData. /// public void EndAppendSession() { try { APILogger.Log("ending append writes ", Filename); AppendSessionWriter.Close(); AppendSessionWriter.Dispose(); AppendSessionWriter = null; } catch (System.Exception ex) { throw new Exception("encountered problem ending data append session", ex); } } /// /// Object to cache header property accesses. /// public TDASBinaryChannelHeader channelHeader = new TDASBinaryChannelHeader(); /// /// Get/set number of samples. /// public ulong NumberOfSamples { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_NumberOfSamplesInitialized) { //APILogger.Log("reading 37 ", Filename); //using (var mutex = new System.Threading.Mutex(false, Filename.Replace(Path.DirectorySeparatorChar, '_'))) lock (MyLock) { //while (!mutex.WaitOne(50, false)) { System.Threading.Thread.Sleep(5); } //try { //long valueOffset = GetFileOffsetOf(PersistentChannel.Field.NumberOfSamples); long valueOffset = GetFileOffsetOf(Field.NumberOfPostT0DataPoints); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open, FileAccess.Read))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; //channelHeader.NumberOfSamples = fileReader.ReadUInt64(); channelHeader.NumberOfPostT0DataPoints = (int)fileReader.ReadUInt32(); valueOffset = GetFileOffsetOf(Field.NumberOfPreT0DataPoints); fileReader.BaseStream.Position = valueOffset; channelHeader.NumberOfPreT0DataPoints = (int)fileReader.ReadUInt32(); fileReader.BaseStream.Position = prevPosition; _NumberOfSamplesInitialized = true; } } //finally { mutex.ReleaseMutex(); } } } //return channelHeader.NumberOfSamples; return (ulong)(channelHeader.NumberOfPostT0DataPoints + channelHeader.NumberOfPreT0DataPoints); } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".NumberOfSamples property value", ex); } } } private bool _NumberOfSamplesInitialized = false; /// /// Get/set acquisition rate. /// public double AcquisitionRate { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_AcquisitionRateInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.AcquisitionRate); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.AcquisitionRate = fileReader.ReadDouble(); fileReader.BaseStream.Position = prevPosition; _AcquisitionRateInitialized = true; } } } } return channelHeader.AcquisitionRate; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".AcquisitionRate property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.AcquisitionRate); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.AcquisitionRate = value); } } } _AcquisitionRateInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".AcquisitionRate property value", ex); } } } private bool _AcquisitionRateInitialized = false; public int NumberOfPreT0DataPoints { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_NumberOfPreT0DataPointsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.NumberOfPreT0DataPoints); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.NumberOfPreT0DataPoints = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _NumberOfPreT0DataPointsInitialized = true; } } } } return channelHeader.NumberOfPreT0DataPoints; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".NumberOfPreT0DataPoints property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.NumberOfPreT0DataPoints); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.NumberOfPreT0DataPoints = value); } } } _NumberOfPreT0DataPointsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".NumberOfPreT0DataPoints property value", ex); } } } private bool _NumberOfPreT0DataPointsInitialized = false; public int NumberOfPostT0DataPoints { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_NumberOfPostT0DataPointsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.NumberOfPostT0DataPoints); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.NumberOfPostT0DataPoints = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _NumberOfPostT0DataPointsInitialized = true; } } } } return channelHeader.NumberOfPostT0DataPoints; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".NumberOfPostT0DataPoints property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.NumberOfPostT0DataPoints); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.NumberOfPostT0DataPoints = value); } } } _NumberOfPostT0DataPointsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".NumberOfPostT0DataPoints property value", ex); } } } private bool _NumberOfPostT0DataPointsInitialized = false; public int PreZeroLevelInCnts { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_PreZeroLevelInCntsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.PreZeroLevelInCnts); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.PreZeroLevelInCnts = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _PreZeroLevelInCntsInitialized = true; } } } } return channelHeader.PreZeroLevelInCnts; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".PreZeroLevelInCnts property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.PreZeroLevelInCnts); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.PreZeroLevelInCnts = value); } } } _PreZeroLevelInCntsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".PreZeroLevelInCnts property value", ex); } } } private bool _PreZeroLevelInCntsInitialized = false; public int PreCalLevelInCnts { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_PreCalLevelInCntsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.PreCalLevelInCnts); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.PreCalLevelInCnts = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _PreCalLevelInCntsInitialized = true; } } } } return channelHeader.PreCalLevelInCnts; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".PreCalLevelInCnts property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.PreCalLevelInCnts); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.PreCalLevelInCnts = value); } } } _PreCalLevelInCntsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + "._PreCalLevelInCnts property value", ex); } } } private bool _PreCalLevelInCntsInitialized = false; public double SignalToNoiseRatioInDb { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_SignalToNoiseRatioInDbInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.SignalToNoiseRatioInDb); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.SignalToNoiseRatioInDb = fileReader.ReadDouble(); fileReader.BaseStream.Position = prevPosition; _SignalToNoiseRatioInDbInitialized = true; } } } } return channelHeader.SignalToNoiseRatioInDb; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".SignalToNoiseRatioInDb property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.SignalToNoiseRatioInDb); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.SignalToNoiseRatioInDb = value); } } } _SignalToNoiseRatioInDbInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".SignalToNoiseRatioInDb property value", ex); } } } private bool _SignalToNoiseRatioInDbInitialized = false; public int PostZeroLevelInCnts { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_PostZeroLevelInCntsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.PostZeroLevelInCnts); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.PostZeroLevelInCnts = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _PostZeroLevelInCntsInitialized = true; } } } } return channelHeader.PostZeroLevelInCnts; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".PostZeroLevelInCnts property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.PostZeroLevelInCnts); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.PostZeroLevelInCnts = value); } } } _PostZeroLevelInCntsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".PostZeroLevelInCnts property value", ex); } } } private bool _PostZeroLevelInCntsInitialized = false; public int PostCalLevelInCnts { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_PostCalLevelInCntsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.PostCalLevelInCnts); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.PostCalLevelInCnts = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _PostCalLevelInCntsInitialized = true; } } } } return channelHeader.PostCalLevelInCnts; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".PostCalLevelInCnts property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.PostCalLevelInCnts); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.PostCalLevelInCnts = value); } } } _PostCalLevelInCntsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".PostCalLevelInCnts property value", ex); } } } private bool _PostCalLevelInCntsInitialized = false; public int DataZeroLevelInCnts { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_DataZeroLevelInCntsInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.DataZeroLevelInCnts); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open, FileAccess.Read))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.DataZeroLevelInCnts = fileReader.ReadInt32(); fileReader.BaseStream.Position = prevPosition; _DataZeroLevelInCntsInitialized = true; } } } } return channelHeader.DataZeroLevelInCnts; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".DataZeroLevelInCnts property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.DataZeroLevelInCnts); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.DataZeroLevelInCnts = value); } } } _DataZeroLevelInCntsInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".DataZeroLevelInCnts property value", ex); } } } private bool _DataZeroLevelInCntsInitialized = false; public double ScaleFactorMVPerCnt { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_ScaleFactorMVPerCntInitialized) { lock (MyLock) { { long valueOffset = GetFileOffsetOf(Field.ScaleFactorMVPerCnt); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.ScaleFactorMVPerCnt = fileReader.ReadDouble(); fileReader.BaseStream.Position = prevPosition; _ScaleFactorMVPerCntInitialized = true; } } } } return channelHeader.ScaleFactorMVPerCnt; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".ScaleFactorMVPerCnt property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.ScaleFactorMVPerCnt); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.ScaleFactorMVPerCnt = value); } } } _ScaleFactorMVPerCntInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".ScaleFactorMVPerCnt property value", ex); } } } private bool _ScaleFactorMVPerCntInitialized = false; public double ScaleFactorEUPerCnt { get { try { if (!IsInitialized && !IsInitializedFromFile) throw new NotInitializedException("object initialization has not completed"); if (!_ScaleFactorEUPerCntInitialized) { //APILogger.Log("reading 38 ", Filename); //using (var mutex = new System.Threading.Mutex(false, Filename.Replace(Path.DirectorySeparatorChar, '_'))) lock (MyLock) { //while (!mutex.WaitOne(50, false)) { System.Threading.Thread.Sleep(5); } //try { long valueOffset = GetFileOffsetOf(Field.ScaleFactorEUPerCnt); using (var fileReader = new BinaryReader(new FileStream(Filename, FileMode.Open))) { var prevPosition = fileReader.BaseStream.Position; fileReader.BaseStream.Position = valueOffset; channelHeader.ScaleFactorEUPerCnt = fileReader.ReadDouble(); fileReader.BaseStream.Position = prevPosition; _ScaleFactorEUPerCntInitialized = true; } } //finally { mutex.ReleaseMutex(); } } } return channelHeader.ScaleFactorEUPerCnt; } catch (System.Exception ex) { throw new Exception("encountered problem getting " + GetType().FullName + ".ScaleFactorEUPerCnt property value", ex); } } set { try { lock (MyLock) { { var offset = GetFileOffsetOf(Field.ScaleFactorEUPerCnt); using (var fileWriter = new BinaryWriter(new FileStream(Filename, FileMode.Open))) { fileWriter.Seek(offset, SeekOrigin.Begin); fileWriter.Write(channelHeader.ScaleFactorEUPerCnt = value); } } } _ScaleFactorEUPerCntInitialized = true; //// If at this point the persistent channel object has been initialized, go ahead and //// keep the CRC current. //if (this.IsInitialized) // this.Crc32 = channelHeader.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem setting " + GetType().FullName + ".ScaleFactorEUPerCnt property value", ex); } } } private bool _ScaleFactorEUPerCntInitialized = false; /// /// Get the CRC for the current state of the header. /// //public UInt32 Crc32 //{ // get // { // try // { // if (!IsInitialized) // throw new NotInitializedException( "object initialization has not completed" ); // else return channelHeader.Crc32; // } // catch ( System.Exception ex ) // { // throw new PersistentChannel.Exception( "encountered problem getting " + this.GetType( ).FullName + ".Crc32 property value", ex ); // } // } // private set // { // try // { // //APILogger.Log("writing 34 ", Filename); // //using (var mutex = new System.Threading.Mutex(false, Filename.Replace(Path.DirectorySeparatorChar, '_'))) // lock(MyLock) // { // //while (!mutex.WaitOne(50, false)) { System.Threading.Thread.Sleep(5); } // //try // { // int offset = GetFileOffsetOf(PersistentChannel.Field.Crc32); // using (BinaryWriter fileWriter = new BinaryWriter(new FileStream(this.Filename, FileMode.Open))) // { // fileWriter.Seek(offset, SeekOrigin.Begin); // fileWriter.Write(value); // } // } // //finally { mutex.ReleaseMutex(); } // } // } // catch ( System.Exception ex ) // { // throw new PersistentChannel.Exception( "encountered problem setting " + this.GetType( ).FullName + ".Crc32 property", ex ); // } // } //} /// /// Populate the persistent CRC property with the CRC of the current state of the channel header. /// public void StampCrc() { try { // // Calling the "get" accessor for all properties will ensure that they // are populated, which is important if the CRC is going to be running // over them. // var header = new TDASBinaryChannelHeader(); header.AcquisitionRate = AcquisitionRate; header.NumberOfPostT0DataPoints = NumberOfPostT0DataPoints; header.NumberOfPreT0DataPoints = NumberOfPreT0DataPoints; header.PreZeroLevelInCnts = PreZeroLevelInCnts; header.PreCalLevelInCnts = PreCalLevelInCnts; header.SignalToNoiseRatioInDb = SignalToNoiseRatioInDb; header.PostZeroLevelInCnts = PostZeroLevelInCnts; header.PostCalLevelInCnts = PostCalLevelInCnts; header.DataZeroLevelInCnts = DataZeroLevelInCnts; header.ScaleFactorMVPerCnt = ScaleFactorMVPerCnt; header.ScaleFactorEUPerCnt = ScaleFactorEUPerCnt; //this.Crc32 = channelHeader.Crc32; //this.Crc32 = header.Crc32; } catch (System.Exception ex) { throw new Exception("encountered problem stamping persistent channel CRC", ex); } } /// /// Dispose of this object's Disposables. /// public void Dispose() { //using (var mutex = new System.Threading.Mutex(false, Filename.Replace(Path.DirectorySeparatorChar, '_'))) lock (MyLock) { //while (!mutex.WaitOne(50, false)) { System.Threading.Thread.Sleep(5); } try { if (_ViewArray.IsInitialized) { IsMemoryMapped = false; //Is this right? } try { ViewArray.Dispose(); } catch (System.Exception) { } } catch (System.Exception ex) { // If the ViewArray was not yet initialized, that's OK. Eat the exception if (null == ex.InnerException || ex.InnerException.GetType() != typeof(Property.NotInitializedException)) { throw new Exception("encountered problem disposing of " + GetType().FullName, ex); } } //finally { mutex.ReleaseMutex(); } } } } } }