Selaa lähdekoodia

assert that rcu is not locked twice

Julius Pfrommer 9 vuotta sitten
vanhempi
commit
696a549402

+ 7 - 7
src/server/ua_nodestore_concurrent.c

@@ -58,13 +58,13 @@ static int compare(struct cds_lfht_node *htn, const void *orig) {
 UA_NodeStore * UA_NodeStore_new() {
     UA_NodeStore *ns;
     if(!(ns = UA_malloc(sizeof(UA_NodeStore))))
-        return UA_NULL;
+        return NULL;
 
     /* 32 is the minimum size for the hashtable. */
     ns->ht = cds_lfht_new(32, 32, 0, CDS_LFHT_AUTO_RESIZE, NULL);
     if(!ns->ht) {
         UA_free(ns);
-        ns = UA_NULL;
+        ns = NULL;
     }
     return ns;
 }
@@ -84,7 +84,7 @@ void UA_NodeStore_delete(UA_NodeStore *ns) {
         cds_lfht_next(ht, &iter);
     }
     rcu_read_unlock();
-    cds_lfht_destroy(ht, UA_NULL);
+    cds_lfht_destroy(ht, NULL);
     UA_free(ns);
 }
 
@@ -124,7 +124,7 @@ UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node, const UA_Node
     if(!(entry = UA_malloc(sizeof(struct nodeEntry) - sizeof(UA_Node) + nodesize)))
         return UA_STATUSCODE_BADOUTOFMEMORY;
     UA_Node *newNode = &entry->node;
-    UA_memcpy(newNode, node, nodesize);
+    memcpy(newNode, node, nodesize);
 
     cds_lfht_node_init(&entry->htn);
     struct cds_lfht_node *result;
@@ -218,7 +218,7 @@ UA_StatusCode UA_NodeStore_replace(UA_NodeStore *ns, const UA_Node *oldNode, UA_
     struct nodeEntry *newEntry;
     if(!(newEntry = UA_malloc(sizeof(struct nodeEntry) - sizeof(UA_Node) + nodesize)))
         return UA_STATUSCODE_BADOUTOFMEMORY;
-    UA_memcpy((void*)&newEntry->node, node, nodesize);
+    memcpy((void*)&newEntry->node, node, nodesize);
     cds_lfht_node_init(&newEntry->htn);
 
     if(cds_lfht_replace(ns->ht, &iter, h, compare, &node->nodeId, &newEntry->htn) != 0) {
@@ -253,7 +253,7 @@ const UA_Node * UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid
     cds_lfht_lookup(ns->ht, h, compare, nodeid, &iter);
     struct nodeEntry *found_entry = (struct nodeEntry*)iter.node;
     if(!found_entry)
-        return UA_NULL;
+        return NULL;
     return &found_entry->node;
 }
 
@@ -261,7 +261,7 @@ void UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visit
     struct cds_lfht *ht = ns->ht;
     struct cds_lfht_iter iter;
     cds_lfht_first(ht, &iter);
-    while(iter.node != UA_NULL) {
+    while(iter.node != NULL) {
         struct nodeEntry *found_entry = (struct nodeEntry*)iter.node;
         visitor(&found_entry->node);
         cds_lfht_next(ht, &iter);

+ 106 - 95
src/server/ua_server.c

@@ -19,6 +19,10 @@ const UA_EXPORT UA_ServerConfig UA_ServerConfig_standard = {
     .Application_applicationURI = "urn:unconfigured:open62541:open62541Server",
     .Application_applicationName = "open62541" };
 
+#if defined(UA_MULTITHREADING) && !defined(NDEBUG)
+UA_THREAD_LOCAL bool rcu_locked = UA_FALSE;
+#endif
+
 static const UA_NodeId nodeIdHasSubType = {
     .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
     .identifier.numeric = UA_NS0ID_HASSUBTYPE};
@@ -104,7 +108,10 @@ UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
 
 UA_StatusCode UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
                                    UA_Boolean deleteReferences) {
-    return Service_DeleteNodes_single(server, &adminSession, &nodeId, deleteReferences);
+    UA_RCU_LOCK();
+    UA_StatusCode retval = Service_DeleteNodes_single(server, &adminSession, &nodeId, deleteReferences);
+    UA_RCU_UNLOCK();
+    return retval;
 }
 
 UA_StatusCode
@@ -117,21 +124,28 @@ UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, const
     item.isForward = isForward;
     item.targetNodeId = targetNodeId;
     item.deleteBidirectional = deleteBidirectional;
-    return Service_DeleteReferences_single(server, &adminSession, &item);
+    UA_RCU_LOCK();
+    UA_StatusCode retval = Service_DeleteReferences_single(server, &adminSession, &item);
+    UA_RCU_UNLOCK();
+    return retval;
 }
 
 UA_StatusCode
 UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
                                UA_NodeIteratorCallback callback, void *handle) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    UA_RCU_LOCK();
     const UA_Node *parent = UA_NodeStore_get(server->nodestore, &parentNodeId);
