Przeglądaj źródła

Merge remote-tracking branch 'origin/master' into connection_secureChannel

Conflicts:
	examples/src/networklayer.h
	examples/src/opcuaServer.c
	src/Makefile.am
	src/ua_application.c
	src/ua_namespace.c
	src/ua_namespace.h
	src/ua_namespace_concurrent.c
	tests/check_namespace.c
FlorianPalm 10 lat temu
rodzic
commit
e6ba7e219f

+ 1 - 2
.travis.yml

@@ -3,8 +3,7 @@ compiler:
 - gcc
 env:
   global:
-  - secure: AgDJV7/ubjxZFcxuOlkOizWyo0VLve9Pdh5Xz+3Ec37SeYotfUWAupwMZdMXZdKiDyHkAo1R0GdHgpkJ+Tm12o8WdsxZvTi0JdNtXObrYstNnzleuzf9fTsaY74wRDC2Q2URhBrR+oNcD19Lp6mpoCk6asDBhn2+6CP+dLBtKOE= 
-  - secure: Tp53B4vuTKhpMsyAFr5zIHzWtD9XoeLS4CzW3bSgUpuzdHUD+SVunwnjileleKzLY6Iqf3v02NK/TqGDNpehdlWGQf9TgSLSqG0GMohLUaipuVj6HS6LD0vAgU+3U1TdBfvDelDIppqK2CCph2g5Vtw0OXvopw6HQdXeBDSOUKE=
+  - secure: "nSunY54Wp5HkQCHHbKwlwpbaKyqRVIu/0EnhaoJSwhM1wqerQV/E5d/2JelO9/tZgbungAO7wk/fjutRMVc7d378RTIPwS8vHpvZfEoGhCFsLoTOlqESzsZFBup2H5t1lpQ23jRHDOxlLdJy2lz5U+zd1YnYgDXqdDFjegsIYdo="
 addons:
   coverity_scan:
     project:

+ 8 - 2
Makefile.am

@@ -22,13 +22,19 @@ if MULTITHREADING
 AM_LDADD += -lpthread -lurcu-cds -lurcu
 endif
 
+# additional encodings
 UA_ENCODING_AMOUNT = 1
 if UA_ENCODING_XML
-UA_ENCODING_AMOUNT := $$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
+UA_ENCODING_AMOUNT = 2 #$$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
 endif
 
-AM_CFLAGS += -D UA_ENCODING_AMOUNT=$(UA_ENCODING_AMOUNT)
+if UA_ENCODING_JSON
+UA_ENCODING_AMOUNT = 3 #$$(echo $(UA_ENCODING_AMOUNT)+1 | bc)
+endif
+
+AM_CFLAGS += -DUA_ENCODING_AMOUNT=$(UA_ENCODING_AMOUNT)
 
+# export flags for sub-makefiles
 export GLOBAL_AM_CFLAGS = $(AM_CFLAGS)
 export GLOBAL_AM_LDADD = $(AM_LDADD)
 

+ 9 - 2
configure.ac

@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.59)
-AC_INIT(Open62541, 1.0)
+AC_INIT(open62541, 0.1)
 
 AC_CANONICAL_SYSTEM
 AM_INIT_AUTOMAKE([subdir-objects])
@@ -50,22 +50,29 @@ AM_COND_IF([VERBOSE],
 # 100: nano
 # 200: embedded
 # 900: all available features
+# 1500: all including custom extensions to the standard
 AC_ARG_ENABLE(profile,
 AS_HELP_STRING([--enable-profile], [select supported features, default: all]),
 	[case "${enableval}" in
         	nano) profile=100;;
             embedded) profile=200;;
             all) profile=900;;
+			extended) profile=1500;;
             *) AC_MSG_ERROR([bad value ${enableval} for --enable-profile]);; 
 	esac],[profile=900])
 AC_DEFINE([PROFILE], [x"$profile"])
 
 #xml encoding
-AM_CONDITIONAL(UA_ENCODING_XML, test x"$profile" -ge 200)
+AM_CONDITIONAL(UA_ENCODING_XML, test "$profile" -ge 200)
 AM_COND_IF([UA_ENCODING_XML],
     AC_DEFINE([UA_ENCODING_XML], [1])
     AC_CHECK_LIB([expat],[XML_Parse],,AC_MSG_ERROR([Libexpat missing])))
 
+#json encoding
+AM_CONDITIONAL(UA_ENCODING_JSON, test "$profile" -ge 1500)
+AM_COND_IF([UA_ENCODING_JSON],
+    AC_DEFINE([UA_ENCODING_JSON], [2])) # if JSON without xml should allowed, the index needs to be computed dynamically
+
 #multithreading
 AC_ARG_ENABLE(multithreading,
 AS_HELP_STRING([--enable-multithreading],

+ 12 - 15
examples/src/generateSam.c

@@ -15,10 +15,7 @@ UA_Int32 UA_Node_getParent(const UA_Node* node, const UA_Node** parent) {
 		UA_Int32 refId = node->references[i].referenceTypeId.identifier.numeric;
 		UA_Int32 isInverse = node->references[i].isInverse;
 		if (isInverse && (refId == 47 || refId == 46)) {
-			Namespace_Entry_Lock* lock = UA_NULL;
-			UA_Int32 retval;
-			retval = Namespace_get(theNamespace, &(node->references[i].targetId.nodeId),parent,&lock);
-			Namespace_Entry_Lock_release(lock);
+			UA_Int32 retval = Namespace_get(theNamespace, &(node->references[i].targetId.nodeId),parent);
 			if (retval == UA_SUCCESS) {
 				DBG(printf(" has parent={i=%d}\n",(*parent)->nodeId.identifier.numeric));
 			} else {
@@ -170,9 +167,7 @@ void sam_attachToNamespace(UA_Node const * node) {
 UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const * id, UA_Int32* number) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Node const * node;
-	if ((retval = Namespace_get(ns,id,&node,UA_NULL)) != UA_SUCCESS)
-		return retval;
-	if (node == UA_NULL)
+	if ((retval = Namespace_get(ns,id,&node)) != UA_SUCCESS)
 		return UA_ERR_INVALID_VALUE;
 	UA_Int32 i, n;
 	for (i = 0, n = 0; i < node->referencesSize; i++ ) {
@@ -180,6 +175,7 @@ UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const *
 			n++;
 		}
 	}
+	Namespace_releaseManagedNode(node);
 	*number = n;
 	return retval;
 }
@@ -188,7 +184,7 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 	UA_Int32 retval = UA_SUCCESS;
 
 	UA_Node const * node;
-	if ((retval = Namespace_get(ns,id,&node,UA_NULL)) != UA_SUCCESS)
+	if ((retval = Namespace_get(ns,id,&node)) != UA_SUCCESS)
 		return retval;
 
 	UA_Int32 i, n;
@@ -197,10 +193,12 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 			n++;
 			if (n == idx) {
 				*result = &(node->references[i].targetId.nodeId);
+				Namespace_releaseManagedNode(node);
 				return retval;
 			}
 		}
 	}
+	Namespace_releaseManagedNode(node);
 	return UA_ERR_INVALID_VALUE;
 }
 
