Browse Source

Use _begin and _finish methods to ensure inherited children are not created multiple times

fixes #1547
Stefan Profanter 7 years ago
parent
commit
0dd0f444b4

+ 8 - 0
include/ua_server.h

@@ -991,6 +991,14 @@ UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId,
                          const UA_NodeId referenceTypeId,
                          const UA_NodeId typeDefinitionId);
 
+UA_StatusCode UA_EXPORT
+UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
+                         const UA_NodeId parentNodeId,
+                         const UA_NodeId referenceTypeId,
+                         UA_MethodCallback method,
+                         size_t inputArgumentsSize, const UA_Argument* inputArguments,
+                         size_t outputArgumentsSize, const UA_Argument* outputArguments);
+
 /* Deletes a node and optionally all references leading to the node. */
 UA_StatusCode UA_EXPORT
 UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,

+ 0 - 7
src/server/ua_server_internal.h

@@ -346,13 +346,6 @@ Operation_addNode_finish(UA_Server *server, UA_Session *session,
                          const UA_NodeId *nodeId, const UA_NodeId *parentNodeId,
                          const UA_NodeId *referenceTypeId, const UA_NodeId *typeDefinitionId);
 
-UA_StatusCode
-UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
-                               const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                               UA_MethodCallback method,
-                               size_t inputArgumentsSize, const UA_Argument* inputArguments,
-                               size_t outputArgumentsSize, const UA_Argument* outputArguments);
-
 /**********************/
 /* Create Namespace 0 */
 /**********************/

+ 15 - 7
tools/nodeset_compiler/backend_open62541.py

@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
 from constants import *
 from nodes import *
 from nodeset import *
-from backend_open62541_nodes import generateNodeCode, generateReferenceCode
+from backend_open62541_nodes import generateNodeCode_begin, generateNodeCode_finish, generateReferenceCode
 
 ##############
 # Sort Nodes #
@@ -160,7 +160,7 @@ def reorderNodesMinDependencies(nodeset):
 # Generate C Code #
 ###################
 
-def generateOpen62541Code(nodeset, outfilename, suppressGenerationOfAttribute=[], generate_ns0=False, internal_headers=False, typesArray=[], max_string_length=0):
+def generateOpen62541Code(nodeset, outfilename, generate_ns0=False, internal_headers=False, typesArray=[], max_string_length=0):
     outfilebase = basename(outfilename)
     # Printing functions
     outfileh = codecs.open(outfilename + ".h", r"w+", encoding='utf-8')
@@ -226,8 +226,8 @@ extern UA_StatusCode %s(UA_Server *server);
         # Print node
         if not node.hidden:
             writec("\n/* " + str(node.displayName) + " - " + str(node.id) + " */")
