Преглед изворни кода

Principal preparations for more complicated instantiation logic (now) allowing nested vars/obj/methods to be instatiated. Will be expanded to allow value overwrites and substructure merging. Current implementation uses *first instance by name* and discards others --> Will be the instance copy of the ObjectType/VarType.

ichrispa пре 8 година
родитељ
комит
1c027faed9

+ 119 - 55
src/server/ua_services_nodemanagement.c

@@ -5,11 +5,22 @@
 /* Add Node */
 /************/
 
+
 static void
 Service_AddNodes_single(UA_Server *server, UA_Session *session,
                         const UA_AddNodesItem *item, UA_AddNodesResult *result,
                         UA_InstantiationCallback *instantiationCallback);
 
+static UA_StatusCode
+copyChildNodesToNode(UA_Server *server, UA_Session *session, 
+                     const UA_NodeId *sourceNodeId, const UA_NodeId *destinationNodeId,
+                     UA_InstantiationCallback *instantiationCallback);
+
+static UA_NodeId
+instanceFindAggregateByBrowsename(UA_Server *server, UA_Session *session, 
+                                  const UA_NodeId *searchInstance, 
+                                  const UA_QualifiedName *browseName);
+
 /* copy an existing variable under the given parent. then instantiate the
  * variable for its type */
 static UA_StatusCode
@@ -63,6 +74,12 @@ copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *va
     UA_AddNodesResult res;
     UA_AddNodesResult_init(&res);
     Service_AddNodes_single(server, session, &item, &res, instantiationCallback);
+    
+    /* Copy any aggregated/nested variables/methods/subobjects this object contains 
+     * These objects may not be part of the nodes type.
+     */
+    copyChildNodesToNode(server, session, &node->nodeId, &res.addedNodeId, instantiationCallback);
+    
     UA_NodeId_deleteMembers(&res.addedNodeId);
     return res.statusCode;
 }
@@ -108,7 +125,14 @@ copyExistingObject(UA_Server *server, UA_Session *session, const UA_NodeId *obje
     UA_AddNodesResult res;
     UA_AddNodesResult_init(&res);
     Service_AddNodes_single(server, session, &item, &res, instantiationCallback);
+    
+    /* Copy any aggregated/nested variables/methods/subobjects this object contains 
+     * These objects may not be part of the nodes type.
+     */
+    copyChildNodesToNode(server, session, &node->nodeId, &res.addedNodeId, instantiationCallback);
+    
     UA_NodeId_deleteMembers(&res.addedNodeId);
+    
     return res.statusCode;
 }
 
