Переглянути джерело

refactor(server): Restore the NodeStore as a true plugin

Julius Pfrommer 5 роки тому
батько
коміт
ddd0fbfcfd

+ 2 - 4
CMakeLists.txt

@@ -207,9 +207,6 @@ if (UA_MULTITHREADING GREATER 100)
     set(UA_ENABLE_IMMUTABLE_NODES ON)
 endif()
 
-option(UA_ENABLE_CUSTOM_NODESTORE "Do not compile the default Nodestore implementation into the library" OFF)
-mark_as_advanced(UA_ENABLE_CUSTOM_NODESTORE)
-
 option(UA_ENABLE_PUBSUB "Enable publish/subscribe" OFF)
 mark_as_advanced(UA_ENABLE_PUBSUB)
 
@@ -688,6 +685,7 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
 set(default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/accesscontrol_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/pki_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/log_stdout.h
+                           ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/nodestore_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/server_config_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/client_config_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/securitypolicy_default.h
@@ -696,7 +694,7 @@ set(default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugi
 set(default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.c
                            ${PROJECT_SOURCE_DIR}/plugins/ua_accesscontrol_default.c
                            ${PROJECT_SOURCE_DIR}/plugins/ua_pki_default.c
-                           ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_default.c
+                           ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_ziptree.c
                            ${PROJECT_SOURCE_DIR}/plugins/ua_config_default.c
                            ${PROJECT_SOURCE_DIR}/plugins/securityPolicies/ua_securitypolicy_none.c
 )

+ 0 - 1
include/open62541/config.h.in

@@ -48,7 +48,6 @@
 #endif
 
 /* Advanced Options */
-#cmakedefine UA_ENABLE_CUSTOM_NODESTORE
 #cmakedefine UA_ENABLE_STATUSCODE_DESCRIPTIONS
 #cmakedefine UA_ENABLE_TYPEDESCRIPTION
 #cmakedefine UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS

+ 45 - 58
include/open62541/plugin/nodestore.h

@@ -446,65 +446,52 @@ typedef struct {
  * nodes. Please use the OPC UA services for that. Otherwise, all consistency
  * checks are omitted. This can crash the application eventually. */
 
-/* For non-multithreaded access, some nodestores allow that nodes are edited
- * without a copy/replace. This is not possible when the node is only an
- * intermediate representation and stored e.g. in a database backend. */
-extern const UA_Boolean inPlaceEditAllowed;
-
-/* Nodestore context and lifecycle */
-UA_StatusCode UA_Nodestore_new(void **nsCtx);
-void UA_Nodestore_delete(void *nsCtx);
-
-/**
- * The following definitions are used to create empty nodes of the different
- * node types. The memory is managed by the nodestore. Therefore, the node has
- * to be removed via a special deleteNode function. (If the new node is not
- * added to the nodestore.) */
-
-UA_Node *
-UA_Nodestore_newNode(void *nsCtx, UA_NodeClass nodeClass);
-
-void
-UA_Nodestore_deleteNode(void *nsCtx, UA_Node *node);
-
-/**
- *``Get`` returns a pointer to an immutable node. ``Release`` indicates that the
- * pointer is no longer accessed afterwards. */
-
-const UA_Node *
-UA_Nodestore_getNode(void *nsCtx, const UA_NodeId *nodeId);
-
-void
-UA_Nodestore_releaseNode(void *nsCtx, const UA_Node *node);
-
-/* Returns an editable copy of a node (needs to be deleted with the
- * deleteNode function or inserted / replaced into the nodestore). */
-UA_StatusCode
-UA_Nodestore_getNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
-                         UA_Node **outNode);
-
-/* Inserts a new node into the nodestore. If the NodeId is zero, then a fresh
- * numeric NodeId is assigned. If insertion fails, the node is deleted. */
-UA_StatusCode
-UA_Nodestore_insertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId);
-
-/* To replace a node, get an editable copy of the node, edit and replace with
- * this function. If the node was already replaced since the copy was made,
- * UA_STATUSCODE_BADINTERNALERROR is returned. If the NodeId is not found,
- * UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases, the editable
- * node is deleted. */
-UA_StatusCode
-UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node);
-
-/* Removes a node from the nodestore. */
-UA_StatusCode
-UA_Nodestore_removeNode(void *nsCtx, const UA_NodeId *nodeId);
-
-/* Execute a callback for every node in the nodestore. */
 typedef void (*UA_NodestoreVisitor)(void *visitorCtx, const UA_Node *node);
-void
-UA_Nodestore_iterate(void *nsCtx, UA_NodestoreVisitor visitor,
-                     void *visitorCtx);
+
+typedef struct {
+    /* Nodestore context and lifecycle */
+    void *context;
+    void (*clear)(void *nsCtx);
+
+    /* The following definitions are used to create empty nodes of the different
+     * node types. The memory is managed by the nodestore. Therefore, the node
+     * has to be removed via a special deleteNode function. (If the new node is
+     * not added to the nodestore.) */
+    UA_Node * (*newNode)(void *nsCtx, UA_NodeClass nodeClass);
+
+    void (*deleteNode)(void *nsCtx, UA_Node *node);
+
+    /* ``Get`` returns a pointer to an immutable node. ``Release`` indicates
+     * that the pointer is no longer accessed afterwards. */
+    const UA_Node * (*getNode)(void *nsCtx, const UA_NodeId *nodeId);
+
+    void (*releaseNode)(void *nsCtx, const UA_Node *node);
+
+    /* Returns an editable copy of a node (needs to be deleted with the
+     * deleteNode function or inserted / replaced into the nodestore). */
+    UA_StatusCode (*getNodeCopy)(void *nsCtx, const UA_NodeId *nodeId,
+                                 UA_Node **outNode);
+
+    /* Inserts a new node into the nodestore. If the NodeId is zero, then a
+     * fresh numeric NodeId is assigned. If insertion fails, the node is
+     * deleted. */
+    UA_StatusCode (*insertNode)(void *nsCtx, UA_Node *node,
+                                UA_NodeId *addedNodeId);
+
+    /* To replace a node, get an editable copy of the node, edit and replace
+     * with this function. If the node was already replaced since the copy was
+     * made, UA_STATUSCODE_BADINTERNALERROR is returned. If the NodeId is not
+     * found, UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases,
+     * the editable node is deleted. */
+    UA_StatusCode (*replaceNode)(void *nsCtx, UA_Node *node);
+
+    /* Removes a node from the nodestore. */
+    UA_StatusCode (*removeNode)(void *nsCtx, const UA_NodeId *nodeId);
+
+    /* Execute a callback for every node in the nodestore. */
+    void (*iterate)(void *nsCtx, UA_NodestoreVisitor visitor,
+                    void *visitorCtx);
+} UA_Nodestore;
 
 /**
  * Node Handling

+ 4 - 0
include/open62541/server_config.h

@@ -12,6 +12,7 @@
 #define UA_SERVER_CONFIG_H_
 
 #include <open62541/plugin/accesscontrol.h>
+#include <open62541/plugin/nodestore.h>
 #include <open62541/plugin/log.h>
 #include <open62541/plugin/network.h>
 #include <open62541/plugin/pki.h>
@@ -155,6 +156,9 @@ struct UA_ServerConfig {
      * .. note:: See the section for :ref:`async
      * operations<async-operations>`. */
 
+    /* Nodestore */
+    UA_Nodestore nodestore;
+
     /* Certificate Verification */
     UA_CertificateVerification certificateVerification;
 

+ 19 - 0
plugins/include/open62541/plugin/nodestore_default.h

@@ -0,0 +1,19 @@
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ *    Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB
+ */
+
+#ifndef UA_NODESTORE_DEFAULT_H_
+#define UA_NODESTORE_DEFAULT_H_
+
+#include <open62541/plugin/nodestore.h>
+
+_UA_BEGIN_DECLS
+
+UA_EXPORT UA_StatusCode
+UA_Nodestore_ZipTree(UA_Nodestore *ns);
+
+_UA_END_DECLS
+
+#endif /* UA_NODESTORE_DEFAULT_H_ */

+ 2 - 4
plugins/ua_config_default.c

@@ -17,6 +17,7 @@
 #include <open62541/network_ws.h>
 #endif
 #include <open62541/plugin/accesscontrol_default.h>
+#include <open62541/plugin/nodestore_default.h>
 #include <open62541/plugin/log_stdout.h>
 #include <open62541/plugin/pki_default.h>
 #include <open62541/plugin/securitypolicy_default.h>
@@ -42,6 +43,7 @@ UA_Server_new() {
     UA_ServerConfig config;
     memset(&config, 0, sizeof(UA_ServerConfig));
     config.logger = UA_Log_Stdout_;
+    UA_Nodestore_ZipTree(&config.nodestore);
     return UA_Server_newWithConfig(&config);
 }
 
@@ -111,10 +113,6 @@ setDefaultConfig(UA_ServerConfig *conf) {
     if (!conf)
         return UA_STATUSCODE_BADINVALIDARGUMENT;
 
-    /* Zero out.. All members have a valid initial value */
-    UA_ServerConfig_clean(conf);
-    memset(conf, 0, sizeof(UA_ServerConfig));
-
     /* --> Start setting the default static config <-- */
     conf->nThreads = 1;
     conf->logger = UA_Log_Stdout_;

+ 68 - 64
plugins/ua_nodestore_default.c

@@ -6,17 +6,15 @@
  *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  */
 
-#include <open62541/plugin/nodestore.h>
+#include <open62541/plugin/nodestore_default.h>
 #include "ziptree.h"
 
-#ifndef UA_ENABLE_CUSTOM_NODESTORE
-
 #if UA_MULTITHREADING >= 100
-#define BEGIN_CRITSECT(NODEMAP) UA_LOCK(NODEMAP->lock)
-#define END_CRITSECT(NODEMAP) UA_UNLOCK(NODEMAP->lock)
+#define BEGIN_CRITSECT(ctx) UA_LOCK(ctx->lock)
+#define END_CRITSECT(ctx) UA_UNLOCK(ctx->lock)
 #else
-#define BEGIN_CRITSECT(NODEMAP) do {} while(0)
-#define END_CRITSECT(NODEMAP) do {} while(0)
+#define BEGIN_CRITSECT(ctx) do {} while(0)
+#define END_CRITSECT(ctx) do {} while(0)
 #endif
 
 /* container_of */
@@ -61,7 +59,7 @@ typedef struct {
 #if UA_MULTITHREADING >= 100
     UA_LOCK_TYPE(lock) /* Protect access */
 #endif
-} NodeMap;
+} ZipContext;
 
 ZIP_PROTTYPE(NodeTree, NodeEntry, NodeEntry)
 ZIP_IMPL(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId)
