/// <summary> /// Creates a new set of monitored items for a set of variables. /// </summary> /// <remarks> /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// </remarks> public virtual void CreateMonitoredItems( OperationContext context, uint subscriptionId, double publishingInterval, TimestampsToReturn timestampsToReturn, IList<MonitoredItemCreateRequest> itemsToCreate, IList<ServiceResult> errors, IList<MonitoringFilterResult> filterErrors, IList<IMonitoredItem> monitoredItems, ref long globalIdCounter) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>(); lock (Lock) { for (int ii = 0; ii < itemsToCreate.Count; ii++) { MonitoredItemCreateRequest itemToCreate = itemsToCreate[ii]; // skip items that have already been processed. if (itemToCreate.Processed) { continue; } ReadValueId itemToMonitor = itemToCreate.ItemToMonitor; // check for valid handle. NodeState source = GetManagerHandle(systemContext, itemToMonitor.NodeId, operationCache) as NodeState; if (source == null) { continue; } // owned by this node manager. itemToCreate.Processed = true; // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a seperate operation. ReadWriteOperationState operation = new ReadWriteOperationState(); operation.Source = source; operation.Index = ii; nodesToValidate.Add(operation); continue; } MonitoringFilterResult filterError = null; IMonitoredItem monitoredItem = null; errors[ii] = CreateMonitoredItem( systemContext, source, subscriptionId, publishingInterval, context.DiagnosticsMask, timestampsToReturn, itemToCreate, ref globalIdCounter, out filterError, out monitoredItem); // save any filter error details. filterErrors[ii] = filterError; if (ServiceResult.IsBad(errors[ii])) { continue; } // save the monitored item. monitoredItems[ii] = monitoredItem; } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; // validate the object. if (!ValidateNode(systemContext, operation.Source)) { continue; } MonitoredItemCreateRequest itemToCreate = itemsToCreate[operation.Index]; MonitoringFilterResult filterError = null; IMonitoredItem monitoredItem = null; errors[operation.Index] = CreateMonitoredItem( systemContext, operation.Source, subscriptionId, publishingInterval, context.DiagnosticsMask, timestampsToReturn, itemToCreate, ref globalIdCounter, out filterError, out monitoredItem); // save any filter error details. filterErrors[operation.Index] = filterError; if (ServiceResult.IsBad(errors[operation.Index])) { continue; } // save the monitored item. monitoredItems[operation.Index] = monitoredItem; } } }
/// <summary> /// Updates the history for the specified nodes. /// </summary> public virtual void HistoryUpdate( OperationContext context, Type detailsType, IList<HistoryUpdateDetails> nodesToUpdate, IList<HistoryUpdateResult> results, IList<ServiceResult> errors) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>(); lock (Lock) { for (int ii = 0; ii < nodesToUpdate.Count; ii++) { HistoryUpdateDetails nodeToUpdate = nodesToUpdate[ii]; // skip items that have already been processed. if (nodeToUpdate.Processed) { continue; } // check for valid handle. NodeState source = GetManagerHandle(systemContext, nodeToUpdate.NodeId, operationCache) as NodeState; if (source == null) { continue; } // owned by this node manager. nodeToUpdate.Processed = true; // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a seperate operation. ReadWriteOperationState operation = new ReadWriteOperationState(); operation.Source = source; operation.Index = ii; nodesToValidate.Add(operation); continue; } // historical data not available. errors[ii] = StatusCodes.BadHistoryOperationUnsupported; } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } // historical data not available. errors[ii] = StatusCodes.BadHistoryOperationUnsupported; } } }
/// <summary> /// Reads the history for the specified nodes. /// </summary> public virtual void HistoryRead( OperationContext context, HistoryReadDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, IList<HistoryReadValueId> nodesToRead, IList<HistoryReadResult> results, IList<ServiceResult> errors) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>(); List<ReadWriteOperationState> readsToComplete = new List<ReadWriteOperationState>(); lock (Lock) { for (int ii = 0; ii < nodesToRead.Count; ii++) { HistoryReadValueId nodeToRead = nodesToRead[ii]; // skip items that have already been processed. if (nodeToRead.Processed) { continue; } // check for valid handle. NodeState source = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache) as NodeState; if (source == null) { continue; } // owned by this node manager. nodeToRead.Processed = true; // only variables supported. BaseVariableState variable = source as BaseVariableState; if (variable == null) { errors[ii] = StatusCodes.BadHistoryOperationUnsupported; continue; } results[ii] = new HistoryReadResult(); ReadWriteOperationState operation = new ReadWriteOperationState(); operation.Source = source; operation.Index = ii; // check if the node is ready for reading. if (source.ValidationRequired) { // must validate node in a seperate operation. errors[ii] = StatusCodes.BadNodeIdUnknown; nodesToValidate.Add(operation); continue; } // read the data. readsToComplete.Add(operation); } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } readsToComplete.Add(operation); } } // reads the data without holding onto the lock. for (int ii = 0; ii < readsToComplete.Count; ii++) { ReadWriteOperationState operation = readsToComplete[ii]; errors[operation.Index] = HistoryRead( systemContext, operation.Source, details, timestampsToReturn, releaseContinuationPoints, nodesToRead[operation.Index], results[operation.Index]); } }
/// <summary> /// Writes the value for the specified attributes. /// </summary> public virtual void Write( OperationContext context, IList<WriteValue> nodesToWrite, IList<ServiceResult> errors) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>(); lock (Lock) { for (int ii = 0; ii < nodesToWrite.Count; ii++) { WriteValue nodeToWrite = nodesToWrite[ii]; // skip items that have already been processed. if (nodeToWrite.Processed) { continue; } // check for valid handle. NodeState source = GetManagerHandle(systemContext, nodeToWrite.NodeId, operationCache) as NodeState; if (source == null) { continue; } // owned by this node manager. nodeToWrite.Processed = true; // index range is not supported. if (!String.IsNullOrEmpty(nodeToWrite.IndexRange)) { errors[ii] = StatusCodes.BadIndexRangeInvalid; continue; } // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a seperate operation. ReadWriteOperationState operation = new ReadWriteOperationState(); operation.Source = source; operation.Index = ii; nodesToValidate.Add(operation); continue; } // write the attribute value. errors[ii] = source.WriteAttribute( systemContext, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. source.ClearChangeMasks(systemContext, false); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } WriteValue nodeToWrite = nodesToWrite[operation.Index]; // write the attribute value. errors[operation.Index] = operation.Source.WriteAttribute( systemContext, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. operation.Source.ClearChangeMasks(systemContext, false); } } }
/// <summary> /// Reads the value for the specified attribute. /// </summary> public virtual void Read( OperationContext context, double maxAge, IList<ReadValueId> nodesToRead, IList<DataValue> values, IList<ServiceResult> errors) { ServerSystemContext systemContext = m_systemContext.Copy(context); IDictionary<NodeId,NodeState> operationCache = new NodeIdDictionary<NodeState>(); List<ReadWriteOperationState> nodesToValidate = new List<ReadWriteOperationState>(); lock (Lock) { for (int ii = 0; ii < nodesToRead.Count; ii++) { ReadValueId nodeToRead = nodesToRead[ii]; // skip items that have already been processed. if (nodeToRead.Processed) { continue; } // check for valid handle. NodeState source = GetManagerHandle(systemContext, nodeToRead.NodeId, operationCache) as NodeState; if (source == null) { continue; } // owned by this node manager. nodeToRead.Processed = true; // create an initial value. DataValue value = values[ii] = new DataValue(); value.Value = null; value.ServerTimestamp = DateTime.UtcNow; value.SourceTimestamp = DateTime.MinValue; value.StatusCode = StatusCodes.Good; // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a seperate operation. ReadWriteOperationState operation = new ReadWriteOperationState(); operation.Source = source; operation.Index = ii; nodesToValidate.Add(operation); continue; } // read the attribute value. errors[ii] = source.ReadAttribute( systemContext, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } ReadValueId nodeToRead = nodesToRead[operation.Index]; DataValue value = values[operation.Index]; // update the attribute value. errors[operation.Index] = operation.Source.ReadAttribute( systemContext, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); } } }