ソースを参照

Created UA_Server_getNodeCopy and UA_Server_deleteNodeCopy to allow userspace function to get detailed information about a node (references, strings, classInfo...). Both functions are using void **ptr to reference the node, since the node structs are currently not part of userspace.

ichrispa 9 年 前
コミット
3ade24fe53
共有2 個のファイルを変更した143 個の追加19 個の削除を含む
  1. 62 1
      include/ua_server.h
  2. 81 18
      src/server/ua_server_addressspace.c

+ 62 - 1
include/ua_server.h

@@ -26,7 +26,7 @@ extern "C" {
 #include "ua_nodeids.h"
 #include "ua_connection.h"
 #include "ua_log.h"
-
+  
 /**
  * @defgroup server Server
  *
@@ -124,19 +124,80 @@ UA_UInt16 UA_EXPORT UA_Server_addNamespace(UA_Server *server, const char* name);
 UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
                                                const UA_NodeId refTypeId, const UA_ExpandedNodeId targetId);
 
+/** Deletes a node from the nodestore.
+ *
+ * @param server The server object
+ * @param nodeId ID of the node to be deleted
+
+ * @return Return UA_STATUSCODE_GOOD if the node was deleted or an appropriate errorcode if the node was not found
+ *         or cannot be deleted.
+ */
 UA_StatusCode UA_EXPORT
 UA_Server_deleteNode(UA_Server *server, UA_NodeId nodeId);
 
 #define UA_SERVER_DELETENODEALIAS_DECL(TYPE) \
 UA_StatusCode UA_EXPORT UA_Server_delete##TYPE##Node(UA_Server *server, UA_NodeId nodeId);
 
+/** Deletes an ObjectNode from the nodestore. This is a high-level alias for UA_Server_deleteNode()
+ *
+ * @param server The server object
+ * @param nodeId ID of the node to be deleted
+ * 
+ * @return Return UA_STATUSCODE_GOOD if the node was deleted or an appropriate errorcode if the node was not found
+ *         or cannot be deleted.
+ */
 UA_SERVER_DELETENODEALIAS_DECL(Object)
+
+/** Deletes a VariableNode from the nodestore. This is a high-level alias for UA_Server_deleteNode()
+ *
+ * @param server The server object
+ * @param nodeId ID of the node to be deleted
+ * 
+ * @return Return UA_STATUSCODE_GOOD if the node was deleted or an appropriate errorcode if the node was not found
+ *         or cannot be deleted.
+ */
 UA_SERVER_DELETENODEALIAS_DECL(Variable)
 
 #ifdef ENABLE_METHODCALLS
+/** Deletes an MethodNode from the nodestore. This is a high-level alias for UA_Server_deleteNode()
+ *
+ * @param server The server object
+ * @param nodeId ID of the node to be deleted
+ * 
+ * @return Return UA_STATUSCODE_GOOD if the node was deleted or an appropriate errorcode if the node was not found
+ *         or cannot be deleted.
+ */
 UA_SERVER_DELETENODEALIAS_DECL(Method)
 #endif
 
+/** Deletes a copied instance of a node by deallocating it and all its attributes. This assumes that the node was
+ * priorly copied using getNodeCopy. To delete nodes that are located in the nodestore, use UA_Server_deleteNode()
+ * instead.
+ *
+ * @param server The server object
+ * @param nodeId ID of the node copy to be deleted
+ * 
+ * @return Return UA_STATUSCODE_GOOD if the node was deleted or an appropriate errorcode if the node was not found
+ *         or cannot be deleted.
+ */
+UA_StatusCode UA_EXPORT 
+UA_Server_deleteNodeCopy(UA_Server *server, void **node);
+
+/** Creates a deep copy of a node located in the nodestore and returns it to the userspace. Note that any manipulation
+ * of this copied node is not reflected by the server, but otherwise not accessible attributes of the node's struct
+ * can be examined in bulk. node->nodeClass can be used to cast the node to a specific node type. Use 
+ * UA_Server_deleteNodeCopy() to deallocate this node.
+ *
+ * @param server The server object
+ * @param nodeId ID of the node copy to be copied
+ * @param copyInto Pointer to a NULL pointer that will hold the copy of the node on a successfull return.
+ * 
+ * @return Return UA_STATUSCODE_GOOD if the node was copied or an appropriate errorcode if the node was not found
+ *         or cannot be copied.
+ */
+UA_StatusCode UA_EXPORT 
+UA_Server_getNodeCopy(UA_Server *server, UA_NodeId nodeId, void **copyInto);
+
 UA_StatusCode UA_EXPORT
 UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_QualifiedName browseName, 
                           UA_NodeId nodeId, const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,

+ 81 - 18
src/server/ua_server_addressspace.c

@@ -21,45 +21,108 @@ UA_Server_deleteNode(UA_Server *server, UA_NodeId nodeId) {
   // Remove the node from the hashmap/slot
   UA_NodeStore_remove(server->nodestore, &nodeId);
   
-  /* Note: this is done by deleteEntry() in _remove()!
+  /* 
    * FIXME: Delete unreachable child nodes???
-  switch(ptrs.delNode->nodeClass) {
+   */
+  
+  return UA_STATUSCODE_GOOD;
+}
+
+UA_SERVER_DELETENODEALIAS(Object)
+UA_SERVER_DELETENODEALIAS(Variable)
+#ifdef ENABLE_METHODCALLS
+UA_SERVER_DELETENODEALIAS(Method)
+#endif
+
+UA_StatusCode UA_Server_getNodeCopy(UA_Server *server, UA_NodeId nodeId, void **copyInto) {
+  const UA_Node *node = UA_NodeStore_get(server->nodestore, &nodeId);
+  UA_Node **copy = (UA_Node **) copyInto;
+  
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  
+  if (!node)
+    return UA_STATUSCODE_BADNODEIDINVALID;
+  
+  switch(node->nodeClass) {
     case UA_NODECLASS_DATATYPE:
-      UA_DataTypeNode_delete((UA_DataTypeNode *) ptrs.delNode);
+      *copy = (UA_Node *) UA_VariableNode_new();
+      retval |= UA_DataTypeNode_copy((const UA_DataTypeNode *) node, (UA_DataTypeNode *) *copy);
       break;
     case UA_NODECLASS_METHOD:
-      UA_MethodNode_delete((UA_MethodNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_MethodNode_new();
+      retval |= UA_MethodNode_copy((const UA_MethodNode *) node, (UA_MethodNode *) *copy);
       break;      
     case UA_NODECLASS_OBJECT:
-      UA_ObjectNode_delete((UA_ObjectNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_ObjectNode_new();
+      retval |= UA_ObjectNode_copy((const UA_ObjectNode *) node, (UA_ObjectNode *) *copy);
       break;      
     case UA_NODECLASS_OBJECTTYPE:
-      UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_ObjectTypeNode_new();
+      retval |= UA_ObjectTypeNode_copy((const UA_ObjectTypeNode *) node, (UA_ObjectTypeNode *) *copy);
       break;      
     case UA_NODECLASS_REFERENCETYPE:
-      UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_ReferenceTypeNode_new();
+      retval |= UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode *) node, (UA_ReferenceTypeNode *) *copy);
       break;      
     case UA_NODECLASS_VARIABLE:
-      UA_VariableNode_delete((UA_VariableNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_VariableNode_new();
+      retval |= UA_VariableNode_copy((const UA_VariableNode *) node, (UA_VariableNode *) *copy);
       break;      
     case UA_NODECLASS_VARIABLETYPE:
-      UA_VariableTypeNode_delete((UA_VariableTypeNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_VariableTypeNode_new();
+      retval |= UA_VariableTypeNode_copy((const UA_VariableTypeNode *) node, (UA_VariableTypeNode *) *copy);
       break;      
     case UA_NODECLASS_VIEW:
-      UA_ViewNode_delete((UA_ViewNode *) ptrs.delNode);
+      *copy =  (UA_Node *) UA_ViewNode_new();
+      retval |= UA_ViewNode_copy((const UA_ViewNode *) node, (UA_ViewNode *) *copy);
       break;      
     default:
       break;
-  } */
+  }
   
-  return UA_STATUSCODE_GOOD;
-}
+  UA_NodeStore_release(node);
+  
+  return retval;
+} 
 
-UA_SERVER_DELETENODEALIAS(Object)
-UA_SERVER_DELETENODEALIAS(Variable)
-#ifdef ENABLE_METHODCALLS
-UA_SERVER_DELETENODEALIAS(Method)
-#endif
+UA_StatusCode UA_Server_deleteNodeCopy(UA_Server *server, void **nodeptr) {
+  UA_StatusCode retval = UA_STATUSCODE_GOOD;
+  UA_Node **node = (UA_Node **) nodeptr;
+  
+  if (!(*node))
+    return UA_STATUSCODE_BADNODEIDINVALID;
+  
+  switch((*node)->nodeClass) {
+    case UA_NODECLASS_DATATYPE:
+      UA_DataTypeNode_delete((UA_DataTypeNode *) *node);
+      break;
+    case UA_NODECLASS_METHOD:
+      UA_MethodNode_delete((UA_MethodNode *) *node);
+      break;      
+    case UA_NODECLASS_OBJECT:
+      UA_ObjectNode_delete((UA_ObjectNode *) *node);
+      break;      
+    case UA_NODECLASS_OBJECTTYPE:
+      UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) *node);
+      break;      
+    case UA_NODECLASS_REFERENCETYPE:
+      UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) *node);
+      break;      
+    case UA_NODECLASS_VARIABLE:
+      UA_VariableNode_delete((UA_VariableNode *) *node);
+      break;      
+    case UA_NODECLASS_VARIABLETYPE:
+      UA_VariableTypeNode_delete((UA_VariableTypeNode *) *node);
+      break;      
+    case UA_NODECLASS_VIEW:
+      UA_ViewNode_delete((UA_ViewNode *) *node);
+      break;      
+    default:
+      break;
+  }
+  
+  return retval;
+} 
 
 UA_StatusCode 
 UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, UA_NodeIteratorCallback callback) {