@@ -121,24 +119,24 @@ cleanupEntry(NodeEntry *entry) {
 /* Interface functions */
 /***********************/
 
-/* Not yet inserted into the NodeMap */
-UA_Node *
-UA_Nodestore_newNode(void *nsCtx, UA_NodeClass nodeClass) {
+/* Not yet inserted into the ZipContext */
+static UA_Node *
+zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) {
     NodeEntry *entry = newEntry(nodeClass);
     if(!entry)
         return NULL;
     return (UA_Node*)&entry->nodeId;
 }
 
-/* Not yet inserted into the NodeMap */
-void
-UA_Nodestore_deleteNode(void *nsCtx, UA_Node *node) {
+/* Not yet inserted into the ZipContext */
+static void
+zipNsDeleteNode(void *nsCtx, UA_Node *node) {
     deleteEntry(container_of(node, NodeEntry, nodeId));
 }
 
-const UA_Node *
-UA_Nodestore_getNode(void *nsCtx, const UA_NodeId *nodeId) {
-    NodeMap *ns = (NodeMap*)nsCtx;
+static const UA_Node *
+zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId) {
+    ZipContext *ns = (ZipContext*)nsCtx;
     BEGIN_CRITSECT(ns);
     NodeEntry dummy;
     dummy.nodeIdHash = UA_NodeId_hash(nodeId);
@@ -153,12 +151,12 @@ UA_Nodestore_getNode(void *nsCtx, const UA_NodeId *nodeId) {
     return (const UA_Node*)&entry->nodeId;
 }
 
-void
-UA_Nodestore_releaseNode(void *nsCtx, const UA_Node *node) {
+static void
+zipNsReleaseNode(void *nsCtx, const UA_Node *node) {
     if(!node)
         return;
 #if UA_MULTITHREADING >= 100
-        NodeMap *ns = (NodeMap*)nsCtx;
+        ZipContext *ns = (ZipContext*)nsCtx;
 #endif
     BEGIN_CRITSECT(ns);
     NodeEntry *entry = container_of(node, NodeEntry, nodeId);
@@ -168,25 +166,25 @@ UA_Nodestore_releaseNode(void *nsCtx, const UA_Node *node) {
     END_CRITSECT(ns);
 }
 
-UA_StatusCode
-UA_Nodestore_getNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
+static UA_StatusCode
+zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
                          UA_Node **outNode) {
     /* Find the node */
-    const UA_Node *node = UA_Nodestore_getNode(nsCtx, nodeId);
+    const UA_Node *node = zipNsGetNode(nsCtx, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
 
     /* Create the new entry */
     NodeEntry *ne = newEntry(node->nodeClass);
     if(!ne) {
-        UA_Nodestore_releaseNode(nsCtx, node);
+        zipNsReleaseNode(nsCtx, node);
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
 
     /* Copy the node content */
     UA_Node *nnode = (UA_Node*)&ne->nodeId;
     UA_StatusCode retval = UA_Node_copy(node, nnode);
-    UA_Nodestore_releaseNode(nsCtx, node);
+    zipNsReleaseNode(nsCtx, node);
     if(retval != UA_STATUSCODE_GOOD) {
         deleteEntry(ne);
         return retval;
@@ -197,10 +195,10 @@ UA_Nodestore_getNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
     return UA_STATUSCODE_GOOD;
 }
 
-UA_StatusCode
-UA_Nodestore_insertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
+static UA_StatusCode
+zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
     NodeEntry *entry = container_of(node, NodeEntry, nodeId);
-    NodeMap *ns = (NodeMap*)nsCtx;
+    ZipContext *ns = (ZipContext*)nsCtx;
     BEGIN_CRITSECT(ns);
 
     /* Ensure that the NodeId is unique */
@@ -239,10 +237,10 @@ UA_Nodestore_insertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
     return UA_STATUSCODE_GOOD;
 }
 
-UA_StatusCode
-UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node) {
+static UA_StatusCode
+zipNsReplaceNode(void *nsCtx, UA_Node *node) {
     /* Find the node */
-    const UA_Node *oldNode = UA_Nodestore_getNode(nsCtx, &node->nodeId);
+    const UA_Node *oldNode = zipNsGetNode(nsCtx, &node->nodeId);
     if(!oldNode) {
         deleteEntry(container_of(node, NodeEntry, nodeId));
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -254,12 +252,12 @@ UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node) {
     if(oldEntry != entry->orig) {
         /* The node was already updated since the copy was made */
         deleteEntry(entry);
-        UA_Nodestore_releaseNode(nsCtx, oldNode);
+        zipNsReleaseNode(nsCtx, oldNode);
         return UA_STATUSCODE_BADINTERNALERROR;
     }
 
     /* Replace */
-    NodeMap *ns = (NodeMap*)nsCtx;
+    ZipContext *ns = (ZipContext*)nsCtx;
     BEGIN_CRITSECT(ns);
     ZIP_REMOVE(NodeTree, &ns->root, oldEntry);
     entry->nodeIdHash = oldEntry->nodeIdHash;
@@ -267,13 +265,13 @@ UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node) {
     oldEntry->deleted = true;
     END_CRITSECT(ns);
 
-    UA_Nodestore_releaseNode(nsCtx, oldNode);
+    zipNsReleaseNode(nsCtx, oldNode);
     return UA_STATUSCODE_GOOD;
 }
 
-UA_StatusCode
-UA_Nodestore_removeNode(void *nsCtx, const UA_NodeId *nodeId) {
-    NodeMap *ns = (NodeMap*)nsCtx;
+static UA_StatusCode
+zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) {
+    ZipContext *ns = (ZipContext*)nsCtx;
     BEGIN_CRITSECT(ns);
     NodeEntry dummy;
     dummy.nodeIdHash = UA_NodeId_hash(nodeId);
@@ -301,13 +299,13 @@ nodeVisitor(NodeEntry *entry, void *data) {
     d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId);
 }
 
-void
-UA_Nodestore_iterate(void *nsCtx, UA_NodestoreVisitor visitor,
-                     void *visitorCtx) {
+static void
+zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor,
+             void *visitorCtx) {
     struct VisitorData d;
     d.visitor = visitor;
     d.visitorContext = visitorCtx;
-    NodeMap *ns = (NodeMap*)nsCtx;
+    ZipContext *ns = (ZipContext*)nsCtx;
     BEGIN_CRITSECT(ns);
     ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d);
     END_CRITSECT(ns);
@@ -322,36 +320,42 @@ deleteNodeVisitor(NodeEntry *entry, void *data) {
 /* Nodestore Lifecycle */
 /***********************/
 
-const UA_Boolean inPlaceEditAllowed = true;
+static void
+zipNsClear(void *nsCtx) {
+    if (!nsCtx)
+        return;
+    ZipContext *ns = (ZipContext*)nsCtx;
+#if UA_MULTITHREADING >= 100
+    UA_LOCK_DESTROY(ns->lock);
+#endif
+    ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
+    UA_free(ns);
+}
 
 UA_StatusCode
-UA_Nodestore_new(void **nsCtx) {
-    /* Allocate and initialize the nodemap */
-    NodeMap *nodemap = (NodeMap*)UA_malloc(sizeof(NodeMap));
-    if(!nodemap)
+UA_Nodestore_ZipTree(UA_Nodestore *ns) {
+    /* Allocate and initialize the context */
+    ZipContext *ctx = (ZipContext*)UA_malloc(sizeof(ZipContext));
+    if(!ctx)
         return UA_STATUSCODE_BADOUTOFMEMORY;
 #if UA_MULTITHREADING >= 100
-    UA_LOCK_INIT(nodemap->lock)
+    UA_LOCK_INIT(ctx->lock)
 #endif
 
-    ZIP_INIT(&nodemap->root);
+    ZIP_INIT(&ctx->root);
 
     /* Populate the nodestore */
-    *nsCtx = (void*)nodemap;
+    ns->context = (void*)ctx;
+    ns->clear = zipNsClear;
+    ns->newNode = zipNsNewNode;
+    ns->deleteNode = zipNsDeleteNode;
+    ns->getNode = zipNsGetNode;
+    ns->releaseNode = zipNsReleaseNode;
+    ns->getNodeCopy = zipNsGetNodeCopy;
+    ns->insertNode = zipNsInsertNode;
+    ns->replaceNode = zipNsReplaceNode;
+    ns->removeNode = zipNsRemoveNode;
+    ns->iterate = zipNsIterate;
+    
     return UA_STATUSCODE_GOOD;
 }
-
-void
-UA_Nodestore_delete(void *nsCtx) {
-    if (!nsCtx)
-        return;
-
-    NodeMap *ns = (NodeMap*)nsCtx;
-#if UA_MULTITHREADING >= 100
-    UA_LOCK_DESTROY(ns->lock);
-#endif
-    ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
-    UA_free(ns);
-}
-
-#endif /* UA_ENABLE_CUSTOM_NODESTORE */

+ 2 - 2
src/pubsub/ua_pubsub_manager.c

@@ -288,8 +288,8 @@ UA_PubSubConfigurationVersionTimeDifference() {
 void
 UA_PubSubManager_generateUniqueNodeId(UA_Server *server, UA_NodeId *nodeId) {
     UA_NodeId newNodeId = UA_NODEID_NUMERIC(0, 0);
-    UA_Node *newNode = UA_Nodestore_newNode(server->nsCtx, UA_NODECLASS_OBJECT);
-    UA_Nodestore_insertNode(server->nsCtx, newNode, &newNodeId);
+    UA_Node *newNode = UA_NODESTORE_NEW(server, UA_NODECLASS_OBJECT);
+    UA_NODESTORE_INSERT(server, newNode, &newNodeId);
     UA_NodeId_copy(&newNodeId, nodeId);
 }
 

+ 4 - 4
src/pubsub/ua_pubsub_ns0.c

@@ -231,7 +231,7 @@ addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connec
     memcpy(connectionName, connection->config->name.data, connection->config->name.length);
     connectionName[connection->config->name.length] = '\0';
     //This code block must use a lock
-    UA_Nodestore_removeNode(server->nsCtx, &connection->identifier);
+    UA_NODESTORE_REMOVE(server, &connection->identifier);
     UA_NodeId pubSubConnectionNodeId;
     UA_ObjectAttributes attr = UA_ObjectAttributes_default;
     attr.displayName = UA_LOCALIZEDTEXT("de-DE", connectionName);
@@ -531,7 +531,7 @@ addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publ
     memcpy(pdsName, publishedDataSet->config.name.data, publishedDataSet->config.name.length);
     pdsName[publishedDataSet->config.name.length] = '\0';
     //This code block must use a lock
-    UA_Nodestore_removeNode(server->nsCtx, &publishedDataSet->identifier);
+    UA_NODESTORE_REMOVE(server, &publishedDataSet->identifier);
     retVal |= addPubSubObjectNode(server, pdsName, publishedDataSet->identifier.identifier.numeric,
                                   UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS,
                                   UA_NS0ID_HASPROPERTY, UA_NS0ID_PUBLISHEDDATAITEMSTYPE);
@@ -747,7 +747,7 @@ addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
     memcpy(wgName, writerGroup->config.name.data, writerGroup->config.name.length);
     wgName[writerGroup->config.name.length] = '\0';
     //This code block must use a lock
-    UA_Nodestore_removeNode(server->nsCtx, &writerGroup->identifier);
+    UA_NODESTORE_REMOVE(server, &writerGroup->identifier);
     retVal |= addPubSubObjectNode(server, wgName, writerGroup->identifier.identifier.numeric,
                                   writerGroup->linkedConnection.identifier.numeric,
                                   UA_NS0ID_HASCOMPONENT, UA_NS0ID_WRITERGROUPTYPE);
@@ -915,7 +915,7 @@ addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWrite
     memcpy(dswName, dataSetWriter->config.name.data, dataSetWriter->config.name.length);
     dswName[dataSetWriter->config.name.length] = '\0';
     //This code block must use a lock
-    UA_Nodestore_removeNode(server->nsCtx, &dataSetWriter->identifier);
+    UA_NODESTORE_REMOVE(server, &dataSetWriter->identifier);
     retVal |= addPubSubObjectNode(server, dswName, dataSetWriter->identifier.identifier.numeric,
                                   dataSetWriter->linkedWriterGroup.identifier.numeric,
                                   UA_NS0ID_HASDATASETWRITER, UA_NS0ID_DATASETWRITERTYPE);

+ 1 - 1
src/server/ua_nodes.c

@@ -15,7 +15,7 @@
 #include "ua_types_encoding_binary.h"
 
 /* There is no UA_Node_new() method here. Creating nodes is part of the
- * NodeStore layer */
+ * Nodestore layer */
 
 static enum ZIP_CMP
 cmpRefTarget(const void *a, const void *b) {

+ 13 - 12
src/server/ua_server.c

@@ -124,7 +124,7 @@ UA_StatusCode
 UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
                                UA_NodeIteratorCallback callback, void *handle) {
     UA_LOCK(server->serviceMutex);
-    const UA_Node *parent = UA_Nodestore_getNode(server->nsCtx, &parentNodeId);
+    const UA_Node *parent = UA_NODESTORE_GET(server, &parentNodeId);
     if(!parent) {
         UA_UNLOCK(server->serviceMutex);
         return UA_STATUSCODE_BADNODEIDINVALID;
@@ -139,7 +139,7 @@ UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
      * */
     UA_Node *parentCopy = UA_Node_copy_alloc(parent);
     if(!parentCopy) {
-        UA_Nodestore_releaseNode(server->nsCtx, parent);
+        UA_NODESTORE_RELEASE(server, parent);
         UA_UNLOCK(server->serviceMutex);
         return UA_STATUSCODE_BADUNEXPECTEDERROR;
     }
@@ -161,7 +161,7 @@ cleanup:
     UA_Node_clear(parentCopy);
     UA_free(parentCopy);
 
-    UA_Nodestore_releaseNode(server->nsCtx, parent);
+    UA_NODESTORE_RELEASE(server, parent);
     UA_UNLOCK(server->serviceMutex);
     return retval;
 }
@@ -214,9 +214,6 @@ void UA_Server_delete(UA_Server *server) {
     /* Delete the timed work */
     UA_Timer_deleteMembers(&server->timer);
 
-    /* Clean up the nodestore */
-    UA_Nodestore_delete(server->nsCtx);
-
     /* Clean up the config */
     UA_ServerConfig_clean(&server->config);
 
@@ -248,6 +245,14 @@ UA_Server_cleanup(UA_Server *server, void *_) {
 
 static UA_Server *
 UA_Server_init(UA_Server *server) {
+    UA_StatusCode res = UA_STATUSCODE_GOOD;
+    
+    if(!server->config.nodestore.getNode) {
+        UA_LOG_FATAL(&server->config.logger, UA_LOGCATEGORY_SERVER,
+                     "No Nodestore configured in the server");
+        goto cleanup;
+    }
+
     /* Init start time to zero, the actual start time will be sampled in
      * UA_Server_run_startup() */
     server->startTime = 0;
@@ -301,12 +306,8 @@ UA_Server_init(UA_Server *server) {
                                   10000.0, NULL);
 
     /* Initialize namespace 0*/
-    UA_StatusCode retVal = UA_Nodestore_new(&server->nsCtx);
-    if(retVal != UA_STATUSCODE_GOOD)
-        goto cleanup;
-
-    retVal = UA_Server_initNS0(server);
-    if(retVal != UA_STATUSCODE_GOOD)
+    res = UA_Server_initNS0(server);
+    if(res != UA_STATUSCODE_GOOD)
         goto cleanup;
 
     /* Build PubSub information model */

+ 6 - 0
src/server/ua_server_config.c

@@ -47,6 +47,12 @@ UA_ServerConfig_clean(UA_ServerConfig *config) {
     config->endpoints = NULL;
     config->endpointsSize = 0;
 
+    /* Nodestore */
+    if(config->nodestore.clear) {
+        config->nodestore.clear(config->nodestore.context);
+        config->nodestore.context = NULL;
+    }
+
     /* Certificate Validation */
     if(config->certificateVerification.clear)
         config->certificateVerification.clear(&config->certificateVerification);

+ 31 - 1
src/server/ua_server_internal.h

@@ -197,7 +197,7 @@ UA_Node_hasSubTypeOrInstances(const UA_Node *node);
 
 /* Recursively searches "upwards" in the tree following specific reference types */
 UA_Boolean
-isNodeInTree(void *nsCtx, const UA_NodeId *leafNode,
+isNodeInTree(UA_Server *server, const UA_NodeId *leafNode,
              const UA_NodeId *nodeToFind, const UA_NodeId *referenceTypeIds,
              size_t referenceTypeIdsSize);
 
@@ -439,6 +439,36 @@ UA_StatusCode UA_Server_initNS0(UA_Server *server);
 UA_StatusCode writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
                       size_t length, const UA_DataType *type);
 
+/***************************/
+/* Nodestore Access Macros */
+/***************************/
+
+#define UA_NODESTORE_NEW(server, nodeClass)                             \
+    server->config.nodestore.newNode(server->config.nodestore.context, nodeClass)
+
+#define UA_NODESTORE_DELETE(server, node)                               \
+    server->config.nodestore.deleteNode(server->config.nodestore.context, node)
+
+#define UA_NODESTORE_GET(server, nodeid)                                \
+    server->config.nodestore.getNode(server->config.nodestore.context, nodeid)
+
+#define UA_NODESTORE_RELEASE(server, node)                              \
+    server->config.nodestore.releaseNode(server->config.nodestore.context, node)
+
+#define UA_NODESTORE_GETCOPY(server, nodeid, outnode)                      \
+    server->config.nodestore.getNodeCopy(server->config.nodestore.context, \
+                                         nodeid, outnode)
+
+#define UA_NODESTORE_INSERT(server, node, addedNodeId)                    \
+    server->config.nodestore.insertNode(server->config.nodestore.context, \
+                                        node, addedNodeId)
+
+#define UA_NODESTORE_REPLACE(server, node)                              \
+    server->config.nodestore.replaceNode(server->config.nodestore.context, node)
+
+#define UA_NODESTORE_REMOVE(server, nodeId)                             \
+    server->config.nodestore.removeNode(server->config.nodestore.context, nodeId)
+
 _UA_END_DECLS
 
 #endif /* UA_SERVER_INTERNAL_H_ */

+ 14 - 14
src/server/ua_server_utils.c

@@ -26,7 +26,7 @@ struct ref_history {
 };
 
 static UA_Boolean
-isNodeInTreeNoCircular(void *nsCtx, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
+isNodeInTreeNoCircular(UA_Server *server, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
                        struct ref_history *visitedRefs, const UA_NodeId *referenceTypeIds,
                        size_t referenceTypeIdsSize) {
     if(UA_NodeId_equal(nodeToFind, leafNode))
@@ -35,7 +35,7 @@ isNodeInTreeNoCircular(void *nsCtx, const UA_NodeId *leafNode, const UA_NodeId *
     if(visitedRefs->depth >= UA_MAX_TREE_RECURSE)
         return false;
 
-    const UA_Node *node = UA_Nodestore_getNode(nsCtx, leafNode);
+    const UA_Node *node = UA_NODESTORE_GET(server, leafNode);
     if(!node)
         return false;
 
@@ -80,24 +80,24 @@ isNodeInTreeNoCircular(void *nsCtx, const UA_NodeId *leafNode, const UA_NodeId *
 
             /* Recurse */
             UA_Boolean foundRecursive =
-                isNodeInTreeNoCircular(nsCtx, &refs->refTargets[j].target.nodeId, nodeToFind,
+                isNodeInTreeNoCircular(server, &refs->refTargets[j].target.nodeId, nodeToFind,
                                        &nextVisitedRefs, referenceTypeIds, referenceTypeIdsSize);
             if(foundRecursive) {
-                UA_Nodestore_releaseNode(nsCtx, node);
+                UA_NODESTORE_RELEASE(server, node);
                 return true;
             }
         }
     }
 
-    UA_Nodestore_releaseNode(nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     return false;
 }
 
 UA_Boolean
-isNodeInTree(void *nsCtx, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
+isNodeInTree(UA_Server *server, const UA_NodeId *leafNode, const UA_NodeId *nodeToFind,
              const UA_NodeId *referenceTypeIds, size_t referenceTypeIdsSize) {
     struct ref_history visitedRefs = {NULL, leafNode, 0};
-    return isNodeInTreeNoCircular(nsCtx, leafNode, nodeToFind, &visitedRefs,
+    return isNodeInTreeNoCircular(server, leafNode, nodeToFind, &visitedRefs,
                                   referenceTypeIds, referenceTypeIdsSize);
 }
 
@@ -138,12 +138,12 @@ getNodeType(UA_Server *server, const UA_Node *node) {
             continue;
         UA_assert(node->references[i].refTargetsSize> 0);
         const UA_NodeId *targetId = &node->references[i].refTargets[0].target.nodeId;
-        const UA_Node *type = UA_Nodestore_getNode(server->nsCtx, targetId);
+        const UA_Node *type = UA_NODESTORE_GET(server, targetId);
         if(!type)
             continue;
         if(type->nodeClass == typeNodeClass)
             return type;
-        UA_Nodestore_releaseNode(server->nsCtx, type);
+        UA_NODESTORE_RELEASE(server, type);
     }
 
     return NULL;
@@ -235,30 +235,30 @@ UA_Server_editNode(UA_Server *server, UA_Session *session,
                    void *data) {
 #ifndef UA_ENABLE_IMMUTABLE_NODES
     /* Get the node and process it in-situ */
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, nodeId);
+    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_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     return retval;
 #else
     UA_StatusCode retval;
     do {
         /* Get an editable copy of the node */
         UA_Node *node;
-        retval = UA_Nodestore_getNodeCopy(server->nsCtx, nodeId, &node);
+        retval = UA_NODESTORE_GETCOPY(server, 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) {
-            UA_Nodestore_deleteNode(server->nsCtx, node);
+            UA_NODESTORE_DELETE(server, node);
             return retval;
         }
 
         /* Replace the node */
-        retval = UA_Nodestore_replaceNode(server->nsCtx, node);
+        retval = UA_NODESTORE_REPLACE(server, node);
     } while(retval != UA_STATUSCODE_GOOD);
     return retval;
 #endif

+ 12 - 12
src/server/ua_services_attribute.c

@@ -118,7 +118,7 @@ readValueAttributeFromNode(UA_Server *server, UA_Session *session,
                                        session->sessionHandle, &vn->nodeId,
                                        vn->context, rangeptr, &vn->value.data.value);
         UA_LOCK(server->serviceMutex);
-        vn = (const UA_VariableNode*)UA_Nodestore_getNode(server->nsCtx, &vn->nodeId);
+        vn = (const UA_VariableNode*)UA_NODESTORE_GET(server, &vn->nodeId);
         if(!vn)
             return UA_STATUSCODE_BADNODEIDUNKNOWN;
     }
@@ -130,7 +130,7 @@ readValueAttributeFromNode(UA_Server *server, UA_Session *session,
 
     /* Clean up */
     if(vn->value.data.callback.onRead)
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node *)vn);
+        UA_NODESTORE_RELEASE(server, (const UA_Node *)vn);
     return retval;
 }
 
@@ -468,12 +468,12 @@ static void
 Operation_Read(UA_Server *server, UA_Session *session, UA_ReadRequest *request,
                UA_ReadValueId *rvi, UA_DataValue *result) {
     /* Get the node */
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &rvi->nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, &rvi->nodeId);
 
     /* Perform the read operation */
     if(node) {
         ReadWithNode(node, server, session, request->timestampsToReturn, rvi, result);
-        UA_Nodestore_releaseNode(server->nsCtx, node);
+        UA_NODESTORE_RELEASE(server, node);
     } else {
         result->hasStatus = true;
         result->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -522,7 +522,7 @@ UA_Server_readWithSession(UA_Server *server, UA_Session *session,
     UA_DataValue_init(&dv);
 
     /* Get the node */
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &item->nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
     if(!node) {
         dv.hasStatus = true;
         dv.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -533,7 +533,7 @@ UA_Server_readWithSession(UA_Server *server, UA_Session *session,
     ReadWithNode(node, server, session, timestampsToReturn, item, &dv);
 
     /* Release the node and return */
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     return dv;
 }
 
@@ -668,12 +668,12 @@ compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
         return true;
 
     /* Is the value-type a subtype of the required type? */
-    if(isNodeInTree(server->nsCtx, dataType, constraintDataType, &subtypeId, 1))
+    if(isNodeInTree(server, dataType, constraintDataType, &subtypeId, 1))
         return true;
 
     /* Enum allows Int32 (only) */
     if(UA_NodeId_equal(dataType, &UA_TYPES[UA_TYPES_INT32].typeId) &&
-       isNodeInTree(server->nsCtx, constraintDataType, &enumNodeId, &subtypeId, 1))
+       isNodeInTree(server, constraintDataType, &enumNodeId, &subtypeId, 1))
         return true;
 
     /* More checks for the data type of real values (variants) */
@@ -685,7 +685,7 @@ compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
         if(dataType->namespaceIndex == 0 &&
            dataType->identifierType == UA_NODEIDTYPE_NUMERIC &&
            dataType->identifier.numeric <= 25 &&
-           isNodeInTree(server->nsCtx, constraintDataType,
+           isNodeInTree(server, constraintDataType,
                         dataType, &subtypeId, 1))
             return true;
     }
@@ -1389,7 +1389,7 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
         GET_NODETYPE
         retval = writeDataTypeAttribute(server, session, (UA_VariableNode*)node,
                                         type, (const UA_NodeId*)value);
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)type);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
         break;
     case UA_ATTRIBUTEID_VALUERANK:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
@@ -1398,7 +1398,7 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
         GET_NODETYPE
         retval = writeValueRankAttribute(server, session, (UA_VariableNode*)node,
                                          type, *(const UA_Int32*)value);
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)type);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
         break;
     case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
@@ -1408,7 +1408,7 @@ copyAttributeIntoNode(UA_Server *server, UA_Session *session,
         retval = writeArrayDimensionsAttribute(server, session, (UA_VariableNode*)node,
                                                type, wvalue->value.value.arrayLength,
                                                (UA_UInt32 *)wvalue->value.value.data);
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)type);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
         break;
     case UA_ATTRIBUTEID_ACCESSLEVEL:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);

+ 15 - 15
src/server/ua_services_method.c

@@ -34,7 +34,7 @@ getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
 
         for(size_t j = 0; j < rk->refTargetsSize; ++j) {
             const UA_Node *refTarget =
-                UA_Nodestore_getNode(server->nsCtx, &rk->refTargets[j].target.nodeId);
+                UA_NODESTORE_GET(server, &rk->refTargets[j].target.nodeId);
             if(!refTarget)
                 continue;
             if(refTarget->nodeClass == UA_NODECLASS_VARIABLE &&
@@ -42,7 +42,7 @@ getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
                UA_String_equal(&withBrowseName, &refTarget->browseName.name)) {
                 return (const UA_VariableNode*)refTarget;
             }
-            UA_Nodestore_releaseNode(server->nsCtx, refTarget);
+            UA_NODESTORE_RELEASE(server, refTarget);
         }
     }
     return NULL;
@@ -107,7 +107,7 @@ validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode
                                               inputArgumentResults);
 
     /* Release the input arguments node */
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)inputArguments);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)inputArguments);
     return retval;
 }
 
@@ -146,7 +146,7 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
         UA_NodeReferenceKind *rk = &object->references[i];
         if(rk->isInverse)
             continue;
-        if(!isNodeInTree(server->nsCtx, &rk->referenceTypeId,
+        if(!isNodeInTree(server, &rk->referenceTypeId,
                          &hasComponentNodeId, &hasSubTypeNodeId, 1))
             continue;
         for(size_t j = 0; j < rk->refTargetsSize; ++j) {
@@ -218,7 +218,7 @@ callWithMethodAndObject(UA_Server *server, UA_Session *session,
     result->outputArgumentsSize = outputArgsSize;
 
     /* Release the output arguments node */
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)outputArguments);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)outputArguments);
 
     /* Call the method */
     UA_UNLOCK(server->serviceMutex);
@@ -257,7 +257,7 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, void *context,
 
     /* Get the method node */
     const UA_MethodNode *method = (const UA_MethodNode*)
-        UA_Nodestore_getNode(server->nsCtx, &request->methodId);
+        UA_NODESTORE_GET(server, &request->methodId);
     if(!method) {
         result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return;
@@ -265,10 +265,10 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, void *context,
 
     /* Get the object node */
     const UA_ObjectNode *object = (const UA_ObjectNode*)
-        UA_Nodestore_getNode(server->nsCtx, &request->objectId);
+        UA_NODESTORE_GET(server, &request->objectId);
     if(!object) {
         result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)method);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
         return;
     }
 
@@ -296,8 +296,8 @@ Operation_CallMethodAsync(UA_Server *server, UA_Session *session, void *context,
     }
 
     /* Release the method and object node */
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)method);
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)object);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)object);
 }
 
 void Service_CallAsync(UA_Server *server, UA_Session *session,
@@ -328,7 +328,7 @@ Operation_CallMethod(UA_Server *server, UA_Session *session, void *context,
                      const UA_CallMethodRequest *request, UA_CallMethodResult *result) {
     /* Get the method node */
     const UA_MethodNode *method = (const UA_MethodNode*)
-        UA_Nodestore_getNode(server->nsCtx, &request->methodId);
+        UA_NODESTORE_GET(server, &request->methodId);
     if(!method) {
         result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return;
@@ -336,10 +336,10 @@ Operation_CallMethod(UA_Server *server, UA_Session *session, void *context,
 
     /* Get the object node */
     const UA_ObjectNode *object = (const UA_ObjectNode*)
-        UA_Nodestore_getNode(server->nsCtx, &request->objectId);
+        UA_NODESTORE_GET(server, &request->objectId);
     if(!object) {
         result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)method);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
         return;
     }
 
@@ -347,8 +347,8 @@ Operation_CallMethod(UA_Server *server, UA_Session *session, void *context,
     callWithMethodAndObject(server, session, request, result, method, object);
 
     /* Release the method and object node */
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)method);
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)object);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)method);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)object);
 }
 
 void Service_Call(UA_Server *server, UA_Session *session,

+ 2 - 2
src/server/ua_services_monitoreditem.c

@@ -92,12 +92,12 @@ setMonitoredItemSettings(UA_Server *server, UA_MonitoredItem *mon,
 
     if(mon->attributeId == UA_ATTRIBUTEID_VALUE) {
         const UA_VariableNode *vn = (const UA_VariableNode *)
-            UA_Nodestore_getNode(server->nsCtx, &mon->monitoredNodeId);
+            UA_NODESTORE_GET(server, &mon->monitoredNodeId);
         if(vn) {
             if(vn->nodeClass == UA_NODECLASS_VARIABLE &&
                samplingInterval < vn->minimumSamplingInterval)
                 samplingInterval = vn->minimumSamplingInterval;
-            UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node *)vn);
+            UA_NODESTORE_RELEASE(server, (const UA_Node *)vn);
         }
     }
 