-    if(!parent)
+    if(!parent) {
+        UA_RCU_UNLOCK();
         return UA_STATUSCODE_BADNODEIDINVALID;
+    }
     for(size_t i = 0; i < parent->referencesSize; i++) {
         UA_ReferenceNode *ref = &parent->references[i];
         retval |= callback(ref->targetId.nodeId, ref->isInverse,
                            ref->referenceTypeId, handle);
     }
+    UA_RCU_UNLOCK();
     return retval;
 }
 
@@ -145,6 +159,21 @@ UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
     item.referenceTypeId = refTypeId;
     item.isForward = isForward;
     item.targetNodeId = targetId;
+    UA_RCU_LOCK();
+    UA_StatusCode retval = Service_AddReferences_single(server, &adminSession, &item);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
+static UA_StatusCode
+addReferenceInternal(UA_Server *server, const UA_NodeId sourceId, const UA_NodeId refTypeId,
+                     const UA_ExpandedNodeId targetId, UA_Boolean isForward) {
+    UA_AddReferencesItem item;
+    UA_AddReferencesItem_init(&item);
+    item.sourceNodeId = sourceId;
+    item.referenceTypeId = refTypeId;
+    item.isForward = isForward;
+    item.targetNodeId = targetId;
     return Service_AddReferences_single(server, &adminSession, &item);
 }
 
@@ -181,8 +210,11 @@ __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
     item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED;
     item.nodeAttributes.content.decoded.type = attributeType;
     item.nodeAttributes.content.decoded.data = attrCopy;
-    if(result.statusCode == UA_STATUSCODE_GOOD)
+    if(result.statusCode == UA_STATUSCODE_GOOD) {
+        UA_RCU_LOCK();
         Service_AddNodes_single(server, &adminSession, &item, &result);
+        UA_RCU_UNLOCK();
+    }
 
     if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD)
         *outNewNodeId = result.addedNodeId;
@@ -241,6 +273,7 @@ void UA_Server_setLogger(UA_Server *server, UA_Logger logger) {
 /* The server needs to be stopped before it can be deleted */
 void UA_Server_delete(UA_Server *server) {
     // Delete the timed work
+    UA_RCU_LOCK();
     UA_Server_deleteAllRepeatedJobs(server);
 
     // Delete all internal data
@@ -264,6 +297,7 @@ void UA_Server_delete(UA_Server *server) {
     }
     UA_free(server->networkLayers);
 
+    UA_RCU_UNLOCK();
 #ifdef UA_MULTITHREADING
     /* so the workers don't spin if the queue is empty */
     pthread_cond_destroy(&server->dispatchQueue_condition);
@@ -419,7 +453,7 @@ addVariableTypeNode_subtype(UA_Server *server, char* name, UA_UInt32 variabletyp
 }
 
 UA_Server * UA_Server_new(UA_ServerConfig config) {
-    UA_Server *server = UA_malloc(sizeof(UA_Server));
+    UA_Server *server = UA_calloc(1, sizeof(UA_Server));
     if(!server)
         return NULL;
 
@@ -432,46 +466,27 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
    	rcu_register_thread();
     cds_wfcq_init(&server->dispatchQueue_head, &server->dispatchQueue_tail);
     cds_lfs_init(&server->mainLoopJobs);
-    server->delayedJobs = NULL;
+    UA_RCU_LOCK();
 #endif
 
-    // logger
-    server->logger = NULL;
-
     // random seed
     server->random_seed = (UA_UInt32)UA_DateTime_now();
 
-    // networklayers
-    server->networkLayers = NULL;
-    server->networkLayersSize = 0;
-
-    UA_ByteString_init(&server->serverCertificate);
-
     // mockup application description
     UA_ApplicationDescription_init(&server->description);
     server->description.productUri = UA_STRING_ALLOC(PRODUCT_URI);
-    server->description.applicationUri =
-        UA_STRING_ALLOC(server->config.Application_applicationURI);
-    server->description.discoveryUrlsSize = 0;
+    server->description.applicationUri = UA_STRING_ALLOC(server->config.Application_applicationURI);
 
     server->description.applicationName =
         UA_LOCALIZEDTEXT_ALLOC("en_US", server->config.Application_applicationName);
     server->description.applicationType = UA_APPLICATIONTYPE_SERVER;
 
-#ifdef UA_EXTERNAL_NAMESPACES
-    server->externalNamespacesSize = 0;
-    server->externalNamespaces = NULL;
-#endif
-
     /* ns0 and ns1 */
     server->namespaces = UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
     server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
     UA_String_copy(&server->description.applicationUri, &server->namespaces[1]);
     server->namespacesSize = 2;
 
-    server->endpointDescriptions = NULL;
-    server->endpointDescriptionsSize = 0;
-
     UA_EndpointDescription *endpoint = UA_EndpointDescription_new(); // todo: check return code
     if(endpoint) {
         endpoint->securityMode = UA_MESSAGESECURITYMODE_NONE;
@@ -691,8 +706,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
                     UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType);
 
     // complete bootstrap of hassubtype
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), UA_TRUE);
 
     UA_ReferenceTypeNode *hasproperty = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasproperty, "HasProperty");
