private bool m_disposed; // Object disposed flag #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="FrameQueue"/>. /// </summary> internal FrameQueue(CreateNewFrameFunction createNewFrame) { m_createNewFrame = createNewFrame; m_frameList = new LinkedList<TrackingFrame>(); m_frameHash = new ConcurrentDictionary<long, TrackingFrame>(); m_queueLock = new SpinLock(); m_downsamplingMethod = DownsamplingMethod.LastReceived; }
private bool m_disposed; // Object disposed flag #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="FrameQueue"/>. /// </summary> internal FrameQueue(CreateNewFrameFunction createNewFrame) { m_createNewFrame = createNewFrame; m_frameList = new LinkedList <TrackingFrame>(); m_frameHash = new ConcurrentDictionary <long, TrackingFrame>(); m_queueLock = new SpinLock(); m_downsamplingMethod = DownsamplingMethod.LastReceived; }
private DatapointDatabase(string path, float downsamplingFactor, DownsamplingMethod downsamplingMethod, int maxRetention, IList <Archive> archives, Func <DateTime> currentTimeProvider) { this.path = path; this.downsamplingFactor = downsamplingFactor; this.downsamplingMethod = downsamplingMethod; this.maxRetention = maxRetention; this.archives = archives; this.currentTimeProvider = currentTimeProvider ?? (() => DateTime.UtcNow); }
/// <summary> /// Constructs a new <see cref="TrackingFrame"/> given the specified parameters. /// </summary> /// <param name="sourceFrame">Source <see cref="IFrame"/> to track.</param> /// <param name="downsamplingMethod"><see cref="DownsamplingMethod"/> to apply.</param> public TrackingFrame(IFrame sourceFrame, DownsamplingMethod downsamplingMethod) { m_sourceFrame = sourceFrame; m_timestamp = sourceFrame.Timestamp; m_downsamplingMethod = downsamplingMethod; m_frameLock = new ReaderWriterSpinLock(); if (downsamplingMethod != DownsamplingMethod.LastReceived) m_measurements = new ConcurrentDictionary<MeasurementKey, List<IMeasurement>>(); }
/// <summary> /// Creates a new instance of the <see cref="SynchronizedSubscriptionInfo"/> class. /// </summary> /// <param name="remotelySynchronized">Flag that determines whether the subscription defined by this object is remotely synchronized or locally synchronized.</param> /// <param name="framesPerSecond">Frame rate of the subscription in frames per second.</param> public SynchronizedSubscriptionInfo(bool remotelySynchronized, int framesPerSecond) { m_remotelySynchronized = remotelySynchronized; m_framesPerSecond = framesPerSecond; m_downsamplingMethod = DownsamplingMethod.LastReceived; m_allowPreemptivePublishing = true; m_allowSortsByArrival = true; m_timeResolution = Ticks.PerMillisecond; }
/// <summary> /// Constructs a new <see cref="TrackingFrame"/> given the specified parameters. /// </summary> /// <param name="sourceFrame">Source <see cref="IFrame"/> to track.</param> /// <param name="downsamplingMethod"><see cref="DownsamplingMethod"/> to apply.</param> public TrackingFrame(IFrame sourceFrame, DownsamplingMethod downsamplingMethod) { m_sourceFrame = sourceFrame; m_timestamp = sourceFrame.Timestamp; m_downsamplingMethod = downsamplingMethod; m_frameLock = new ReaderWriterSpinLock(); if (downsamplingMethod != DownsamplingMethod.LastReceived) { m_measurements = new ConcurrentDictionary <MeasurementKey, List <IMeasurement> >(); } }
private static double Aggregate(IEnumerable <double> values, DownsamplingMethod downsamplingMethod) { switch (downsamplingMethod) { case DownsamplingMethod.Average: return(values.Average()); case DownsamplingMethod.Sum: return(values.Sum()); case DownsamplingMethod.Last: return(values.Last()); case DownsamplingMethod.Max: return(values.Max()); case DownsamplingMethod.Min: return(values.Min()); default: throw new ArgumentOutOfRangeException("downsamplingMethod"); } }
private bool m_disposed; // Disposed flag detects redundant calls to dispose method #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="ConcentratorBase"/>. /// </summary> /// <remarks> /// Concentration will not begin until consumer "Starts" concentrator (i.e., calling <see cref="ConcentratorBase.Start"/> method or setting /// <c><see cref="ConcentratorBase.Enabled"/> = true</c>). /// </remarks> protected ConcentratorBase() { m_usePrecisionTimer = true; m_allowSortsByArrival = true; m_allowPreemptivePublishing = true; m_performTimestampReasonabilityCheck = true; m_processingInterval = -1; m_downsamplingMethod = DownsamplingMethod.LastReceived; m_latestMeasurements = new ImmediateMeasurements(this); m_maximumPublicationTimeout = Timeout.Infinite; // Create a new queue for managing real-time frames m_frameQueue = new FrameQueue(this.CreateNewFrame); // Set minimum timer resolution to one millisecond to improve timer accuracy PrecisionTimer.SetMinimumTimerResolution(1); // Create publication wait handle m_publicationWaitHandle = new AutoResetEvent(false); // Create publication thread - this may be one of the few times when you can // accurately argue that you need high priority thread scheduling... m_publicationThread = new Thread(PublishFrames); m_publicationThread.Priority = ThreadPriority.Highest; m_publicationThread.Start(); // This timer monitors the total number of unpublished samples every 5 seconds. This is a useful statistic // to monitor: if total number of unpublished samples exceed lag time, measurement concentration could // be falling behind. m_monitorTimer = new System.Timers.Timer(); m_monitorTimer.Interval = 5000; m_monitorTimer.AutoReset = true; m_monitorTimer.Elapsed += MonitorUnpublishedSamples; }
public virtual bool LocallySynchronizedSubscribe(bool compactFormat, int framesPerSecond, double lagTime, double leadTime, string filterExpression, string dataChannel = null, bool useLocalClockAsRealTime = false, bool ignoreBadTimestamps = false, bool allowSortsByArrival = true, long timeResolution = Ticks.PerMillisecond, bool allowPreemptivePublishing = true, DownsamplingMethod downsamplingMethod = DownsamplingMethod.LastReceived, string startTime = null, string stopTime = null, string constraintParameters = null, int processingInterval = -1, string waitHandleNames = null, int waitHandleTimeout = 0) { // Dispose of any previously established local concentrator DisposeLocalConcentrator(); // Establish a local concentrator to synchronize received measurements m_localConcentrator = new LocalConcentrator(this); m_localConcentrator.ProcessException += m_localConcentrator_ProcessException; m_localConcentrator.FramesPerSecond = framesPerSecond; m_localConcentrator.LagTime = lagTime; m_localConcentrator.LeadTime = leadTime; m_localConcentrator.UseLocalClockAsRealTime = useLocalClockAsRealTime; m_localConcentrator.IgnoreBadTimestamps = ignoreBadTimestamps; m_localConcentrator.AllowSortsByArrival = allowSortsByArrival; m_localConcentrator.TimeResolution = timeResolution; m_localConcentrator.AllowPreemptivePublishing = allowPreemptivePublishing; m_localConcentrator.DownsamplingMethod = downsamplingMethod; m_localConcentrator.UsePrecisionTimer = false; // Parse time constraints, if defined DateTime startTimeConstraint = !string.IsNullOrWhiteSpace(startTime) ? ParseTimeTag(startTime) : DateTime.MinValue; DateTime stopTimeConstraint = !string.IsNullOrWhiteSpace(stopTime) ? ParseTimeTag(stopTime) : DateTime.MaxValue; // When processing historical data, timestamps should not be evaluated for reasonability if (startTimeConstraint != DateTime.MinValue || stopTimeConstraint != DateTime.MaxValue) { m_localConcentrator.PerformTimestampReasonabilityCheck = false; m_localConcentrator.LeadTime = double.MaxValue; } // Assign alternate processing interval, if defined if (processingInterval != -1) m_localConcentrator.ProcessingInterval = processingInterval; // Initiate unsynchronized subscribe StringBuilder connectionString = new StringBuilder(); AssemblyInfo assemblyInfo = AssemblyInfo.ExecutingAssembly; connectionString.AppendFormat("trackLatestMeasurements={0}; ", false); connectionString.AppendFormat("inputMeasurementKeys={{{0}}}; ", filterExpression.ToNonNullString()); connectionString.AppendFormat("dataChannel={{{0}}}; ", dataChannel.ToNonNullString()); connectionString.AppendFormat("includeTime={0}; ", true); connectionString.AppendFormat("lagTime={0}; ", 10.0D); connectionString.AppendFormat("leadTime={0}; ", 5.0D); connectionString.AppendFormat("useLocalClockAsRealTime={0}; ", false); connectionString.AppendFormat("startTimeConstraint={0}; ", startTime.ToNonNullString()); connectionString.AppendFormat("stopTimeConstraint={0}; ", stopTime.ToNonNullString()); connectionString.AppendFormat("timeConstraintParameters={0}; ", constraintParameters.ToNonNullString()); connectionString.AppendFormat("processingInterval={0}; ", processingInterval); connectionString.AppendFormat("useMillisecondResolution={0}; ", m_useMillisecondResolution); connectionString.AppendFormat("assemblyInfo={{source={0}; version={1}.{2}.{3}; buildDate={4}}}", assemblyInfo.Name, assemblyInfo.Version.Major, assemblyInfo.Version.Minor, assemblyInfo.Version.Build, assemblyInfo.BuildDate.ToString("yyyy-MM-dd HH:mm:ss")); if (!string.IsNullOrWhiteSpace(waitHandleNames)) { connectionString.AppendFormat("; waitHandleNames={0}", waitHandleNames); connectionString.AppendFormat("; waitHandleTimeout={0}", waitHandleTimeout); } // Start subscription process if (Subscribe(false, compactFormat, connectionString.ToString())) { // If subscription succeeds, start local concentrator m_localConcentrator.Start(); return true; } return false; }
public virtual bool RemotelySynchronizedSubscribe(bool compactFormat, int framesPerSecond, double lagTime, double leadTime, string filterExpression, string dataChannel = null, bool useLocalClockAsRealTime = false, bool ignoreBadTimestamps = false, bool allowSortsByArrival = true, long timeResolution = Ticks.PerMillisecond, bool allowPreemptivePublishing = true, DownsamplingMethod downsamplingMethod = DownsamplingMethod.LastReceived, string startTime = null, string stopTime = null, string constraintParameters = null, int processingInterval = -1, string waitHandleNames = null, int waitHandleTimeout = 0) { // Dispose of any previously established local concentrator DisposeLocalConcentrator(); StringBuilder connectionString = new StringBuilder(); AssemblyInfo assemblyInfo = AssemblyInfo.ExecutingAssembly; connectionString.AppendFormat("framesPerSecond={0}; ", framesPerSecond); connectionString.AppendFormat("lagTime={0}; ", lagTime); connectionString.AppendFormat("leadTime={0}; ", leadTime); connectionString.AppendFormat("inputMeasurementKeys={{{0}}}; ", filterExpression.ToNonNullString()); connectionString.AppendFormat("dataChannel={{{0}}}; ", dataChannel.ToNonNullString()); connectionString.AppendFormat("includeTime=false; "); connectionString.AppendFormat("useLocalClockAsRealTime={0}; ", useLocalClockAsRealTime); connectionString.AppendFormat("ignoreBadTimestamps={0}; ", ignoreBadTimestamps); connectionString.AppendFormat("allowSortsByArrival={0}; ", allowSortsByArrival); connectionString.AppendFormat("timeResolution={0}; ", (long)timeResolution); connectionString.AppendFormat("allowPreemptivePublishing={0}; ", allowPreemptivePublishing); connectionString.AppendFormat("downsamplingMethod={0}; ", downsamplingMethod.ToString()); connectionString.AppendFormat("startTimeConstraint={0}; ", startTime.ToNonNullString()); connectionString.AppendFormat("stopTimeConstraint={0}; ", stopTime.ToNonNullString()); connectionString.AppendFormat("timeConstraintParameters={0}; ", constraintParameters.ToNonNullString()); connectionString.AppendFormat("processingInterval={0}; ", processingInterval); connectionString.AppendFormat("assemblyInfo={{source={0}; version={1}.{2}.{3}; buildDate={4}}}", assemblyInfo.Name, assemblyInfo.Version.Major, assemblyInfo.Version.Minor, assemblyInfo.Version.Build, assemblyInfo.BuildDate.ToString("yyyy-MM-dd HH:mm:ss")); if (!string.IsNullOrWhiteSpace(waitHandleNames)) { connectionString.AppendFormat("; waitHandleNames={0}", waitHandleNames); connectionString.AppendFormat("; waitHandleTimeout={0}", waitHandleTimeout); } return Subscribe(true, compactFormat, connectionString.ToString()); }
public static DatapointDatabase Create(string path, float downsamplingFactor, DownsamplingMethod downsamplingMethod, RetentionPolicy retentionPolicy, Func <DateTime> currentTimeProvider = null) { EnsureValidRetentionPolicy(retentionPolicy); using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, 8192, FileOptions.WriteThrough)) return(Create(path, fileStream, downsamplingFactor, downsamplingMethod, retentionPolicy, currentTimeProvider)); }
private static DatapointDatabase Create(string path, FileStream stream, float downsamplingFactor, DownsamplingMethod downsamplingMethod, RetentionPolicy retentionPolicy, Func <DateTime> currentTimeProvider = null) { var maxRetention = retentionPolicy.Select(h => h.Precision * h.History).Max(); var headerSize = sizeof(byte) * Signature.Length + sizeof(byte) * Version.Length + sizeof(int) + sizeof(float) + sizeof(int) + sizeof(int) + ArchiveHeaderSize * retentionPolicy.Count; var archives = new List <Archive>(); using (var binaryWriter = new BinaryWriter(stream)) { binaryWriter.Write(Signature); binaryWriter.Write(Version); // ReSharper disable RedundantCast binaryWriter.Write((int)downsamplingMethod); binaryWriter.Write((float)downsamplingFactor); binaryWriter.Write((int)maxRetention); binaryWriter.Write((int)retentionPolicy.Count); // ReSharper restore RedundantCast var offset = headerSize; foreach (var retention in retentionPolicy) { // ReSharper disable RedundantCast binaryWriter.Write((int)offset); binaryWriter.Write((int)retention.Precision); binaryWriter.Write((int)retention.History); // ReSharper restore RedundantCast archives.Add(new Archive(offset, retention.History * DatapointSize, retention)); offset += retention.History * DatapointSize; } // foreach stream.SetLength(offset); } // using return(new DatapointDatabase(path, downsamplingFactor, downsamplingMethod, maxRetention, archives, currentTimeProvider)); }
private bool m_disposed; // Disposed flag detects redundant calls to dispose method #endregion #region [ Constructors ] /// <summary> /// Creates a new <see cref="ConcentratorBase"/>. /// </summary> /// <remarks> /// Concentration will not begin until consumer "Starts" concentrator (i.e., calling <see cref="ConcentratorBase.Start"/> method or setting /// <c><see cref="ConcentratorBase.Enabled"/> = true</c>). /// </remarks> protected ConcentratorBase() { Log = Logger.CreatePublisher(GetType(), MessageClass.Framework); m_usePrecisionTimer = true; m_allowSortsByArrival = true; m_allowPreemptivePublishing = true; m_performTimestampReasonabilityCheck = true; m_processingInterval = -1; m_downsamplingMethod = DownsamplingMethod.LastReceived; m_latestMeasurements = new ImmediateMeasurements(this); m_maximumPublicationTimeout = Timeout.Infinite; // Create a new queue for managing real-time frames m_frameQueue = new FrameQueue(this.CreateNewFrame); // Set minimum timer resolution to one millisecond to improve timer accuracy PrecisionTimer.SetMinimumTimerResolution(1); // Create publication wait handle m_publicationWaitHandle = new AutoResetEvent(false); // Create publication thread m_publicationThread = new Thread(PublishFrames); m_publicationThread.Start(); // This timer monitors the total number of unpublished samples every 5 seconds. This is a useful statistic // to monitor: if total number of unpublished samples exceed lag time, measurement concentration could // be falling behind. m_monitorTimer = Common.TimerScheduler.CreateTimer(5000); m_monitorTimer.AutoReset = true; m_monitorTimer.Elapsed += MonitorUnpublishedSamples; }