+ 50 - 49
src/server/ua_services_nodemanagement.c

@@ -35,11 +35,11 @@ UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
 UA_StatusCode
 getNodeContext(UA_Server *server, UA_NodeId nodeId,
                          void **nodeContext) {
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, &nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
     *nodeContext = node->context;
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     return UA_STATUSCODE_GOOD;
 }
 
@@ -99,7 +99,7 @@ checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeCl
         return UA_STATUSCODE_GOOD;
 
     /* See if the parent exists */
-    const UA_Node *parent = UA_Nodestore_getNode(server->nsCtx, parentNodeId);
+    const UA_Node *parent = UA_NODESTORE_GET(server, parentNodeId);
     if(!parent) {
         UA_LOG_NODEID_WRAP(parentNodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
                             "AddNodes: Parent node %.*s not found",
@@ -108,11 +108,11 @@ checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeCl
     }
 
     UA_NodeClass parentNodeClass = parent->nodeClass;
-    UA_Nodestore_releaseNode(server->nsCtx, parent);
+    UA_NODESTORE_RELEASE(server, parent);
 
     /* Check the referencetype exists */
     const UA_ReferenceTypeNode *referenceType = (const UA_ReferenceTypeNode*)
-        UA_Nodestore_getNode(server->nsCtx, referenceTypeId);
+        UA_NODESTORE_GET(server, referenceTypeId);
     if(!referenceType) {
         UA_LOG_NODEID_WRAP(referenceTypeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
                            "AddNodes: Reference type %.*s to the parent not found",
@@ -125,12 +125,12 @@ checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeCl
         UA_LOG_NODEID_WRAP(referenceTypeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
                            "AddNodes: Reference type %.*s to the parent is not a ReferenceTypeNode",
                            (int)nodeIdStr.length, nodeIdStr.data));
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)referenceType);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)referenceType);
         return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
     }
 
     UA_Boolean referenceTypeIsAbstract = referenceType->isAbstract;