@@ -812,8 +827,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     addNodeInternal(server, (UA_Node*)referencetypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
                     nodeIdOrganizes);
 
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), nodeIdOrganizes,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), nodeIdOrganizes,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES), UA_TRUE);
 
     /**********************/
     /* Basic Object Types */
@@ -828,18 +843,18 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     addObjectTypeNode(server, "BaseObjectType", UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER,
                       UA_NS0ID_ORGANIZES);
     addObjectTypeNode(server, "FolderType", UA_NS0ID_FOLDERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
     addObjectTypeNode(server, "ServerType", UA_NS0ID_SERVERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
     addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE,
                       UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
@@ -858,8 +873,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     copyNames((UA_Node*)datatypes, "DataTypes");
     datatypes->nodeId.identifier.numeric = UA_NS0ID_DATATYPESFOLDER;
     addNodeInternal(server, (UA_Node*)datatypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), nodeIdOrganizes);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATATYPESFOLDER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATATYPESFOLDER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
 
     addDataTypeNode(server, "BaseDataType", UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER);
     addDataTypeNode(server, "Boolean", UA_NS0ID_BOOLEAN, UA_NS0ID_BASEDATATYPE);
@@ -899,8 +914,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     variabletypes->nodeId.identifier.numeric = UA_NS0ID_VARIABLETYPESFOLDER;
     addNodeInternal(server, (UA_Node*)variabletypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
                     nodeIdOrganizes);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), UA_TRUE);
     addVariableTypeNode_organized(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE,
                                   UA_NS0ID_VARIABLETYPESFOLDER, UA_TRUE);
     addVariableTypeNode_subtype(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE,
@@ -923,8 +938,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;
     addNodeInternal(server, (UA_Node*)servernode, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                     nodeIdOrganizes);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERTYPE), UA_TRUE);
 
     UA_VariableNode *namespaceArray = UA_VariableNode_new();
     copyNames((UA_Node*)namespaceArray, "NamespaceArray");
@@ -935,9 +950,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     namespaceArray->valueRank = 1;
     namespaceArray->minimumSamplingInterval = 1.0;
     addNodeInternal(server, (UA_Node*)namespaceArray, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasProperty);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE),
-                           UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
 
     UA_VariableNode *serverArray = UA_VariableNode_new();
     copyNames((UA_Node*)serverArray, "ServerArray");
@@ -950,17 +964,16 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     serverArray->valueRank = 1;
     serverArray->minimumSamplingInterval = 1.0;
     addNodeInternal(server, (UA_Node*)serverArray, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasProperty);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERARRAY), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERARRAY), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
 
     UA_ObjectNode *servercapablities = UA_ObjectNode_new();
     copyNames((UA_Node*)servercapablities, "ServerCapabilities");
     servercapablities->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES;
     addNodeInternal(server, (UA_Node*)servercapablities, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
                     nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
-                           nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERCAPABILITIESTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERCAPABILITIESTYPE), UA_TRUE);
 
     UA_VariableNode *localeIdArray = UA_VariableNode_new();
     copyNames((UA_Node*)localeIdArray, "LocaleIdArray");