@@ -145,43 +169,13 @@ instantiateObjectNode(UA_Server *server, UA_Session *session,
         return UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
 
     /* Add all the child nodes */
+    copyChildNodesToNode(server, session, typeId, nodeId, instantiationCallback);
+    
+    /* Instantiate supertype attributes if a supertype is available */
     UA_BrowseDescription browseChildren;
     UA_BrowseDescription_init(&browseChildren);
-    browseChildren.nodeId = *typeId;
-    browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
-    browseChildren.includeSubtypes = true;
-    browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD;
-    browseChildren.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
-    browseChildren.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS;
-
     UA_BrowseResult browseResult;
     UA_BrowseResult_init(&browseResult);
-    // todo: continuation points if there are too many results
-    Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
-
-    for(size_t i = 0; i < browseResult.referencesSize; i++) {
-        UA_ReferenceDescription *rd = &browseResult.references[i];
-        if(rd->nodeClass == UA_NODECLASS_METHOD) {
-            /* add a reference to the method in the objecttype */
-            UA_AddReferencesItem item;
-            UA_AddReferencesItem_init(&item);
-            item.sourceNodeId = *nodeId;
-            item.referenceTypeId = rd->referenceTypeId;
-            item.isForward = true;
-            item.targetNodeId = rd->nodeId;
-            item.targetNodeClass = UA_NODECLASS_METHOD;
-            Service_AddReferences_single(server, session, &item);
-        } else if(rd->nodeClass == UA_NODECLASS_VARIABLE)
-          copyExistingVariable(server, session, &rd->nodeId.nodeId,
-                               &rd->referenceTypeId, nodeId, instantiationCallback);
-        else if(rd->nodeClass == UA_NODECLASS_OBJECT)
-          copyExistingObject(server, session, &rd->nodeId.nodeId,
-                             &rd->referenceTypeId, nodeId, instantiationCallback);
-    }
-    UA_BrowseResult_deleteMembers(&browseResult);
-    
-    /* Instantiate supertype attributes if a supertype is available */
-    UA_BrowseResult_init(&browseResult);
     browseChildren.nodeId = *typeId;
     browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
     browseChildren.includeSubtypes = false;
@@ -241,32 +235,14 @@ instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId
         return UA_STATUSCODE_BADNODEIDINVALID;
 
     /* get the references to child properties */
+    /* Add all the child nodes */
+    copyChildNodesToNode(server, session, typeId, nodeId, instantiationCallback);
+    
+    /* Instantiate supertypes */
     UA_BrowseDescription browseChildren;
     UA_BrowseDescription_init(&browseChildren);
-    browseChildren.nodeId = *typeId;
-    browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY);
-    browseChildren.includeSubtypes = true;
-    browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD;
-    browseChildren.nodeClassMask = UA_NODECLASS_VARIABLE;
-    browseChildren.resultMask =
-        UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS;
-
     UA_BrowseResult browseResult;
     UA_BrowseResult_init(&browseResult);
-    // todo: continuation points if there are too many results
-    Service_Browse_single(server, session, NULL, &browseChildren,
-                          100, &browseResult);
-
-    /* add the child properties */
-    for(size_t i = 0; i < browseResult.referencesSize; i++) {
-        UA_ReferenceDescription *rd = &browseResult.references[i];
-        copyExistingVariable(server, session, &rd->nodeId.nodeId,
-                             &rd->referenceTypeId, nodeId, instantiationCallback);
-    }
-    UA_BrowseResult_deleteMembers(&browseResult);
-
-    /* Instantiate supertypes */
-    UA_BrowseResult_init(&browseResult);
     browseChildren.nodeId = *typeId;
     browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
     browseChildren.includeSubtypes = false;
@@ -298,6 +274,94 @@ instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId
     return UA_STATUSCODE_GOOD;
 } 
 
