|
@@ -1141,19 +1141,15 @@ UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
|
|
|
/* Delete Nodes */
|
|
|
/****************/
|
|
|
|
|
|
-/* In the single-threaded case, references are removed in the node (even though
|
|
|
- * it appears to be const here). We always delete the last element. And then
|
|
|
- * reread the node. */
|
|
|
static void
|
|
|
-removeReferences(UA_Server *server, UA_Session *session, const volatile UA_Node *node) {
|
|
|
+removeReferences(UA_Server *server, UA_Session *session, const UA_Node *node) {
|
|
|
UA_DeleteReferencesItem item;
|
|
|
UA_DeleteReferencesItem_init(&item);
|
|
|
- item.sourceNodeId = node->nodeId;
|
|
|
- item.deleteBidirectional = true;
|
|
|
- for(size_t refs = node->referencesSize; refs > 0; --refs) {
|
|
|
- item.isForward = !node->references[refs - 1].isInverse;
|
|
|
- item.targetNodeId.nodeId = node->references[refs - 1].targetId.nodeId;
|
|
|
- item.referenceTypeId = node->references[refs - 1].referenceTypeId;
|
|
|
+ item.targetNodeId.nodeId = node->nodeId;
|
|
|
+ for(size_t i = 0; i < node->referencesSize; ++i) {
|
|
|
+ item.isForward = node->references[i].isInverse;
|
|
|
+ item.sourceNodeId = node->references[i].targetId.nodeId;
|
|
|
+ item.referenceTypeId = node->references[i].referenceTypeId;
|
|
|
Service_DeleteReferences_single(server, session, &item);
|
|
|
}
|
|
|
}
|
|
@@ -1165,30 +1161,20 @@ Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
|
|
|
if(!node)
|
|
|
return UA_STATUSCODE_BADNODEIDUNKNOWN;
|
|
|
|
|
|
- /* TODO: check if consistency is violated */
|
|
|
+ /* TODO: check if the information model consistency is violated */
|
|
|
|
|
|
/* Destroy an object before removing it */
|
|
|
if(node->nodeClass == UA_NODECLASS_OBJECT) {
|
|
|
- /* find the object type(s) */
|
|
|
- UA_BrowseDescription bd;
|
|
|
- UA_BrowseDescription_init(&bd);
|
|
|
- bd.browseDirection = UA_BROWSEDIRECTION_INVERSE;
|
|
|
- bd.nodeId = *nodeId;
|
|
|
- bd.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
|
|
|
- bd.includeSubtypes = true;
|
|
|
- bd.nodeClassMask = UA_NODECLASS_OBJECTTYPE;
|
|
|
-
|
|
|
/* Call the destructor from the object type */
|
|
|
const UA_ObjectTypeNode *typenode = getObjectNodeType(server, (const UA_ObjectNode*)node);
|
|
|
if(typenode && typenode->lifecycleManagement.destructor)
|
|
|
typenode->lifecycleManagement.destructor(*nodeId, ((const UA_ObjectNode*)node)->instanceHandle);
|
|
|
}
|
|
|
|
|
|
- /* Remove references */
|
|
|
- if(deleteReferences) {
|
|
|
+ /* Remove references to the node (not the references in the node that will
|
|
|
+ * be deleted anyway) */
|
|
|
+ if(deleteReferences)
|
|
|
removeReferences(server, session, node);
|
|
|
- UA_assert(node->referencesSize == 0);
|
|
|
- }
|
|
|
|
|
|
return UA_NodeStore_remove(server->nodestore, nodeId);
|
|
|
}
|