/// <summary> /// Checks if the item meets the group's criteria. /// </summary> private bool MeetsGroupCriteria(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { // can only sample variables. if ((monitoredItem.MonitoredItemType & MonitoredItemTypeMask.DataChange) == 0) { return(false); } // can't sample disabled items. if (monitoredItem.MonitoringMode == MonitoringMode.Disabled) { return(false); } // check sampling interval. if (AdjustSamplingInterval(monitoredItem.SamplingInterval) != m_samplingInterval) { return(false); } // compare session. if (context.SessionId != m_session.Id) { return(false); } // check the diagnostics marks. if (m_diagnosticsMask != (context.DiagnosticsMask & DiagnosticsMasks.OperationAll)) { return(false); } return(true); }
/// <summary> /// Changes monitoring attributes the item. /// </summary> /// <remarks> /// It will call the external source to change the monitoring if an external source was provided originally. /// The changes will not take affect until the ApplyChanges() method is called. /// </remarks> public virtual void ModifyMonitoring(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { // find existing sampling group. SamplingGroup samplingGroup = null; if (m_sampledItems.TryGetValue(monitoredItem, out samplingGroup)) { if (samplingGroup != null) { if (samplingGroup.ModifyMonitoring(context, monitoredItem)) { return; } } m_sampledItems.Remove(monitoredItem); } // assign to a new sampling group. StartMonitoring(context, monitoredItem); return; } }
/// <summary> /// Starts monitoring the item. /// </summary> /// <remarks> /// It will use the external source for monitoring if the source accepts the item. /// The changes will not take affect until the ApplyChanges() method is called. /// </remarks> public virtual void StartMonitoring(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { // do nothing for disabled or exception based items. if (monitoredItem.MonitoringMode == MonitoringMode.Disabled || monitoredItem.MinimumSamplingInterval == 0) { m_sampledItems.Add(monitoredItem, null); return; } // find a suitable sampling group. foreach (SamplingGroup samplingGroup in m_samplingGroups) { if (samplingGroup.StartMonitoring(context, monitoredItem)) { m_sampledItems.Add(monitoredItem, samplingGroup); return; } } // create a new sampling group. SamplingGroup samplingGroup2 = new SamplingGroup( m_server, m_nodeManager, m_samplingRates, context, monitoredItem.SamplingInterval); samplingGroup2.StartMonitoring(context, monitoredItem); m_samplingGroups.Add(samplingGroup2); m_sampledItems.Add(monitoredItem, samplingGroup2); } }
/// <summary> /// Updates the group by apply any pending changes. /// </summary> /// <returns> /// Returns true if the group has no more items and can be dropped. /// </returns> public bool ApplyChanges() { lock (m_lock) { // add items. List <ISampledDataChangeMonitoredItem> itemsToSample = new List <ISampledDataChangeMonitoredItem>(); for (int ii = 0; ii < m_itemsToAdd.Count; ii++) { ISampledDataChangeMonitoredItem monitoredItem = m_itemsToAdd[ii]; if (!m_items.ContainsKey(monitoredItem.Id)) { m_items.Add(monitoredItem.Id, monitoredItem); if (monitoredItem.MonitoringMode != MonitoringMode.Disabled) { itemsToSample.Add(monitoredItem); } } } m_itemsToAdd.Clear(); // collect first sample. if (itemsToSample.Count > 0) { Task.Run(() => { DoSample(itemsToSample); }); } // remove items. for (int ii = 0; ii < m_itemsToRemove.Count; ii++) { m_items.Remove(m_itemsToRemove[ii].Id); } m_itemsToRemove.Clear(); // start the group if it is not running. if (m_items.Count > 0) { Startup(); } // stop the group if it is running. else if (m_items.Count == 0) { Shutdown(); } // can be shutdown if no items left. return(m_items.Count == 0); } }
/// <summary> /// Stops monitoring the item. /// </summary> /// <returns> /// Returns true if the items was marked for removal from the group. /// </returns> public bool StopMonitoring(ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { if (m_items.ContainsKey(monitoredItem.Id)) { m_itemsToRemove.Add(monitoredItem); return(true); } return(false); } }
/// <summary> /// Checks if the monitored item can be handled by the group. /// </summary> /// <returns> /// True if the item was added to the group. /// </returns> /// <remarks> /// The ApplyChanges() method must be called to actually start sampling the item. /// </remarks> public bool StartMonitoring(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { if (MeetsGroupCriteria(context, monitoredItem)) { m_itemsToAdd.Add(monitoredItem); monitoredItem.SetSamplingInterval(m_samplingInterval); return(true); } return(false); } }
/// <summary> /// Checks if the monitored item can still be handled by the group. /// </summary> /// <returns> /// False if the item has be marked for removal from the group. /// </returns> /// <remarks> /// The ApplyChanges() method must be called to actually stop sampling the item. /// </remarks> public bool ModifyMonitoring(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { if (m_items.ContainsKey(monitoredItem.Id)) { if (MeetsGroupCriteria(context, monitoredItem)) { monitoredItem.SetSamplingInterval(m_samplingInterval); return(true); } m_itemsToRemove.Add(monitoredItem); } return(false); } }
/// <summary> /// Stops monitoring the item. /// </summary> /// <remarks> /// It will call the external source to stop the monitoring if an external source was provided originally. /// The changes will not take affect until the ApplyChanges() method is called. /// </remarks> public virtual void StopMonitoring(ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { // check for sampling group. SamplingGroup samplingGroup = null; if (m_sampledItems.TryGetValue(monitoredItem, out samplingGroup)) { if (samplingGroup != null) { samplingGroup.StopMonitoring(monitoredItem); } m_sampledItems.Remove(monitoredItem); return; } } }
/// <summary> /// Periodically checks if the sessions have timed out. /// </summary> private void SampleMonitoredItems(object data) { try { //Utils.Trace("Server: {0} Thread Started.", Thread.CurrentThread.Name); int sleepCycle = Convert.ToInt32(data, CultureInfo.InvariantCulture); int timeToWait = sleepCycle; while (m_server.IsRunning) { DateTime start = DateTime.UtcNow; // wait till next sample. if (m_shutdownEvent.WaitOne(timeToWait)) { break; } // get current list of items to sample. List <ISampledDataChangeMonitoredItem> items = new List <ISampledDataChangeMonitoredItem>(); lock (m_lock) { uint disabledItemCount = 0; Dictionary <uint, ISampledDataChangeMonitoredItem> .Enumerator enumerator = m_items.GetEnumerator(); while (enumerator.MoveNext()) { ISampledDataChangeMonitoredItem monitoredItem = enumerator.Current.Value; if (monitoredItem.MonitoringMode == MonitoringMode.Disabled) { disabledItemCount++; continue; } // check whether the item should be sampled. //if (!monitoredItem.SamplingIntervalExpired()) //{ // continue; //} items.Add(monitoredItem); } } // sample the values. DoSample(items); int delay = (int)(DateTime.UtcNow - start).TotalMilliseconds; timeToWait = sleepCycle; if (delay > sleepCycle) { timeToWait = 2 * sleepCycle - delay; if (timeToWait < 0) { Utils.Trace("WARNING: SamplingGroup cannot sample fast enough. TimeToSample={0}ms, SamplingInterval={1}ms", delay, sleepCycle); timeToWait = sleepCycle; } } } //Utils.Trace("Server: {0} Thread Exited Normally.", Thread.CurrentThread.Name); } catch (Exception e) { Utils.Trace(e, "Server: SampleMonitoredItems Thread Exited Unexpectedly."); } }
/// <summary> /// Checks if the monitored item can be handled by the group. /// </summary> /// <returns> /// True if the item was added to the group. /// </returns> /// <remarks> /// The ApplyChanges() method must be called to actually start sampling the item. /// </remarks> public bool StartMonitoring(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { if (MeetsGroupCriteria(context, monitoredItem)) { m_itemsToAdd.Add(monitoredItem); monitoredItem.SetSamplingInterval(m_samplingInterval); return true; } return false; } }
/// <summary> /// Checks if the monitored item can still be handled by the group. /// </summary> /// <returns> /// False if the item has be marked for removal from the group. /// </returns> /// <remarks> /// The ApplyChanges() method must be called to actually stop sampling the item. /// </remarks> public bool ModifyMonitoring(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { if (m_items.ContainsKey(monitoredItem.Id)) { if (MeetsGroupCriteria(context, monitoredItem)) { monitoredItem.SetSamplingInterval(m_samplingInterval); return true; } m_itemsToRemove.Add(monitoredItem); } return false; } }
/// <summary> /// Modifies a monitored item and calls ModifyMonitoring(). /// </summary> public virtual ServiceResult ModifyMonitoredItem( OperationContext context, TimestampsToReturn timestampsToReturn, ISampledDataChangeMonitoredItem monitoredItem, MonitoredItemModifyRequest itemToModify, Range range) { // use existing interval as sampling interval. double samplingInterval = itemToModify.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = monitoredItem.SamplingInterval; } // limit the sampling interval. double minimumSamplingInterval = monitoredItem.MinimumSamplingInterval; if (minimumSamplingInterval > 0 && samplingInterval < minimumSamplingInterval) { samplingInterval = minimumSamplingInterval; } // calculate queue size. uint queueSize = itemToModify.RequestedParameters.QueueSize; if (queueSize == 0) { queueSize = monitoredItem.QueueSize; } if (queueSize > m_maxQueueSize) { queueSize = m_maxQueueSize; } // get filter. MonitoringFilter filter = null; if (!ExtensionObject.IsNull(itemToModify.RequestedParameters.Filter)) { filter = (MonitoringFilter)itemToModify.RequestedParameters.Filter.Body; } // update limits for event filters. if (filter is EventFilter) { samplingInterval = 0; } // modify the item attributes. ServiceResult error = monitoredItem.ModifyAttributes( context.DiagnosticsMask, timestampsToReturn, itemToModify.RequestedParameters.ClientHandle, filter, filter, range, samplingInterval, queueSize, itemToModify.RequestedParameters.DiscardOldest); // state of item did not change if an error returned here. if (ServiceResult.IsBad(error)) { return error; } // update sampling. ModifyMonitoring(context, monitoredItem); // everything is ok. return ServiceResult.Good; }
/// <summary> /// Stops monitoring the item. /// </summary> /// <returns> /// Returns true if the items was marked for removal from the group. /// </returns> public bool StopMonitoring(ISampledDataChangeMonitoredItem monitoredItem) { lock (m_lock) { if (m_items.ContainsKey(monitoredItem.Id)) { m_itemsToRemove.Add(monitoredItem); return true; } return false; } }
/// <summary> /// Modifies a monitored item and calls ModifyMonitoring(). /// </summary> public virtual ServiceResult ModifyMonitoredItem( OperationContext context, TimestampsToReturn timestampsToReturn, ISampledDataChangeMonitoredItem monitoredItem, MonitoredItemModifyRequest itemToModify, Range range) { // use existing interval as sampling interval. double samplingInterval = itemToModify.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = monitoredItem.SamplingInterval; } // limit the sampling interval. double minimumSamplingInterval = monitoredItem.MinimumSamplingInterval; if (minimumSamplingInterval > 0 && samplingInterval < minimumSamplingInterval) { samplingInterval = minimumSamplingInterval; } // calculate queue size. uint queueSize = itemToModify.RequestedParameters.QueueSize; if (queueSize == 0) { queueSize = monitoredItem.QueueSize; } if (queueSize > m_maxQueueSize) { queueSize = m_maxQueueSize; } // get filter. MonitoringFilter filter = null; if (!ExtensionObject.IsNull(itemToModify.RequestedParameters.Filter)) { filter = (MonitoringFilter)itemToModify.RequestedParameters.Filter.Body; } // update limits for event filters. if (filter is EventFilter) { samplingInterval = 0; } // modify the item attributes. ServiceResult error = monitoredItem.ModifyAttributes( context.DiagnosticsMask, timestampsToReturn, itemToModify.RequestedParameters.ClientHandle, filter, filter, range, samplingInterval, queueSize, itemToModify.RequestedParameters.DiscardOldest); // state of item did not change if an error returned here. if (ServiceResult.IsBad(error)) { return(error); } // update sampling. ModifyMonitoring(context, monitoredItem); // everything is ok. return(ServiceResult.Good); }
/// <summary> /// Checks if the item meets the group's criteria. /// </summary> private bool MeetsGroupCriteria(OperationContext context, ISampledDataChangeMonitoredItem monitoredItem) { // can only sample variables. if ((monitoredItem.MonitoredItemType & MonitoredItemTypeMask.DataChange) == 0) { return false; } // can't sample disabled items. if (monitoredItem.MonitoringMode == MonitoringMode.Disabled) { return false; } // check sampling interval. if (AdjustSamplingInterval(monitoredItem.SamplingInterval) != m_samplingInterval) { return false; } // compare session. if (context.SessionId != m_session.Id) { return false; } // check the diagnostics marks. if (m_diagnosticsMask != (context.DiagnosticsMask & DiagnosticsMasks.OperationAll)) { return false; } return true; }