+/* Search for an instance of "browseName" in node searchInstance
+ * Used during copyChildNodes to find overwritable/mergable nodes
+ */
+static UA_NodeId
+instanceFindAggregateByBrowsename(UA_Server *server, UA_Session *session, 
+                                  const UA_NodeId *searchInstance, 
+                                  const UA_QualifiedName *browseName) {
+    UA_NodeId retval = UA_NODEID_NULL;
+    
+    UA_BrowseDescription browseChildren;
+    UA_BrowseDescription_init(&browseChildren);
+    UA_NodeId_copy(searchInstance, &browseChildren.nodeId);
+    browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
+    browseChildren.includeSubtypes = true;
+    browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+    browseChildren.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
+    browseChildren.resultMask = UA_BROWSERESULTMASK_NODECLASS | UA_BROWSERESULTMASK_BROWSENAME;
+    
+    UA_BrowseResult browseResult;
+    UA_BrowseResult_init(&browseResult);
+    Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
+    
+    for(size_t i = 0; i < browseResult.referencesSize; i++) {
+      UA_ReferenceDescription *rd = &browseResult.references[i];
+      if (strncmp((const char*) rd->browseName.name.data, (const char*) browseName->name.data, 
+        (browseName->name.length>rd->browseName.name.length ? browseName->name.length : rd->browseName.name.length) ) == 0) {
+        // Found
+        retval = rd->nodeId.nodeId;
+        break;
+      }
+    }
+    
+    UA_BrowseResult_deleteMembers(&browseResult);
+    return retval;
+}
+
+/* Copy any children of Node sourceNodeId to another node destinationNodeId 
+ * Used at 2 places: 
+ *  (1) During instantiation, when any children of the Type are copied
+ *  (2) During instantiation to copy any *nested* instances to the new node
+ */
+static UA_StatusCode
+copyChildNodesToNode(UA_Server* server, UA_Session* session, 
+                     const UA_NodeId* sourceNodeId, const UA_NodeId* destinationNodeId, 
+                     UA_InstantiationCallback* instantiationCallback) {
+  /* Add all the child nodes */
+  UA_BrowseDescription browseChildren;
+  UA_BrowseDescription_init(&browseChildren);
+  UA_NodeId_copy(sourceNodeId, &browseChildren.nodeId);
+  browseChildren.referenceTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES);
+  browseChildren.includeSubtypes = true;
+  browseChildren.browseDirection = UA_BROWSEDIRECTION_FORWARD;
+  browseChildren.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
+  browseChildren.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS | UA_BROWSERESULTMASK_BROWSENAME;
+  
+  UA_BrowseResult browseResult;
+  UA_BrowseResult_init(&browseResult);
+  // todo: continuation points if there are too many results
+  Service_Browse_single(server, session, NULL, &browseChildren, 100, &browseResult);
+  
+  for(size_t i = 0; i < browseResult.referencesSize; i++) {
+    UA_ReferenceDescription *rd = &browseResult.references[i];
+    // Check for deduplication
+    UA_NodeId existing = instanceFindAggregateByBrowsename(server, session, destinationNodeId, &rd->browseName);
+    if (UA_NodeId_equal(&UA_NODEID_NULL, &existing) == UA_TRUE) {
+      if(rd->nodeClass == UA_NODECLASS_METHOD) {
+        /* add a reference to the method in the objecttype */
+        UA_AddReferencesItem newItem;
+        UA_AddReferencesItem_init(&newItem);
+        UA_NodeId_copy(destinationNodeId, &newItem.sourceNodeId);
+        newItem.referenceTypeId = rd->referenceTypeId;
+        newItem.isForward = true;
+        newItem.targetNodeId = rd->nodeId;
+        newItem.targetNodeClass = UA_NODECLASS_METHOD;
+        Service_AddReferences_single(server, session, &newItem);
+      } else if(rd->nodeClass == UA_NODECLASS_VARIABLE)
+          copyExistingVariable(server, session, &rd->nodeId.nodeId,
+                              &rd->referenceTypeId, destinationNodeId, instantiationCallback);
+        else if(rd->nodeClass == UA_NODECLASS_OBJECT)
+          copyExistingObject(server, session, &rd->nodeId.nodeId,
+                            &rd->referenceTypeId, destinationNodeId, instantiationCallback);
+    }
+  }
+  UA_BrowseResult_deleteMembers(&browseResult);
+  
+  return UA_STATUSCODE_GOOD;
+}
+
 static UA_StatusCode
 checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeClass,
                      const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId) {

+ 0 - 29
tools/pyUANamespace/NodeID_AssumeExternal.txt

@@ -1,29 +0,0 @@
-i=2253
-i=2254
-i=2255
-i=2256
-i=2257
-i=2258
-i=2259
-i=2260
-i=2261
-i=2262
-i=2263
-i=2264
-i=2265
-i=2266
-i=2267
-i=2271
-i=2274
-i=2292
-i=2294
-i=2735
-i=2992
-i=2993
-i=2994
-i=2268
-i=274
-i=295
-i=296
-i=11715
-i=11492

+ 0 - 0
tools/pyUANamespace/NodeID_Blacklist.txt


Разлика између датотеке није приказан због своје велике величине
+ 0 - 1514
tools/pyUANamespace/NodeID_Blacklist_FullNS0.txt