@@ -973,8 +986,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     localeIdArray->minimumSamplingInterval = 1.0;
     addNodeInternal(server, (UA_Node*)localeIdArray,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
 
     UA_VariableNode *maxBrowseContinuationPoints = UA_VariableNode_new();
     copyNames((UA_Node*)maxBrowseContinuationPoints, "MaxBrowseContinuationPoints");
@@ -985,8 +998,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     maxBrowseContinuationPoints->value.variant.value.type = &UA_TYPES[UA_TYPES_UINT16];
     addNodeInternal(server, (UA_Node*)maxBrowseContinuationPoints,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
 
     /** ServerProfileArray **/
 #define MAX_PROFILEARRAY 16 //a *magic* limit to the number of supported profiles
@@ -1017,16 +1030,16 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     serverProfileArray->minimumSamplingInterval = 1.0;
     addNodeInternal(server, (UA_Node*)serverProfileArray,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
 
     UA_ObjectNode *serverdiagnostics = UA_ObjectNode_new();
     copyNames((UA_Node*)serverdiagnostics, "ServerDiagnostics");
     serverdiagnostics->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS;
     addNodeInternal(server, (UA_Node*)serverdiagnostics,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERDIAGNOSTICSTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERDIAGNOSTICSTYPE), UA_TRUE);
 
     UA_VariableNode *enabledFlag = UA_VariableNode_new();
     copyNames((UA_Node*)enabledFlag, "EnabledFlag");
@@ -1037,9 +1050,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     enabledFlag->minimumSamplingInterval = 1.0;
     addNodeInternal(server, (UA_Node*)enabledFlag,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS), nodeIdHasProperty);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE),
-                           UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE), UA_TRUE);
 
     UA_VariableNode *serverstatus = UA_VariableNode_new();
     copyNames((UA_Node*)serverstatus, "ServerStatus");
@@ -1047,8 +1059,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     serverstatus->valueSource = UA_VALUESOURCE_DATASOURCE;
     serverstatus->value.dataSource = (UA_DataSource) {.handle = server, .read = readStatus, .write = NULL};
     addNodeInternal(server, (UA_Node*)serverstatus, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasTypeDefinition,
-                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERSTATUSTYPE), UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasTypeDefinition,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERSTATUSTYPE), UA_TRUE);
 
     UA_VariableNode *starttime = UA_VariableNode_new();
     copyNames((UA_Node*)starttime, "StartTime");
@@ -1058,8 +1070,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     starttime->value.variant.value.type = &UA_TYPES[UA_TYPES_DATETIME];
     addNodeInternal(server, (UA_Node*)starttime, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
                     nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *currenttime = UA_VariableNode_new();
     copyNames((UA_Node*)currenttime, "CurrentTime");
@@ -1069,8 +1081,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
                                                      .write = NULL};
     addNodeInternal(server, (UA_Node*)currenttime,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *state = UA_VariableNode_new();
     UA_ServerState *stateEnum = UA_ServerState_new();
@@ -1082,8 +1094,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     state->value.variant.value.data = stateEnum; // points into the other object.
     addNodeInternal(server, (UA_Node*)state, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
                     nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *buildinfo = UA_VariableNode_new();
     copyNames((UA_Node*)buildinfo, "BuildInfo");
@@ -1093,9 +1105,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     getBuildInfo(server, (UA_BuildInfo*)buildinfo->value.variant.value.data);
     addNodeInternal(server, (UA_Node*)buildinfo,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BUILDINFOTYPE),
-                           UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BUILDINFOTYPE), UA_TRUE);
 
     UA_VariableNode *producturi = UA_VariableNode_new();
     copyNames((UA_Node*)producturi, "ProductUri");