-    UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)referenceType);
+    UA_NODESTORE_RELEASE(server, (const UA_Node*)referenceType);
     /* Check that the reference type is not abstract */
     if(referenceTypeIsAbstract == true) {
         UA_LOG_NODEID_WRAP(referenceTypeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
@@ -162,8 +162,7 @@ checkParentReference(UA_Server *server, UA_Session *session, UA_NodeClass nodeCl
     }
 
     /* Test if the referencetype is hierarchical */
-    if(!isNodeInTree(server->nsCtx, referenceTypeId,
-                     &hierarchicalReferences, &subtypeId, 1)) {
+    if(!isNodeInTree(server, referenceTypeId, &hierarchicalReferences, &subtypeId, 1)) {
         UA_LOG_INFO_SESSION(&server->config.logger, session,
                             "AddNodes: Reference type to the parent is not hierarchical");
         return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
@@ -337,12 +336,12 @@ useVariableTypeAttributes(UA_Server *server, UA_Session *session,
     /* If the node was modified, update the pointer to the new version */
     if(modified) {
         const UA_VariableNode *updated = (const UA_VariableNode*)
-            UA_Nodestore_getNode(server->nsCtx, &node->nodeId);
+            UA_NODESTORE_GET(server, &node->nodeId);
 
         if(!updated)
             return UA_STATUSCODE_BADINTERNALERROR;
 
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)node);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)node);
         *node_ptr = updated;
     }
 
@@ -396,7 +395,7 @@ static UA_Boolean
 isMandatoryChild(UA_Server *server, UA_Session *session,
                  const UA_NodeId *childNodeId) {
     /* Get the child */
-    const UA_Node *child = UA_Nodestore_getNode(server->nsCtx, childNodeId);
+    const UA_Node *child = UA_NODESTORE_GET(server, childNodeId);
     if(!child)
         return false;
 
@@ -409,13 +408,13 @@ isMandatoryChild(UA_Server *server, UA_Session *session,
             continue;
         for(size_t j = 0; j < refs->refTargetsSize; ++j) {
             if(UA_NodeId_equal(&mandatoryId, &refs->refTargets[j].target.nodeId)) {
-                UA_Nodestore_releaseNode(server->nsCtx, child);
+                UA_NODESTORE_RELEASE(server, child);
                 return true;
             }
         }
     }
 
-    UA_Nodestore_releaseNode(server->nsCtx, child);
+    UA_NODESTORE_RELEASE(server, child);
     return false;
 }
 
@@ -487,7 +486,7 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
        rd->nodeClass == UA_NODECLASS_OBJECT) {
         /* Make a copy of the node */
         UA_Node *node;
-        retval = UA_Nodestore_getNodeCopy(server->nsCtx, &rd->nodeId.nodeId, &node);
+        retval = UA_NODESTORE_GETCOPY(server, &rd->nodeId.nodeId, &node);
         if(retval != UA_STATUSCODE_GOOD)
             return retval;
 
@@ -509,7 +508,7 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
                                                                       &node->nodeId);
             UA_LOCK(server->serviceMutex);
             if(retval != UA_STATUSCODE_GOOD) {
-                UA_Nodestore_deleteNode(server->nsCtx, node);
+                UA_NODESTORE_DELETE(server, node);
                 return retval;
             }
         }
