瀏覽代碼

Remove duplicate code for UA_Node_deleteReferences

Julius Pfrommer 6 年之前
父節點
當前提交
dad8e92bad
共有 3 個文件被更改,包括 53 次插入80 次删除
  1. 44 7
      src/server/ua_nodes.c
  2. 7 1
      src/server/ua_server_internal.h
  3. 2 72
      src/server/ua_services_nodemanagement.c

+ 44 - 7
src/server/ua_nodes.c

@@ -2,7 +2,7 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. 
  *
- *    Copyright 2015-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
+ *    Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  *    Copyright 2015-2016 (c) Sten Grüner
  *    Copyright 2015 (c) Chris Iatrou
  *    Copyright 2015, 2017 (c) Florian Palm
@@ -595,14 +595,51 @@ UA_Node_deleteReference(UA_Node *node, const UA_DeleteReferencesItem *item) {
     return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED;
 }
 
-void UA_Node_deleteReferences(UA_Node *node) {
-    for(size_t i = 0; i < node->referencesSize; ++i) {
-        UA_NodeReferenceKind *refs = &node->references[i];
+void
+UA_Node_deleteReferencesSubset(UA_Node *node, size_t referencesSkipSize,
+                               UA_NodeId* referencesSkip) {
+    /* Nothing to do */
+    if(node->referencesSize == 0 || node->references == NULL)
+        return;
+
+    for(size_t i = node->referencesSize; i > 0; --i) {
+        UA_NodeReferenceKind *refs = &node->references[i-1];
+
+        /* Shall we keep the references of this type? */
+        UA_Boolean skip = false;
+        for(size_t j = 0; j < referencesSkipSize; j++) {
+            if(UA_NodeId_equal(&refs->referenceTypeId, &referencesSkip[j])) {
+                skip = true;
+                break;
+            }
+        }
+        if(skip)
+            continue;
+
+        /* Remove references */
         UA_Array_delete(refs->targetIds, refs->targetIdsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
         UA_NodeId_deleteMembers(&refs->referenceTypeId);
+        node->referencesSize--;
+
+        /* Move last references-kind entry to this position */
+        if(i-1 == node->referencesSize) /* Don't memcpy over the same position */
+            continue;
+        node->references[i-1] = node->references[node->referencesSize];
     }
-    if(node->references)
+
+    if(node->referencesSize == 0) {
+        /* The array is empty. Remove. */
         UA_free(node->references);
-    node->references = NULL;
-    node->referencesSize = 0;
+        node->references = NULL;
+    } else {
+        /* Realloc to save memory */
+        UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
+            UA_realloc(node->references, sizeof(UA_NodeReferenceKind) * node->referencesSize);
+        if(refs) /* Do nothing if realloc fails */
+            node->references = refs;
+    }
+}
+
+void UA_Node_deleteReferences(UA_Node *node) {
+    UA_Node_deleteReferencesSubset(node, 0, NULL);
 }

+ 7 - 1
src/server/ua_server_internal.h

@@ -1,6 +1,6 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. 
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  *    Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  *    Copyright 2014, 2017 (c) Florian Palm
@@ -215,6 +215,12 @@ struct UA_Server {
 #define UA_Nodestore_remove(SERVER, NODEID)                             \
     (SERVER)->config.nodestore.removeNode((SERVER)->config.nodestore.context, NODEID)
 
+/* Deletes references from the node which are not matching any type in the given
+ * array. Could be used to e.g. delete all the references, except
+ * 'HASMODELINGRULE' */
+void UA_Node_deleteReferencesSubset(UA_Node *node, size_t referencesSkipSize,
+                                    UA_NodeId* referencesSkip);
+
 /* Calls the callback with the node retrieved from the nodestore on top of the
  * stack. Either a copy or the original node for in-situ editing. Depends on
  * multithreading and the nodestore.*/

+ 2 - 72
src/server/ua_services_nodemanagement.c

@@ -1,6 +1,6 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. 
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  *    Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  *    Copyright 2014-2017 (c) Florian Palm
@@ -380,76 +380,6 @@ static void
 Operation_addReference(UA_Server *server, UA_Session *session, void *context,
                        const UA_AddReferencesItem *item, UA_StatusCode *retval);
 
-
-/*
- * This method only deletes references from the node which are not matching any type in the given array.
- * Could be used to e.g. delete all the references, except 'HASMODELINGRULE'
- */
-static void deleteReferencesSubset(UA_Node *node, size_t referencesSkipSize, UA_NodeId* referencesSkip) {
-    if(referencesSkipSize == 0) {
-        UA_Node_deleteReferences(node);
-        return;
-    }
-
-    /* Let's count if there are references left. If not just delete all the references.
-     * It's faster */
-    size_t newSize = 0;
-    for(size_t i = 0; i < node->referencesSize; ++i) {
-        for(size_t j = 0; j < referencesSkipSize; j++) {
-            if(UA_NodeId_equal(&node->references[i].referenceTypeId, &referencesSkip[j])) {
-                newSize++;
-            }
-        }
-    }
-    if(newSize == 0) {
-        UA_Node_deleteReferences(node);
-        return;
-    }
-
-    /* Now copy the remaining references to a new array */
-    UA_NodeReferenceKind *newReferences = (UA_NodeReferenceKind *)UA_malloc(sizeof(UA_NodeReferenceKind) * (newSize));
-    size_t curr = 0;
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    for(size_t i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; ++i) {
-        for(size_t j = 0; j < referencesSkipSize; j++) {
-            if(!UA_NodeId_equal(&node->references[i].referenceTypeId, &referencesSkip[j]))
-                continue;
-
-            // copy the reference
-            UA_NodeReferenceKind *srefs = &node->references[i];
-            UA_NodeReferenceKind *drefs = &newReferences[curr++];
-            drefs->isInverse = srefs->isInverse;
-            retval = UA_NodeId_copy(&srefs->referenceTypeId, &drefs->referenceTypeId);
-            if(retval != UA_STATUSCODE_GOOD)
-                break;
-            retval = UA_Array_copy(srefs->targetIds, srefs->targetIdsSize,
-                                   (void**)&drefs->targetIds,
-                                   &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
-            if(retval != UA_STATUSCODE_GOOD)
-                break;
-            drefs->targetIdsSize = srefs->targetIdsSize;
-            break;
-        }
-        if(retval != UA_STATUSCODE_GOOD) {
-            for(size_t k=0; k<i; k++) {
-                UA_NodeReferenceKind *refs = &newReferences[i];
-                for(size_t j = 0; j < refs->targetIdsSize; ++j)
-                    UA_ExpandedNodeId_deleteMembers(&refs->targetIds[j]);
-                UA_Array_delete(refs->targetIds, refs->targetIdsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
-                UA_NodeId_deleteMembers(&refs->referenceTypeId);
-            }
-        }
-    }
-
-    UA_Node_deleteReferences(node);
-    if(retval == UA_STATUSCODE_GOOD) {
-        node->references = newReferences;
-        node->referencesSize = newSize;
-    } else {
-        UA_free(newReferences);
-    }
-}
-
 static UA_StatusCode
 copyChildNode(UA_Server *server, UA_Session *session,
               const UA_NodeId *destinationNodeId,
@@ -516,7 +446,7 @@ copyChildNode(UA_Server *server, UA_Session *session,
          * manually added by the user during addnode_begin and addnode_finish. */
         /* For now we keep all the modelling rule references and delete all others */
         UA_NodeId modellingRuleReferenceId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE);
-        deleteReferencesSubset(node, 1, &modellingRuleReferenceId);
+        UA_Node_deleteReferencesSubset(node, 1, &modellingRuleReferenceId);
 
         /* Add the node to the nodestore */
         UA_NodeId newNodeId;