@@ -208,10 +206,11 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const * id, UA_UInt32* pos, UA_ByteString *dst) {
 	UA_Int32 i, retval = UA_SUCCESS;
 	if (UA_NodeId_isBasicType(id)) {
-		UA_Node const * result;
-		Namespace_Entry_Lock* lock;
-		if ((retval = Namespace_get(ns,id,&result,&lock)) == UA_SUCCESS)
+		const UA_Node * result;
+		if ((retval = Namespace_get(ns,id,&result)) == UA_SUCCESS) {
 			UA_Variant_encodeBinary(&((UA_VariableNode *) result)->value,dst,pos);
+			Namespace_releaseManagedNode(result);
+		}
 	} else {
 		UA_Int32 nComp = 0;
 		if ((retval = Namespace_getNumberOfComponents(ns,id,&nComp)) == UA_SUCCESS) {
@@ -228,13 +227,11 @@ UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const
 UA_Int32 UAX_NodeId_encodeBinary(Namespace const * ns, UA_NodeId const * id, UA_ByteString *dst, UA_UInt32* offset) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Node const * node;
-	Namespace_Entry_Lock* lock;
-
-	if ((retval = Namespace_get(ns,id,&node,&lock)) == UA_SUCCESS) {
+	if ((retval = Namespace_get(ns,id,&node)) == UA_SUCCESS) {
 		if (node->nodeClass == UA_NODECLASS_VARIABLE) {
 			retval = UA_Variant_encodeBinary(&((UA_VariableNode*) node)->value,dst,offset);
 		}
-		Namespace_Entry_Lock_release(lock);
+		Namespace_releaseManagedNode(node);
 	}
 	return retval;
 }

+ 0 - 2
examples/src/networklayer.c

@@ -102,9 +102,7 @@ UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), v
 
 		}
 		worker(arg);
-
 	}
-
 	return UA_SUCCESS;
 }
 #endif

+ 0 - 2
examples/src/networklayer.h

@@ -2,11 +2,9 @@
 #define NETWORKLAYER_H_
 
 #include "ua_types.h"
-#include "ua_types_generated.h"
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
 #include "util/ua_list.h"
-#include "ua_transport_connection_manager.h"
 
 #ifdef MULTITHREADING
 #include <pthread.h> // pthreadcreate, pthread_t

+ 2 - 8
examples/src/opcuaServer.c

@@ -38,7 +38,7 @@ UA_Int32 serverCallback(void * arg) {
 }
 
 
-int main(int argc, char** argv) {
+int main(int argc, char** arsgv) {
 
 	/* gets called at ctrl-c */
 	signal(SIGINT, stopHandler);
@@ -47,12 +47,6 @@ int main(int argc, char** argv) {
 	NL_data* nl = NL_init(&NL_Description_TcpBinary, 16664);
 
 	struct timeval tv = {1, 0}; // 1 second
+  	NL_msgLoop(nl, &tv, serverCallback, argv[0]);
 
-	SL_ChannelManager_init(6,3600000, 873, 23, &nl->endpointUrl);
-	UA_SessionManager_init(2,30000,5);
-	//UA_TL_ConnectionManager_init(10);
-   NL_msgLoop(nl, &tv, serverCallback, argv[0], &running);
-
-	printf("Shutting down after Ctrl-C.\n");
-	exit(0);
 }

+ 15 - 12
examples/src/xml2ns0.c

@@ -25,14 +25,13 @@ char* buildNumber = "999-" __DATE__ "-001" ;
 } while(0)
 
 void sam_attach(Namespace *ns,UA_UInt32 ns0id,UA_Int32 type, void* p) {
-	Namespace_Entry_Lock* lock;
 	UA_NodeId nodeid;
-	nodeid.namespace = ns->namespaceId;
+	nodeid.namespace = 0; // we cannot access ns->namespaceId;
 	nodeid.identifier.numeric = ns0id;
 	nodeid.encodingByte = UA_NODEIDTYPE_FOURBYTE;
 	const UA_Node* result;
-	UA_Int32 retval;
-	if ((retval = Namespace_get(ns,&nodeid,&result,&lock)) == UA_SUCCESS) {
+	UA_Int32 retval = Namespace_get(ns,&nodeid,&result);
+	if (retval == UA_SUCCESS) {
 		if (result->nodeId.identifier.numeric == ns0id) {
 			if (result->nodeClass == UA_NODECLASS_VARIABLE) {
 				UA_VariableNode* variable = (UA_VariableNode*) result;
@@ -50,6 +49,7 @@ void sam_attach(Namespace *ns,UA_UInt32 ns0id,UA_Int32 type, void* p) {
 				}
 			}
 		}
+		Namespace_releaseManagedNode(result);
 	}
 }
 	/* 	} else { */
@@ -91,7 +91,7 @@ void sam_init(Namespace* ns) {
 UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const * id, UA_Int32* number) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Node const * node;
-	if ((retval = Namespace_get(ns,id,&node,UA_NULL)) != UA_SUCCESS)
+	if ((retval = Namespace_get(ns,id,&node)) != UA_SUCCESS)
 		return retval;
 	if (node == UA_NULL)
 		return UA_ERR_INVALID_VALUE;
@@ -101,6 +101,7 @@ UA_Int32 Namespace_getNumberOfComponents(Namespace const * ns, UA_NodeId const *
 			n++;
 		}
 	}
+	Namespace_releaseManagedNode(node);
 	*number = n;
 	return retval;
 }
@@ -109,7 +110,7 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 	UA_Int32 retval = UA_SUCCESS;
 
 	UA_Node const * node;
-	if ((retval = Namespace_get(ns,id,&node,UA_NULL)) != UA_SUCCESS)
+	if ((retval = Namespace_get(ns,id,&node)) != UA_SUCCESS)
 		return retval;
 
 	UA_Int32 i, n;
@@ -118,10 +119,13 @@ UA_Int32 Namespace_getComponent(Namespace const * ns, UA_NodeId const * id, UA_I
 			n++;
 			if (n == idx) {
 				*result = &(node->references[i].targetId.nodeId);
+				Namespace_releaseManagedNode(node);
 				return retval;
 			}
 		}
 	}
+
+	Namespace_releaseManagedNode(node);
 	return UA_ERR_INVALID_VALUE;
 }
 