@@ -525,7 +524,7 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
 
         /* Add the node to the nodestore */
         UA_NodeId newNodeId;
-        retval = UA_Nodestore_insertNode(server->nsCtx, node, &newNodeId);
+        retval = UA_NODESTORE_INSERT(server, node, &newNodeId);
         if(retval != UA_STATUSCODE_GOOD)
             return retval;
 
@@ -533,7 +532,7 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
         retval = AddNode_addRefs(server, session, &newNodeId, destinationNodeId,
                                  &rd->referenceTypeId, &rd->typeDefinition.nodeId);
         if(retval != UA_STATUSCODE_GOOD) {
-            UA_Nodestore_removeNode(server->nsCtx, &newNodeId);
+            UA_NODESTORE_REMOVE(server, &newNodeId);
             return retval;
         }
 
@@ -631,7 +630,7 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
                 const UA_NodeId *typeDefinitionId) {
     /* Get the node */
     const UA_Node *type = NULL;
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
 
@@ -642,11 +641,11 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
        node->nodeClass == UA_NODECLASS_DATATYPE) {
         if(UA_NodeId_equal(referenceTypeId, &UA_NODEID_NULL))
             referenceTypeId = &hasSubtype;
-        const UA_Node *parentNode = UA_Nodestore_getNode(server->nsCtx, parentNodeId);
+        const UA_Node *parentNode = UA_NODESTORE_GET(server, parentNodeId);
         if(parentNode) {
             if(parentNode->nodeClass == node->nodeClass)
                 typeDefinitionId = parentNodeId;
-            UA_Nodestore_releaseNode(server->nsCtx, parentNode);
+            UA_NODESTORE_RELEASE(server, parentNode);
         }
     }
 
