Przeglądaj źródła

Realloc references array in addOneWayReferenceWithSession if multithreading is disabled. See #224.

Julius Pfrommer 10 lat temu
rodzic
commit
59d9945576
1 zmienionych plików z 34 dodań i 9 usunięć
  1. 34 9
      src/server/ua_server_addressspace.c

+ 34 - 9
src/server/ua_server_addressspace.c

@@ -57,7 +57,31 @@ addOneWayReferenceWithSession(UA_Server *server, UA_Session *session, const UA_A
     const UA_Node *node = UA_NodeStore_get(server->nodestore, &item->sourceNodeId);
     if(!node)
         return UA_STATUSCODE_BADINTERNALERROR;
-
+	UA_StatusCode retval = UA_STATUSCODE_GOOD;
+#ifndef UA_MULTITHREADING
+	size_t i = node->referencesSize;
+	if(node->referencesSize < 0)
+		i = 0;
+	UA_ReferenceNode *new_refs = UA_realloc(node->references, sizeof(UA_ReferenceNode) * (i + 1));
+	if(!new_refs)
+		retval = UA_STATUSCODE_BADOUTOFMEMORY;
+	else {
+		UA_ReferenceNode_init(&new_refs[i]);
+		retval = UA_NodeId_copy(&item->referenceTypeId, &new_refs[i].referenceTypeId);
+		new_refs[i].isInverse = !item->isForward;
+		retval |= UA_ExpandedNodeId_copy(&item->targetNodeId, &new_refs[i].targetId);
+		/* hack. be careful! possible only in the single-threaded case. */
+		UA_Node *mutable_node = (UA_Node*)(uintptr_t)node;
+		mutable_node->references = new_refs;
+		if(retval != UA_STATUSCODE_GOOD) {
+			UA_NodeId_deleteMembers(&new_refs[node->referencesSize].referenceTypeId);
+			UA_ExpandedNodeId_deleteMembers(&new_refs[node->referencesSize].targetId);
+		} else
+			mutable_node->referencesSize = i+1;
+	}
+	UA_NodeStore_release(node);
+	return retval;
+#else
     UA_Node *newNode = UA_NULL;
     void (*deleteNode)(UA_Node*) = UA_NULL;
     switch(node->nodeClass) {
@@ -119,7 +143,7 @@ addOneWayReferenceWithSession(UA_Server *server, UA_Session *session, const UA_A
     // insert the new reference
     UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
     UA_ReferenceNode_init(&new_refs[count]);
-    UA_StatusCode retval = UA_NodeId_copy(&item->referenceTypeId, &new_refs[count].referenceTypeId);
+    retval = UA_NodeId_copy(&item->referenceTypeId, &new_refs[count].referenceTypeId);
     new_refs[count].isInverse = !item->isForward;
     retval |= UA_ExpandedNodeId_copy(&item->targetNodeId, &new_refs[count].targetId);
     if(retval != UA_STATUSCODE_GOOD) {
@@ -135,13 +159,14 @@ addOneWayReferenceWithSession(UA_Server *server, UA_Session *session, const UA_A
     newNode->references = new_refs;
     newNode->referencesSize = ++count;
     retval = UA_NodeStore_replace(server->nodestore, node, newNode, UA_NULL);
-    UA_NodeStore_release(node);
-    if(retval != UA_STATUSCODE_BADINTERNALERROR)
-        return retval;
-    
-    // error presumably because the node was replaced and an old version was updated just try again
-    deleteNode(newNode);
-    return addOneWayReferenceWithSession(server, session, item);
+	UA_NodeStore_release(node);
+	if (retval == UA_STATUSCODE_BADINTERNALERROR) {
+		/* presumably because the node was replaced and an old version was updated at the same time. just try again */
+		deleteNode(newNode);
+		return addOneWayReferenceWithSession(server, session, item);
+	}
+	return retval;
+#endif
 }
 
 /* userland version of addReferenceWithSession */