Commit c1162fb4 authored by oroulet's avatar oroulet Committed by oroulet

reduce number of dictionnary lookup in address space. might break something...

parent 46a1ebd5
......@@ -188,54 +188,60 @@ class NodeManagementService(object):
results.append(self._add_node(item, user))
return results
def try_add_nodes(self, addnodeitems, user=User.Admin):
def try_add_nodes(self, addnodeitems, user=User.Admin, check=True):
for item in addnodeitems:
ret = self._add_node(item, user)
ret = self._add_node(item, user, check=check)
if not ret.StatusCode.is_good():
yield item
def _add_node(self, item, user):
def _add_node(self, item, user, check=True):
self.logger.debug("Adding node %s %s", item.RequestedNewNodeId, item.BrowseName)
result = ua.AddNodesResult()
# If Identifier of requested NodeId is null we generate a new NodeId using
# the namespace of the nodeid, this is an extention of the spec to allow
# to requests the server to generate a new nodeid in a specified namespace
if not user == User.Admin:
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadUserAccessDenied)
return result
if item.RequestedNewNodeId.has_null_identifier():
# If Identifier of requested NodeId is null we generate a new NodeId using
# the namespace of the nodeid, this is an extention of the spec to allow
# to requests the server to generate a new nodeid in a specified namespace
self.logger.debug("RequestedNewNodeId has null identifier, generating Identifier")
nodedata = NodeData(self._aspace.generate_nodeid(item.RequestedNewNodeId.NamespaceIndex))
item.RequestedNewNodeId = self._aspace.generate_nodeid(item.RequestedNewNodeId.NamespaceIndex)
else:
nodedata = NodeData(item.RequestedNewNodeId)
if nodedata.nodeid in self._aspace:
self.logger.warning("AddNodesItem: Requested NodeId %s already exists", nodedata.nodeid)
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdExists)
return result
if item.RequestedNewNodeId in self._aspace:
self.logger.warning("AddNodesItem: Requested NodeId %s already exists", item.RequestedNewNodeId)
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdExists)
return result
if item.ParentNodeId.is_null():
# self.logger.warning("add_node: creating node %s without parent", nodedata.nodeid)
# should return Error here, but the standard namespace define many nodes without parents...
pass
elif item.ParentNodeId not in self._aspace:
self.logger.warning("add_node: while adding node %s, requested parent node %s does not exists", nodedata.nodeid, item.ParentNodeId)
self.logger.info("add_node: while adding node %s, requested parent node is null %s %s",
item.RequestedNewNodeId, item.ParentNodeId, item.ParentNodeId.is_null())
if check:
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadParentNodeIdInvalid)
return result
parentdata = self._aspace.get(item.ParentNodeId)
if parentdata is None and not item.ParentNodeId.is_null():
self.logger.info("add_node: while adding node %s, requested parent node %s does not exists",
item.RequestedNewNodeId, item.ParentNodeId)
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadParentNodeIdInvalid)
return result
if not user == User.Admin:
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadUserAccessDenied)
return result
nodedata = NodeData(item.RequestedNewNodeId)
self._add_node_attributes(nodedata, item)
# now add our node to db
self._aspace[nodedata.nodeid] = nodedata
if not item.ParentNodeId.is_null():
self._add_ref_from_parent(nodedata, item)
self._add_ref_to_parent(nodedata, item, user)
if parentdata is not None:
self._add_ref_from_parent(nodedata, item, parentdata)
self._add_ref_to_parent(nodedata, item, parentdata)
# add type definition
if item.TypeDefinition != ua.NodeId():
self._add_type_definition(nodedata, item, user)
self._add_type_definition(nodedata, item)
result.StatusCode = ua.StatusCode()
result.AddedNodeId = nodedata.nodeid
......@@ -256,20 +262,18 @@ class NodeManagementService(object):
# add requested attrs
self._add_nodeattributes(item.NodeAttributes, nodedata)
def _add_unique_reference(self, source, desc):
refs = self._aspace[source].references
for r in refs:
def _add_unique_reference(self, nodedata, desc):
for r in nodedata.references:
if r.ReferenceTypeId == desc.ReferenceTypeId and r.NodeId == desc.NodeId:
if r.IsForward != desc.IsForward:
if r.IsForward != desc.IsForward:
self.logger.error("Cannot add conflicting reference %s ", str(desc))
return ua.StatusCode(ua.StatusCodes.BadReferenceNotAllowed)
break # ref already exists
break # ref already exists
else:
refs.append(desc)
nodedata.references.append(desc)
return ua.StatusCode()
def _add_ref_from_parent(self, nodedata, item):
def _add_ref_from_parent(self, nodedata, item, parentdata):
desc = ua.ReferenceDescription()
desc.ReferenceTypeId = item.ReferenceTypeId
desc.NodeId = nodedata.nodeid
......@@ -278,25 +282,25 @@ class NodeManagementService(object):
desc.DisplayName = item.NodeAttributes.DisplayName
desc.TypeDefinition = item.TypeDefinition
desc.IsForward = True
self._add_unique_reference(item.ParentNodeId, desc)
self._add_unique_reference(parentdata, desc)
def _add_ref_to_parent(self, nodedata, item, user):
def _add_ref_to_parent(self, nodedata, item, parentdata):
addref = ua.AddReferencesItem()
addref.ReferenceTypeId = item.ReferenceTypeId
addref.SourceNodeId = nodedata.nodeid
addref.TargetNodeId = item.ParentNodeId
addref.TargetNodeClass = self._aspace[item.ParentNodeId].attributes[ua.AttributeIds.NodeClass].value.Value.Value
addref.TargetNodeClass = parentdata.attributes[ua.AttributeIds.NodeClass].value.Value.Value
addref.IsForward = False
self._add_reference(addref, user)
self._add_reference_no_check(nodedata, addref)
def _add_type_definition(self, nodedata, item, user):
def _add_type_definition(self, nodedata, item):
addref = ua.AddReferencesItem()
addref.SourceNodeId = nodedata.nodeid
addref.IsForward = True
addref.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasTypeDefinition)
addref.TargetNodeId = item.TypeDefinition
addref.TargetNodeClass = ua.NodeClass.DataType
self._add_reference(addref, user)
self._add_reference_no_check(nodedata, addref)
def delete_nodes(self, deletenodeitems, user=User.Admin):
results = []
......@@ -345,12 +349,16 @@ class NodeManagementService(object):
yield ref
def _add_reference(self, addref, user):
if addref.SourceNodeId not in self._aspace:
sourcedata = self._aspace.get(addref.SourceNodeId)
if sourcedata is None:
return ua.StatusCode(ua.StatusCodes.BadSourceNodeIdInvalid)
if addref.TargetNodeId not in self._aspace:
return ua.StatusCode(ua.StatusCodes.BadTargetNodeIdInvalid)
if user != User.Admin:
return ua.StatusCode(ua.StatusCodes.BadUserAccessDenied)
return self._add_reference_no_check(sourcedata, addref)
def _add_reference_no_check(self, sourcedata, addref):
rdesc = ua.ReferenceDescription()
rdesc.ReferenceTypeId = addref.ReferenceTypeId
rdesc.IsForward = addref.IsForward
......@@ -362,7 +370,7 @@ class NodeManagementService(object):
dname = self._aspace.get_attribute_value(addref.TargetNodeId, ua.AttributeIds.DisplayName).Value.Value
if dname:
rdesc.DisplayName = dname
return self._add_unique_reference(addref.SourceNodeId, rdesc)
return self._add_unique_reference(sourcedata, rdesc)
def delete_references(self, refs, user=User.Admin):
result = []
......@@ -370,7 +378,7 @@ class NodeManagementService(object):
result.append(self._delete_reference(ref, user))
return result
def _delete_unique_reference(self, item, invert = False):
def _delete_unique_reference(self, item, invert=False):
if invert:
source, target, forward = item.TargetNodeId, item.SourceNodeId, not item.IsForward
else:
......@@ -485,8 +493,11 @@ class AddressSpace(object):
def __getitem__(self, nodeid):
with self._lock:
if nodeid in self._nodes:
return self._nodes.__getitem__(nodeid)
return self._nodes.__getitem__(nodeid)
def get(self, nodeid):
with self._lock:
return self._nodes.get(nodeid, None)
def __setitem__(self, nodeid, value):
with self._lock:
......
......@@ -20,7 +20,7 @@ class PostponeReferences(object):
#self.add_nodes = self.server.add_nodes
def add_nodes(self,nodes):
self.postponed_nodes.extend(self.server.try_add_nodes(nodes))
self.postponed_nodes.extend(self.server.try_add_nodes(nodes, check=False))
def add_references(self, refs):
self.postponed_refs.extend(self.server.try_add_references(refs))
......@@ -33,7 +33,7 @@ class PostponeReferences(object):
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None and exc_val is None:
remaining_nodes = list(self.server.try_add_nodes(self.postponed_nodes))
remaining_nodes = list(self.server.try_add_nodes(self.postponed_nodes, check=False))
assert len(remaining_nodes) == 0, remaining_nodes
remaining_refs = list(self.server.try_add_references(self.postponed_refs))
assert len(remaining_refs) == 0, remaining_refs
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment