Prechádzať zdrojové kódy

Add UA_ENABLE_IMMUTABLE_NODES option

This lets us select copy-on-write behaviour also without multithreading
enabled. So we can read-access the nodestore from an interrupt.
Julius Pfrommer 6 rokov pred
rodič
commit
dd14302a60
4 zmenil súbory, kde vykonal 26 pridanie a 6 odobranie
  1. 6 0
      CMakeLists.txt
  2. 2 0
      doc/building.rst
  3. 8 1
      include/ua_config.h.in
  4. 10 5
      src/server/ua_server_utils.c

+ 6 - 0
CMakeLists.txt

@@ -86,6 +86,12 @@ endif()
 option(UA_ENABLE_MULTITHREADING "Enable multithreading (experimental)" OFF)
 mark_as_advanced(UA_ENABLE_MULTITHREADING)
 
+option(UA_ENABLE_IMMUTABLE_NODES "Nodes in the information model are not edited but copied and replaced" OFF)
+mark_as_advanced(UA_ENABLE_IMMUTABLE_NODES)
+if(UA_ENABLE_MULTITHREADING)
+    set(UA_ENABLE_IMMUTABLE_NODES ON)
+endif()
+
 option(UA_ENABLE_PUBSUB "Enable publish/subscribe (experimental)" OFF)
 mark_as_advanced(UA_ENABLE_PUBSUB)
 

+ 2 - 0
doc/building.rst

@@ -186,6 +186,8 @@ This group contains build options related to the supported OPC UA features.
    Compile a single-file release into the files :file:`open62541.c` and :file:`open62541.h`
 **UA_ENABLE_MULTITHREADING**
    Enable multi-threading support
+**UA_ENABLE_IMMUTABLE_NODES**
+   Nodes in the information model are not edited but copied and replaced. The replacement is done with atomic operations so that the information model is always consistent and can be accessed from an interrupt or parallel thread (depends on the node storage plugin implementation). This feature is a prerequisite for ``UA_ENABLE_MULTITHREADING``.
 **UA_ENABLE_COVERAGE**
    Measure the coverage of unit tests
 

+ 8 - 1
include/ua_config.h.in

@@ -22,14 +22,21 @@ extern "C" {
  * Feature Options
  * ---------------
  * Changing the feature options has no effect on a pre-compiled library. */
+
 #define UA_LOGLEVEL ${UA_LOGLEVEL}
 #cmakedefine UA_ENABLE_METHODCALLS
 #cmakedefine UA_ENABLE_NODEMANAGEMENT
 #cmakedefine UA_ENABLE_SUBSCRIPTIONS
-#cmakedefine UA_ENABLE_MULTITHREADING
 #cmakedefine UA_ENABLE_PUBSUB
 #cmakedefine UA_ENABLE_ENCRYPTION
 
+/* Multithreading */
+#cmakedefine UA_ENABLE_MULTITHREADING
+#cmakedefine UA_ENABLE_IMMUTABLE_NODES
+#if defined(UA_ENABLE_MULTITHREADING) && !defined(UA_ENABLE_IMMUTABLE_NODES)
+#error "The multithreading feature requires nodes to be immutable"
+#endif
+
 /* Advanced Options */
 #cmakedefine UA_ENABLE_STATUSCODE_DESCRIPTIONS
 #cmakedefine UA_ENABLE_TYPENAMES

+ 10 - 5
src/server/ua_server_utils.c

@@ -354,27 +354,32 @@ UA_StatusCode
 UA_Server_editNode(UA_Server *server, UA_Session *session,
                    const UA_NodeId *nodeId, UA_EditNodeCallback callback,
                    void *data) {
-#ifndef UA_ENABLE_MULTITHREADING
+#ifndef UA_ENABLE_IMMUTABLE_NODES
+    /* Get the node and process it in-situ */
     const UA_Node *node = UA_Nodestore_get(server, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
-    UA_StatusCode retval = callback(server, session,
-                                    (UA_Node*)(uintptr_t)node, data);
+    UA_StatusCode retval = callback(server, session, (UA_Node*)(uintptr_t)node, data);
     UA_Nodestore_release(server, node);
     return retval;
 #else
     UA_StatusCode retval;
     do {
+        /* Get an editable copy of the node */
         UA_Node *node;
-        retval = server->config.nodestore.getNodeCopy(server->config.nodestore.context,
-                                                      nodeId, &node);
+        retval = server->config.nodestore.
+            getNodeCopy(server->config.nodestore.context, nodeId, &node);
         if(retval != UA_STATUSCODE_GOOD)
             return retval;
+
+        /* Run the operation on the copy */
         retval = callback(server, session, node, data);
         if(retval != UA_STATUSCODE_GOOD) {
             server->config.nodestore.deleteNode(server->config.nodestore.context, node);
             return retval;
         }
+
+        /* Replace the node */
         retval = server->config.nodestore.replaceNode(server->config.nodestore.context, node);
     } while(retval != UA_STATUSCODE_GOOD);
     return retval;