@@ -130,9 +134,10 @@ UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const
 	UA_Int32 i, retval = UA_SUCCESS;
 	if (UA_NodeId_isBasicType(id)) {
 		UA_Node const * result;
-		Namespace_Entry_Lock* lock;
-		if ((retval = Namespace_get(ns,id,&result,&lock)) == UA_SUCCESS)
+		if ((retval = Namespace_get(ns,id,&result)) == UA_SUCCESS) {
 			UA_Variant_encodeBinary(&((UA_VariableNode *) result)->value,dst,offset);
+			Namespace_releaseManagedNode(result);
+		}
 	} else {
 		UA_Int32 nComp = 0;
 		if ((retval = Namespace_getNumberOfComponents(ns,id,&nComp)) == UA_SUCCESS) {
@@ -149,13 +154,11 @@ UA_Int32 UAX_NodeId_encodeBinaryByMetaData(Namespace const * ns, UA_NodeId const
 UA_Int32 UAX_NodeId_encodeBinary(Namespace const * ns, UA_NodeId const * id, UA_ByteString *dst, UA_UInt32* offset) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Node const * node;
-	Namespace_Entry_Lock* lock;
-
-	if ((retval = Namespace_get(ns,id,&node,&lock)) == UA_SUCCESS) {
+	if ((retval = Namespace_get(ns,id,&node)) == UA_SUCCESS) {
 		if (node->nodeClass == UA_NODECLASS_VARIABLE) {
 			retval = UA_Variant_encodeBinary(&((UA_VariableNode*) node)->value,dst,offset);
 		}
-		Namespace_Entry_Lock_release(lock);
+		Namespace_releaseManagedNode(node);
 	}
 	return retval;
 }

schema/UA_stackInternalTypes.bsd → schema/Custom.Opc.Ua.Transport.bsd


+ 1 - 0
src/Makefile.am

@@ -15,6 +15,7 @@ libopen62541_la_SOURCES = ua_types.c \
 						  ua_transport.c \
 						  ua_transport_binary.c \
 						  ua_transport_binary_secure.c \
+						  ua_namespace.c \
 						  ua_services_attribute.c \
 						  ua_services_session.c \
 						  ua_services_discovery.c \

+ 140 - 0
src/ua_application.c

@@ -82,7 +82,11 @@ void appMockup_init() {
 	references->description = UA_LOCALIZEDTEXT_STATIC("References");
 	references->isAbstract = UA_TRUE;
 	references->symmetric = UA_TRUE;
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&references, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&references, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hierarchicalreferences;
 	UA_ReferenceTypeNode_new(&hierarchicalreferences);
@@ -95,7 +99,11 @@ void appMockup_init() {
 	hierarchicalreferences->symmetric = UA_FALSE;
 	AddReference((UA_Node*)hierarchicalreferences, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_References, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hierarchicalreferences, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hierarchicalreferences, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *nonhierarchicalreferences;
 	UA_ReferenceTypeNode_new(&nonhierarchicalreferences);
@@ -108,7 +116,11 @@ void appMockup_init() {
 	nonhierarchicalreferences->symmetric = UA_FALSE;
 	AddReference((UA_Node*)nonhierarchicalreferences, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_References, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&nonhierarchicalreferences, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&nonhierarchicalreferences, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *haschild;
 	UA_ReferenceTypeNode_new(&haschild);
@@ -121,7 +133,11 @@ void appMockup_init() {
 	haschild->symmetric = UA_FALSE;
 	AddReference((UA_Node*)haschild, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&haschild, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&haschild, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *organizes;
 	UA_ReferenceTypeNode_new(&organizes);
@@ -135,7 +151,11 @@ void appMockup_init() {
 	organizes->inverseName = UA_LOCALIZEDTEXT_STATIC("OrganizedBy");
 	AddReference((UA_Node*)organizes, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&organizes, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&organizes, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *haseventsource;
 	UA_ReferenceTypeNode_new(&haseventsource);
@@ -149,7 +169,11 @@ void appMockup_init() {
 	haseventsource->inverseName = UA_LOCALIZEDTEXT_STATIC("EventSourceOf");
 	AddReference((UA_Node*)haseventsource, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&haseventsource, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&haseventsource, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasmodellingrule;
 	UA_ReferenceTypeNode_new(&hasmodellingrule);
@@ -163,7 +187,11 @@ void appMockup_init() {
 	hasmodellingrule->inverseName = UA_LOCALIZEDTEXT_STATIC("ModellingRuleOf");
 	AddReference((UA_Node*)hasmodellingrule, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasmodellingrule, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasmodellingrule, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasencoding;
 	UA_ReferenceTypeNode_new(&hasencoding);
@@ -177,7 +205,11 @@ void appMockup_init() {
 	hasencoding->inverseName = UA_LOCALIZEDTEXT_STATIC("EncodingOf");
 	AddReference((UA_Node*)hasencoding, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasencoding, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasencoding, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasdescription;
 	UA_ReferenceTypeNode_new(&hasdescription);
@@ -191,7 +223,11 @@ void appMockup_init() {
 	hasdescription->inverseName = UA_LOCALIZEDTEXT_STATIC("DescriptionOf");
 	AddReference((UA_Node*)hasdescription, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasdescription, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasdescription, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hastypedefinition;
 	UA_ReferenceTypeNode_new(&hastypedefinition);
@@ -205,7 +241,11 @@ void appMockup_init() {
 	hastypedefinition->inverseName = UA_LOCALIZEDTEXT_STATIC("TypeDefinitionOf");
 	AddReference((UA_Node*)hastypedefinition, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hastypedefinition, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hastypedefinition, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *generatesevent;
 	UA_ReferenceTypeNode_new(&generatesevent);
@@ -219,7 +259,11 @@ void appMockup_init() {
 	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("GeneratedBy");
 	AddReference((UA_Node*)generatesevent, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&generatesevent, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&generatesevent, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *aggregates;
 	UA_ReferenceTypeNode_new(&aggregates);
@@ -232,7 +276,11 @@ void appMockup_init() {
 	aggregates->symmetric = UA_FALSE;
 	AddReference((UA_Node*)aggregates, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HasChild, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&aggregates, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&aggregates, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hassubtype;
 	UA_ReferenceTypeNode_new(&hassubtype);
@@ -246,7 +294,11 @@ void appMockup_init() {
 	hassubtype->inverseName = UA_LOCALIZEDTEXT_STATIC("SubtypeOf");
 	AddReference((UA_Node*)hassubtype, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HasChild, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hassubtype, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hassubtype, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasproperty;
 	UA_ReferenceTypeNode_new(&hasproperty);
@@ -260,7 +312,11 @@ void appMockup_init() {
 	hasproperty->inverseName = UA_LOCALIZEDTEXT_STATIC("PropertyOf");
 	AddReference((UA_Node*)hasproperty, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_Aggregates, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasproperty, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasproperty, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hascomponent;
 	UA_ReferenceTypeNode_new(&hascomponent);
@@ -274,7 +330,11 @@ void appMockup_init() {
 	hascomponent->inverseName = UA_LOCALIZEDTEXT_STATIC("ComponentOf");
 	AddReference((UA_Node*)hascomponent, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_Aggregates, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hascomponent, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hascomponent, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasnotifier;
 	UA_ReferenceTypeNode_new(&hasnotifier);
@@ -288,7 +348,11 @@ void appMockup_init() {
 	hasnotifier->inverseName = UA_LOCALIZEDTEXT_STATIC("NotifierOf");
 	AddReference((UA_Node*)hasnotifier, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HasEventSource, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasnotifier, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasnotifier, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasorderedcomponent;
 	UA_ReferenceTypeNode_new(&hasorderedcomponent);
@@ -302,7 +366,11 @@ void appMockup_init() {
 	hasorderedcomponent->inverseName = UA_LOCALIZEDTEXT_STATIC("OrderedComponentOf");
 	AddReference((UA_Node*)hasorderedcomponent, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_HasComponent, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasorderedcomponent, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasorderedcomponent, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hasmodelparent;
 	UA_ReferenceTypeNode_new(&hasmodelparent);
@@ -316,7 +384,11 @@ void appMockup_init() {
 	hasmodelparent->inverseName = UA_LOCALIZEDTEXT_STATIC("ModelParentOf");
 	AddReference((UA_Node*)hasmodelparent, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hasmodelparent, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hasmodelparent, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *fromstate;
 	UA_ReferenceTypeNode_new(&fromstate);
@@ -330,7 +402,11 @@ void appMockup_init() {
 	fromstate->inverseName = UA_LOCALIZEDTEXT_STATIC("ToTransition");
 	AddReference((UA_Node*)fromstate, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&fromstate, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&fromstate, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *tostate;
 	UA_ReferenceTypeNode_new(&tostate);
@@ -344,7 +420,11 @@ void appMockup_init() {
 	tostate->inverseName = UA_LOCALIZEDTEXT_STATIC("FromTransition");
 	AddReference((UA_Node*)tostate, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&tostate, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&tostate, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hascause;
 	UA_ReferenceTypeNode_new(&hascause);
@@ -358,7 +438,11 @@ void appMockup_init() {
 	hascause->inverseName = UA_LOCALIZEDTEXT_STATIC("MayBeCausedBy");
 	AddReference((UA_Node*)hascause, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hascause, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hascause, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *haseffect;
 	UA_ReferenceTypeNode_new(&haseffect);
@@ -372,7 +456,11 @@ void appMockup_init() {
 	haseffect->inverseName = UA_LOCALIZEDTEXT_STATIC("MayBeEffectedBy");
 	AddReference((UA_Node*)haseffect, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
 		(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&haseffect, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&haseffect, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	UA_ReferenceTypeNode *hashistoricalconfiguration;
 	UA_ReferenceTypeNode_new(&hashistoricalconfiguration);
@@ -386,7 +474,11 @@ void appMockup_init() {
 	hashistoricalconfiguration->inverseName = UA_LOCALIZEDTEXT_STATIC("HistoricalConfigurationOf");
 	AddReference((UA_Node*)hashistoricalconfiguration, &(UA_ReferenceNode){RefTypeId_HasSubtype,
 		UA_TRUE, (UA_ExpandedNodeId){RefTypeId_Aggregates, UA_STRING_NULL, 0}}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&hashistoricalconfiguration, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&hashistoricalconfiguration, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 
 	// ObjectTypes (Ids only)
@@ -411,7 +503,11 @@ void appMockup_init() {
 	folderType->browseName = UA_QUALIFIEDNAME_STATIC("FolderType");
 	folderType->displayName = UA_LOCALIZEDTEXT_STATIC("FolderType");
 	folderType->description = UA_LOCALIZEDTEXT_STATIC("FolderType");
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&folderType, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&folderType, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// Root
 	UA_ObjectNode *root;
@@ -426,7 +522,11 @@ void appMockup_init() {
 	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_TypesFolder}, ns0);
 	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_ViewsFolder}, ns0);
 	/* root becomes a managed node. we need to release it at the end.*/
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&root, NAMESPACE_INSERT_UNIQUE | NAMESPACE_INSERT_GETMANAGED);
+=======
+	Namespace_insert(ns0,(UA_Node**)&root, NAMESPACE_INSERT_UNIQUE | NAMESPACE_INSERT_GETMANAGED);
+>>>>>>> origin/master
 
 	// Objects
 	UA_ObjectNode *objects;
@@ -438,7 +538,11 @@ void appMockup_init() {
 	objects->description = UA_LOCALIZEDTEXT_STATIC("Objects");
 	AddReference((UA_Node*)objects, &(UA_ReferenceNode){RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}, ns0);
 	AddReference((UA_Node*)objects, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_Server}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&objects, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&objects, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// Types
 	UA_ObjectNode *types;
@@ -449,7 +553,11 @@ void appMockup_init() {
 	types->displayName = UA_LOCALIZEDTEXT_STATIC("Types");
 	types->description = UA_LOCALIZEDTEXT_STATIC("Types");
 	AddReference((UA_Node*)types, &(UA_ReferenceNode){RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&types, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&types, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// Views
 	UA_ObjectNode *views;
@@ -460,7 +568,11 @@ void appMockup_init() {
 	views->displayName = UA_LOCALIZEDTEXT_STATIC("Views");
 	views->description = UA_LOCALIZEDTEXT_STATIC("Views");
 	AddReference((UA_Node*)views, &(UA_ReferenceNode){RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&views, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&views, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// Server
 	UA_ObjectNode *server;
@@ -474,7 +586,11 @@ void appMockup_init() {
 	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasComponent, UA_FALSE, ObjId_NamespaceArray}, ns0);
 	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasProperty, UA_FALSE, ObjId_ServerStatus}, ns0);
 	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasProperty, UA_FALSE, ObjId_ServerArray}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&server, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&server, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// NamespaceArray
 	UA_VariableNode *namespaceArray;
@@ -498,7 +614,11 @@ void appMockup_init() {
 	namespaceArray->valueRank = 1;
 	namespaceArray->minimumSamplingInterval = 1.0;
 	namespaceArray->historizing = UA_FALSE;
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&namespaceArray, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&namespaceArray, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// ServerStatus
 	UA_VariableNode *serverstatus;
@@ -525,7 +645,11 @@ void appMockup_init() {
 	serverstatus->value.vt = &UA_.types[UA_SERVERSTATUSDATATYPE]; // gets encoded as an extensionobject
 	serverstatus->value.arrayLength = 1;
 	serverstatus->value.data = status;
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&serverstatus, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&serverstatus, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	// State (Component of ServerStatus)
 	UA_VariableNode *state;
@@ -538,7 +662,11 @@ void appMockup_init() {
 	state->value.vt = &UA_borrowed_.types[UA_SERVERSTATE];
 	state->value.arrayLength = 1;
 	state->value.data = &status->state; // points into the other object.
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&state, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&state, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 	//TODO: free(namespaceArray->value.data) later or forget it
 
@@ -584,7 +712,11 @@ void appMockup_init() {
 	tmpNodeValue->vt = &UA_.types[UA_FLOAT];
 
 	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_temperature1}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&temperature1, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&temperature1, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 
 	UA_ExpandedNodeId ObjId_redLED = (UA_ExpandedNodeId){.nodeId = (UA_NodeId){.encodingByte = UA_NODEIDTYPE_TWOBYTE, .namespace = 0, .identifier.numeric = 109}, .namespaceUri = {-1, ((void *)0)}, .serverIndex = 0};
@@ -609,7 +741,11 @@ void appMockup_init() {
 	tmpNodeValue1->vt = &UA_.types[UA_BOOLEAN];
 
 	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_redLED}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&redLED, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&redLED, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 
 
 	UA_ExpandedNodeId ObjId_yellowLED = (UA_ExpandedNodeId){.nodeId = (UA_NodeId){.encodingByte = UA_NODEIDTYPE_TWOBYTE, .namespace = 0, .identifier.numeric = 110}, .namespaceUri = {-1, ((void *)0)}, .serverIndex = 0};
@@ -634,7 +770,11 @@ void appMockup_init() {
 	tmpNodeValue2->vt = &UA_.types[UA_BOOLEAN];
 
 	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_yellowLED}, ns0);
+<<<<<<< HEAD
 	Namespace_insert(ns0,(const UA_Node**)&yellowLED, NAMESPACE_INSERT_UNIQUE);
+=======
+	Namespace_insert(ns0,(UA_Node**)&yellowLED, NAMESPACE_INSERT_UNIQUE);
+>>>>>>> origin/master
 	
 	Namespace_releaseManagedNode((const UA_Node*)root);
 

+ 4 - 0
src/ua_namespace.c

@@ -263,7 +263,11 @@ UA_Int32 Namespace_delete(Namespace * ns) {
 	return UA_SUCCESS;
 }
 
+<<<<<<< HEAD
 UA_Int32 Namespace_insert(Namespace *ns, const UA_Node **node, UA_Byte flags) {
+=======
+UA_Int32 Namespace_insert(Namespace *ns, UA_Node **node, UA_Byte flags) {
+>>>>>>> origin/master
 	if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL)
 		return UA_ERROR;
 	

+ 55 - 44
src/ua_namespace.h

@@ -5,61 +5,72 @@
 #include "ua_types_generated.h"
 #include "util/ua_list.h"
 
-/**
-   @defgroup namespace Namespace
-
-   @brief The namespace is the central storage for nodes in the UA address
-   space. Internally, the namespace is realised as hash-map where nodes are
-   stored and retrieved with their nodeid.
-
-   The nodes in the namespace are immutable. To change the content of a node, it
-   needs to be replaced as a whole. When a node is inserted into the namespace,
-   it gets replaced with a pointer to a managed node. Managed nodes shall never
-   be freed by the user. This is done by the namespace when the node is removed
-   and no readers (in other threads) access the node.
-
-   @{
- */
-
-/** @brief Namespace datastructure. Mainly a hashmap to UA_Nodes */
-struct Namespace;
-typedef struct Namespace Namespace;
+#ifdef MULTITHREADING
+#define _XOPEN_SOURCE 500
+#define __USE_UNIX98
+#include <pthread.h>
+#endif
+
+/** @brief Namespace entries point to an UA_Node. But the actual data structure
+	is opaque outside of ua_namespace.c */
+
+typedef struct Namespace_Entry {
+	UA_UInt64 status;	/* 2 bits status | 14 bits checkout count | 48 bits timestamp */
+	const UA_Node *node;	/* Nodes are immutable. It is not recommended to change nodes in place */
+} Namespace_Entry;
+
+/** @brief Namespace datastructure. It mainly serves as a hashmap to UA_Nodes. */
+typedef struct Namespace {
+	UA_UInt32 namespaceId;
+	Namespace_Entry *entries;
+	UA_UInt32 size;
+	UA_UInt32 count;
+	UA_UInt32 sizePrimeIndex;	/* Current size, as an index into the table of primes.  */
+} Namespace;
+
+/** Namespace locks indicate that a thread currently operates on an entry. */
+struct Namespace_Entry_Lock;
+typedef struct Namespace_Entry_Lock Namespace_Entry_Lock;
+
+/** @brief Release a lock on a namespace entry. */
+void Namespace_Entry_Lock_release(Namespace_Entry_Lock * lock);
 
 /** @brief Create a new namespace */
-UA_Int32 Namespace_new(Namespace **result, UA_UInt32 namespaceId);
+UA_Int32 Namespace_new(Namespace ** result, UA_UInt32 size, UA_UInt32 namespaceId);
+
+/** @brief Delete all nodes in the namespace */
+void Namespace_empty(Namespace * ns);
 
 /** @brief Delete the namespace and all nodes in it */
-UA_Int32 Namespace_delete(Namespace *ns);
+void Namespace_delete(Namespace * ns);
 
-#define NAMESPACE_INSERT_UNIQUE 1
-#define NAMESPACE_INSERT_GETMANAGED 2
-/** @brief Insert a new node into the namespace
+/** @brief Insert a new node into the namespace. Abort an entry with the same
+	NodeId is already present */
+UA_Int32 Namespace_insert(Namespace * ns, const UA_Node * node);
 
-    With the UNIQUE flag, the node is only inserted if the nodeid does not
-    already exist. With the GETMANAGED flag, the node pointer is replaced with
-    the managed pointer. Otherwise, it is set to UA_NULL. */
-UA_Int32 Namespace_insert(Namespace *ns, const UA_Node **node, UA_Byte flags);
+/** @brief Insert a new node or replace an existing node if an entry has the same NodeId. */
+// UA_Int32 Namespace_insertOrReplace(Namespace * ns, const UA_Node * node);
 
-/** @brief Remove a node from the namespace. Always succeeds, even if the node
-	was not found. */
-UA_Int32 Namespace_remove(Namespace *ns, const UA_NodeId *nodeid);
+/** @brief Find an unused (numeric) NodeId in the namespace and insert the node.
+	The node is modified to contain the new nodeid after insertion. */
+UA_Int32 Namespace_insertUnique(Namespace * ns, UA_Node * node);
 
-/** @brief Retrieve a node (read-only) from the namespace. Nodes are immutable.
-    They can only be replaced. After the Node is no longer used, the locked
-    entry needs to be released. */
-UA_Int32 Namespace_get(const Namespace *ns, const UA_NodeId *nodeid, const UA_Node **managedNode);
+/** @brief Remove a node from the namespace */
+UA_Int32 Namespace_remove(Namespace * ns, const UA_NodeId * nodeid);
 
-/** @brief Release a managed node. Do never insert a node that isn't stored in a
-	namespace. */
-void Namespace_releaseManagedNode(const UA_Node *managed);
+/** @brief Tests whether the namespace contains an entry for a given NodeId */
+UA_Int32 Namespace_contains(const Namespace * ns, const UA_NodeId * nodeid);
 
-/** @brief A function that can be evaluated on all entries in a namespace via
-	Namespace_iterate. Note that the visitor is read-only on the nodes. */
-typedef void (*Namespace_nodeVisitor)(const UA_Node *node);
+/** @brief Retrieve a node (read-only) from the namespace. Nodes are identified
+	by their NodeId. After the Node is no longer used, the lock needs to be
+	released. */
+UA_Int32 Namespace_get(const Namespace *ns, const UA_NodeId * nodeid, const UA_Node **result,
+					   Namespace_Entry_Lock ** lock);
 
-/** @brief Iterate over all nodes in a namespace. */
-UA_Int32 Namespace_iterate(const Namespace *ns, Namespace_nodeVisitor visitor);
+/** @brief A function that can be evaluated on all entries in a namespace via Namespace_iterate */
+typedef void (*Namespace_nodeVisitor) (const UA_Node *node);
 
-/// @} /* end of group */
+/** @brief Iterate over all nodes in a namespace */
+UA_Int32 Namespace_iterate(const Namespace * ns, Namespace_nodeVisitor visitor);
 
 #endif /* __NAMESPACE_H */

+ 18 - 11
src/ua_namespace_concurrent.c

@@ -9,6 +9,7 @@
 #define ALIVE_BIT (1 << 15) /* Alive bit in the readcount */
 typedef struct Namespace_Entry {
 	struct cds_lfht_node htn; /* contains next-ptr for urcu-hashmap */
+	struct rcu_head rcu_head; /* For call-rcu */
 	UA_UInt16 readcount;      /* Counts the amount of readers on it [alive-bit, 15 counter-bits] */
 	UA_Node   node;           /* Might be cast from any _bigger_ UA_Node* type. Allocate enough memory! */
 } Namespace_Entry;
@@ -152,7 +153,8 @@ static int compare(struct cds_lfht_node *htn, const void *orig) {
    all readers using the node for a longer time (outside the rcu critical
    section) increased the readcount, we only need to wait for the readcount
    to reach zero. */
-static void markDead(Namespace_Entry *entry) {
+static void markDead(struct rcu_head *head) {
+	Namespace_Entry *entry = caa_container_of(head, Namespace_Entry, rcu_head);
 	if(uatomic_sub_return(&entry->readcount, ALIVE_BIT) > 0)
 		return;
 
@@ -166,7 +168,7 @@ void Namespace_releaseManagedNode(const UA_Node *managed) {
 	if(managed == UA_NULL)
 		return;
 	
-	Namespace_Entry *entry = caa_container_of(managed, Namespace_Entry, htn); // pointer to the first entry
+	Namespace_Entry *entry = caa_container_of(managed, Namespace_Entry, node); // pointer to the first entry
 	if(uatomic_sub_return(&entry->readcount, 1) > 0)
 		return;
 
@@ -204,8 +206,10 @@ UA_Int32 Namespace_delete(Namespace *ns) {
 	cds_lfht_first(ht, &iter);
 	while(iter.node != UA_NULL) {
 		found_htn = cds_lfht_iter_get_node(&iter);
-		if(!cds_lfht_del(ht, found_htn))
-			call_rcu(found_htn, markDead);
+		if(!cds_lfht_del(ht, found_htn)) {
+			Namespace_Entry *entry = caa_container_of(found_htn, Namespace_Entry, htn);
+			call_rcu(&entry->rcu_head, markDead);
+		}
 		cds_lfht_next(ht, &iter);
 	}
 	rcu_read_unlock();
@@ -218,7 +222,7 @@ UA_Int32 Namespace_delete(Namespace *ns) {
 		return UA_ERROR;
 }
 
-UA_Int32 Namespace_insert(Namespace *ns, const UA_Node **node, UA_Byte flags) {
+UA_Int32 Namespace_insert(Namespace *ns, UA_Node **node, UA_Byte flags) {
 	if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL || (*node)->nodeId.namespace != ns->namespaceId)
 		return UA_ERROR;
 
@@ -262,7 +266,7 @@ UA_Int32 Namespace_insert(Namespace *ns, const UA_Node **node, UA_Byte flags) {
 	}
 
 	Namespace_Entry *entry;
-	if(UA_alloc((void **)&entry, sizeof(struct cds_lfht_node) + sizeof(UA_UInt16) + nodesize))
+	if(UA_alloc((void **)&entry, sizeof(Namespace_Entry) - sizeof(UA_Node) + nodesize))
 		return UA_ERR_NO_MEMORY;
 	memcpy(&entry->node, *node, nodesize);
 
@@ -287,8 +291,10 @@ UA_Int32 Namespace_insert(Namespace *ns, const UA_Node **node, UA_Byte flags) {
 		rcu_read_lock();
 		result = cds_lfht_add_replace(ns->ht, nhash, compare, &(*node)->nodeId, &entry->htn);
 		/* If an entry got replaced, mark it as dead. */
-		if(result)
-			call_rcu(markDead, result);      /* Queue this for the next time when no readers are on the entry.*/
+		if(result) {
+			Namespace_Entry *entry = caa_container_of(result, Namespace_Entry, htn);
+			call_rcu(&entry->rcu_head, markDead);      /* Queue this for the next time when no readers are on the entry.*/
+		}
 		rcu_read_unlock();
 	}
 
@@ -307,15 +313,16 @@ UA_Int32 Namespace_remove(Namespace *ns, const UA_NodeId *nodeid) {
 
 	rcu_read_lock();
 	cds_lfht_lookup(ns->ht, nhash, compare, &nodeid, &iter);
-	struct cds_lfht_node *found_node = cds_lfht_iter_get_node(&iter);
+	struct cds_lfht_node *found_htn = cds_lfht_iter_get_node(&iter);
 
 	/* If this fails, then the node has already been removed. */
-	if(!found_node || cds_lfht_del(ns->ht, found_node) != 0) {
+	if(!found_htn || cds_lfht_del(ns->ht, found_htn) != 0) {
 		rcu_read_unlock();
 		return UA_ERROR;
 	}
 	
-	call_rcu(markDead, found_node);
+	Namespace_Entry *entry = caa_container_of(found_htn, Namespace_Entry, htn);
+	call_rcu(&entry->rcu_head, markDead);
 	rcu_read_unlock();
 
 	return UA_SUCCESS;

+ 4 - 0
src/ua_types_encoding_json.c

@@ -0,0 +1,4 @@
+#include "ua_types_encoding_json.h"
+
+// TODO: Implement encoding of the builtin types (in ua_types.h). Then add JSON
+// encoding to the structure generation in tools/generate_builtin.py

+ 73 - 0
src/ua_types_encoding_json.h

@@ -0,0 +1,73 @@
+#ifndef UA_TYPES_ENCODING_JSON_H_
+#define UA_TYPES_ENCODING_JSON_H_
+
+#include "util/ua_util.h"
+#include "ua_types.h"
+
+/**
+ * @ingroup encoding
+ * @defgroup encoding_json JSON Encoding
+ *
+ * @brief Encoding of UA datatypes in JSON. This extends the IEC 62541 standard
+ * and is only included in the "extended" profile. The extension is intended to
+ * be used with a webserver that transmits JSON over HTTP.
+ *
+ * @{
+ */
+
+#define UA_TYPE_CALCSIZEJSON_AS(TYPE, TYPE_AS)       \
+    UA_Int32 TYPE##_calcSizeJSON(TYPE const *p) {    \
+		return TYPE_AS##_calcSizeJSON((TYPE_AS *)p); \
+	}
+
+#define UA_TYPE_ENCODEJSON_AS(TYPE, TYPE_AS)                                             \
+    UA_Int32 TYPE##_encodeJSON(TYPE const *src, UA_ByteString *dst, UA_UInt32 *offset) { \
+		return TYPE_AS##_encodeJSON((TYPE_AS *)src, dst, offset);                        \
+	}
+
+#define UA_TYPE_DECODEJSON_AS(TYPE, TYPE_AS)                                             \
+    UA_Int32 TYPE##_decodeJSON(UA_ByteString const *src, UA_UInt32 *offset, TYPE *dst) { \
+		return TYPE_AS##_decodeJSON(src, offset, (TYPE_AS *)dst);                        \
+	}
+#define UA_TYPE_JSON_ENCODING_AS(TYPE, TYPE_AS) \
+    UA_TYPE_CALCSIZEJSON_AS(TYPE, TYPE_AS)      \
+    UA_TYPE_ENCODEJSON_AS(TYPE, TYPE_AS)        \
+    UA_TYPE_DECODEJSON_AS(TYPE, TYPE_AS)
+
+#define UA_TYPE_JSON_ENCODING(TYPE)                                                     \
+    UA_Int32 TYPE##_calcSizeJSON(TYPE const *p);                                        \
+    UA_Int32 TYPE##_encodeJSON(TYPE const *src, UA_ByteString *dst, UA_UInt32 *offset); \
+    UA_Int32 TYPE##_decodeJSON(UA_ByteString const *src, UA_UInt32 *offset, TYPE *dst);
+
+UA_TYPE_JSON_ENCODING(UA_Boolean)
+UA_TYPE_JSON_ENCODING(UA_SByte)
+UA_TYPE_JSON_ENCODING(UA_Byte)
+UA_TYPE_JSON_ENCODING(UA_Int16)
+UA_TYPE_JSON_ENCODING(UA_UInt16)
+UA_TYPE_JSON_ENCODING(UA_Int32)
+UA_TYPE_JSON_ENCODING(UA_UInt32)
+UA_TYPE_JSON_ENCODING(UA_Int64)
+UA_TYPE_JSON_ENCODING(UA_UInt64)
+UA_TYPE_JSON_ENCODING(UA_Float)
+UA_TYPE_JSON_ENCODING(UA_Double)
+UA_TYPE_JSON_ENCODING(UA_String)
+UA_TYPE_JSON_ENCODING(UA_DateTime)
+UA_TYPE_JSON_ENCODING(UA_Guid)
+UA_TYPE_JSON_ENCODING(UA_ByteString)
+UA_TYPE_JSON_ENCODING(UA_XmlElement)
+UA_TYPE_JSON_ENCODING(UA_NodeId)
+UA_TYPE_JSON_ENCODING(UA_ExpandedNodeId)
+UA_TYPE_JSON_ENCODING(UA_StatusCode)
+UA_TYPE_JSON_ENCODING(UA_QualifiedName)
+UA_TYPE_JSON_ENCODING(UA_LocalizedText)
+UA_TYPE_JSON_ENCODING(UA_ExtensionObject)
+UA_TYPE_JSON_ENCODING(UA_DataValue)
+UA_TYPE_JSON_ENCODING(UA_Variant)
+UA_TYPE_JSON_ENCODING(UA_DiagnosticInfo)
+
+/* Not built-in types */
+UA_TYPE_JSON_ENCODING(UA_InvalidType)
+
+/// @} /* end of group */
+
+#endif /* UA_TYPES_ENCODING_JSON_H_ */

+ 2 - 3
src/ua_xml.c

@@ -67,7 +67,7 @@ UA_Int32 UA_NodeSetAliases_println(cstring label, UA_NodeSetAliases *p) {
 }
 
 UA_Int32 UA_NodeSet_init(UA_NodeSet *p, UA_UInt32 nsid) {
-	Namespace_new(&(p->ns), 100, nsid);
+	Namespace_new(&(p->ns), nsid);
 	p->aliases.size    = -1;
 	p->aliases.aliases = UA_NULL;
 	return UA_SUCCESS;
@@ -848,9 +848,8 @@ UA_Int32 UA_NodeSet_decodeXmlFromStack(XML_Stack *s, XML_Attr *attr, UA_NodeSet
 		} else {
 			UA_Node* node = (UA_Node*) attr;
 			DBG(printf("UA_NodeSet_decodeXML - finished node: node=%p\n", (void* )node));
-			Namespace_insert(dst->ns, node);
+			Namespace_insert(dst->ns, &node, 0);
 			DBG(printf("UA_NodeSet_decodeXml - Inserting "));
-			DBG(print_node(node));
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 		}
 	}

+ 159 - 0
tests/check_namespace.c

@@ -1,11 +1,16 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <time.h>
 
 #include "ua_types.h"
 #include "ua_namespace.h"
 #include "check.h"
 
 #ifdef MULTITHREADING
+<<<<<<< HEAD
+=======
+#include <pthread.h>
+>>>>>>> origin/master
 #include <urcu.h>
 #endif
 
@@ -27,6 +32,7 @@ START_TEST(test_Namespace) {
 }
 END_TEST
 
+<<<<<<< HEAD
 UA_Int32 createNode(const UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
 	UA_VariableNode * p2;
 	UA_VariableNode_new(&p2);
@@ -35,6 +41,14 @@ UA_Int32 createNode(const UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
 	p2->nodeId.identifier.numeric = id;
 	p2->nodeClass = UA_NODECLASS_VARIABLE;
 	*p = (const UA_Node *)p2;
+=======
+UA_Int32 createNode(UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
+	UA_VariableNode_new((UA_VariableNode **)p);
+	(*p)->nodeId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	(*p)->nodeId.namespace = nsid;
+	(*p)->nodeId.identifier.numeric = id;
+	(*p)->nodeClass = UA_NODECLASS_VARIABLE;
+>>>>>>> origin/master
 	return UA_SUCCESS;
 }
 
@@ -45,12 +59,20 @@ START_TEST(findNodeInNamespaceWithSingleEntry) {
 	// given
 	Namespace *ns;
 	Namespace_new(&ns, 0);
+<<<<<<< HEAD
 	const UA_Node* n1; createNode(&n1,0,2253);
+=======
+	UA_Node* n1; createNode(&n1,0,2253);
+>>>>>>> origin/master
 	Namespace_insert(ns, &n1, NAMESPACE_INSERT_UNIQUE | NAMESPACE_INSERT_GETMANAGED);
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
 	// when
+<<<<<<< HEAD
 	retval = Namespace_get(ns,&(n1->nodeId),&nr);
+=======
+	retval = Namespace_get(ns,&n1->nodeId,&nr);
+>>>>>>> origin/master
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_ptr_eq(nr,n1);
@@ -72,6 +94,7 @@ START_TEST(failToFindNodeInOtherNamespace) {
 	Namespace *ns = UA_NULL;
 	Namespace_new(&ns, 0);
 
+<<<<<<< HEAD
 	const UA_Node* n1 = UA_NULL; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
 	const UA_Node* n2 = UA_NULL; createNode(&n1,0,2253); Namespace_insert(ns, &n2, 0);
 
@@ -84,6 +107,19 @@ START_TEST(failToFindNodeInOtherNamespace) {
 	ck_assert_int_ne(retval, UA_SUCCESS);
 	// finally
 	UA_free((void *)n);
+=======
+	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2253); Namespace_insert(ns, &n2, 0);
+
+	const UA_Node* nr = UA_NULL;
+	// when
+	UA_Node* n; createNode(&n,1,2255);
+	UA_Int32 retval = Namespace_get(ns,&n->nodeId, &nr);
+	// then
+	ck_assert_int_ne(retval, UA_SUCCESS);
+	// finally
+	UA_Node_delete(n);
+>>>>>>> origin/master
 	Namespace_releaseManagedNode(nr);
 	Namespace_delete(ns);
 #ifdef MULTITHREADING
@@ -99,12 +135,21 @@ START_TEST(findNodeInNamespaceWithSeveralEntries) {
 	// given
 	Namespace *ns;
 	Namespace_new(&ns, 0);
+<<<<<<< HEAD
 	const UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
 	const UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
 	const UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, NAMESPACE_INSERT_GETMANAGED);
 	const UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
 	const UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
 	const UA_Node* n6; createNode(&n6,0,12); Namespace_insert(ns, &n6, 0);
+=======
+	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
+	UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, NAMESPACE_INSERT_GETMANAGED);
+	UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
+	UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
+	UA_Node* n6; createNode(&n6,0,12); Namespace_insert(ns, &n6, 0);
+>>>>>>> origin/master
 
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
@@ -130,12 +175,21 @@ START_TEST(iterateOverNamespaceShallNotVisitEmptyNodes) {
 	// given
 	Namespace *ns;
 	Namespace_new(&ns, 0);
+<<<<<<< HEAD
 	const UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
 	const UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
 	const UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, 0);
 	const UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
 	const UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
 	const UA_Node* n6; createNode(&n6,0,12); Namespace_insert(ns, &n6, 0);
+=======
+	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
+	UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, 0);
+	UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
+	UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
+	UA_Node* n6; createNode(&n6,0,12); Namespace_insert(ns, &n6, 0);
+>>>>>>> origin/master
 
 	UA_Int32 retval;
 	// when
@@ -161,7 +215,11 @@ START_TEST(findNodeInExpandedNamespace) {
 	// given
 	Namespace *ns;
 	Namespace_new(&ns, 0);
+<<<<<<< HEAD
 	const UA_Node* n;
+=======
+	UA_Node* n;
+>>>>>>> origin/master
 	UA_Int32 i=0;
 	for (; i<200; i++) {
 		createNode(&n,0,i); Namespace_insert(ns, &n, 0);
@@ -191,7 +249,11 @@ START_TEST(iterateOverExpandedNamespaceShallNotVisitEmptyNodes) {
 	// given
 	Namespace *ns;
 	Namespace_new(&ns, 0);
+<<<<<<< HEAD
 	const UA_Node* n;
+=======
+	UA_Node* n;
+>>>>>>> origin/master
 	UA_Int32 i=0;
 	for (; i<200; i++) {
 		createNode(&n,0,i); Namespace_insert(ns, &n, 0);
@@ -220,12 +282,21 @@ START_TEST(failToFindNonExistantNodeInNamespaceWithSeveralEntries) {
 	// given
 	Namespace *ns;
 	Namespace_new(&ns, 0);
+<<<<<<< HEAD
 	const UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
 	const UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
 	const UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, 0);
 	const UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
 	const UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
 	const UA_Node* n6; createNode(&n6,0,12); 
+=======
+	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
+	UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, 0);
+	UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
+	UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
+	UA_Node* n6; createNode(&n6,0,12); 
+>>>>>>> origin/master
 
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
@@ -239,6 +310,90 @@ START_TEST(failToFindNonExistantNodeInNamespaceWithSeveralEntries) {
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
+<<<<<<< HEAD
+=======
+}
+END_TEST
+
+/************************************/
+/* Performance Profiling Test Cases */
+/************************************/
+
+#ifdef MULTITHREADING
+struct NamespaceProfileTest {
+	Namespace *ns;
+	UA_Int32 min_val;
+	UA_Int32 max_val;
+	UA_Int32 rounds;
+};
+
+void *profileGetThread(void *arg) {
+   	rcu_register_thread();
+	struct NamespaceProfileTest *test = (struct NamespaceProfileTest*) arg;
+	UA_NodeId id = NS0NODEID(0);
+	const UA_Node *cn;
+	UA_Int32 max_val = test->max_val;
+	Namespace *ns = test->ns;
+	for(UA_Int32 x = 0; x<test->rounds; x++) {
+		for (UA_Int32 i=test->min_val; i<max_val; i++) {
+			id.identifier.numeric = i;
+			Namespace_get(ns,&id, &cn);
+			Namespace_releaseManagedNode(cn);
+		}
+	}
+	rcu_unregister_thread();
+	
+	return UA_NULL;
+}
+#endif
+
+START_TEST(profileGetDelete) {
+#ifdef MULTITHREADING
+   	rcu_register_thread();
+#endif
+
+#define N 1000000
+	Namespace *ns;
+	Namespace_new(&ns, 0);
+	UA_Int32 i=0;
+	UA_Node *n;
+	for (; i<N; i++) {
+		createNode(&n,0,i); Namespace_insert(ns, &n, 0);
+	}
+	clock_t begin, end;
+	begin = clock();
+#ifdef MULTITHREADING
+#define THREADS 4
+    pthread_t t[THREADS];
+	struct NamespaceProfileTest p[THREADS];
+	for (int i = 0; i < THREADS; i++) {
+		p[i] = (struct NamespaceProfileTest){ns, i*(N/THREADS), (i+1)*(N/THREADS), 50};
+		pthread_create(&t[i], NULL, profileGetThread, &p[i]);
+	}
+	for (int i = 0; i < THREADS; i++)
+		pthread_join(t[i], NULL);
+	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 = NS0NODEID(0);
+	for(UA_Int32 x = 0; x<50; x++) {
+	    for(i=0; i<N; i++) {
+	        id.identifier.numeric = i;
+			Namespace_get(ns,&id, &cn);
+			Namespace_releaseManagedNode(cn);
+        }
+    }
+	end = clock();
+	printf("Time for single-threaded %d create/get/delete in a namespace: %fs.\n", N, (double)(end - begin) / CLOCKS_PER_SEC);
+#endif
+
+	Namespace_delete(ns);
+
+#ifdef MULTITHREADING
+	rcu_unregister_thread();
+#endif
+>>>>>>> origin/master
 }
 END_TEST
 
@@ -261,6 +416,10 @@ Suite * namespace_suite (void) {
 	tcase_add_test (tc_iterate, iterateOverNamespaceShallNotVisitEmptyNodes);
 	tcase_add_test (tc_iterate, iterateOverExpandedNamespaceShallNotVisitEmptyNodes);
 	suite_add_tcase (s, tc_iterate);
+	
+	/* TCase* tc_profile = tcase_create ("Profile"); */
+	/* tcase_add_test (tc_profile, profileGetDelete); */
+	/* suite_add_tcase (s, tc_profile); */
 
 	return s;
 }

+ 6 - 5
tools/generate_builtin.py

@@ -10,10 +10,11 @@ import inspect
 import argparse
 
 parser = argparse.ArgumentParser()
-parser.add_argument('types', help='path/to/Opc.Ua.Types.bsd')
-parser.add_argument('outfile', help='outfile w/o extension')
 parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
+parser.add_argument('--with-json', action='store_true', help='generate json encoding')
 parser.add_argument('--only-nano', action='store_true', help='generate only the types for the nano profile')
+parser.add_argument('types', help='path/to/Opc.Ua.Types.bsd')
+parser.add_argument('outfile', help='outfile w/o extension')
 args = parser.parse_args()
         
 ns = {"opc": "http://opcfoundation.org/BinarySchema/"}
@@ -279,8 +280,8 @@ printh('''/**
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  */
 
-#ifndef ''' + sys.argv[2].upper() + '''_H_
-#define ''' + sys.argv[2].upper() + '''_H_
+#ifndef ''' + args.outfile.upper() + '''_H_
+#define ''' + args.outfile.upper() + '''_H_
 
 #include "ua_types.h"
 #include "ua_types_encoding_binary.h"
@@ -296,7 +297,7 @@ printc('''/**
  * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+ time.strftime("%Y-%m-%d %I:%M:%S")+'''
  */
  
-#include "''' + sys.argv[2] + '.h"\n')
+#include "''' + args.outfile + '.h"\n')
 #include "ua_types_encoding_binary.h"
 #include "util/ua_util.h"
 

+ 2 - 1
tools/generate_namespace.py

@@ -8,9 +8,10 @@ import re
 import argparse
 
 parser = argparse.ArgumentParser()
+parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
+parser.add_argument('--with-json', action='store_true', help='generate json encoding')
 parser.add_argument('nodeids', help='path/to/NodeIds.csv')
 parser.add_argument('outfile', help='outfile w/o extension')
-parser.add_argument('--with-xml', action='store_true', help='generate xml encoding')
 args = parser.parse_args()
 
 # types that are to be excluded