@@ -692,7 +691,7 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
      * and type-nodes. See the above checks. */
     if(!UA_NodeId_isNull(typeDefinitionId)) {
         /* Get the type node */
-        type = UA_Nodestore_getNode(server->nsCtx, typeDefinitionId);
+        type = UA_NODESTORE_GET(server, typeDefinitionId);
         if(!type) {
             UA_LOG_NODEID_WRAP(typeDefinitionId, UA_LOG_INFO_SESSION(&server->config.logger, session,
                                 "AddNodes: Node type %.*s not found",
@@ -760,9 +759,9 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
                  * object type which again is below BaseObjectType */
                 const UA_NodeId variableTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
                 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
-                if(!isNodeInTree(server->nsCtx, parentNodeId, &variableTypes,
+                if(!isNodeInTree(server, parentNodeId, &variableTypes,
                                  parentTypeHierarchy, parentTypeHierarchySize) &&
-                   !isNodeInTree(server->nsCtx, parentNodeId, &objectTypes,
+                   !isNodeInTree(server, parentNodeId, &objectTypes,
                                  parentTypeHierarchy, parentTypeHierarchySize)) {
                     UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
                                         "AddNodes: Type of variable node %.*s must "
@@ -795,11 +794,13 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
                 /* Object node created of an abstract ObjectType. Only allowed
                  * if within BaseObjectType folder or if it's an event (subType of BaseEventType) */
                 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
-                UA_Boolean isInBaseObjectType = isNodeInTree(server->nsCtx, parentNodeId, &objectTypes,
-                                                             parentTypeHierarchy, parentTypeHierarchySize);
+                UA_Boolean isInBaseObjectType =
+                    isNodeInTree(server, parentNodeId, &objectTypes,
+                                 parentTypeHierarchy, parentTypeHierarchySize);
 
                 const UA_NodeId eventTypes = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
-                UA_Boolean isInBaseEventType = isNodeInTree(server->nsCtx, &type->nodeId, &eventTypes, &hasSubtype, 1);
+                UA_Boolean isInBaseEventType =
+                    isNodeInTree(server, &type->nodeId, &eventTypes, &hasSubtype, 1);
 
                 if(!isInBaseObjectType && !(isInBaseEventType && UA_NodeId_isNull(parentNodeId))) {
                     UA_LOG_NODEID_WRAP(nodeId, UA_LOG_INFO_SESSION(&server->config.logger, session,
@@ -850,9 +851,9 @@ AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
     }
 
  cleanup:
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     if(type)
-        UA_Nodestore_releaseNode(server->nsCtx, type);
+        UA_NODESTORE_RELEASE(server, type);
     return retval;
 }
 
@@ -887,7 +888,7 @@ AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
     }
 
     /* Create a node */
-    UA_Node *node = UA_Nodestore_newNode(server->nsCtx, item->nodeClass);
+    UA_Node *node = UA_NODESTORE_NEW(server, item->nodeClass);
     if(!node) {
         UA_LOG_INFO_SESSION(&server->config.logger, session,
                             "AddNodes: Node could not create a node "
@@ -911,7 +912,7 @@ AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
         goto create_error;
 
     /* Add the node to the nodestore */
-    retval = UA_Nodestore_insertNode(server->nsCtx, node, outNewNodeId);
+    retval = UA_NODESTORE_INSERT(server, node, outNewNodeId);
     if(retval != UA_STATUSCODE_GOOD)
         UA_LOG_INFO_SESSION(&server->config.logger, session,
                             "AddNodes: Node could not add the new node "
@@ -923,7 +924,7 @@ create_error:
     UA_LOG_INFO_SESSION(&server->config.logger, session,
                         "AddNodes: Node could not create a node "
                         "with error code %s", UA_StatusCode_name(retval));
-    UA_Nodestore_deleteNode(server->nsCtx, node);
+    UA_NODESTORE_DELETE(server, node);
     return retval;
 }
 
@@ -1113,11 +1114,11 @@ recursiveCallConstructors(UA_Server *server, UA_Session *session,
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     for(size_t i = 0; i < br.referencesSize; ++i) {
         UA_ReferenceDescription *rd = &br.references[i];
-        const UA_Node *target = UA_Nodestore_getNode(server->nsCtx, &rd->nodeId.nodeId);
+        const UA_Node *target = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
         if(!target)
             continue;
         if(target->constructed) {
-            UA_Nodestore_releaseNode(server->nsCtx, target);
+            UA_NODESTORE_RELEASE(server, target);
             continue;
         }
 
@@ -1126,15 +1127,15 @@ recursiveCallConstructors(UA_Server *server, UA_Session *session,
            node->nodeClass == UA_NODECLASS_OBJECT) {
             targetType = getNodeType(server, target);
             if(!targetType) {
-                UA_Nodestore_releaseNode(server->nsCtx, target);
+                UA_NODESTORE_RELEASE(server, target);
                 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
                 break;
             }
         }
         retval = recursiveCallConstructors(server, session, target, targetType);
-        UA_Nodestore_releaseNode(server->nsCtx, target);
+        UA_NODESTORE_RELEASE(server, target);
         if(targetType)
-            UA_Nodestore_releaseNode(server->nsCtx, targetType);
+            UA_NODESTORE_RELEASE(server, targetType);
         if(retval != UA_STATUSCODE_GOOD)
             break;
     }
@@ -1227,7 +1228,7 @@ AddNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId)
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
 
     /* Get the node */
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
 
@@ -1270,12 +1271,12 @@ AddNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId)
 
  cleanup:
     if(type)
-        UA_Nodestore_releaseNode(server->nsCtx, type);
+        UA_NODESTORE_RELEASE(server, type);
     if(retval != UA_STATUSCODE_GOOD) {
         recursiveDeconstructNode(server, session, 0, NULL, node);
         recursiveDeleteNode(server, session, 0, NULL, node, true);
     }
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     return retval;
 }
 
@@ -1494,7 +1495,7 @@ recursiveDeconstructNode(UA_Server *server, UA_Session *session,
                                       &node->nodeId, &context);
                 UA_LOCK(server->serviceMutex);
             }
-            UA_Nodestore_releaseNode(server->nsCtx, type);
+            UA_NODESTORE_RELEASE(server, type);
         }
     }
 
@@ -1529,14 +1530,14 @@ recursiveDeconstructNode(UA_Server *server, UA_Session *session,
     /* Deconstruct every child node */
     for(size_t i = 0; i < br.referencesSize; ++i) {
         UA_ReferenceDescription *rd = &br.references[i];
-        const UA_Node *child = UA_Nodestore_getNode(server->nsCtx, &rd->nodeId.nodeId);
+        const UA_Node *child = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
         if(!child)
             continue;
         /* Only delete child nodes that have no other parent */
         if(!multipleHierarchies(hierarchicalRefsSize, hierarchicalRefs, child))
             recursiveDeconstructNode(server, session, hierarchicalRefsSize,
                                      hierarchicalRefs, child);
-        UA_Nodestore_releaseNode(server->nsCtx, child);
+        UA_NODESTORE_RELEASE(server, child);
     }
 
     UA_BrowseResult_clear(&br);
@@ -1568,14 +1569,14 @@ recursiveDeleteNode(UA_Server *server, UA_Session *session,
         /* Check for self-reference to avoid endless loop */
         if(UA_NodeId_equal(&node->nodeId, &rd->nodeId.nodeId))
             continue;
-        const UA_Node *child = UA_Nodestore_getNode(server->nsCtx, &rd->nodeId.nodeId);
+        const UA_Node *child = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
         if(!child)
             continue;
         /* Only delete child nodes that have no other parent */
         if(!multipleHierarchies(hierarchicalRefsSize, hierarchicalRefs, child))
             recursiveDeleteNode(server, session, hierarchicalRefsSize,
                                 hierarchicalRefs, child, true);
-        UA_Nodestore_releaseNode(server->nsCtx, child);
+        UA_NODESTORE_RELEASE(server, child);
     }
 
     UA_BrowseResult_clear(&br);
@@ -1583,7 +1584,7 @@ recursiveDeleteNode(UA_Server *server, UA_Session *session,
     if(removeTargetRefs)
         removeIncomingReferences(server, session, node);
 
-    UA_Nodestore_removeNode(server->nsCtx, &node->nodeId);
+    UA_NODESTORE_REMOVE(server, &node->nodeId);
 }
 
 static void
@@ -1601,7 +1602,7 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
         UA_LOCK(server->serviceMutex);
     }
 
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &item->nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
     if(!node) {
         *result = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return;
@@ -1611,7 +1612,7 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
         UA_LOG_INFO_SESSION(&server->config.logger, session,
                             "Delete Nodes: Cannot delete a type node "
                             "with active instances or subtypes");
-        UA_Nodestore_releaseNode(server->nsCtx, node);
+        UA_NODESTORE_RELEASE(server, node);
         *result = UA_STATUSCODE_BADINTERNALERROR;
         return;
     }
@@ -1639,7 +1640,7 @@ deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
                         item->deleteTargetReferences);
     UA_Array_delete(hierarchicalRefs, hierarchicalRefsSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
     
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
 }
 
 void Service_DeleteNodes(UA_Server *server, UA_Session *session,

+ 22 - 22
src/server/ua_services_view.c

@@ -165,7 +165,7 @@ static UA_StatusCode
 addRelevantReferences(UA_Server *server, RefTree *rt, const UA_NodeId *nodeId,
                       size_t refTypesSize, const UA_NodeId *refTypes,
                       UA_BrowseDirection browseDirection) {
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
 
@@ -191,7 +191,7 @@ addRelevantReferences(UA_Server *server, RefTree *rt, const UA_NodeId *nodeId,
     }
 
  cleanup:
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     return retval;
 }
 
@@ -432,7 +432,7 @@ addReferenceDescription(UA_Server *server, RefResult *rr, const UA_NodeReference
             const UA_Node *type = getNodeType(server, curr);
             if(type) {
                 retval |= UA_NodeId_copy(&type->nodeId, &descr->typeDefinition.nodeId);
-                UA_Nodestore_releaseNode(server->nsCtx, type);
+                UA_NODESTORE_RELEASE(server, type);
             }
         }
     }
@@ -486,13 +486,13 @@ browseReferences(UA_Server *server, const UA_Node *node,
             /* Get the node if it is not a remote reference */
             if(rk->refTargets[targetIndex].target.serverIndex == 0 &&
                rk->refTargets[targetIndex].target.namespaceUri.data == NULL) {
-                target = UA_Nodestore_getNode(server->nsCtx,
-                                              &rk->refTargets[targetIndex].target.nodeId);
+                target = UA_NODESTORE_GET(server,
+                                          &rk->refTargets[targetIndex].target.nodeId);
 
                 /* Test if the node class matches */
                 if(target && !matchClassMask(target, bd->nodeClassMask)) {
                     if(target)
-                        UA_Nodestore_releaseNode(server->nsCtx, target);
+                        UA_NODESTORE_RELEASE(server, target);
                     continue;
                 }
             }
@@ -502,14 +502,14 @@ browseReferences(UA_Server *server, const UA_Node *node,
                 cp->referenceKindIndex = referenceKindIndex;
                 cp->targetIndex = targetIndex;
                 if(target)
-                    UA_Nodestore_releaseNode(server->nsCtx, target);
+                    UA_NODESTORE_RELEASE(server, target);
                 return UA_STATUSCODE_GOOD;
             }
 
             /* Copy the node description. Target is on top of the stack */
             retval = addReferenceDescription(server, rr, rk, bd->resultMask,
                                              &rk->refTargets[targetIndex].target, target);
-            UA_Nodestore_releaseNode(server->nsCtx, target);
+            UA_NODESTORE_RELEASE(server, target);
             if(retval != UA_STATUSCODE_GOOD)
                 return retval;
         }
@@ -541,14 +541,14 @@ browseWithContinuation(UA_Server *server, UA_Session *session,
 
     /* Is the reference type valid? */
     if(!UA_NodeId_isNull(&descr->referenceTypeId)) {
-        const UA_Node *reftype = UA_Nodestore_getNode(server->nsCtx, &descr->referenceTypeId);
+        const UA_Node *reftype = UA_NODESTORE_GET(server, &descr->referenceTypeId);
         if(!reftype) {
             result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
             return true;
         }
 
         UA_Boolean isRef = (reftype->nodeClass == UA_NODECLASS_REFERENCETYPE);
-        UA_Nodestore_releaseNode(server->nsCtx, reftype);
+        UA_NODESTORE_RELEASE(server, reftype);
 
         if(!isRef) {
             result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
@@ -556,7 +556,7 @@ browseWithContinuation(UA_Server *server, UA_Session *session,
         }
     }
 
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &descr->nodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, &descr->nodeId);
     if(!node) {
         result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return true;
@@ -565,14 +565,14 @@ browseWithContinuation(UA_Server *server, UA_Session *session,
     RefResult rr;
     result->statusCode = RefResult_init(&rr);
     if(result->statusCode != UA_STATUSCODE_GOOD) {
-        UA_Nodestore_releaseNode(server->nsCtx, node);
+        UA_NODESTORE_RELEASE(server, node);
         return true;
     }
 
     /* Browse the references */
     UA_Boolean done = false;
     result->statusCode = browseReferences(server, node, cp, &rr, &done);
-    UA_Nodestore_releaseNode(server->nsCtx, node);
+    UA_NODESTORE_RELEASE(server, node);
     if(result->statusCode != UA_STATUSCODE_GOOD) {
         RefResult_clear(&rr);
         return true;
@@ -875,11 +875,11 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, UA_UInt32 nodeClas
     /* Return all references? */
     UA_Boolean all_refs = UA_NodeId_isNull(&elem->referenceTypeId);
     if(!all_refs) {
-        const UA_Node *rootRef = UA_Nodestore_getNode(server->nsCtx, &elem->referenceTypeId);
+        const UA_Node *rootRef = UA_NODESTORE_GET(server, &elem->referenceTypeId);
         if(!rootRef)
             return;
         UA_Boolean match = (rootRef->nodeClass == UA_NODECLASS_REFERENCETYPE);
-        UA_Nodestore_releaseNode(server->nsCtx, rootRef);
+        UA_NODESTORE_RELEASE(server, rootRef);
         if(!match)
             return;
     }
@@ -887,7 +887,7 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, UA_UInt32 nodeClas
     /* Iterate over all nodes at the current depth-level */
     for(size_t i = 0; i < currentCount; ++i) {
         /* Get the node */
-        const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &current[i]);
+        const UA_Node *node = UA_NODESTORE_GET(server, &current[i]);
         if(!node) {
             /* If we cannot find the node at depth 0, the starting node does not exist */
             if(elemDepth == 0)
@@ -897,7 +897,7 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, UA_UInt32 nodeClas
 
         /* Test whether the node fits the class mask */
         if(!matchClassMask(node, nodeClassMask)) {
-            UA_Nodestore_releaseNode(server->nsCtx, node);
+            UA_NODESTORE_RELEASE(server, node);
             continue;
         }
 
@@ -905,7 +905,7 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, UA_UInt32 nodeClas
          * path element */
         if(targetName && (targetName->namespaceIndex != node->browseName.namespaceIndex ||
                           !UA_String_equal(&targetName->name, &node->browseName.name))) {
-            UA_Nodestore_releaseNode(server->nsCtx, node);
+            UA_NODESTORE_RELEASE(server, node);
             continue;
         }
 
@@ -922,7 +922,7 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, UA_UInt32 nodeClas
             if(!all_refs) {
                 if(!elem->includeSubtypes && !UA_NodeId_equal(&rk->referenceTypeId, &elem->referenceTypeId))
                     continue;
-                if(!isNodeInTree(server->nsCtx, &rk->referenceTypeId, &elem->referenceTypeId, &subtypeId, 1))
+                if(!isNodeInTree(server, &rk->referenceTypeId, &elem->referenceTypeId, &subtypeId, 1))
                     continue;
             }
 
@@ -931,7 +931,7 @@ walkBrowsePathElement(UA_Server *server, UA_Session *session, UA_UInt32 nodeClas
                                                   nextCount, elemDepth, rk);
         }
 
-        UA_Nodestore_releaseNode(server->nsCtx, node);
+        UA_NODESTORE_RELEASE(server, node);
     }
 }
 
@@ -941,7 +941,7 @@ addBrowsePathTargets(UA_Server *server, UA_Session *session, UA_UInt32 nodeClass
                      UA_BrowsePathResult *result, const UA_QualifiedName *targetName,
                      UA_NodeId *current, size_t currentCount) {
     for(size_t i = 0; i < currentCount; i++) {
-        const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &current[i]);
+        const UA_Node *node = UA_NODESTORE_GET(server, &current[i]);
         if(!node) {
             UA_NodeId_clear(&current[i]);
             continue;
@@ -956,7 +956,7 @@ addBrowsePathTargets(UA_Server *server, UA_Session *session, UA_UInt32 nodeClass
            !UA_String_equal(&targetName->name, &node->browseName.name))
             skip = true;
 
-        UA_Nodestore_releaseNode(server->nsCtx, node);
+        UA_NODESTORE_RELEASE(server, node);
 
         if(skip) {
             UA_NodeId_clear(&current[i]);

+ 2 - 2
src/server/ua_subscription_datachange.c

@@ -344,7 +344,7 @@ monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem)
     UA_assert(monitoredItem->attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
 
     /* Get the node */
-    const UA_Node *node = UA_Nodestore_getNode(server->nsCtx, &monitoredItem->monitoredNodeId);
+    const UA_Node *node = UA_NODESTORE_GET(server, &monitoredItem->monitoredNodeId);
 
     /* Sample the value. The sample can still point into the node. */
     UA_DataValue value;
@@ -375,7 +375,7 @@ monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem)
     if(!movedValue)
         UA_DataValue_clear(&value); /* Does nothing for UA_VARIANT_DATA_NODELETE */
     if(node)
-        UA_Nodestore_releaseNode(server->nsCtx, node);
+        UA_NODESTORE_RELEASE(server, node);
 }
 
 #endif /* UA_ENABLE_SUBSCRIPTIONS */

+ 9 - 9
src/server/ua_subscription_events.c

@@ -68,7 +68,7 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
     /* Make sure the eventType is a subtype of BaseEventType */
     UA_NodeId hasSubtypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
     UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
-    if(!isNodeInTree(server->nsCtx, &eventType, &baseEventTypeId, &hasSubtypeId, 1)) {
+    if(!isNodeInTree(server, &eventType, &baseEventTypeId, &hasSubtypeId, 1)) {
         UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
                      "Event type must be a subtype of BaseEventType!");
         UA_UNLOCK(server->serviceMutex);
@@ -160,7 +160,7 @@ isValidEvent(UA_Server *server, const UA_NodeId *validEventParent,
     UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CONDITIONTYPE);
     UA_NodeId hasSubtypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
     if(UA_NodeId_equal(validEventParent, &conditionTypeId) ||
-       isNodeInTree(server->nsCtx, tEventType, &conditionTypeId, &hasSubtypeId, 1)) {
+       isNodeInTree(server, tEventType, &conditionTypeId, &hasSubtypeId, 1)) {
         UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
                      "Alarms and Conditions are not supported yet!");
         UA_BrowsePathResult_clear(&bpr);
@@ -170,7 +170,7 @@ isValidEvent(UA_Server *server, const UA_NodeId *validEventParent,
 
     /* check whether Valid Event other than Conditions */
     UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEEVENTTYPE);
-    UA_Boolean isSubtypeOfBaseEvent = isNodeInTree(server->nsCtx, tEventType,
+    UA_Boolean isSubtypeOfBaseEvent = isNodeInTree(server, tEventType,
                                                    &baseEventTypeId, &hasSubtypeId, 1);
 
     UA_BrowsePathResult_clear(&bpr);
@@ -406,17 +406,17 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
 #endif
 
     /* Check that the origin node exists */
-    const UA_Node *originNode = UA_Nodestore_getNode(server->nsCtx, &origin);
+    const UA_Node *originNode = UA_NODESTORE_GET(server, &origin);
     if(!originNode) {
         UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
                      "Origin node for event does not exist.");
         UA_UNLOCK(server->serviceMutex);
         return UA_STATUSCODE_BADNOTFOUND;
     }
-    UA_Nodestore_releaseNode(server->nsCtx, originNode);
+    UA_NODESTORE_RELEASE(server, originNode);
 
     /* Make sure the origin is in the ObjectsFolder (TODO: or in the ViewsFolder) */
-    if(!isNodeInTree(server->nsCtx, &origin, &objectsFolderId,
+    if(!isNodeInTree(server, &origin, &objectsFolderId,
                      emitReferencesRoots, 2)) { /* Only use Organizes and
                                                  * HasComponent to check if we
                                                  * are below the ObjectsFolder */
@@ -492,11 +492,11 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
     /* Add the event to the listening MonitoredItems at each relevant node */
     for(size_t i = 0; i < emitNodesSize; i++) {
         const UA_ObjectNode *node = (const UA_ObjectNode*)
-            UA_Nodestore_getNode(server->nsCtx, &emitNodes[i].nodeId);
+            UA_NODESTORE_GET(server, &emitNodes[i].nodeId);
         if(!node)
             continue;
         if(node->nodeClass != UA_NODECLASS_OBJECT) {
-            UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)node);
+            UA_NODESTORE_RELEASE(server, (const UA_Node*)node);
             continue;
         }
         for(UA_MonitoredItem *mi = node->monitoredItemQueue; mi != NULL; mi = mi->next) {
@@ -508,7 +508,7 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
                 retval = UA_STATUSCODE_GOOD; /* Only log problems with individual emit nodes */
             }
         }
-        UA_Nodestore_releaseNode(server->nsCtx, (const UA_Node*)node);
+        UA_NODESTORE_RELEASE(server, (const UA_Node*)node);
     }
 
     /* Delete the node representation of the event */

+ 1 - 1
src/server/ua_subscription_monitoreditem.c

@@ -34,7 +34,7 @@ UA_Notification_isOverflowEvent(UA_Server *server, UA_Notification *n) {
     UA_EventFieldList *efl = &n->data.event.fields;
     if(efl->eventFieldsSize >= 1 &&
        efl->eventFields[0].type == &UA_TYPES[UA_TYPES_NODEID] &&
-       isNodeInTree(server->nsCtx, (const UA_NodeId *)efl->eventFields[0].data,
+       isNodeInTree(server, (const UA_NodeId *)efl->eventFields[0].data,
                     &overflowEventType, &subtypeId, 1)) {
         return true;
     }

+ 1 - 1
tests/CMakeLists.txt

@@ -60,7 +60,7 @@ set(test_plugin_sources ${PROJECT_SOURCE_DIR}/arch/network_tcp.c
     ${PROJECT_SOURCE_DIR}/plugins/ua_config_default.c
     ${PROJECT_SOURCE_DIR}/plugins/ua_accesscontrol_default.c
     ${PROJECT_SOURCE_DIR}/plugins/ua_pki_default.c
-    ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_default.c
+    ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_ziptree.c
     ${PROJECT_SOURCE_DIR}/plugins/securityPolicies/ua_securitypolicy_none.c
     ${PROJECT_SOURCE_DIR}/tests/testing-plugins/testing_policy.c
     ${PROJECT_SOURCE_DIR}/tests/testing-plugins/testing_networklayers.c

+ 50 - 78
tests/server/check_nodestore.c

@@ -4,53 +4,25 @@
 
 #include <open62541/types.h>
 #include <open62541/util.h>
-#include <open62541/plugin/nodestore.h>
+#include <open62541/plugin/nodestore_default.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-
 #include "check.h"
-#include "ziptree.h"
-
-/* container_of */
-#define container_of(ptr, type, member) \
-    (type *)((uintptr_t)ptr - offsetof(type,member))
 
 #if UA_MULTITHREADING >= 200
 #include <pthread.h>
 #endif
 
-/* Dirty redifinition from ua_nodestore_default.c to check that all nodes were
- * released */
-struct NodeEntry;
-typedef struct NodeEntry NodeEntry;
-
-struct NodeEntry {
-    ZIP_ENTRY(NodeEntry) zipfields;
-    UA_UInt32 nodeIdHash;
-    UA_UInt16 refCount; /* How many consumers have a reference to the node? */
-    UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
-    NodeEntry *orig;    /* If a copy is made to replace a node, track that we
-                         * replace only the node from which the copy was made.
-                         * Important for concurrent operations. */
-    UA_NodeId nodeId; /* This is actually a UA_Node that also starts with a NodeId */
-};
-
-static void checkAllReleased(void *context, const UA_Node* node) {
-    NodeEntry *entry = container_of(node, NodeEntry, nodeId);
-    ck_assert_int_eq(entry->refCount, 0); /* The count is increased when the visited node is checked out */
-}
-
-void *nsCtx;
+UA_Nodestore ns;
 
 static void setup(void) {
-    UA_Nodestore_new(&nsCtx);
+    UA_Nodestore_ZipTree(&ns);
 }
 
 static void teardown(void) {
-    UA_Nodestore_iterate(nsCtx, checkAllReleased, NULL);
-    UA_Nodestore_delete(nsCtx);
+    ns.clear(ns.context);
 }
 
 static int zeroCnt = 0;
@@ -61,7 +33,7 @@ static void checkZeroVisitor(void *context, const UA_Node* node) {
 }
 
 static UA_Node* createNode(UA_Int16 nsid, UA_Int32 id) {
-    UA_Node *p = UA_Nodestore_newNode(nsCtx, UA_NODECLASS_VARIABLE);
+    UA_Node *p = ns.newNode(&ns.context, UA_NODECLASS_VARIABLE);
     p->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
     p->nodeId.namespaceIndex = nsid;
     p->nodeId.identifier.numeric = id;
@@ -71,91 +43,91 @@ static UA_Node* createNode(UA_Int16 nsid, UA_Int32 id) {
 
 START_TEST(replaceExistingNode) {
     UA_Node* n1 = createNode(0,2253);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_NodeId in1 = UA_NODEID_NUMERIC(0, 2253);
     UA_Node* n2;
-    UA_Nodestore_getNodeCopy(nsCtx, &in1, &n2);
-    UA_StatusCode retval = UA_Nodestore_replaceNode(nsCtx, n2);
+    ns.getNodeCopy(ns.context, &in1, &n2);
+    UA_StatusCode retval = ns.replaceNode(ns.context, n2);
     ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
 }
 END_TEST
 
 START_TEST(replaceOldNode) {
     UA_Node* n1 = createNode(0,2253);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_NodeId in1 = UA_NODEID_NUMERIC(0,2253);
     UA_Node* n2;
     UA_Node* n3;
-    UA_Nodestore_getNodeCopy(nsCtx, &in1, &n2);
-    UA_Nodestore_getNodeCopy(nsCtx, &in1, &n3);
+    ns.getNodeCopy(ns.context, &in1, &n2);
+    ns.getNodeCopy(ns.context, &in1, &n3);
 
     /* shall succeed */
-    UA_StatusCode retval = UA_Nodestore_replaceNode(nsCtx, n2);
+    UA_StatusCode retval = ns.replaceNode(ns.context, n2);
     ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
 
     /* shall fail */
-    retval = UA_Nodestore_replaceNode(nsCtx, n3);
+    retval = ns.replaceNode(ns.context, n3);
     ck_assert_int_ne(retval, UA_STATUSCODE_GOOD);
 }
 END_TEST
 
 START_TEST(findNodeInUA_NodeStoreWithSingleEntry) {
     UA_Node* n1 = createNode(0,2253);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_NodeId in1 = UA_NODEID_NUMERIC(0,2253);
-    const UA_Node* nr = UA_Nodestore_getNode(nsCtx, &in1);
+    const UA_Node* nr = ns.getNode(ns.context, &in1);
     ck_assert_int_eq((uintptr_t)n1, (uintptr_t)nr);
-    UA_Nodestore_releaseNode(nsCtx, nr);
+    ns.releaseNode(ns.context, nr);
 }
 END_TEST
 
 START_TEST(failToFindNodeInOtherUA_NodeStore) {
     UA_Node* n1 = createNode(0,2255);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_NodeId in1 = UA_NODEID_NUMERIC(1, 2255);
-    const UA_Node* nr = UA_Nodestore_getNode(nsCtx, &in1);
+    const UA_Node* nr = ns.getNode(ns.context, &in1);
     ck_assert_int_eq((uintptr_t)nr, 0);
 }
 END_TEST
 
 START_TEST(findNodeInUA_NodeStoreWithSeveralEntries) {
     UA_Node* n1 = createNode(0,2253);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_Node* n2 = createNode(0,2255);
-    UA_Nodestore_insertNode(nsCtx, n2, NULL);
+    ns.insertNode(ns.context, n2, NULL);
     UA_Node* n3 = createNode(0,2257);
-    UA_Nodestore_insertNode(nsCtx, n3, NULL);
+    ns.insertNode(ns.context, n3, NULL);
     UA_Node* n4 = createNode(0,2200);
-    UA_Nodestore_insertNode(nsCtx, n4, NULL);
+    ns.insertNode(ns.context, n4, NULL);
     UA_Node* n5 = createNode(0,1);
-    UA_Nodestore_insertNode(nsCtx, n5, NULL);
+    ns.insertNode(ns.context, n5, NULL);
     UA_Node* n6 = createNode(0,12);
-    UA_Nodestore_insertNode(nsCtx, n6, NULL);
+    ns.insertNode(ns.context, n6, NULL);
 
     UA_NodeId in3 = UA_NODEID_NUMERIC(0, 2257);
-    const UA_Node* nr = UA_Nodestore_getNode(nsCtx, &in3);
+    const UA_Node* nr = ns.getNode(ns.context, &in3);
     ck_assert_int_eq((uintptr_t)nr, (uintptr_t)n3);
-    UA_Nodestore_releaseNode(nsCtx, nr);
+    ns.releaseNode(ns.context, nr);
 }
 END_TEST
 
 START_TEST(iterateOverUA_NodeStoreShallNotVisitEmptyNodes) {
     UA_Node* n1 = createNode(0,2253);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_Node* n2 = createNode(0,2255);
-    UA_Nodestore_insertNode(nsCtx, n2, NULL);
+    ns.insertNode(ns.context, n2, NULL);
     UA_Node* n3 = createNode(0,2257);
-    UA_Nodestore_insertNode(nsCtx, n3, NULL);
+    ns.insertNode(ns.context, n3, NULL);
     UA_Node* n4 = createNode(0,2200);
-    UA_Nodestore_insertNode(nsCtx, n4, NULL);
+    ns.insertNode(ns.context, n4, NULL);
     UA_Node* n5 = createNode(0,1);
-    UA_Nodestore_insertNode(nsCtx, n5, NULL);
+    ns.insertNode(ns.context, n5, NULL);
     UA_Node* n6 = createNode(0,12);
-    UA_Nodestore_insertNode(nsCtx, n6, NULL);
+    ns.insertNode(ns.context, n6, NULL);
 
     zeroCnt = 0;
     visitCnt = 0;
-    UA_Nodestore_iterate(nsCtx, checkZeroVisitor, NULL);
+    ns.iterate(ns.context, checkZeroVisitor, NULL);
     ck_assert_int_eq(zeroCnt, 0);
     ck_assert_int_eq(visitCnt, 6);
 }
@@ -164,26 +136,26 @@ END_TEST
 START_TEST(findNodeInExpandedNamespace) {
     for(UA_UInt32 i = 0; i < 200; i++) {
         UA_Node* n = createNode(0,i);
-        UA_Nodestore_insertNode(nsCtx, n, NULL);
+        ns.insertNode(ns.context, n, NULL);
     }
     // when
     UA_Node *n2 = createNode(0,25);
-    const UA_Node* nr = UA_Nodestore_getNode(nsCtx, &n2->nodeId);
+    const UA_Node* nr = ns.getNode(ns.context, &n2->nodeId);
     ck_assert_int_eq(nr->nodeId.identifier.numeric, n2->nodeId.identifier.numeric);
-    UA_Nodestore_releaseNode(nsCtx, nr);
-    UA_Nodestore_deleteNode(nsCtx, n2);
+    ns.releaseNode(ns.context, nr);
+    ns.deleteNode(ns.context, n2);
 }
 END_TEST
 
 START_TEST(iterateOverExpandedNamespaceShallNotVisitEmptyNodes) {
     for(UA_UInt32 i = 0; i < 200; i++) {
         UA_Node* n = createNode(0,i+1);
-        UA_Nodestore_insertNode(nsCtx, n, NULL);
+        ns.insertNode(ns.context, n, NULL);
     }
     // when
     zeroCnt = 0;
     visitCnt = 0;
-    UA_Nodestore_iterate(nsCtx, checkZeroVisitor, NULL);
+    ns.iterate(ns.context, checkZeroVisitor, NULL);
     // then
     ck_assert_int_eq(zeroCnt, 0);
     ck_assert_int_eq(visitCnt, 200);
@@ -192,18 +164,18 @@ END_TEST
 
 START_TEST(failToFindNonExistentNodeInUA_NodeStoreWithSeveralEntries) {
     UA_Node* n1 = createNode(0,2253);
-    UA_Nodestore_insertNode(nsCtx, n1, NULL);
+    ns.insertNode(ns.context, n1, NULL);
     UA_Node* n2 = createNode(0,2255);
-    UA_Nodestore_insertNode(nsCtx, n2, NULL);
+    ns.insertNode(ns.context, n2, NULL);
     UA_Node* n3 = createNode(0,2257);
-    UA_Nodestore_insertNode(nsCtx, n3, NULL);
+    ns.insertNode(ns.context, n3, NULL);
     UA_Node* n4 = createNode(0,2200);
-    UA_Nodestore_insertNode(nsCtx, n4, NULL);
+    ns.insertNode(ns.context, n4, NULL);
     UA_Node* n5 = createNode(0,1);
-    UA_Nodestore_insertNode(nsCtx, n5, NULL);
+    ns.insertNode(ns.context, n5, NULL);
 
     UA_NodeId id = UA_NODEID_NUMERIC(0, 12);
-    const UA_Node* nr = UA_Nodestore_getNode(nsCtx, &id);
+    const UA_Node* nr = ns.getNode(ns.context, &id);
     ck_assert_int_eq((uintptr_t)nr, 0);
 }
 END_TEST
@@ -227,8 +199,8 @@ static void *profileGetThread(void *arg) {
     for(UA_Int32 x = 0; x<test->rounds; x++) {
         for(UA_Int32 i=test->min_val; i<max_val; i++) {
             id.identifier.numeric = i+1;
-            const UA_Node *n = UA_Nodestore_getNode(nsCtx, &id);
-            UA_Nodestore_releaseNode(nsCtx, n);
+            const UA_Node *n = ns.getNode(ns.context, &id);
+            ns.releaseNode(ns.context, n);
         }
     }
     return NULL;
@@ -243,7 +215,7 @@ START_TEST(profileGetDelete) {
 
     for(UA_UInt32 i = 0; i < N; i++) {
         UA_Node *n = createNode(0,i+1);
-        UA_Nodestore_insertNode(nsCtx, n, NULL);
+        ns.insertNode(ns.context, n, NULL);
     }
 
 #if UA_MULTITHREADING >= 200
@@ -262,8 +234,8 @@ START_TEST(profileGetDelete) {
     UA_NodeId id = UA_NODEID_NULL;
     for(size_t i = 0; i < N; i++) {
         id.identifier.numeric = (UA_UInt32)i+1;
-        const UA_Node *node = UA_Nodestore_getNode(nsCtx, &id);
-        UA_Nodestore_releaseNode(nsCtx, node);
+        const UA_Node *node = ns.getNode(ns.context, &id);
+        ns.releaseNode(ns.context, node);
     }
     end = clock();
     printf("Time for single-threaded %d create/get/delete in a namespace: %fs.\n", N,

+ 4 - 4
tests/server/check_services_attributes.c

@@ -152,7 +152,7 @@ static void setup(void) {
 
 static UA_VariableNode* makeCompareSequence(void) {
     UA_VariableNode *node = (UA_VariableNode*)
-        UA_Nodestore_newNode(server->nsCtx, UA_NODECLASS_VARIABLE);
+        UA_NODESTORE_NEW(server, UA_NODECLASS_VARIABLE);
 
     UA_Int32 myInteger = 42;
     UA_Variant_setScalarCopy(&node->value.data.value.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
@@ -287,7 +287,7 @@ START_TEST(ReadSingleAttributeDisplayNameWithoutTimestamp) {
     ck_assert(UA_String_equal(&comp.text, &respval->text));
     ck_assert(UA_String_equal(&compNode->displayName.locale, &respval->locale));
     UA_DataValue_deleteMembers(&resp);
-    UA_Nodestore_deleteNode(server->nsCtx, (UA_Node*)compNode);
+    UA_NODESTORE_DELETE(server, (UA_Node*)compNode);
 } END_TEST
 
 START_TEST(ReadSingleAttributeDescriptionWithoutTimestamp) {
@@ -305,7 +305,7 @@ START_TEST(ReadSingleAttributeDescriptionWithoutTimestamp) {
     ck_assert(UA_String_equal(&compNode->description.locale, &respval->locale));
     ck_assert(UA_String_equal(&compNode->description.text, &respval->text));
     UA_DataValue_deleteMembers(&resp);
-    UA_Nodestore_deleteNode(server->nsCtx, (UA_Node*)compNode);
+    UA_NODESTORE_DELETE(server, (UA_Node*)compNode);
 } END_TEST
 
 START_TEST(ReadSingleAttributeWriteMaskWithoutTimestamp) {
@@ -505,7 +505,7 @@ START_TEST(ReadSingleAttributeMinimumSamplingIntervalWithoutTimestamp) {
     ck_assert(&UA_TYPES[UA_TYPES_DOUBLE] == resp.value.type);
     ck_assert(*respval == comp);
     UA_DataValue_deleteMembers(&resp);
-    UA_Nodestore_deleteNode(server->nsCtx, (UA_Node*)compNode);
+    UA_NODESTORE_DELETE(server, (UA_Node*)compNode);
 } END_TEST
 
 START_TEST(ReadSingleAttributeHistorizingWithoutTimestamp) {