@@ -1105,8 +1116,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     producturi->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     addNodeInternal(server, (UA_Node*)producturi,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *manufacturername = UA_VariableNode_new();
     copyNames((UA_Node*)manufacturername, "ManufacturererName");
@@ -1116,9 +1127,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     manufacturername->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     addNodeInternal(server, (UA_Node*)manufacturername,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
-    UA_Server_addReference(server,
-                           UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *productname = UA_VariableNode_new();
     copyNames((UA_Node*)productname, "ProductName");
@@ -1128,8 +1138,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     productname->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     addNodeInternal(server, (UA_Node*)productname,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *softwareversion = UA_VariableNode_new();
     copyNames((UA_Node*)softwareversion, "SoftwareVersion");
@@ -1139,8 +1149,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     softwareversion->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     addNodeInternal(server, (UA_Node*)softwareversion,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *buildnumber = UA_VariableNode_new();
     copyNames((UA_Node*)buildnumber, "BuildNumber");
@@ -1150,8 +1160,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     buildnumber->value.variant.value.type = &UA_TYPES[UA_TYPES_STRING];
     addNodeInternal(server, (UA_Node*)buildnumber,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *builddate = UA_VariableNode_new();
     copyNames((UA_Node*)builddate, "BuildDate");
@@ -1161,8 +1171,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     builddate->value.variant.value.type = &UA_TYPES[UA_TYPES_DATETIME];
     addNodeInternal(server, (UA_Node*)builddate,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *secondstillshutdown = UA_VariableNode_new();
     copyNames((UA_Node*)secondstillshutdown, "SecondsTillShutdown");
@@ -1171,8 +1181,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     secondstillshutdown->value.variant.value.type = &UA_TYPES[UA_TYPES_UINT32];
     addNodeInternal(server, (UA_Node*)secondstillshutdown,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
 
     UA_VariableNode *shutdownreason = UA_VariableNode_new();
     copyNames((UA_Node*)shutdownreason, "ShutdownReason");
@@ -1181,8 +1191,9 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     shutdownreason->value.variant.value.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
     addNodeInternal(server, (UA_Node*)shutdownreason,
                     UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
-    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON),
-                           nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON),
+                         nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype, UA_TRUE);
+    UA_RCU_UNLOCK();
     return server;
 }
 

+ 2 - 0
src/server/ua_server_worker.c

@@ -148,9 +148,11 @@ static void * workerLoop(struct workerStartData *startInfo) {
         struct DispatchJobsList *wln = (struct DispatchJobsList*)
             cds_wfcq_dequeue_blocking(&server->dispatchQueue_head, &server->dispatchQueue_tail);
         if(wln) {
+            UA_RCU_LOCK();
             processJobs(server, wln->jobs, wln->jobsSize);
             UA_free(wln->jobs);
             UA_free(wln);
+            UA_RCU_UNLOCK();
         } else {
             /* sleep until a work arrives (and wakes up all worker threads) */
             #if defined(__APPLE__) || defined(__MACH__) // OS X does not have clock_gettime, use clock_get_time

+ 1 - 1
src/server/ua_services_nodemanagement.c

@@ -814,7 +814,7 @@ void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddR
 
 UA_StatusCode Service_DeleteNodes_single(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
                                          UA_Boolean deleteReferences) {
-    UA_Node *node = UA_NodeStore_get(server->nodestore, nodeId);
+    UA_MT_CONST UA_Node *node = UA_NodeStore_get(server->nodestore, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDINVALID;
     if(deleteReferences == UA_TRUE) {

+ 18 - 1
src/ua_util.h

@@ -85,7 +85,24 @@
 # include <urcu/wfcqueue.h>
 # include <urcu/uatomic.h>
 # include <urcu/rculfhash.h>
-#include <urcu/lfstack.h>
+# include <urcu/lfstack.h>
+# ifdef NDEBUG
+# define UA_RCU_LOCK() rcu_read_lock()
+# define UA_RCU_UNLOCK() rcu_read_unlock()
+# else
+extern UA_THREAD_LOCAL bool rcu_locked;
+# define UA_RCU_LOCK() do {     \
+        assert(!rcu_locked);    \
+        rcu_locked = UA_TRUE;   \
+        rcu_read_lock(); } while(0)
+# define UA_RCU_UNLOCK() do { \
+        assert(rcu_locked);   \
+        rcu_locked = UA_FALSE;    \
+        rcu_read_lock(); } while(0)
+# endif
+#else
+# define UA_RCU_LOCK()
+# define UA_RCU_UNLOCK()
 #endif
 
 #endif /* UA_UTIL_H_ */

+ 6 - 16
tests/check_nodestore.c

@@ -35,11 +35,10 @@ static UA_Node* createNode(UA_Int16 nsid, UA_Int32 id) {
 START_TEST(replaceExistingNode) {
 	UA_NodeStore *ns = UA_NodeStore_new();
 	UA_Node* n1 = createNode(0,2253);
-    const UA_Node *inserted;
+    UA_MT_CONST UA_Node *inserted;
 	UA_NodeStore_insert(ns, n1, &inserted);
 	UA_Node* n2 = createNode(0,2253);
     UA_StatusCode retval = UA_NodeStore_replace(ns, inserted, n2, NULL);
-    UA_NodeStore_release(inserted);
     
 	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
     
@@ -67,15 +66,13 @@ START_TEST(findNodeInUA_NodeStoreWithSingleEntry) {
 #endif
 	// given
 	UA_NodeStore *ns = UA_NodeStore_new();
-    const UA_Node *inserted;
+    UA_MT_CONST UA_Node *inserted;
 	UA_Node* n1 = createNode(0,2253);
 	UA_NodeStore_insert(ns, n1, &inserted);
 	const UA_Node* nr = UA_NodeStore_get(ns,&inserted->nodeId);
 	// then
 	ck_assert_int_eq((uintptr_t)inserted, (uintptr_t)nr);
 	// finally
-	UA_NodeStore_release(inserted);
-	UA_NodeStore_release(nr);
 	UA_NodeStore_delete(ns);
 #ifdef UA_MULTITHREADING
 	rcu_unregister_thread();
@@ -118,7 +115,7 @@ START_TEST(findNodeInUA_NodeStoreWithSeveralEntries) {
 	UA_Node* n2 = createNode(0,2255);
     UA_NodeStore_insert(ns, n2, NULL);
 	UA_Node* n3 = createNode(0,2257);
-    const UA_Node *inserted;
+    UA_MT_CONST UA_Node *inserted;
     UA_NodeStore_insert(ns, n3, &inserted);
 	UA_Node* n4 = createNode(0,2200);
     UA_NodeStore_insert(ns, n4, NULL);
@@ -132,8 +129,6 @@ START_TEST(findNodeInUA_NodeStoreWithSeveralEntries) {
 	// then
 	ck_assert_int_eq((uintptr_t)nr, (uintptr_t)inserted);
 	// finally
-	UA_NodeStore_release(inserted);
-	UA_NodeStore_release(nr);
 	UA_NodeStore_delete(ns);
 #ifdef UA_MULTITHREADING
 	rcu_unregister_thread();
@@ -194,7 +189,6 @@ START_TEST(findNodeInExpandedNamespace) {
 	ck_assert_int_eq(nr->nodeId.identifier.numeric,n2->nodeId.identifier.numeric);
 	// finally
 	UA_free((void*)n2);
-	UA_NodeStore_release(nr);
 	UA_NodeStore_delete(ns);
 #ifdef UA_MULTITHREADING
 	rcu_unregister_thread();
@@ -277,14 +271,12 @@ static void *profileGetThread(void *arg) {
 	struct UA_NodeStoreProfileTest *test = (struct UA_NodeStoreProfileTest*) arg;
 	UA_NodeId id;
     UA_NodeId_init(&id);
-	const UA_Node *cn;
 	UA_Int32 max_val = test->max_val;
 	UA_NodeStore *ns = test->ns;
 	for(UA_Int32 x = 0; x<test->rounds; x++) {
-		for (UA_Int32 i=test->min_val; i<max_val; i++) {
+		for(UA_Int32 i=test->min_val; i<max_val; i++) {
 			id.identifier.numeric = i;
-			cn = UA_NodeStore_get(ns,&id);
-			UA_NodeStore_release(cn);
+			UA_NodeStore_get(ns,&id);
 		}
 	}
 	rcu_unregister_thread();
@@ -320,14 +312,12 @@ START_TEST(profileGetDelete) {
 	end = clock();
 	printf("Time for %d create/get/delete on %d threads in a namespace: %fs.\n", N, THREADS, (double)(end - begin) / CLOCKS_PER_SEC);
 #else
-	const UA_Node *cn;
 	UA_NodeId id;
     UA_NodeId_init(&id);
 	for(UA_Int32 x = 0; x<50; x++) {
 	    for(int i=0; i<N; i++) {
 	        id.identifier.numeric = i;
-			cn = UA_NodeStore_get(ns,&id);
-			UA_NodeStore_release(cn);
+            UA_NodeStore_get(ns,&id);
         }
     }
 	end = clock();

+ 0 - 1
tests/check_services_attributes.c

@@ -492,7 +492,6 @@ START_TEST(ReadSingleAttributeUserAccessLevelWithoutTimestamp) {
     ck_assert_int_eq(0, resp.value.arrayLength);
     ck_assert_ptr_eq(&UA_TYPES[UA_TYPES_BYTE], resp.value.type);
     ck_assert_int_eq(*(UA_Byte*)resp.value.data, compNode->userAccessLevel);
-    UA_NodeStore_release((const UA_Node*)compNode);
     UA_Server_delete(server);
     UA_DataValue_deleteMembers(&resp);
     UA_ReadRequest_deleteMembers(&rReq);