-            writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "(UA_Server *server, UA_UInt16* ns){\n")
-            code = generateNodeCode(node, suppressGenerationOfAttribute, generate_ns0, parentrefs, nodeset, max_string_length)
+            writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_begin(UA_Server *server, UA_UInt16* ns){\n")
+            code = generateNodeCode_begin(node, nodeset, max_string_length)
             if code is None:
                 writec("/* Ignored. No parent */")
                 nodeset.hide_node(node.id)
@@ -240,6 +240,11 @@ extern UA_StatusCode %s(UA_Server *server);
             writec(generateReferenceCode(ref))
             
         writec("return retVal;\n}")
+
+        writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_finish(UA_Server *server, UA_UInt16* ns){\n")
+        code = generateNodeCode_finish(node, generate_ns0, parentrefs)
+        writec("return " + code + "\n}\n")
+
         functionNumber = functionNumber + 1
     
     
@@ -255,9 +260,12 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;""" % (outfilebase))
         writec("ns[" + str(i) + "] = UA_Server_addNamespace(server, \"" + nsid + "\");")
 
     for i in range(0, functionNumber):
-        writec("retVal |= function_" + outfilebase + "_" + str(i) + "(server, ns);")
-    
-        
+        writec("retVal |= function_" + outfilebase + "_" + str(i) + "_begin(server, ns);")
+
+
+    for i in reversed(range(0, functionNumber)):
+        writec("retVal |= function_" + outfilebase + "_" + str(i) + "_finish(server, ns);")
+
     writec("return retVal;\n}")
     outfileh.close()
     fullCode = outfilec.getvalue()

+ 40 - 18
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -459,7 +459,7 @@ def generateSubtypeOfDefinitionCode(node):
             return generateNodeIdCode(ref.target)
     return "UA_NODEID_NULL"
 
-def generateNodeCode(node, suppressGenerationOfAttribute, generate_ns0, parentrefs, nodeset, max_string_length):
+def generateNodeCode_begin(node, nodeset, max_string_length):
     code = []
     code.append("UA_StatusCode retVal = UA_STATUSCODE_GOOD;")
 
@@ -491,22 +491,10 @@ def generateNodeCode(node, suppressGenerationOfAttribute, generate_ns0, parentre
     code.append("attr.writeMask = %d;" % node.writeMask)
     code.append("attr.userWriteMask = %d;" % node.userWriteMask)
 
-
     typeDef = getNodeTypeDefinition(node)
-    isDataTypeEncodingType = typeDef is not None and typeDef.ns == 0 and typeDef.i == 76
-
-    # Object nodes of type DataTypeEncoding do not have any parent
-    if not generate_ns0 and not isDataTypeEncodingType:
-        (parentNode, parentRef) = extractNodeParent(node, parentrefs)
-        if parentNode is None or parentRef is None:
-            return None
-    else:
-        (parentNode, parentRef) = (NodeId(), NodeId())
 
-    code.append("retVal |= UA_Server_add%s(server," % node.__class__.__name__)
+    code.append("retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_{},".format(node.__class__.__name__.upper().replace("NODE" ,"")))
     code.append(generateNodeIdCode(node.id) + ",")
-    code.append(generateNodeIdCode(parentNode) + ",")
-    code.append(generateNodeIdCode(parentRef) + ",")
     code.append(generateQualifiedNameCode(node.browseName, max_string_length=max_string_length) + ",")
     if isinstance(node, VariableTypeNode):
         # we need the HasSubtype reference
@@ -519,11 +507,45 @@ def generateNodeCode(node, suppressGenerationOfAttribute, generate_ns0, parentre
             if ref.referenceType.i == 40:
                 if (ref.isForward and ref.source == node.id) or (not ref.isForward and ref.target == node.id):
                     node.printRefs.remove(ref)
-    code.append("attr,")
-    if isinstance(node, MethodNode):
-        code.append("NULL, 0, NULL, 0, NULL, NULL, NULL);")
     else:
-        code.append("NULL, NULL);")
+        code.append("UA_NODEID_NULL,")
+    code.append("(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_{}ATTRIBUTES],NULL, NULL);".format(node.__class__.__name__.upper().replace("NODE" ,"")))
     code.extend(codeCleanup)
     
     return "\n".join(code)
+
+def generateNodeCode_finish(node, generate_ns0, parentrefs):
+    code = []
+
+    typeDef = getNodeTypeDefinition(node)
+    isDataTypeEncodingType = typeDef is not None and typeDef.ns == 0 and typeDef.i == 76
+    # Object nodes of type DataTypeEncoding do not have any parent
+    if not generate_ns0 and not isDataTypeEncodingType:
+        (parentNode, parentRef) = extractNodeParent(node, parentrefs)
+        if parentNode is None or parentRef is None:
+            return None
+    else:
+        (parentNode, parentRef) = (NodeId(), NodeId())
+
+
+    if isinstance(node, MethodNode):
+        code.append("UA_Server_addMethodNode_finish(server, ")
+    else:
+        code.append("UA_Server_addNode_finish(server, ")
+    code.append(generateNodeIdCode(node.id) + ",")
+    code.append(generateNodeIdCode(parentNode) + ",")
+    code.append(generateNodeIdCode(parentRef) + ",")
+
+    if isinstance(node, MethodNode):
+        code.append("NULL, 0, NULL, 0, NULL);")
+    else:
+
+        if isinstance(node, VariableTypeNode):
+            # we need the HasSubtype reference
+            code.append(generateSubtypeOfDefinitionCode(node) + ");")
+        else:
+            typeDefCode = "UA_NODEID_NULL" if typeDef is None else generateNodeIdCode(typeDef)
+            code.append(typeDefCode + ");")
+
+    return "\n".join(code)
+

+ 1 - 9
tools/nodeset_compiler/nodeset_compiler.py

@@ -74,14 +74,6 @@ parser.add_argument('-i', '--ignore',
                     default=[],
                     help='Loads a list of NodeIDs stored in ignoreFile (one NodeID per line). Any of the nodeIds encountered in this file will be kept in the nodestore but not printed in the generated code')
 
-parser.add_argument('-s', '--suppress',
-                    metavar="<attribute>",
-                    action='append',
-                    dest="suppressedAttributes",
-                    choices=['description', 'browseName', 'displayName', 'writeMask', 'userWriteMask', 'nodeid'],
-                    default=[],
-                    help="Suppresses the generation of some node attributes. Currently supported options are 'description', 'browseName', 'displayName', 'writeMask', 'userWriteMask' and 'nodeid'.")
-
 parser.add_argument('-t', '--types-array',
                     metavar="<typesArray>",
                     action='append',
@@ -189,5 +181,5 @@ ns.allocateVariables()
 
 # Create the C code with the open62541 backend of the compiler
 logger.info("Generating Code")
-generateOpen62541Code(ns, args.outputFile, args.suppressedAttributes, args.generate_ns0, args.internal_headers, args.typesArray, args.max_string_length)
+generateOpen62541Code(ns, args.outputFile, args.generate_ns0, args.internal_headers, args.typesArray, args.max_string_length)
 logger.info("NodeSet generation code successfully printed")