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);
}
}
}