Просмотр исходного кода

fixes errors within read/write/nodes

FlorianPalm лет назад: 10
Родитель
Сommit
1558c08885

+ 2 - 2
CMakeLists.txt

@@ -39,6 +39,7 @@ set(lib_sources src/ua_types.c
 				src/server/nodestore/open62541_nodestore_attribute.c
 				src/server/nodestore/open62541_nodestore_nodemanagement.c
 				src/server/nodestore/open62541_nodestore.c
+				src/server/ua_nodestore_interface.c
                 ${headers}
                 ${generated_headers})
 
@@ -113,8 +114,7 @@ if(ENABLE_MULTITHREADING)
     find_package(Threads REQUIRED)
     list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
 else()
-    list(APPEND lib_sources src/server/nodestore/ua_nodestore.c)
-    list(APPEND lib_sources src/server/nodestore/ua_nodestoreExample.c)
+    list(APPEND lib_sources src/server/nodestore/open62541_nodestore.c)
 endif()
 
 add_library(open62541-objects OBJECT ${lib_sources}) # static version that exports all symbols

+ 42 - 111
Makefile

@@ -1,14 +1,10 @@
 # CMAKE generated file: DO NOT EDIT!
-# Generated by "Unix Makefiles" Generator, CMake Version 3.1
+# Generated by "Unix Makefiles" Generator, CMake Version 2.8
 
 # Default target executed when no arguments are given to make.
 default_target: all
 .PHONY : default_target
 
-# Allow only one "make -f Makefile2" at a time, but pass parallelism.
-.NOTPARALLEL:
-.PHONY : .NOTPARALLEL
-
 #=============================================================================
 # Special targets provided by cmake.
 
@@ -34,27 +30,30 @@ cmake_force:
 SHELL = /bin/sh
 
 # The CMake executable.
-CMAKE_COMMAND = /usr/local/bin/cmake
+CMAKE_COMMAND = /usr/bin/cmake
 
 # The command to remove a file.
-RM = /usr/local/bin/cmake -E remove -f
+RM = /usr/bin/cmake -E remove -f
 
 # Escaping for special characters.
 EQUALS = =
 
+# The program to use to edit the cache.
+CMAKE_EDIT_COMMAND = /usr/bin/cmake-gui
+
 # The top-level source directory on which CMake was run.
-CMAKE_SOURCE_DIR = /home/open62541/Downloads/open62541_ext
+CMAKE_SOURCE_DIR = /home/opcua/Downloads/open62541_external_datasource
 
 # The top-level build directory on which CMake was run.
-CMAKE_BINARY_DIR = /home/open62541/Downloads/open62541_ext
+CMAKE_BINARY_DIR = /home/opcua/Downloads/open62541_external_datasource
 
 #=============================================================================
 # Targets provided globally by CMake.
 
 # Special rule for the target edit_cache
 edit_cache:
-	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
-	/usr/local/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
+	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
+	/usr/bin/cmake-gui -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
 .PHONY : edit_cache
 
 # Special rule for the target edit_cache
@@ -64,7 +63,7 @@ edit_cache/fast: edit_cache
 # Special rule for the target rebuild_cache
 rebuild_cache:
 	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
-	/usr/local/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+	/usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
 .PHONY : rebuild_cache
 
 # Special rule for the target rebuild_cache
@@ -73,9 +72,9 @@ rebuild_cache/fast: rebuild_cache
 
 # The main all target
 all: cmake_check_build_system
-	$(CMAKE_COMMAND) -E cmake_progress_start /home/open62541/Downloads/open62541_ext/CMakeFiles /home/open62541/Downloads/open62541_ext/CMakeFiles/progress.marks
+	$(CMAKE_COMMAND) -E cmake_progress_start /home/opcua/Downloads/open62541_external_datasource/CMakeFiles /home/opcua/Downloads/open62541_external_datasource/CMakeFiles/progress.marks
 	$(MAKE) -f CMakeFiles/Makefile2 all
-	$(CMAKE_COMMAND) -E cmake_progress_start /home/open62541/Downloads/open62541_ext/CMakeFiles 0
+	$(CMAKE_COMMAND) -E cmake_progress_start /home/opcua/Downloads/open62541_external_datasource/CMakeFiles 0
 .PHONY : all
 
 # The main clean target
@@ -102,19 +101,6 @@ depend:
 	$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
 .PHONY : depend
 
-#=============================================================================
-# Target rules for targets named exampleClient
-
-# Build rule for target.
-exampleClient: cmake_check_build_system
-	$(MAKE) -f CMakeFiles/Makefile2 exampleClient
-.PHONY : exampleClient
-
-# fast build rule for target.
-exampleClient/fast:
-	$(MAKE) -f CMakeFiles/exampleClient.dir/build.make CMakeFiles/exampleClient.dir/build
-.PHONY : exampleClient/fast
-
 #=============================================================================
 # Target rules for targets named exampleServer
 
@@ -226,30 +212,6 @@ examples/nodestoreAccessExample.c.s:
 	$(MAKE) -f CMakeFiles/exampleServer.dir/build.make CMakeFiles/exampleServer.dir/examples/nodestoreAccessExample.c.s
 .PHONY : examples/nodestoreAccessExample.c.s
 
-examples/opcuaClient.o: examples/opcuaClient.c.o
-.PHONY : examples/opcuaClient.o
-
-# target to build an object file
-examples/opcuaClient.c.o:
-	$(MAKE) -f CMakeFiles/exampleClient.dir/build.make CMakeFiles/exampleClient.dir/examples/opcuaClient.c.o
-.PHONY : examples/opcuaClient.c.o
-
-examples/opcuaClient.i: examples/opcuaClient.c.i
-.PHONY : examples/opcuaClient.i
-
-# target to preprocess a source file
-examples/opcuaClient.c.i:
-	$(MAKE) -f CMakeFiles/exampleClient.dir/build.make CMakeFiles/exampleClient.dir/examples/opcuaClient.c.i
-.PHONY : examples/opcuaClient.c.i
-
-examples/opcuaClient.s: examples/opcuaClient.c.s
-.PHONY : examples/opcuaClient.s
-
-# target to generate assembly for a file
-examples/opcuaClient.c.s:
-	$(MAKE) -f CMakeFiles/exampleClient.dir/build.make CMakeFiles/exampleClient.dir/examples/opcuaClient.c.s
-.PHONY : examples/opcuaClient.c.s
-
 examples/opcuaServer.o: examples/opcuaServer.c.o
 .PHONY : examples/opcuaServer.o
 
@@ -370,54 +332,6 @@ src/server/nodestore/open62541_nodestore_view.c.s:
 	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/open62541_nodestore_view.c.s
 .PHONY : src/server/nodestore/open62541_nodestore_view.c.s
 
-src/server/nodestore/ua_nodestore.o: src/server/nodestore/ua_nodestore.c.o
-.PHONY : src/server/nodestore/ua_nodestore.o
-
-# target to build an object file
-src/server/nodestore/ua_nodestore.c.o:
-	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/ua_nodestore.c.o
-.PHONY : src/server/nodestore/ua_nodestore.c.o
-
-src/server/nodestore/ua_nodestore.i: src/server/nodestore/ua_nodestore.c.i
-.PHONY : src/server/nodestore/ua_nodestore.i
-
-# target to preprocess a source file
-src/server/nodestore/ua_nodestore.c.i:
-	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/ua_nodestore.c.i
-.PHONY : src/server/nodestore/ua_nodestore.c.i
-
-src/server/nodestore/ua_nodestore.s: src/server/nodestore/ua_nodestore.c.s
-.PHONY : src/server/nodestore/ua_nodestore.s
-
-# target to generate assembly for a file
-src/server/nodestore/ua_nodestore.c.s:
-	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/ua_nodestore.c.s
-.PHONY : src/server/nodestore/ua_nodestore.c.s
-
-src/server/nodestore/ua_nodestoreExample.o: src/server/nodestore/ua_nodestoreExample.c.o
-.PHONY : src/server/nodestore/ua_nodestoreExample.o
-
-# target to build an object file
-src/server/nodestore/ua_nodestoreExample.c.o:
-	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/ua_nodestoreExample.c.o
-.PHONY : src/server/nodestore/ua_nodestoreExample.c.o
-
-src/server/nodestore/ua_nodestoreExample.i: src/server/nodestore/ua_nodestoreExample.c.i
-.PHONY : src/server/nodestore/ua_nodestoreExample.i
-
-# target to preprocess a source file
-src/server/nodestore/ua_nodestoreExample.c.i:
-	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/ua_nodestoreExample.c.i
-.PHONY : src/server/nodestore/ua_nodestoreExample.c.i
-
-src/server/nodestore/ua_nodestoreExample.s: src/server/nodestore/ua_nodestoreExample.c.s
-.PHONY : src/server/nodestore/ua_nodestoreExample.s
-
-# target to generate assembly for a file
-src/server/nodestore/ua_nodestoreExample.c.s:
-	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/ua_nodestoreExample.c.s
-.PHONY : src/server/nodestore/ua_nodestoreExample.c.s
-
 src/server/ua_namespace_manager.o: src/server/ua_namespace_manager.c.o
 .PHONY : src/server/ua_namespace_manager.o
 
@@ -442,6 +356,30 @@ src/server/ua_namespace_manager.c.s:
 	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/ua_namespace_manager.c.s
 .PHONY : src/server/ua_namespace_manager.c.s
 
+src/server/ua_nodestore_interface.o: src/server/ua_nodestore_interface.c.o
+.PHONY : src/server/ua_nodestore_interface.o
+
+# target to build an object file
+src/server/ua_nodestore_interface.c.o:
+	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/ua_nodestore_interface.c.o
+.PHONY : src/server/ua_nodestore_interface.c.o
+
+src/server/ua_nodestore_interface.i: src/server/ua_nodestore_interface.c.i
+.PHONY : src/server/ua_nodestore_interface.i
+
+# target to preprocess a source file
+src/server/ua_nodestore_interface.c.i:
+	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/ua_nodestore_interface.c.i
+.PHONY : src/server/ua_nodestore_interface.c.i
+
+src/server/ua_nodestore_interface.s: src/server/ua_nodestore_interface.c.s
+.PHONY : src/server/ua_nodestore_interface.s
+
+# target to generate assembly for a file
+src/server/ua_nodestore_interface.c.s:
+	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/ua_nodestore_interface.c.s
+.PHONY : src/server/ua_nodestore_interface.c.s
+
 src/server/ua_securechannel_manager.o: src/server/ua_securechannel_manager.c.o
 .PHONY : src/server/ua_securechannel_manager.o
 
@@ -953,11 +891,10 @@ help:
 	@echo "... clean"
 	@echo "... depend"
 	@echo "... edit_cache"
-	@echo "... rebuild_cache"
-	@echo "... exampleClient"
-	@echo "... open62541"
 	@echo "... exampleServer"
+	@echo "... open62541"
 	@echo "... open62541-objects"
+	@echo "... rebuild_cache"
 	@echo "... examples/logger_stdout.o"
 	@echo "... examples/logger_stdout.i"
 	@echo "... examples/logger_stdout.s"
@@ -967,9 +904,6 @@ help:
 	@echo "... examples/nodestoreAccessExample.o"
 	@echo "... examples/nodestoreAccessExample.i"
 	@echo "... examples/nodestoreAccessExample.s"
-	@echo "... examples/opcuaClient.o"
-	@echo "... examples/opcuaClient.i"
-	@echo "... examples/opcuaClient.s"
 	@echo "... examples/opcuaServer.o"
 	@echo "... examples/opcuaServer.i"
 	@echo "... examples/opcuaServer.s"
@@ -985,15 +919,12 @@ help:
 	@echo "... src/server/nodestore/open62541_nodestore_view.o"
 	@echo "... src/server/nodestore/open62541_nodestore_view.i"
 	@echo "... src/server/nodestore/open62541_nodestore_view.s"
-	@echo "... src/server/nodestore/ua_nodestore.o"
-	@echo "... src/server/nodestore/ua_nodestore.i"
-	@echo "... src/server/nodestore/ua_nodestore.s"
-	@echo "... src/server/nodestore/ua_nodestoreExample.o"
-	@echo "... src/server/nodestore/ua_nodestoreExample.i"
-	@echo "... src/server/nodestore/ua_nodestoreExample.s"
 	@echo "... src/server/ua_namespace_manager.o"
 	@echo "... src/server/ua_namespace_manager.i"
 	@echo "... src/server/ua_namespace_manager.s"
+	@echo "... src/server/ua_nodestore_interface.o"
+	@echo "... src/server/ua_nodestore_interface.i"
+	@echo "... src/server/ua_nodestore_interface.s"
 	@echo "... src/server/ua_securechannel_manager.o"
 	@echo "... src/server/ua_securechannel_manager.i"
 	@echo "... src/server/ua_securechannel_manager.s"

+ 11 - 11
examples/opcuaServer.c

@@ -17,10 +17,10 @@
 #include "networklayer_tcp.h"
 
 
-#include "../src/server/nodestore/ua_nodestore.h"
+#include "../src/server/ua_nodestore_interface.h"
 #include "../src/server/ua_namespace_manager.h"
 #include "../src/server/nodestore/open62541_nodestore.h"
-#include "../src/server/nodestore/ua_nodestoreExample.h"
+
 UA_Boolean running = UA_TRUE;
 
 
@@ -54,7 +54,7 @@ UA_ByteString loadCertificate() {
 
     return certificate;
 }
-UA_StatusCode UA_EXPORT UA_NodeStoreExample_new(UA_NodeStoreExample **result);
+UA_StatusCode UA_EXPORT open62541NodeStore_new(open62541NodeStore **result);
 
 int main(int argc, char** argv) {
 	signal(SIGINT, stopHandler); /* catches ctrl-c */
@@ -63,14 +63,14 @@ int main(int argc, char** argv) {
 	UA_String endpointUrl;
 	UA_String_copycstring("no endpoint url",&endpointUrl);
 	UA_NodeStore newNodeStore;
-	UA_NodeStoreExample_new(&server.nodestore);
+	open62541NodeStore_new(&server.nodestore);
 
-	Nodestore_set(server.nodestore);
+	open62541NodeStore_setNodeStore(server.nodestore);
 	UA_NamespaceManager_new(&server.namespaceManager);
 	UA_NamespaceManager_addNamespace(server.namespaceManager,0, &newNodeStore);
 	UA_NodeStore_registerReadNodesOperation(&newNodeStore,open62541NodeStore_ReadNodes);
 	UA_NodeStore_registerBrowseNodesOperation(&newNodeStore,open62541NodeStore_BrowseNodes);
-	UA_NodeStore_registerAddNodesOperation(&newNodeStore,open62541Nodestore_addNodes);
+	UA_NodeStore_registerAddNodesOperation(&newNodeStore,open62541NodeStore_AddNodes);
 	//UA_NodeStore_registerWriteNodesOperation(&newNodeStore,writeNodes);
 	UA_Server_init(&server, &endpointUrl);
 
@@ -79,11 +79,11 @@ int main(int argc, char** argv) {
 	Logger_Stdout_init(&server.logger);
     server.serverCertificate = loadCertificate();
 
-    UA_Int32 myInteger = 42;
-    UA_String myIntegerName;
-    UA_STRING_STATIC(myIntegerName, "The Answer");
-    UA_Server_addScalarVariableNode(&server, &myIntegerName, (void*)&myInteger, &UA_[UA_INT32],
-                                    &server.objectsNodeId, &server.hasComponentReferenceTypeId);
+//    UA_Int32 myInteger = 42;
+//    UA_String myIntegerName;
+//    UA_STRING_STATIC(myIntegerName, "The Answer");
+//    UA_Server_addScalarVariableNode(&server, &myIntegerName, (void*)&myInteger, &UA_[UA_INT32],
+//                                    &server.objectsNodeId, &server.hasComponentReferenceTypeId);
 
 #ifdef BENCHMARK
     UA_UInt32 nodeCount = 500;

+ 7 - 7
include/ua_server.h

@@ -40,8 +40,8 @@ typedef struct UA_SessionManager UA_SessionManager;
 struct UA_NodeStore;
 typedef struct UA_NodeStore UA_NodeStore;
 
-struct UA_NodeStoreExample;
-typedef struct UA_NodeStoreExample UA_NodeStoreExample;
+struct open62541NodeStore;
+typedef struct open62541NodeStore open62541NodeStore;
 
 //struct UA_Namespace;
 //typedef struct UA_Namespace UA_Namespace;
@@ -80,7 +80,7 @@ typedef struct UA_Server {
 	UA_SecureChannelManager *secureChannelManager;
 	UA_SessionManager *sessionManager;
 	UA_NamespaceManager* namespaceManager;
-	UA_NodeStoreExample *nodestore;
+	open62541NodeStore *nodestore;
 	UA_Logger logger;
 	UA_ByteString serverCertificate;
 
@@ -98,10 +98,10 @@ void UA_EXPORT UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *
 UA_AddNodesResult UA_EXPORT UA_Server_addScalarVariableNode(UA_Server *server, UA_String *browseName, void *value,
 		const UA_VTable_Entry *vt, UA_ExpandedNodeId *parentNodeId,
 		UA_NodeId *referenceTypeId );
-UA_AddNodesResult UA_EXPORT UA_Server_addNode(UA_Server *server, UA_Node **node, UA_ExpandedNodeId *parentNodeId,
-		UA_NodeId *referenceTypeId);
-void UA_EXPORT UA_Server_addReferences(UA_Server *server, const UA_AddReferencesRequest *request,
-		UA_AddReferencesResponse *response);
+//UA_AddNodesResult UA_EXPORT UA_Server_addNode(UA_Server *server, UA_Node **node, UA_ExpandedNodeId *parentNodeId,
+//		UA_NodeId *referenceTypeId);
+//void UA_EXPORT UA_Server_addReferences(UA_Server *server, const UA_AddReferencesRequest *request,
+//		UA_AddReferencesResponse *response);
 
 UA_Int32 UA_EXPORT UA_Server_addNamespace(UA_Server *server, UA_UInt16 namespaceIndex, UA_NodeStore *nodeStore);
 

+ 359 - 10
src/server/nodestore/open62541_nodestore.c

@@ -1,17 +1,366 @@
-/*
- * open62541_nodestore.c
- *
- *  Created on: Oct 27, 2014
- *      Author: opcua
- */
-
 #include "open62541_nodestore.h"
-static UA_NodeStoreExample *open62541_nodestore;
+#include "ua_util.h"
+#include "ua_statuscodes.h"
+
+struct open62541NodeStore {
+	const UA_Node **entries;
+	UA_UInt32 size;
+	UA_UInt32 count;
+	UA_UInt32 sizePrimeIndex;
+};
+
 
-void Nodestore_set(UA_NodeStoreExample *nodestore){
+
+static open62541NodeStore *open62541_nodestore;
+
+void open62541NodeStore_setNodeStore(open62541NodeStore *nodestore){
 	open62541_nodestore = nodestore;
 }
 
-UA_NodeStoreExample *Nodestore_get(){
+open62541NodeStore *open62541NodeStore_getNodeStore(){
 	return open62541_nodestore;
 }
+
+
+
+typedef UA_UInt32 hash_t;
+/* The size of the hash-map is always a prime number. They are chosen to be
+ close to the next power of 2. So the size ca. doubles with each prime. */
+static hash_t const primes[] = { 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093,
+		8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
+		4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399,
+		536870909, 1073741789, 2147483647, 4294967291 };
+
+static INLINE hash_t mod(hash_t h, hash_t size) {
+	return h % size;
+}
+static INLINE hash_t mod2(hash_t h, hash_t size) {
+	return 1 + (h % (size - 2));
+}
+
+static INLINE UA_Int16 higher_prime_index(hash_t n) {
+	UA_UInt16 low = 0;
+	UA_UInt16 high = sizeof(primes) / sizeof(hash_t);
+	while (low != high) {
+		UA_UInt16 mid = low + (high - low) / 2;
+		if (n > primes[mid])
+			low = mid + 1;
+		else
+			high = mid;
+	}
+	return low;
+}
+
+/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
+static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len,
+		UA_UInt32 seed) {
+	const int32_t nblocks = len / 4;
+	const uint32_t *blocks;
+
+	static const uint32_t c1 = 0xcc9e2d51;
+	static const uint32_t c2 = 0x1b873593;
+	static const uint32_t r1 = 15;
+	static const uint32_t r2 = 13;
+	static const uint32_t m = 5;
+	static const uint32_t n = 0xe6546b64;
+	hash_t hash = seed;
+
+	if (data == UA_NULL)
+		return 0;
+
+	blocks = (const uint32_t *) data;
+	for (int32_t i = 0; i < nblocks; i++) {
+		uint32_t k = blocks[i];
+		k *= c1;
+		k = (k << r1) | (k >> (32 - r1));
+		k *= c2;
+		hash ^= k;
+		hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
+	}
+
+	const uint8_t *tail = (const uint8_t *) (data + nblocks * 4);
+	uint32_t k1 = 0;
+
+	switch (len & 3) {
+	case 3:
+		k1 ^= tail[2] << 16;
+
+	case 2:
+		k1 ^= tail[1] << 8;
+
+	case 1:
+		k1 ^= tail[0];
+		k1 *= c1;
+		k1 = (k1 << r1) | (k1 >> (32 - r1));
+		k1 *= c2;
+		hash ^= k1;
+	}
+
+	hash ^= len;
+	hash ^= (hash >> 16);
+	hash *= 0x85ebca6b;
+	hash ^= (hash >> 13);
+	hash *= 0xc2b2ae35;
+	hash ^= (hash >> 16);
+
+	return hash;
+}
+
+static INLINE hash_t hash(const UA_NodeId *n) {
+	switch (n->identifierType) {
+	case UA_NODEIDTYPE_NUMERIC:
+		/*  Knuth's multiplicative hashing */
+		return (n->identifier.numeric + n->namespaceIndex) * 2654435761; // mod(2^32) is implicit
+
+	case UA_NODEIDTYPE_STRING:
+		return hash_array(n->identifier.string.data,
+				n->identifier.string.length, n->namespaceIndex);
+
+	case UA_NODEIDTYPE_GUID:
+		return hash_array((UA_Byte *) &(n->identifier.guid), sizeof(UA_Guid),
+				n->namespaceIndex);
+
+	case UA_NODEIDTYPE_BYTESTRING:
+		return hash_array((UA_Byte *) n->identifier.byteString.data,
+				n->identifier.byteString.length, n->namespaceIndex);
+
+	default:
+		UA_assert(UA_FALSE);
+		return 0;
+	}
+}
+
+static INLINE void clear_entry(open62541NodeStore *ns, const UA_Node **entry) {
+	const UA_Node *node;
+	if (entry == UA_NULL || *entry == UA_NULL)
+		return;
+
+	node = *entry;
+	switch (node->nodeClass) {
+	case UA_NODECLASS_OBJECT:
+		UA_ObjectNode_delete((UA_ObjectNode *) node);
+		break;
+
+	case UA_NODECLASS_VARIABLE:
+		UA_VariableNode_delete((UA_VariableNode *) node);
+		break;
+
+	case UA_NODECLASS_METHOD:
+		UA_MethodNode_delete((UA_MethodNode *) node);
+		break;
+
+	case UA_NODECLASS_OBJECTTYPE:
+		UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) node);
+		break;
+
+	case UA_NODECLASS_VARIABLETYPE:
+		UA_VariableTypeNode_delete((UA_VariableTypeNode *) node);
+		break;
+
+	case UA_NODECLASS_REFERENCETYPE:
+		UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) node);
+		break;
+
+	case UA_NODECLASS_DATATYPE:
+		UA_DataTypeNode_delete((UA_DataTypeNode *) node);
+		break;
+
+	case UA_NODECLASS_VIEW:
+		UA_ViewNode_delete((UA_ViewNode *) node);
+		break;
+
+	default:
+		UA_assert(UA_FALSE);
+		break;
+	}
+	entry = UA_NULL;
+	ns->count--;
+}
+
+/* Returns UA_SUCCESS if an entry was found. Otherwise, UA_ERROR is returned and the "entry"
+ argument points to the first free entry under the NodeId. */
+static INLINE UA_StatusCode find_entry(const open62541NodeStore *ns,
+		const UA_NodeId *nodeid, const UA_Node ***entry) {
+	hash_t h = hash(nodeid);
+	UA_UInt32 size = ns->size;
+	hash_t index = mod(h, size);
+	const UA_Node **e = &ns->entries[index];
+
+	if (*e == UA_NULL) {
+		*entry = e;
+		return UA_STATUSCODE_BADINTERNALERROR;
+	}
+
+	if (UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
+		*entry = e;
+		return UA_STATUSCODE_GOOD;
+	}
+
+	hash_t hash2 = mod2(h, size);
+	for (;;) {
+		index += hash2;
+		if (index >= size)
+			index -= size;
+
+		e = &ns->entries[index];
+
+		if (*e == UA_NULL) {
+			*entry = e;
+			return UA_STATUSCODE_BADINTERNALERROR;
+		}
+
+		if (UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
+			*entry = e;
+			return UA_STATUSCODE_GOOD;
+		}
+	}
+
+	/* NOTREACHED */
+	return UA_STATUSCODE_GOOD;
+}
+
+/* The following function changes size of memory allocated for the entries and
+ repeatedly inserts the table elements. The occupancy of the table after the
+ call will be about 50%. If memory allocation failures occur, this function
+ will return UA_ERROR. */
+static UA_StatusCode expand(open62541NodeStore *ns) {
+	const UA_Node **nentries;
+	int32_t nsize;
+	UA_UInt32 nindex;
+
+	const UA_Node **oentries = ns->entries;
+	int32_t osize = ns->size;
+	const UA_Node **olimit = &oentries[osize];
+	int32_t count = ns->count;
+
+	/* Resize only when table after removal of unused elements is either too full or too empty.  */
+	if (count * 2 < osize && (count * 8 > osize || osize <= 32))
+		return UA_STATUSCODE_GOOD;
+
+	nindex = higher_prime_index(count * 2);
+	nsize = primes[nindex];
+
+	if (!(nentries = UA_alloc(sizeof(UA_Node *) * nsize)))
+		return UA_STATUSCODE_BADOUTOFMEMORY;
+
+	memset(nentries, 0, nsize * sizeof(UA_Node *));
+	ns->entries = nentries;
+	ns->size = nsize;
+	ns->sizePrimeIndex = nindex;
+
+	const UA_Node **p = oentries;
+	do {
+		if (*p != UA_NULL) {
+			const UA_Node **e;
+			find_entry(ns, &(*p)->nodeId, &e); /* We know this returns an empty entry here */
+			*e = *p;
+		}
+		p++;
+	} while (p < olimit);
+
+	UA_free(oentries);
+	return UA_STATUSCODE_GOOD;
+}
+
+/**********************/
+/* Exported functions */
+/**********************/
+
+UA_StatusCode open62541NodeStore_new(open62541NodeStore **result) {
+	open62541NodeStore *ns;
+	UA_UInt32 sizePrimeIndex, size;
+	if (!(ns = UA_alloc(sizeof(UA_NodeStore))))
+		return UA_STATUSCODE_BADOUTOFMEMORY;
+
+	sizePrimeIndex = higher_prime_index(32);
+	size = primes[sizePrimeIndex];
+	if (!(ns->entries = UA_alloc(sizeof(UA_Node *) * size))) {
+		UA_free(ns);
+		return UA_STATUSCODE_BADOUTOFMEMORY;
+	}
+
+	/* set entries to zero */
+	memset(ns->entries, 0, size * sizeof(UA_Node *));
+
+	*ns = (open62541NodeStore ) { ns->entries, size, 0, sizePrimeIndex };
+	*result = ns;
+	return UA_STATUSCODE_GOOD;
+}
+
+void open62541NodeStore_delete(open62541NodeStore *ns) {
+	UA_UInt32 size = ns->size;
+	const UA_Node **entries = ns->entries;
+
+	for (UA_UInt32 i = 0; i < size; i++)
+		clear_entry(ns, &entries[i]);
+
+	UA_free(ns->entries);
+	UA_free(ns);
+}
+
+UA_StatusCode open62541NodeStore_insert(open62541NodeStore *ns, UA_Node **node,
+		UA_Byte flags) {
+	if (ns->size * 3 <= ns->count * 4) {
+		if (expand(ns) != UA_STATUSCODE_GOOD)
+			return UA_STATUSCODE_BADINTERNALERROR;
+	}
+
+	const UA_Node **entry;
+	UA_Int32 found = find_entry(ns, &(*node)->nodeId, &entry);
+
+	if (flags & UA_NODESTORE_INSERT_UNIQUE) {
+		if (found == UA_STATUSCODE_GOOD)
+			return UA_STATUSCODE_BADNODEIDEXISTS;
+		else
+			*entry = *node;
+	} else {
+		if (found == UA_STATUSCODE_GOOD)
+			clear_entry(ns, entry);
+		*entry = *node;
+	}
+
+	if (!(flags & UA_NODESTORE_INSERT_GETMANAGED))
+		*node = UA_NULL;
+
+	ns->count++;
+	return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode open62541NodeStore_get(const open62541NodeStore *ns,
+		const UA_NodeId *nodeid, const UA_Node **managedNode) {
+	const UA_Node **entry;
+	if (find_entry(ns, nodeid, &entry) != UA_STATUSCODE_GOOD)
+		return UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+	*managedNode = *entry;
+	return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode open62541NodeStore_remove(open62541NodeStore *ns,
+		const UA_NodeId *nodeid) {
+	const UA_Node **entry;
+	if (find_entry(ns, nodeid, &entry) != UA_STATUSCODE_GOOD)
+		return UA_STATUSCODE_BADNODEIDUNKNOWN;
+
+	// Check before if deleting the node makes the UA_NodeStore inconsistent.
+	clear_entry(ns, entry);
+
+	/* Downsize the hashmap if it is very empty */
+	if (ns->count * 8 < ns->size && ns->size > 32)
+		expand(ns); // this can fail. we just continue with the bigger hashmap.
+
+	return UA_STATUSCODE_GOOD;
+}
+
+void open62541NodeStore_iterate(const open62541NodeStore *ns,
+		UA_NodeStore_nodeVisitor visitor) {
+	for (UA_UInt32 i = 0; i < ns->size; i++) {
+		const UA_Node *node = ns->entries[i];
+		if (node != UA_NULL)
+			visitor(node);
+	}
+}
+
+void open62541NodeStore_releaseManagedNode(const UA_Node *managed) {
+	;
+}

+ 72 - 17
src/server/nodestore/open62541_nodestore.h

@@ -1,28 +1,83 @@
-/*
- * open62541_nodestore.h
- *
- *  Created on: Oct 27, 2014
- *      Author: opcua
+#ifndef UA_OPEN62541_NODESTORE_H_
+#define UA_OPEN62541_NODESTORE_H_
+
+#include "ua_server.h"
+#include "ua_config.h"
+/**
+ @ingroup server
+
+ @defgroup nodestore NodeStore
+
+ @brief The nodestore is the central storage for nodes in the UA address
+ space. Internally, the nodestore is realised as hash-map where nodes are
+ stored and retrieved with their nodeid.
+
+ The nodes in the nodestore 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.
+
+ @{
  */
 
-#ifndef OPEN62541_NODESTORE_H_
-#define OPEN62541_NODESTORE_H_
+void UA_EXPORT open62541NodeStore_setNodeStore(open62541NodeStore *nodestore);
+open62541NodeStore UA_EXPORT *open62541NodeStore_getNodeStore();
 
+/** @brief Create a new namespace */
+UA_StatusCode UA_EXPORT open62541NodeStore_new(open62541NodeStore **result);
 
+/** @brief Delete the namespace and all nodes in it */
+void open62541NodeStore_delete(open62541NodeStore *ns);
 
+#define UA_NODESTORE_INSERT_UNIQUE 1
+#define UA_NODESTORE_INSERT_GETMANAGED 2
+/** @brief Insert a new node into the namespace
 
-#include "ua_server.h"
+ 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_StatusCode open62541NodeStore_insert(open62541NodeStore *ns, UA_Node **node,
+		UA_Byte flags);
 
+/** @brief Remove a node from the namespace. Always succeeds, even if the node
+ was not found. */
+UA_StatusCode open62541NodeStore_remove(open62541NodeStore *ns,
+		const UA_NodeId *nodeid);
 
-void UA_EXPORT Nodestore_set(UA_NodeStoreExample *nodestore);
-UA_NodeStoreExample UA_EXPORT *Nodestore_get();
+/** @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_StatusCode open62541NodeStore_get(const open62541NodeStore *ns,
+		const UA_NodeId *nodeid, const UA_Node **managedNode);
 
+/** @brief Release a managed node. Do never insert a node that isn't stored in a
+ namespace. */
+void open62541NodeStore_releaseManagedNode(const UA_Node *managed);
 
-UA_Int32 UA_EXPORT open62541NodeStore_ReadNodes(UA_ReadValueId *readValueIds,UA_UInt32 *indices,UA_UInt32 indicesSize,UA_DataValue *readNodesResults, UA_Boolean timeStampToReturn, UA_DiagnosticInfo *diagnosticInfos);
-UA_Int32 UA_EXPORT open62541NodeStore_BrowseNodes(UA_BrowseDescription *browseDescriptions,UA_UInt32 *indices,UA_UInt32 indicesSize, UA_UInt32 requestedMaxReferencesPerNode,
-		UA_BrowseResult *browseResults,
-		UA_DiagnosticInfo *diagnosticInfos);
-UA_Int32 UA_EXPORT open62541Nodestore_addNodes(UA_AddNodesItem *nodesToAdd,UA_UInt32 *indices,
-		UA_UInt32 indicesSize, UA_AddNodesResult* addNodesResults,
+/** @brief A function that can be evaluated on all entries in a namespace via
+ UA_NodeStore_iterate. Note that the visitor is read-only on the nodes. */
+typedef void (*UA_NodeStore_nodeVisitor)(const UA_Node *node);
+
+/** @brief Iterate over all nodes in a namespace. */
+void open62541NodeStore_iterate(const open62541NodeStore *ns,
+		UA_NodeStore_nodeVisitor visitor);
+
+/// @} /* end of group */
+
+//service implementations
+UA_Int32 UA_EXPORT open62541NodeStore_ReadNodes(UA_ReadValueId *readValueIds,
+		UA_UInt32 *indices, UA_UInt32 indicesSize,
+		UA_DataValue *readNodesResults, UA_Boolean timeStampToReturn,
 		UA_DiagnosticInfo *diagnosticInfos);
-#endif /* OPEN62541_NODESTORE_H_ */
+
+UA_Int32 UA_EXPORT open62541NodeStore_BrowseNodes(
+		UA_BrowseDescription *browseDescriptions, UA_UInt32 *indices,
+		UA_UInt32 indicesSize, UA_UInt32 requestedMaxReferencesPerNode,
+		UA_BrowseResult *browseResults, UA_DiagnosticInfo *diagnosticInfos);
+
+UA_Int32 UA_EXPORT open62541NodeStore_AddNodes(UA_AddNodesItem *nodesToAdd,
+		UA_UInt32 *indices, UA_UInt32 indicesSize,
+		UA_AddNodesResult* addNodesResults, UA_DiagnosticInfo *diagnosticInfos);
+
+#endif /* UA_OPEN62541_NODESTORE_H_ */

+ 9 - 9
src/server/nodestore/open62541_nodestore_attribute.c

@@ -4,7 +4,7 @@
  *  Created on: Oct 27, 2014
  *      Author: opcua
  */
-#include "ua_nodestoreExample.h"
+
 #include "../ua_services.h"
 #include "open62541_nodestore.h"
 #include "ua_namespace_0.h"
@@ -22,8 +22,8 @@ static UA_DataValue service_read_node(UA_Server *server, const UA_ReadValueId *i
     UA_DataValue_init(&v);
 
     UA_Node const *node   = UA_NULL;
-    UA_NodeStoreExample *ns =  Nodestore_get();
-    UA_Int32       result = UA_NodeStoreExample_get(ns, &(id->nodeId), &node);
+    open62541NodeStore *ns =  open62541NodeStore_getNodeStore();
+    UA_Int32       result = open62541NodeStore_get(ns, &(id->nodeId), &node);
     if(result != UA_STATUSCODE_GOOD || node == UA_NULL) {
         v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
         v.status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -38,9 +38,9 @@ static UA_DataValue service_read_node(UA_Server *server, const UA_ReadValueId *i
         break;
 
     case UA_ATTRIBUTEID_NODECLASS:
-        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v.value, &UA_[UA_INT32], &node->nodeClass);
 
+        retval |= UA_Variant_copySetValue(&v.value, &UA_[UA_INT32], &node->nodeClass);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
         break;
 
     case UA_ATTRIBUTEID_BROWSENAME:
@@ -184,7 +184,7 @@ static UA_DataValue service_read_node(UA_Server *server, const UA_ReadValueId *i
         break;
     }
 
-    UA_NodeStoreExample_releaseManagedNode(node);
+    open62541NodeStore_releaseManagedNode(node);
 
     if(retval != UA_STATUSCODE_GOOD) {
         v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
@@ -204,10 +204,10 @@ UA_Int32 open62541NodeStore_ReadNodes(UA_ReadValueId *readValueIds,UA_UInt32 *in
 }
 
 
-static UA_StatusCode Service_Write_writeNode(UA_NodeStoreExample *nodestore, UA_WriteValue *writeValue) {
+static UA_StatusCode Service_Write_writeNode(open62541NodeStore *nodestore, UA_WriteValue *writeValue) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     const UA_Node *node;
-    retval = UA_NodeStoreExample_get(nodestore, &writeValue->nodeId, &node);
+    retval = open62541NodeStore_get(nodestore, &writeValue->nodeId, &node);
     if(retval)
         return retval;
 
@@ -330,7 +330,7 @@ static UA_StatusCode Service_Write_writeNode(UA_NodeStoreExample *nodestore, UA_
         break;
     }
 
-    UA_NodeStoreExample_releaseManagedNode(node);
+    open62541NodeStore_releaseManagedNode(node);
     return retval;
 
 }

+ 11 - 11
src/server/nodestore/open62541_nodestore_nodemanagement.c

@@ -4,7 +4,7 @@
  *  Created on: Oct 27, 2014
  *      Author: opcua
  */
-#include "ua_nodestoreExample.h"
+
 #include "../ua_services.h"
 #include "open62541_nodestore.h"
 #include "ua_namespace_0.h"
@@ -36,7 +36,7 @@ static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
 	return UA_STATUSCODE_GOOD;
 }
 
-static UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
+static UA_Int32 AddReference(open62541NodeStore *nodestore, UA_Node *node,
 		UA_ReferenceNode *reference) {
 	UA_Int32 retval = AddSingleReference(node, reference);
 	UA_Node *targetnode;
@@ -45,7 +45,7 @@ static UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
 		return retval;
 
 	// Do a copy every time?
-	if (UA_NodeStoreExample_get(nodestore, &reference->targetId.nodeId,
+	if (open62541NodeStore_get(nodestore, &reference->targetId.nodeId,
 			(const UA_Node **) &targetnode) != UA_STATUSCODE_GOOD)
 		return UA_STATUSCODE_BADINTERNALERROR;
 
@@ -55,7 +55,7 @@ static UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
 	inversereference.targetId.namespaceUri = UA_STRING_NULL;
 	inversereference.targetId.serverIndex = 0;
 	retval = AddSingleReference(targetnode, &inversereference);
-	UA_NodeStoreExample_releaseManagedNode(targetnode);
+	open62541NodeStore_releaseManagedNode(targetnode);
 
 	return retval;
 }
@@ -165,8 +165,8 @@ UA_Int32 open62541NodeStore_addReferences(UA_AddReferencesItem* referencesToAdd,
 {
 	for(UA_UInt32 i = 0;i<indicesSize;i++){
 		UA_Node *node = UA_NULL;
-		UA_NodeStoreExample *ns = Nodestore_get();
-		UA_NodeStoreExample_get((const UA_NodeStoreExample*)ns,(const UA_NodeId*)&referencesToAdd[indices[i]].sourceNodeId, (const UA_Node**)&node);
+		open62541NodeStore *ns = open62541NodeStore_getNodeStore();
+		open62541NodeStore_get((const open62541NodeStore*)ns,(const UA_NodeId*)&referencesToAdd[indices[i]].sourceNodeId, (const UA_Node**)&node);
 		if(node == UA_NULL){
 			addReferencesResults[indices[i]] = UA_STATUSCODE_BADSOURCENODEIDINVALID;
 			continue;
@@ -199,7 +199,7 @@ UA_Int32 open62541NodeStore_addReferences(UA_AddReferencesItem* referencesToAdd,
 UA_Boolean isRootNode(UA_NodeId *nodeId){
 	return nodeId->identifierType == UA_NODEIDTYPE_NUMERIC && nodeId->namespaceIndex == 0 && nodeId->identifier.numeric == 84;
 }
-UA_Int32 open62541Nodestore_addNodes(UA_AddNodesItem *nodesToAdd,UA_UInt32 *indices,
+UA_Int32 open62541NodeStore_AddNodes(UA_AddNodesItem *nodesToAdd,UA_UInt32 *indices,
 		UA_UInt32 indicesSize, UA_AddNodesResult* addNodesResults,
 		UA_DiagnosticInfo *diagnosticInfos){
 
@@ -208,15 +208,15 @@ UA_Int32 open62541Nodestore_addNodes(UA_AddNodesItem *nodesToAdd,UA_UInt32 *indi
 
 		const UA_Node *parent;
 		//todo what if node is in another namespace, readrequest to test, if it exists?
-		UA_NodeStoreExample *ns = Nodestore_get();
-		if (UA_NodeStoreExample_get(ns, &nodesToAdd->parentNodeId.nodeId,
+		open62541NodeStore *ns = open62541NodeStore_getNodeStore();
+		if (open62541NodeStore_get(ns, &nodesToAdd->parentNodeId.nodeId,
 				&parent) != UA_STATUSCODE_GOOD && !isRootNode(&nodesToAdd->parentNodeId.nodeId)) {
 			addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
 			continue;
 		}
 
 
-		UA_NodeStoreExample_get((const UA_NodeStoreExample*)ns, (const UA_NodeId*)&nodesToAdd[indices[i]].requestedNewNodeId.nodeId , (const UA_Node**)&node);
+		open62541NodeStore_get((const open62541NodeStore*)ns, (const UA_NodeId*)&nodesToAdd[indices[i]].requestedNewNodeId.nodeId , (const UA_Node**)&node);
 
 
 		if(node!=UA_NULL){
@@ -296,7 +296,7 @@ UA_Int32 open62541Nodestore_addNodes(UA_AddNodesItem *nodesToAdd,UA_UInt32 *indi
 		addRefItem.targetNodeClass = newNode->nodeClass;
 
 
-		UA_NodeStoreExample_insert(ns, (UA_Node**) &newNode,
+		open62541NodeStore_insert(ns, (UA_Node**) &newNode,
 				UA_NODESTORE_INSERT_UNIQUE);
 		if (!isRootNode(&nodesToAdd[indices[i]].requestedNewNodeId.nodeId)) {
 			UA_UInt32 ind = 0;

+ 13 - 15
src/server/nodestore/open62541_nodestore_view.c

@@ -4,18 +4,16 @@
  *  Created on: Oct 27, 2014
  *      Author: opcua
  */
-#include "ua_nodestoreExample.h"
-#include "../ua_services.h"
 #include "open62541_nodestore.h"
 #include "../ua_services.h"
 #include "ua_namespace_0.h"
 #include "ua_util.h"
 
-UA_Int32 Service_Browse_getReferenceDescription(UA_NodeStoreExample *ns, UA_ReferenceNode *reference,
+UA_Int32 Service_Browse_getReferenceDescription(open62541NodeStore *ns, UA_ReferenceNode *reference,
                                                 UA_UInt32 nodeClassMask, UA_UInt32 resultMask,
                                                 UA_ReferenceDescription *referenceDescription) {
     const UA_Node *foundNode;
-    if(UA_NodeStoreExample_get(ns, &reference->targetId.nodeId, &foundNode) != UA_STATUSCODE_GOOD)
+    if(open62541NodeStore_get(ns, &reference->targetId.nodeId, &foundNode) != UA_STATUSCODE_GOOD)
     	return UA_STATUSCODE_BADINTERNALERROR;
 
     UA_NodeId_copy(&foundNode->nodeId, &referenceDescription->nodeId.nodeId);
@@ -50,7 +48,7 @@ UA_Int32 Service_Browse_getReferenceDescription(UA_NodeStoreExample *ns, UA_Refe
         }
     }
  end:
-    UA_NodeStoreExample_releaseManagedNode(foundNode);
+    open62541NodeStore_releaseManagedNode(foundNode);
     return UA_STATUSCODE_GOOD;
 }
 
@@ -61,7 +59,7 @@ struct SubRefTypeId {
 };
 SLIST_HEAD(SubRefTypeIdList, SubRefTypeId);
 
-static UA_UInt32 walkReferenceTree(UA_NodeStoreExample *ns, const UA_ReferenceTypeNode *current,
+static UA_UInt32 walkReferenceTree(open62541NodeStore *ns, const UA_ReferenceTypeNode *current,
                                    struct SubRefTypeIdList *list) {
     // insert the current referencetype
     struct SubRefTypeId *element = UA_alloc(sizeof(struct SubRefTypeId));
@@ -75,10 +73,10 @@ static UA_UInt32 walkReferenceTree(UA_NodeStoreExample *ns, const UA_ReferenceTy
         if(current->references[i].referenceTypeId.identifier.numeric == 45 /* HasSubtype */ &&
            current->references[i].isInverse == UA_FALSE) {
             const UA_Node *node;
-            if(UA_NodeStoreExample_get(ns, &current->references[i].targetId.nodeId, &node) == UA_STATUSCODE_GOOD
+            if(open62541NodeStore_get(ns, &current->references[i].targetId.nodeId, &node) == UA_STATUSCODE_GOOD
                && node->nodeClass == UA_NODECLASS_REFERENCETYPE) {
                 count += walkReferenceTree(ns, (UA_ReferenceTypeNode *)node, list);
-                UA_NodeStoreExample_releaseManagedNode(node);
+                open62541NodeStore_releaseManagedNode(node);
             }
         }
     }
@@ -86,7 +84,7 @@ static UA_UInt32 walkReferenceTree(UA_NodeStoreExample *ns, const UA_ReferenceTy
 }
 
 /* We do not search across namespaces so far. The id of the father-referencetype is returned in the array also. */
-static UA_Int32 findSubReferenceTypes(UA_NodeStoreExample *ns, UA_NodeId *rootReferenceType,
+static UA_Int32 findSubReferenceTypes(open62541NodeStore *ns, UA_NodeId *rootReferenceType,
                                       UA_NodeId **ids, UA_UInt32 *idcount) {
     struct SubRefTypeIdList list;
     UA_UInt32 count;
@@ -95,11 +93,11 @@ static UA_Int32 findSubReferenceTypes(UA_NodeStoreExample *ns, UA_NodeId *rootRe
     // walk the tree
     const UA_ReferenceTypeNode *root;
 
-    if(UA_NodeStoreExample_get(ns, rootReferenceType, (const UA_Node **)&root) != UA_STATUSCODE_GOOD ||
+    if(open62541NodeStore_get(ns, rootReferenceType, (const UA_Node **)&root) != UA_STATUSCODE_GOOD ||
        root->nodeClass != UA_NODECLASS_REFERENCETYPE)
         return UA_STATUSCODE_BADINTERNALERROR;
     count = walkReferenceTree(ns, root, &list);
-    UA_NodeStoreExample_releaseManagedNode((const UA_Node *)root);
+    open62541NodeStore_releaseManagedNode((const UA_Node *)root);
 
     // copy results into an array
     *ids = UA_alloc(sizeof(UA_NodeId)*count);
@@ -133,14 +131,14 @@ static INLINE UA_Boolean Service_Browse_returnReference(UA_BrowseDescription *br
 }
 
 /* Return results to a single browsedescription. */
-static void NodeStore_Browse_getBrowseResult(UA_NodeStoreExample         *ns,
+static void NodeStore_Browse_getBrowseResult(open62541NodeStore         *ns,
                                            UA_BrowseDescription *browseDescription,
                                            UA_UInt32             maxReferences,
                                            UA_BrowseResult      *browseResult) {
     const UA_Node *node;
     UA_NodeId     *relevantReferenceTypes = UA_NULL;
     UA_UInt32      relevantReferenceTypesCount = 0;
-    if(UA_NodeStoreExample_get(ns, &browseDescription->nodeId, &node) != UA_STATUSCODE_GOOD) {
+    if(open62541NodeStore_get(ns, &browseDescription->nodeId, &node) != UA_STATUSCODE_GOOD) {
         browseResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return;
     }
@@ -197,7 +195,7 @@ static void NodeStore_Browse_getBrowseResult(UA_NodeStoreExample         *ns,
         // Todo. Set the Statuscode and the continuation point.
     }
 
-    UA_NodeStoreExample_releaseManagedNode(node);
+    open62541NodeStore_releaseManagedNode(node);
     UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesCount, &UA_[UA_NODEID]);
 }
 
@@ -207,7 +205,7 @@ UA_Int32 open62541NodeStore_BrowseNodes(UA_BrowseDescription *browseDescriptions
 
 
 	for(UA_UInt32 i = 0; i < indicesSize; i++){
-		NodeStore_Browse_getBrowseResult(Nodestore_get(),&browseDescriptions[indices[i]],requestedMaxReferencesPerNode, &browseResults[indices[i]]);
+		NodeStore_Browse_getBrowseResult(open62541NodeStore_getNodeStore(),&browseDescriptions[indices[i]],requestedMaxReferencesPerNode, &browseResults[indices[i]]);
 	}
 	return UA_STATUSCODE_GOOD;
 }

+ 0 - 352
src/server/nodestore/ua_nodestoreExample.c

@@ -1,352 +0,0 @@
-#include "ua_nodestoreExample.h"
-#include "ua_util.h"
-#include "ua_statuscodes.h"
-
-struct UA_NodeStoreExample {
-	const UA_Node **entries;
-	UA_UInt32 size;
-	UA_UInt32 count;
-	UA_UInt32 sizePrimeIndex;
-};
-
-typedef UA_UInt32 hash_t;
-/* The size of the hash-map is always a prime number. They are chosen to be
- close to the next power of 2. So the size ca. doubles with each prime. */
-static hash_t const primes[] = { 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093,
-		8191, 16381, 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
-		4194301, 8388593, 16777213, 33554393, 67108859, 134217689, 268435399,
-		536870909, 1073741789, 2147483647, 4294967291 };
-
-static INLINE hash_t mod(hash_t h, hash_t size) {
-	return h % size;
-}
-static INLINE hash_t mod2(hash_t h, hash_t size) {
-	return 1 + (h % (size - 2));
-}
-
-static INLINE UA_Int16 higher_prime_index(hash_t n) {
-	UA_UInt16 low = 0;
-	UA_UInt16 high = sizeof(primes) / sizeof(hash_t);
-	while (low != high) {
-		UA_UInt16 mid = low + (high - low) / 2;
-		if (n > primes[mid])
-			low = mid + 1;
-		else
-			high = mid;
-	}
-	return low;
-}
-
-/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
-static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len,
-		UA_UInt32 seed) {
-	const int32_t nblocks = len / 4;
-	const uint32_t *blocks;
-
-	static const uint32_t c1 = 0xcc9e2d51;
-	static const uint32_t c2 = 0x1b873593;
-	static const uint32_t r1 = 15;
-	static const uint32_t r2 = 13;
-	static const uint32_t m = 5;
-	static const uint32_t n = 0xe6546b64;
-	hash_t hash = seed;
-
-	if (data == UA_NULL)
-		return 0;
-
-	blocks = (const uint32_t *) data;
-	for (int32_t i = 0; i < nblocks; i++) {
-		uint32_t k = blocks[i];
-		k *= c1;
-		k = (k << r1) | (k >> (32 - r1));
-		k *= c2;
-		hash ^= k;
-		hash = ((hash << r2) | (hash >> (32 - r2))) * m + n;
-	}
-
-	const uint8_t *tail = (const uint8_t *) (data + nblocks * 4);
-	uint32_t k1 = 0;
-
-	switch (len & 3) {
-	case 3:
-		k1 ^= tail[2] << 16;
-
-	case 2:
-		k1 ^= tail[1] << 8;
-
-	case 1:
-		k1 ^= tail[0];
-		k1 *= c1;
-		k1 = (k1 << r1) | (k1 >> (32 - r1));
-		k1 *= c2;
-		hash ^= k1;
-	}
-
-	hash ^= len;
-	hash ^= (hash >> 16);
-	hash *= 0x85ebca6b;
-	hash ^= (hash >> 13);
-	hash *= 0xc2b2ae35;
-	hash ^= (hash >> 16);
-
-	return hash;
-}
-
-static INLINE hash_t hash(const UA_NodeId *n) {
-	switch (n->identifierType) {
-	case UA_NODEIDTYPE_NUMERIC:
-		/*  Knuth's multiplicative hashing */
-		return (n->identifier.numeric + n->namespaceIndex) * 2654435761; // mod(2^32) is implicit
-
-	case UA_NODEIDTYPE_STRING:
-		return hash_array(n->identifier.string.data,
-				n->identifier.string.length, n->namespaceIndex);
-
-	case UA_NODEIDTYPE_GUID:
-		return hash_array((UA_Byte *) &(n->identifier.guid), sizeof(UA_Guid),
-				n->namespaceIndex);
-
-	case UA_NODEIDTYPE_BYTESTRING:
-		return hash_array((UA_Byte *) n->identifier.byteString.data,
-				n->identifier.byteString.length, n->namespaceIndex);
-
-	default:
-		UA_assert(UA_FALSE);
-		return 0;
-	}
-}
-
-static INLINE void clear_entry(UA_NodeStoreExample *ns, const UA_Node **entry) {
-	const UA_Node *node;
-	if (entry == UA_NULL || *entry == UA_NULL)
-		return;
-
-	node = *entry;
-	switch (node->nodeClass) {
-	case UA_NODECLASS_OBJECT:
-		UA_ObjectNode_delete((UA_ObjectNode *) node);
-		break;
-
-	case UA_NODECLASS_VARIABLE:
-		UA_VariableNode_delete((UA_VariableNode *) node);
-		break;
-
-	case UA_NODECLASS_METHOD:
-		UA_MethodNode_delete((UA_MethodNode *) node);
-		break;
-
-	case UA_NODECLASS_OBJECTTYPE:
-		UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) node);
-		break;
-
-	case UA_NODECLASS_VARIABLETYPE:
-		UA_VariableTypeNode_delete((UA_VariableTypeNode *) node);
-		break;
-
-	case UA_NODECLASS_REFERENCETYPE:
-		UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) node);
-		break;
-
-	case UA_NODECLASS_DATATYPE:
-		UA_DataTypeNode_delete((UA_DataTypeNode *) node);
-		break;
-
-	case UA_NODECLASS_VIEW:
-		UA_ViewNode_delete((UA_ViewNode *) node);
-		break;
-
-	default:
-		UA_assert(UA_FALSE);
-		break;
-	}
-	entry = UA_NULL;
-	ns->count--;
-}
-
-/* Returns UA_SUCCESS if an entry was found. Otherwise, UA_ERROR is returned and the "entry"
- argument points to the first free entry under the NodeId. */
-static INLINE UA_StatusCode find_entry(const UA_NodeStoreExample *ns,
-		const UA_NodeId *nodeid, const UA_Node ***entry) {
-	hash_t h = hash(nodeid);
-	UA_UInt32 size = ns->size;
-	hash_t index = mod(h, size);
-	const UA_Node **e = &ns->entries[index];
-
-	if (*e == UA_NULL) {
-		*entry = e;
-		return UA_STATUSCODE_BADINTERNALERROR;
-	}
-
-	if (UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
-		*entry = e;
-		return UA_STATUSCODE_GOOD;
-	}
-
-	hash_t hash2 = mod2(h, size);
-	for (;;) {
-		index += hash2;
-		if (index >= size)
-			index -= size;
-
-		e = &ns->entries[index];
-
-		if (*e == UA_NULL) {
-			*entry = e;
-			return UA_STATUSCODE_BADINTERNALERROR;
-		}
-
-		if (UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
-			*entry = e;
-			return UA_STATUSCODE_GOOD;
-		}
-	}
-
-	/* NOTREACHED */
-	return UA_STATUSCODE_GOOD;
-}
-
-/* The following function changes size of memory allocated for the entries and
- repeatedly inserts the table elements. The occupancy of the table after the
- call will be about 50%. If memory allocation failures occur, this function
- will return UA_ERROR. */
-static UA_StatusCode expand(UA_NodeStoreExample *ns) {
-	const UA_Node **nentries;
-	int32_t nsize;
-	UA_UInt32 nindex;
-
-	const UA_Node **oentries = ns->entries;
-	int32_t osize = ns->size;
-	const UA_Node **olimit = &oentries[osize];
-	int32_t count = ns->count;
-
-	/* Resize only when table after removal of unused elements is either too full or too empty.  */
-	if (count * 2 < osize && (count * 8 > osize || osize <= 32))
-		return UA_STATUSCODE_GOOD;
-
-	nindex = higher_prime_index(count * 2);
-	nsize = primes[nindex];
-
-	if (!(nentries = UA_alloc(sizeof(UA_Node *) * nsize)))
-		return UA_STATUSCODE_BADOUTOFMEMORY;
-
-	memset(nentries, 0, nsize * sizeof(UA_Node *));
-	ns->entries = nentries;
-	ns->size = nsize;
-	ns->sizePrimeIndex = nindex;
-
-	const UA_Node **p = oentries;
-	do {
-		if (*p != UA_NULL) {
-			const UA_Node **e;
-			find_entry(ns, &(*p)->nodeId, &e); /* We know this returns an empty entry here */
-			*e = *p;
-		}
-		p++;
-	} while (p < olimit);
-
-	UA_free(oentries);
-	return UA_STATUSCODE_GOOD;
-}
-
-/**********************/
-/* Exported functions */
-/**********************/
-
-UA_StatusCode UA_NodeStoreExample_new(UA_NodeStoreExample **result) {
-	UA_NodeStoreExample *ns;
-	UA_UInt32 sizePrimeIndex, size;
-	if (!(ns = UA_alloc(sizeof(UA_NodeStore))))
-		return UA_STATUSCODE_BADOUTOFMEMORY;
-
-	sizePrimeIndex = higher_prime_index(32);
-	size = primes[sizePrimeIndex];
-	if (!(ns->entries = UA_alloc(sizeof(UA_Node *) * size))) {
-		UA_free(ns);
-		return UA_STATUSCODE_BADOUTOFMEMORY;
-	}
-
-	/* set entries to zero */
-	memset(ns->entries, 0, size * sizeof(UA_Node *));
-
-	*ns = (UA_NodeStoreExample ) { ns->entries, size, 0, sizePrimeIndex };
-	*result = ns;
-	return UA_STATUSCODE_GOOD;
-}
-
-void UA_NodeStoreExample_delete(UA_NodeStoreExample *ns) {
-	UA_UInt32 size = ns->size;
-	const UA_Node **entries = ns->entries;
-
-	for (UA_UInt32 i = 0; i < size; i++)
-		clear_entry(ns, &entries[i]);
-
-	UA_free(ns->entries);
-	UA_free(ns);
-}
-
-UA_StatusCode UA_NodeStoreExample_insert(UA_NodeStoreExample *ns, UA_Node **node,
-		UA_Byte flags) {
-	if (ns->size * 3 <= ns->count * 4) {
-		if (expand(ns) != UA_STATUSCODE_GOOD)
-			return UA_STATUSCODE_BADINTERNALERROR;
-	}
-
-	const UA_Node **entry;
-	UA_Int32 found = find_entry(ns, &(*node)->nodeId, &entry);
-
-	if (flags & UA_NODESTORE_INSERT_UNIQUE) {
-		if (found == UA_STATUSCODE_GOOD)
-			return UA_STATUSCODE_BADNODEIDEXISTS;
-		else
-			*entry = *node;
-	} else {
-		if (found == UA_STATUSCODE_GOOD)
-			clear_entry(ns, entry);
-		*entry = *node;
-	}
-
-	if (!(flags & UA_NODESTORE_INSERT_GETMANAGED))
-		*node = UA_NULL;
-
-	ns->count++;
-	return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_NodeStoreExample_get(const UA_NodeStoreExample *ns,
-		const UA_NodeId *nodeid, const UA_Node **managedNode) {
-	const UA_Node **entry;
-	if (find_entry(ns, nodeid, &entry) != UA_STATUSCODE_GOOD)
-		return UA_STATUSCODE_BADNODEIDUNKNOWN;
-
-	*managedNode = *entry;
-	return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_NodeStoreExample_remove(UA_NodeStoreExample *ns,
-		const UA_NodeId *nodeid) {
-	const UA_Node **entry;
-	if (find_entry(ns, nodeid, &entry) != UA_STATUSCODE_GOOD)
-		return UA_STATUSCODE_BADNODEIDUNKNOWN;
-
-	// Check before if deleting the node makes the UA_NodeStore inconsistent.
-	clear_entry(ns, entry);
-
-	/* Downsize the hashmap if it is very empty */
-	if (ns->count * 8 < ns->size && ns->size > 32)
-		expand(ns); // this can fail. we just continue with the bigger hashmap.
-
-	return UA_STATUSCODE_GOOD;
-}
-
-void UA_NodeStoreExample_iterate(const UA_NodeStoreExample *ns,
-		UA_NodeStore_nodeVisitor visitor) {
-	for (UA_UInt32 i = 0; i < ns->size; i++) {
-		const UA_Node *node = ns->entries[i];
-		if (node != UA_NULL)
-			visitor(node);
-	}
-}
-
-void UA_NodeStoreExample_releaseManagedNode(const UA_Node *managed) {
-	;
-}

+ 0 - 62
src/server/nodestore/ua_nodestoreExample.h

@@ -1,62 +0,0 @@
-#ifndef UA_NODESTORE_H_
-#define UA_NODESTORE_H_
-
-#include "ua_server.h"
-#include "ua_config.h"
-/**
-   @ingroup server
-
-   @defgroup nodestore NodeStore
-
-   @brief The nodestore is the central storage for nodes in the UA address
-   space. Internally, the nodestore is realised as hash-map where nodes are
-   stored and retrieved with their nodeid.
-
-   The nodes in the nodestore 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 Create a new namespace */
-UA_StatusCode UA_EXPORT UA_NodeStoreExample_new(UA_NodeStoreExample **result);
-
-/** @brief Delete the namespace and all nodes in it */
-void UA_NodeStoreExample_delete(UA_NodeStoreExample *ns);
-
-#define UA_NODESTORE_INSERT_UNIQUE 1
-#define UA_NODESTORE_INSERT_GETMANAGED 2
-/** @brief Insert a new node into the namespace
-
-    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_StatusCode UA_NodeStoreExample_insert(UA_NodeStoreExample *ns, UA_Node **node, UA_Byte flags);
-
-/** @brief Remove a node from the namespace. Always succeeds, even if the node
-    was not found. */
-UA_StatusCode UA_NodeStoreExample_remove(UA_NodeStoreExample *ns, const UA_NodeId *nodeid);
-
-/** @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_StatusCode UA_NodeStoreExample_get(const UA_NodeStoreExample *ns, const UA_NodeId *nodeid,
-                          const UA_Node **managedNode);
-
-/** @brief Release a managed node. Do never insert a node that isn't stored in a
-    namespace. */
-void UA_NodeStoreExample_releaseManagedNode(const UA_Node *managed);
-
-/** @brief A function that can be evaluated on all entries in a namespace via
-    UA_NodeStore_iterate. Note that the visitor is read-only on the nodes. */
-typedef void (*UA_NodeStore_nodeVisitor)(const UA_Node *node);
-
-/** @brief Iterate over all nodes in a namespace. */
-void UA_NodeStoreExample_iterate(const UA_NodeStoreExample *ns, UA_NodeStore_nodeVisitor visitor);
-
-/// @} /* end of group */
-
-#endif /* UA_NODESTORE_H_ */

+ 1 - 1
src/server/ua_namespace_manager.h

@@ -8,7 +8,7 @@
 #ifndef UA_NAMESPACE_MANAGER_H_
 #define UA_NAMESPACE_MANAGER_H_
 #include "ua_server.h"
-#include "nodestore/ua_nodestore.h"
+#include "ua_nodestore_interface.h"
 
 
 void UA_EXPORT UA_NamespaceManager_new(UA_NamespaceManager** namespaceManager);

+ 1 - 1
src/server/nodestore/ua_nodestore.c

@@ -1,4 +1,4 @@
-#include "ua_nodestore.h"
+#include "ua_nodestore_interface.h"
 #include "ua_util.h"
 #include "ua_statuscodes.h"
 

src/server/nodestore/ua_nodestore.h → src/server/ua_nodestore_interface.h


+ 45 - 43
src/server/ua_server.c

@@ -1,5 +1,5 @@
 #include "ua_server.h"
-#include "nodestore/ua_nodestoreExample.h"
+//#include "nodestore/ua_nodestoreExample.h"
 #include "ua_services_internal.h" // AddReferences
 #include "ua_namespace_0.h"
 #include "ua_securechannel_manager.h"
@@ -12,7 +12,7 @@ UA_StatusCode UA_Server_deleteMembers(UA_Server *server) {
     UA_ApplicationDescription_deleteMembers(&server->description);
     UA_SecureChannelManager_delete(server->secureChannelManager);
     UA_SessionManager_delete(server->sessionManager);
-    UA_NodeStoreExample_delete(server->nodestore);
+ //   UA_NodeStoreExample_delete(server->nodestore);
     UA_ByteString_deleteMembers(&server->serverCertificate);
     return UA_STATUSCODE_GOOD;
 }
@@ -138,7 +138,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     addSingleNode(ns0,&addNodesItem);\
 }while(1==0);
 
-
+/*
 #define ADDREFERENCE(NODE, REFTYPE, INVERSE, TARGET_NODEID) do { \
     static struct UA_ReferenceNode NODE##REFTYPE##TARGET_NODEID;    \
     UA_ReferenceNode_init(&NODE##REFTYPE##TARGET_NODEID);       \
@@ -149,10 +149,10 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     } while(0)
 
 
-
+*/
 
     // ObjectTypes (Ids only)
-    UA_ExpandedNodeId ObjTypeId_FolderType; NS0EXPANDEDNODEID(ObjTypeId_FolderType, 61);
+//    UA_ExpandedNodeId ObjTypeId_FolderType; NS0EXPANDEDNODEID(ObjTypeId_FolderType, 61);
 
     // Objects (Ids only)
     UA_ExpandedNodeId ObjId_Null; NS0EXPANDEDNODEID(ObjId_Null, 0);
@@ -161,12 +161,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_ExpandedNodeId ObjId_TypesFolder; NS0EXPANDEDNODEID(ObjId_TypesFolder, 86);
     UA_ExpandedNodeId ObjId_ViewsFolder; NS0EXPANDEDNODEID(ObjId_ViewsFolder, 87);
     UA_ExpandedNodeId ObjId_ReferenceTypesFolder; NS0EXPANDEDNODEID(ObjId_ReferenceTypesFolder, 91);
-    UA_ExpandedNodeId ObjId_Server; NS0EXPANDEDNODEID(ObjId_Server, 2253);
-    UA_ExpandedNodeId ObjId_ServerArray; NS0EXPANDEDNODEID(ObjId_ServerArray, 2254);
-    UA_ExpandedNodeId ObjId_NamespaceArray; NS0EXPANDEDNODEID(ObjId_NamespaceArray, 2255);
-    UA_ExpandedNodeId ObjId_ServerStatus; NS0EXPANDEDNODEID(ObjId_ServerStatus, 2256);
-    UA_ExpandedNodeId ObjId_ServerCapabilities; NS0EXPANDEDNODEID(ObjId_ServerCapabilities, 2268);
-    UA_ExpandedNodeId ObjId_State; NS0EXPANDEDNODEID(ObjId_State, 2259);
+//    UA_ExpandedNodeId ObjId_Server; NS0EXPANDEDNODEID(ObjId_Server, 2253);
+//    UA_ExpandedNodeId ObjId_ServerArray; NS0EXPANDEDNODEID(ObjId_ServerArray, 2254);
+//    UA_ExpandedNodeId ObjId_NamespaceArray; NS0EXPANDEDNODEID(ObjId_NamespaceArray, 2255);
+//    UA_ExpandedNodeId ObjId_ServerStatus; NS0EXPANDEDNODEID(ObjId_ServerStatus, 2256);
+//    UA_ExpandedNodeId ObjId_ServerCapabilities; NS0EXPANDEDNODEID(ObjId_ServerCapabilities, 2268);
+//    UA_ExpandedNodeId ObjId_State; NS0EXPANDEDNODEID(ObjId_State, 2259);
 
 
 
@@ -539,7 +539,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&hashistoricalconfiguration, UA_NODESTORE_INSERT_UNIQUE);
 
 */
-
+/*
 
     // FolderType
     UA_ObjectNode *folderType;
@@ -563,8 +563,10 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_ObjectsFolder);
     ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_TypesFolder);
     ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_ViewsFolder);
-    /* root becomes a managed node. we need to release it at the end.*/
-    UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&root, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
+ */
+    		 /* root becomes a managed node. we need to release it at the end.*/
+ /*
+    		UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&root, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
 
 
 
@@ -687,7 +689,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
 
     UA_Namespace *namespace;
     UA_NamespaceManager_getNamespace(server->namespaceManager,0,&namespace);
-
+*/
 
 
 
@@ -734,7 +736,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
 
     addSingleNode(namespace,&addNodesItem);
  */
-    UA_ObjectAttributes objAttr;
+ /*   UA_ObjectAttributes objAttr;
     UA_AddNodesItem addNodesItem;
     addNodesItem.parentNodeId.nodeId = root->nodeId;
     addNodesItem.requestedNewNodeId.nodeId.identifier.numeric = 222;
@@ -762,40 +764,40 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_Namespace *ns0;
     UA_NamespaceManager_getNamespace(server->namespaceManager,0,&ns0);
     addSingleNode(ns0,&addNodesItem);
+*/
 
 
 
 
 
-
-}
-
-UA_AddNodesResult UA_Server_addNode(UA_Server *server, UA_Node **node, UA_ExpandedNodeId *parentNodeId,
-                                    UA_NodeId *referenceTypeId) {
-    return AddNode(server, &adminSession, node, parentNodeId, referenceTypeId);
 }
 
-void UA_Server_addReference(UA_Server *server, const UA_AddReferencesRequest *request,
-                            UA_AddReferencesResponse *response) {
-    Service_AddReferences(server, &adminSession, request, response);
-}
-
-UA_AddNodesResult UA_Server_addScalarVariableNode(UA_Server *server, UA_String *browseName, void *value,
-                                                  const UA_VTable_Entry *vt, UA_ExpandedNodeId *parentNodeId,
-                                                  UA_NodeId *referenceTypeId ) {
-    UA_VariableNode *tmpNode;
-    UA_VariableNode_new(&tmpNode);
-    UA_String_copy(browseName, &tmpNode->browseName.name);
-    UA_String_copy(browseName, &tmpNode->displayName.text);
-    /* UA_LocalizedText_copycstring("integer value", &tmpNode->description); */
-    tmpNode->nodeClass = UA_NODECLASS_VARIABLE;
-    tmpNode->valueRank = -1;
-    tmpNode->value.vt = vt;
-    tmpNode->value.storage.data.dataPtr = value;
-    tmpNode->value.storageType = UA_VARIANT_DATA_NODELETE;
-    tmpNode->value.storage.data.arrayLength = 1;
-    return UA_Server_addNode(server, (UA_Node**)&tmpNode, parentNodeId, referenceTypeId);
-}
+//UA_AddNodesResult UA_Server_addNode(UA_Server *server, UA_Node **node, UA_ExpandedNodeId *parentNodeId,
+//                                    UA_NodeId *referenceTypeId) {
+//    return AddNode(server, &adminSession, node, parentNodeId, referenceTypeId);
+//}
+
+//void UA_Server_addReference(UA_Server *server, const UA_AddReferencesRequest *request,
+//                            UA_AddReferencesResponse *response) {
+//    Service_AddReferences(server, &adminSession, request, response);
+//}
+
+//UA_AddNodesResult UA_Server_addScalarVariableNode(UA_Server *server, UA_String *browseName, void *value,
+//                                                  const UA_VTable_Entry *vt, UA_ExpandedNodeId *parentNodeId,
+//                                                  UA_NodeId *referenceTypeId ) {
+//    UA_VariableNode *tmpNode;
+//    UA_VariableNode_new(&tmpNode);
+//    UA_String_copy(browseName, &tmpNode->browseName.name);
+//    UA_String_copy(browseName, &tmpNode->displayName.text);
+//    /* UA_LocalizedText_copycstring("integer value", &tmpNode->description); */
+//    tmpNode->nodeClass = UA_NODECLASS_VARIABLE;
+//    tmpNode->valueRank = -1;
+//    tmpNode->value.vt = vt;
+//    tmpNode->value.storage.data.dataPtr = value;
+//    tmpNode->value.storageType = UA_VARIANT_DATA_NODELETE;
+//    tmpNode->value.storage.data.arrayLength = 1;
+//    return UA_Server_addNode(server, (UA_Node**)&tmpNode, parentNodeId, referenceTypeId);
+//}
 
 UA_Int32 UA_Server_addNamespace(UA_Server *server, UA_UInt16 namespaceIndex, UA_NodeStore *nodeStore)
 {

+ 191 - 186
src/server/ua_services_attribute.c

@@ -1,11 +1,11 @@
 #include "ua_services.h"
-#include "nodestore/ua_nodestoreExample.h"
+
 #include "ua_statuscodes.h"
-#include "nodestore/ua_nodestore.h"
+
 #include "ua_namespace_manager.h"
 #include "ua_namespace_0.h"
 #include "ua_util.h"
-
+/*
 #define CHECK_NODECLASS(CLASS)                                 \
     if(!(node->nodeClass & (CLASS))) {                         \
         v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE; \
@@ -208,7 +208,7 @@ static UA_DataValue service_read_node(UA_Server *server,
 
 	return v;
 }
-
+*/
 void Service_Read(UA_Server *server, UA_Session *session,
 		const UA_ReadRequest *request, UA_ReadResponse *response) {
 	UA_assert(server != UA_NULL && session != UA_NULL && request != UA_NULL && response != UA_NULL);
@@ -252,208 +252,213 @@ void Service_Read(UA_Server *server, UA_Session *session,
 		//for(UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++){
 		UA_UInt32 j = 0;
 		do {
-			if(associatedIndices[j] == request->nodesToRead[i].nodeId.namespaceIndex) {
-				if(differentNamespaceIndexCount == 0){
+			if (associatedIndices[j]
+					== request->nodesToRead[i].nodeId.namespaceIndex) {
+				if (differentNamespaceIndexCount == 0) {
 					differentNamespaceIndexCount++;
 				}
 				numberOfFoundIndices[j]++;
 				break;
-			}
-			else if(j == (differentNamespaceIndexCount - 1)) {
-				associatedIndices[j+1] = request->nodesToRead[i].nodeId.namespaceIndex;
-				associatedIndices[j+1] = 1;
+			} else if (j == (differentNamespaceIndexCount - 1)) {
+				associatedIndices[j + 1] =
+						request->nodesToRead[i].nodeId.namespaceIndex;
+				associatedIndices[j + 1] = 1;
 				differentNamespaceIndexCount++;
 				break;
 			}
 			j++;
-		}while(j<=differentNamespaceIndexCount);
+		} while (j <= differentNamespaceIndexCount);
 	}
 
-UA_UInt32 *readValueIdIndices;
-if (UA_Array_new((void **) &readValueIdIndices, request->nodesToReadSize,
-		&UA_[UA_UINT32]) != UA_STATUSCODE_GOOD) {
-	response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
-	return;
-}
+	UA_UInt32 *readValueIdIndices;
+	if (UA_Array_new((void **) &readValueIdIndices, request->nodesToReadSize,
+			&UA_[UA_UINT32]) != UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
 
-for (UA_UInt32 i = 0; i < differentNamespaceIndexCount; i++) {
-	UA_Namespace *tmpNamespace;
-	UA_NamespaceManager_getNamespace(server->namespaceManager,
-			associatedIndices[i], &tmpNamespace);
-	if (tmpNamespace != UA_NULL) {
-
-		//build up index array for each read operation onto a different namespace
-		UA_UInt32 n = 0;
-		for (UA_Int32 j = 0; j < request->nodesToReadSize; j++) {
-			if (request->nodesToRead[j].nodeId.namespaceIndex
-					== associatedIndices[i]) {
-				readValueIdIndices[n] = j;
+	for (UA_UInt32 i = 0; i < differentNamespaceIndexCount; i++) {
+		UA_Namespace *tmpNamespace;
+		UA_NamespaceManager_getNamespace(server->namespaceManager,
+				associatedIndices[i], &tmpNamespace);
+		if (tmpNamespace != UA_NULL) {
+
+			//build up index array for each read operation onto a different namespace
+			UA_UInt32 n = 0;
+			for (UA_Int32 j = 0; j < request->nodesToReadSize; j++) {
+				if (request->nodesToRead[j].nodeId.namespaceIndex
+						== associatedIndices[i]) {
+					readValueIdIndices[n] = j;
+					n++;
+				}
 			}
-		}
-		//call read for every namespace
-		tmpNamespace->nodeStore->readNodes(request->nodesToRead,
-				readValueIdIndices, numberOfFoundIndices[i], response->results,
-				request->timestampsToReturn, response->diagnosticInfos);
+			//call read for every namespace
+			tmpNamespace->nodeStore->readNodes(request->nodesToRead,
+					readValueIdIndices, numberOfFoundIndices[i],
+					response->results, request->timestampsToReturn,
+					response->diagnosticInfos);
 
-		//	response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+			//	response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+		}
 	}
-}
-UA_free(readValueIdIndices);
-UA_free(numberOfFoundIndices);
-UA_free(associatedIndices);
-/*
- for(UA_Int32 i = 0;i < response->resultsSize;i++){
- response->results[i] = service_read_node(server, &request->nodesToRead[i]);
- }
- }
- */
+	UA_free(readValueIdIndices);
+	UA_free(numberOfFoundIndices);
+	UA_free(associatedIndices);
 
-}
-
-static UA_StatusCode Service_Write_writeNode(UA_Server *server,
-UA_WriteValue *writeValue) {
-UA_StatusCode retval = UA_STATUSCODE_GOOD;
-const UA_Node *node;
-retval = UA_NodeStoreExample_get(server->nodestore, &writeValue->nodeId, &node);
-if (retval)
-return retval;
-
-switch (writeValue->attributeId) {
-case UA_ATTRIBUTEID_NODEID:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_NODECLASS:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_BROWSENAME:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_DISPLAYNAME:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_DESCRIPTION:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_WRITEMASK:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_USERWRITEMASK:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_ISABSTRACT:
-
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_SYMMETRIC:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_INVERSENAME:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_EVENTNOTIFIER:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_VALUE:
-if (writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT) {
-	retval |= UA_Variant_copy(&writeValue->value.value,
-			&((UA_VariableNode *) node)->value); // todo: zero-copy
-}
-break;
-
-case UA_ATTRIBUTEID_DATATYPE:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_VALUERANK:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_ACCESSLEVEL:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_USERACCESSLEVEL:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_HISTORIZING:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_EXECUTABLE:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-case UA_ATTRIBUTEID_USEREXECUTABLE:
-/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-break;
-
-default:
-retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
-break;
-}
+//	 for(UA_Int32 i = 0;i < response->resultsSize;i++){
+//	 response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+//	 }
 
-UA_NodeStoreExample_releaseManagedNode(node);
-return retval;
 
 }
+/*
+static UA_StatusCode Service_Write_writeNode(UA_Server *server,
+		UA_WriteValue *writeValue) {
+	UA_StatusCode retval = UA_STATUSCODE_GOOD;
+	const UA_Node *node;
+	retval = UA_NodeStoreExample_get(server->nodestore, &writeValue->nodeId,
+			&node);
+	if (retval)
+		return retval;
+
+	switch (writeValue->attributeId) {
+	case UA_ATTRIBUTEID_NODEID:
+	*/
+		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+		//		break;
+
+//	case UA_ATTRIBUTEID_NODECLASS:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_BROWSENAME:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_DISPLAYNAME:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_DESCRIPTION:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_WRITEMASK:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_USERWRITEMASK:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_ISABSTRACT:
+//
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_SYMMETRIC:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_INVERSENAME:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_EVENTNOTIFIER:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_VALUE:
+//		if (writeValue->value.encodingMask
+//				== UA_DATAVALUE_ENCODINGMASK_VARIANT) {
+//			retval |= UA_Variant_copy(&writeValue->value.value,
+//					&((UA_VariableNode *) node)->value); // todo: zero-copy
+//		}
+//		break;
+//
+//	case UA_ATTRIBUTEID_DATATYPE:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_VALUERANK:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_ACCESSLEVEL:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_USERACCESSLEVEL:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_HISTORIZING:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_EXECUTABLE:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	case UA_ATTRIBUTEID_USEREXECUTABLE:
+//		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+//		retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+//		break;
+//
+//	default:
+//		retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+//		break;
+//	}
+//
+//	UA_NodeStoreExample_releaseManagedNode(node);
+//	return retval;
+//
+//}
 
 void Service_Write(UA_Server *server, UA_Session *session,
-const UA_WriteRequest *request, UA_WriteResponse *response) {
-UA_assert(server != UA_NULL && session != UA_NULL && request != UA_NULL && response != UA_NULL);
+		const UA_WriteRequest *request, UA_WriteResponse *response) {
+	UA_assert(server != UA_NULL && session != UA_NULL && request != UA_NULL && response != UA_NULL);
 
-if (UA_Array_new((void **) &response->results, request->nodesToWriteSize,
-	&UA_[UA_STATUSCODE])) {
-response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
-return;
-}
+	if (UA_Array_new((void **) &response->results, request->nodesToWriteSize,
+			&UA_[UA_STATUSCODE])) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
 
-response->resultsSize = request->nodesToWriteSize;
-for (UA_Int32 i = 0; i < request->nodesToWriteSize; i++)
-response->results[i] = Service_Write_writeNode(server,
-		&request->nodesToWrite[i]);
+	response->resultsSize = request->nodesToWriteSize;
+	for (UA_Int32 i = 0; i < request->nodesToWriteSize; i++){}
+	//	response->results[i] = Service_Write_writeNode(server,
+	//			&request->nodesToWrite[i]);
 }

+ 13 - 13
src/server/ua_services_internal.h

@@ -3,16 +3,16 @@
  * internally as well (with a simplified API as no access rights are checked).
  */
 
-#include "ua_session.h"
-#include "nodestore/ua_nodestore.h"
-#include "ua_types_generated.h"
-
-/* @brief Add a reference (and the inverse reference to the target node).
- *
- * @param The node to which the reference shall be added
- * @param The reference itself
- * @param The namespace where the target node is looked up for the reverse reference (this is omitted if targetns is UA_NULL)
- */
-UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node, UA_ReferenceNode *reference);
-UA_AddNodesResult AddNode(UA_Server *server, UA_Session *session, UA_Node **node,
-                          UA_ExpandedNodeId *parentNodeId, UA_NodeId *referenceTypeId);
+//#include "ua_session.h"
+//#include "nodestore/ua_nodestore.h"
+//#include "ua_types_generated.h"
+//
+///* @brief Add a reference (and the inverse reference to the target node).
+// *
+// * @param The node to which the reference shall be added
+// * @param The reference itself
+// * @param The namespace where the target node is looked up for the reverse reference (this is omitted if targetns is UA_NULL)
+// */
+//UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node, UA_ReferenceNode *reference);
+//UA_AddNodesResult AddNode(UA_Server *server, UA_Session *session, UA_Node **node,
+//                          UA_ExpandedNodeId *parentNodeId, UA_NodeId *referenceTypeId);

+ 243 - 235
src/server/ua_services_nodemanagement.c

@@ -1,13 +1,13 @@
 #include "ua_services.h"
 #include "ua_namespace_0.h"
 #include "ua_statuscodes.h"
-#include "nodestore/ua_nodestoreExample.h"
+
 #include "ua_services_internal.h"
 #include "ua_namespace_manager.h"
 #include "ua_session.h"
 #include "ua_util.h"
-
-#define COPY_STANDARDATTRIBUTES do {                                    \
+/*
+ #define COPY_STANDARDATTRIBUTES do {                                    \
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DISPLAYNAME) {  \
         vnode->displayName = attr.displayName;                          \
         UA_LocalizedText_init(&attr.displayName);                       \
@@ -21,177 +21,177 @@
     if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERWRITEMASK)  \
         vnode->userWriteMask = attr.userWriteMask;                      \
     } while(0)
-
-static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes,
-		UA_Node **new_node, const UA_VTable_Entry **vt) {
-	if (attributes->typeId.identifier.numeric != 357) // VariableAttributes_Encoding_DefaultBinary,357,Object
-		return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
-
-	UA_VariableAttributes attr;
-	UA_UInt32 pos = 0;
-	// todo return more informative error codes from decodeBinary
-	if (UA_VariableAttributes_decodeBinary(&attributes->body, &pos, &attr)
-			!= UA_STATUSCODE_GOOD)
-		return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
-
-	UA_VariableNode *vnode;
-	if (UA_VariableNode_new(&vnode) != UA_STATUSCODE_GOOD) {
-		UA_VariableAttributes_deleteMembers(&attr);
-		return UA_STATUSCODE_BADOUTOFMEMORY;
-	}
-
-	// now copy all the attributes. This potentially removes them from the decoded attributes.
-	COPY_STANDARDATTRIBUTES;
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
-		vnode->accessLevel = attr.accessLevel;
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
-		vnode->userAccessLevel = attr.userAccessLevel;
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
-		vnode->historizing = attr.historizing;
-
-	if (attr.specifiedAttributes
-			& UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
-		vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
-		vnode->valueRank = attr.valueRank;
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS) {
-		vnode->arrayDimensionsSize = attr.arrayDimensionsSize;
-		vnode->arrayDimensions = attr.arrayDimensions;
-		attr.arrayDimensionsSize = -1;
-		attr.arrayDimensions = UA_NULL;
-	}
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE
-			|| attr.specifiedAttributes
-					& UA_NODEATTRIBUTESMASK_OBJECTTYPEORDATATYPE) {
-		vnode->dataType = attr.dataType;
-		UA_NodeId_init(&attr.dataType);
-	}
-
-	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE) {
-		vnode->value = attr.value;
-		UA_Variant_init(&attr.value);
-	}
-
-	UA_VariableAttributes_deleteMembers(&attr);
-
-	*new_node = (UA_Node*) vnode;
-	*vt = &UA_[UA_VARIABLENODE];
-	return UA_STATUSCODE_GOOD;
-}
-
-UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
-		UA_ReferenceNode *reference);
-
-/**
- If adding the node succeeds, the pointer will be set to zero. If the nodeid
- of the node is null (ns=0,i=0), a unique new nodeid will be assigned and
- returned in the AddNodesResult.
- */
-UA_AddNodesResult AddNode(UA_Server *server, UA_Session *session,
-		UA_Node **node, UA_ExpandedNodeId *parentNodeId,
-		UA_NodeId *referenceTypeId) {
-	UA_AddNodesResult result;
-	UA_AddNodesResult_init(&result);
-
-	const UA_Node *parent;
-	if (UA_NodeStoreExample_get(server->nodestore, &parentNodeId->nodeId,
-			&parent) != UA_STATUSCODE_GOOD) {
-		result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
-		return result;
-	}
-
-	const UA_ReferenceTypeNode *referenceType;
-	if (UA_NodeStoreExample_get(server->nodestore, referenceTypeId,
-			(const UA_Node**) &referenceType) != UA_STATUSCODE_GOOD) {
-		result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
-		goto ret;
-	}
-
-	if (referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
-		result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
-		goto ret2;
-	}
-
-	if (referenceType->isAbstract == UA_TRUE) {
-		result.statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
-		goto ret2;
-	}
-
-	// todo: test if the referenetype is hierarchical
-
-	if (UA_NodeId_isNull(&(*node)->nodeId)) {
-		if (UA_NodeStoreExample_insert(server->nodestore, node,
-		UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED)
-				!= UA_STATUSCODE_GOOD) {
-			result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
-			goto ret2;
-		}
-		result.addedNodeId = (*node)->nodeId; // cannot fail as unique nodeids are numeric
-	} else {
-		if (UA_NodeId_copy(&(*node)->nodeId, &result.addedNodeId)
-				!= UA_STATUSCODE_GOOD) {
-			result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
-			goto ret2;
-		}
-
-		if (UA_NodeStoreExample_insert(server->nodestore, node,
-				UA_NODESTORE_INSERT_GETMANAGED) != UA_STATUSCODE_GOOD) {
-			result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; // todo: differentiate out of memory
-			UA_NodeId_deleteMembers(&result.addedNodeId);
-			goto ret2;
-		}
-	}
-
-	UA_ReferenceNode ref;
-	UA_ReferenceNode_init(&ref);
-	ref.referenceTypeId = referenceType->nodeId; // is numeric
-	ref.isInverse = UA_TRUE; // todo: check if they are all not inverse..
-	ref.targetId.nodeId = parent->nodeId;
-	AddReference(server->nodestore, *node, &ref);
-
-	// todo: error handling. remove new node from nodestore
-
-	UA_NodeStoreExample_releaseManagedNode(*node);
-	*node = UA_NULL;
-
-	ret2: UA_NodeStoreExample_releaseManagedNode((UA_Node*) referenceType);
-	ret: UA_NodeStoreExample_releaseManagedNode(parent);
-
-	return result;
-}
-
-static void addNodeFromAttributes(UA_Server *server, UA_Session *session,
-		UA_AddNodesItem *item, UA_AddNodesResult *result) {
-	if (item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
-		// adding nodes to ns0 is not allowed over the wire
-		result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
-		return;
-	}
-
-	UA_Node *newNode;
-	const UA_VTable_Entry *newNodeVT = UA_NULL;
-	if (item->nodeClass == UA_NODECLASS_VARIABLE)
-		result->statusCode = parseVariableNode(&item->nodeAttributes, &newNode,
-				&newNodeVT);
-	else
-		// add more node types here..
-		result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
-
-	if (result->statusCode != UA_STATUSCODE_GOOD)
-		return;
-
-	*result = AddNode(server, session, &newNode, &item->parentNodeId,
-			&item->referenceTypeId);
-	if (result->statusCode != UA_STATUSCODE_GOOD)
-		newNodeVT->delete(newNode);
-}
-
+*/
+//static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes,
+//		UA_Node **new_node, const UA_VTable_Entry **vt) {
+//	if (attributes->typeId.identifier.numeric != 357) // VariableAttributes_Encoding_DefaultBinary,357,Object
+//		return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+//
+//	UA_VariableAttributes attr;
+//	UA_UInt32 pos = 0;
+//	// todo return more informative error codes from decodeBinary
+//	if (UA_VariableAttributes_decodeBinary(&attributes->body, &pos, &attr)
+//			!= UA_STATUSCODE_GOOD)
+//		return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+//
+//	UA_VariableNode *vnode;
+//	if (UA_VariableNode_new(&vnode) != UA_STATUSCODE_GOOD) {
+//		UA_VariableAttributes_deleteMembers(&attr);
+//		return UA_STATUSCODE_BADOUTOFMEMORY;
+//	}
+//
+//	// now copy all the attributes. This potentially removes them from the decoded attributes.
+//	COPY_STANDARDATTRIBUTES;
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
+//		vnode->accessLevel = attr.accessLevel;
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
+//		vnode->userAccessLevel = attr.userAccessLevel;
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
+//		vnode->historizing = attr.historizing;
+//
+//	if (attr.specifiedAttributes
+//			& UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
+//		vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
+//		vnode->valueRank = attr.valueRank;
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS) {
+//		vnode->arrayDimensionsSize = attr.arrayDimensionsSize;
+//		vnode->arrayDimensions = attr.arrayDimensions;
+//		attr.arrayDimensionsSize = -1;
+//		attr.arrayDimensions = UA_NULL;
+//	}
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE
+//			|| attr.specifiedAttributes
+//					& UA_NODEATTRIBUTESMASK_OBJECTTYPEORDATATYPE) {
+//		vnode->dataType = attr.dataType;
+//		UA_NodeId_init(&attr.dataType);
+//	}
+//
+//	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE) {
+//		vnode->value = attr.value;
+//		UA_Variant_init(&attr.value);
+//	}
+//
+//	UA_VariableAttributes_deleteMembers(&attr);
+//
+//	*new_node = (UA_Node*) vnode;
+//	*vt = &UA_[UA_VARIABLENODE];
+//	return UA_STATUSCODE_GOOD;
+//}
+//
+//UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
+//		UA_ReferenceNode *reference);
+//
+///**
+// If adding the node succeeds, the pointer will be set to zero. If the nodeid
+// of the node is null (ns=0,i=0), a unique new nodeid will be assigned and
+// returned in the AddNodesResult.
+// */
+//UA_AddNodesResult AddNode(UA_Server *server, UA_Session *session,
+//		UA_Node **node, UA_ExpandedNodeId *parentNodeId,
+//		UA_NodeId *referenceTypeId) {
+//	UA_AddNodesResult result;
+//	UA_AddNodesResult_init(&result);
+//
+//	const UA_Node *parent;
+//	if (UA_NodeStoreExample_get(server->nodestore, &parentNodeId->nodeId,
+//			&parent) != UA_STATUSCODE_GOOD) {
+//		result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
+//		return result;
+//	}
+//
+//	const UA_ReferenceTypeNode *referenceType;
+//	if (UA_NodeStoreExample_get(server->nodestore, referenceTypeId,
+//			(const UA_Node**) &referenceType) != UA_STATUSCODE_GOOD) {
+//		result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+//		goto ret;
+//	}
+//
+//	if (referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
+//		result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+//		goto ret2;
+//	}
+//
+//	if (referenceType->isAbstract == UA_TRUE) {
+//		result.statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
+//		goto ret2;
+//	}
+//
+//	// todo: test if the referenetype is hierarchical
+//
+//	if (UA_NodeId_isNull(&(*node)->nodeId)) {
+//		if (UA_NodeStoreExample_insert(server->nodestore, node,
+//		UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED)
+//				!= UA_STATUSCODE_GOOD) {
+//			result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+//			goto ret2;
+//		}
+//		result.addedNodeId = (*node)->nodeId; // cannot fail as unique nodeids are numeric
+//	} else {
+//		if (UA_NodeId_copy(&(*node)->nodeId, &result.addedNodeId)
+//				!= UA_STATUSCODE_GOOD) {
+//			result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+//			goto ret2;
+//		}
+//
+//		if (UA_NodeStoreExample_insert(server->nodestore, node,
+//				UA_NODESTORE_INSERT_GETMANAGED) != UA_STATUSCODE_GOOD) {
+//			result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; // todo: differentiate out of memory
+//			UA_NodeId_deleteMembers(&result.addedNodeId);
+//			goto ret2;
+//		}
+//	}
+//
+//	UA_ReferenceNode ref;
+//	UA_ReferenceNode_init(&ref);
+//	ref.referenceTypeId = referenceType->nodeId; // is numeric
+//	ref.isInverse = UA_TRUE; // todo: check if they are all not inverse..
+//	ref.targetId.nodeId = parent->nodeId;
+//	AddReference(server->nodestore, *node, &ref);
+//
+//	// todo: error handling. remove new node from nodestore
+//
+//	UA_NodeStoreExample_releaseManagedNode(*node);
+//	*node = UA_NULL;
+//
+//	ret2: UA_NodeStoreExample_releaseManagedNode((UA_Node*) referenceType);
+//	ret: UA_NodeStoreExample_releaseManagedNode(parent);
+//
+//	return result;
+//}
+//
+//static void addNodeFromAttributes(UA_Server *server, UA_Session *session,
+//		UA_AddNodesItem *item, UA_AddNodesResult *result) {
+//	if (item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
+//		// adding nodes to ns0 is not allowed over the wire
+//		result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
+//		return;
+//	}
+//
+//	UA_Node *newNode;
+//	const UA_VTable_Entry *newNodeVT = UA_NULL;
+//	if (item->nodeClass == UA_NODECLASS_VARIABLE)
+//		result->statusCode = parseVariableNode(&item->nodeAttributes, &newNode,
+//				&newNodeVT);
+//	else
+//		// add more node types here..
+//		result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
+//
+//	if (result->statusCode != UA_STATUSCODE_GOOD)
+//		return;
+//
+//	*result = AddNode(server, session, &newNode, &item->parentNodeId,
+//			&item->referenceTypeId);
+//	if (result->statusCode != UA_STATUSCODE_GOOD)
+//		newNodeVT->delete(newNode);
+//}
+//
 void Service_AddNodes(UA_Server *server, UA_Session *session,
 		const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
 	UA_assert(server != UA_NULL && session != UA_NULL);
@@ -233,22 +233,25 @@ void Service_AddNodes(UA_Server *server, UA_Session *session,
 	// find out count of different namespace indices
 
 	for (UA_Int32 i = 0; i < request->nodesToAddSize; i++) {
-
-		for (UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++) {
+		//for(UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++){
+		UA_UInt32 j = 0;
+		do {
 			if (associatedIndices[j]
 					== request->nodesToAdd[i].requestedNewNodeId.nodeId.namespaceIndex) {
-				if (j == 0) {
+				if (differentNamespaceIndexCount == 0) {
 					differentNamespaceIndexCount++;
 				}
 				numberOfFoundIndices[j]++;
 				break;
 			} else if (j == (differentNamespaceIndexCount - 1)) {
-				associatedIndices[j] =
+				associatedIndices[j + 1] =
 						request->nodesToAdd[i].requestedNewNodeId.nodeId.namespaceIndex;
-				associatedIndices[j] = 1;
+				associatedIndices[j + 1] = 1;
 				differentNamespaceIndexCount++;
+				break;
 			}
-		}
+			j++;
+		} while (j <= differentNamespaceIndexCount);
 	}
 
 	UA_UInt32 *addNodesIndices;
@@ -270,6 +273,7 @@ void Service_AddNodes(UA_Server *server, UA_Session *session,
 				if (request->nodesToAdd[j].requestedNewNodeId.nodeId.namespaceIndex
 						== associatedIndices[i]) {
 					addNodesIndices[n] = j;
+					n++;
 				}
 			}
 			//call read for every namespace
@@ -301,55 +305,55 @@ void Service_AddNodes(UA_Server *server, UA_Session *session,
 				&response->results[i]);
 				*/
 }
-
-static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
-	// TODO: Check if reference already exists
-	UA_Int32 count = node->referencesSize;
-	UA_ReferenceNode *old_refs = node->references;
-	UA_ReferenceNode *new_refs;
-
-	if (count < 0)
-		count = 0;
-
-	if (!(new_refs = UA_alloc(sizeof(UA_ReferenceNode) * (count + 1))))
-		return UA_STATUSCODE_BADOUTOFMEMORY;
-
-	UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode) * count);
-	if (UA_ReferenceNode_copy(reference, &new_refs[count])
-			!= UA_STATUSCODE_GOOD) {
-		UA_free(new_refs);
-		return UA_STATUSCODE_BADOUTOFMEMORY;
-	}
-
-	node->references = new_refs;
-	node->referencesSize = count + 1;
-	UA_free(old_refs);
-	return UA_STATUSCODE_GOOD;
-}
-
-UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
-		UA_ReferenceNode *reference) {
-	UA_Int32 retval = AddSingleReference(node, reference);
-	UA_Node *targetnode;
-	UA_ReferenceNode inversereference;
-	if (retval != UA_STATUSCODE_GOOD || nodestore == UA_NULL)
-		return retval;
-
-	// Do a copy every time?
-	if (UA_NodeStoreExample_get(nodestore, &reference->targetId.nodeId,
-			(const UA_Node **) &targetnode) != UA_STATUSCODE_GOOD)
-		return UA_STATUSCODE_BADINTERNALERROR;
-
-	inversereference.referenceTypeId = reference->referenceTypeId;
-	inversereference.isInverse = !reference->isInverse;
-	inversereference.targetId.nodeId = node->nodeId;
-	inversereference.targetId.namespaceUri = UA_STRING_NULL;
-	inversereference.targetId.serverIndex = 0;
-	retval = AddSingleReference(targetnode, &inversereference);
-	UA_NodeStoreExample_releaseManagedNode(targetnode);
-
-	return retval;
-}
+//
+//static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
+//	// TODO: Check if reference already exists
+//	UA_Int32 count = node->referencesSize;
+//	UA_ReferenceNode *old_refs = node->references;
+//	UA_ReferenceNode *new_refs;
+//
+//	if (count < 0)
+//		count = 0;
+//
+//	if (!(new_refs = UA_alloc(sizeof(UA_ReferenceNode) * (count + 1))))
+//		return UA_STATUSCODE_BADOUTOFMEMORY;
+//
+//	UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode) * count);
+//	if (UA_ReferenceNode_copy(reference, &new_refs[count])
+//			!= UA_STATUSCODE_GOOD) {
+//		UA_free(new_refs);
+//		return UA_STATUSCODE_BADOUTOFMEMORY;
+//	}
+//
+//	node->references = new_refs;
+//	node->referencesSize = count + 1;
+//	UA_free(old_refs);
+//	return UA_STATUSCODE_GOOD;
+//}
+//
+//UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
+//		UA_ReferenceNode *reference) {
+//	UA_Int32 retval = AddSingleReference(node, reference);
+//	UA_Node *targetnode;
+//	UA_ReferenceNode inversereference;
+//	if (retval != UA_STATUSCODE_GOOD || nodestore == UA_NULL)
+//		return retval;
+//
+//	// Do a copy every time?
+//	if (UA_NodeStoreExample_get(nodestore, &reference->targetId.nodeId,
+//			(const UA_Node **) &targetnode) != UA_STATUSCODE_GOOD)
+//		return UA_STATUSCODE_BADINTERNALERROR;
+//
+//	inversereference.referenceTypeId = reference->referenceTypeId;
+//	inversereference.isInverse = !reference->isInverse;
+//	inversereference.targetId.nodeId = node->nodeId;
+//	inversereference.targetId.namespaceUri = UA_STRING_NULL;
+//	inversereference.targetId.serverIndex = 0;
+//	retval = AddSingleReference(targetnode, &inversereference);
+//	UA_NodeStoreExample_releaseManagedNode(targetnode);
+//
+//	return retval;
+//}
 
 void Service_AddReferences(UA_Server *server, UA_Session *session,
 		const UA_AddReferencesRequest *request,
@@ -392,22 +396,25 @@ void Service_AddReferences(UA_Server *server, UA_Session *session,
 	// find out count of different namespace indices
 
 	for (UA_Int32 i = 0; i < request->referencesToAddSize; i++) {
-
-		for (UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++) {
+		//for(UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++){
+		UA_UInt32 j = 0;
+		do {
 			if (associatedIndices[j]
 					== request->referencesToAdd[i].sourceNodeId.namespaceIndex) {
-				if (j == 0) {
+				if (differentNamespaceIndexCount == 0) {
 					differentNamespaceIndexCount++;
 				}
 				numberOfFoundIndices[j]++;
 				break;
 			} else if (j == (differentNamespaceIndexCount - 1)) {
-				associatedIndices[j] =
+				associatedIndices[j + 1] =
 						request->referencesToAdd[i].sourceNodeId.namespaceIndex;
-				associatedIndices[j] = 1;
+				associatedIndices[j + 1] = 1;
 				differentNamespaceIndexCount++;
+				break;
 			}
-		}
+			j++;
+		} while (j <= differentNamespaceIndexCount);
 	}
 
 	UA_UInt32 *readValueIdIndices;
@@ -429,6 +436,7 @@ void Service_AddReferences(UA_Server *server, UA_Session *session,
 				if (request->referencesToAdd[j].sourceNodeId.namespaceIndex
 						== associatedIndices[i]) {
 					readValueIdIndices[n] = j;
+					n++;
 				}
 			}
 			//call read for every namespace

+ 21 - 16
src/server/ua_services_view.c

@@ -1,6 +1,6 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
-#include "nodestore/ua_nodestoreExample.h"
+
 #include "ua_namespace_0.h"
 #include "ua_util.h"
 #include "ua_namespace_manager.h"
@@ -34,23 +34,27 @@ void Service_Browse(UA_Server *server, UA_Session *session,
     	return ;
     }
     // find out count of different namespace indices
-   for(UA_Int32 i = 0; i<request->nodesToBrowseSize; i++){
-
-    	for(UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++){
-    		if(associatedIndices[j] == request->nodesToBrowse[i].nodeId.namespaceIndex){
-    			if(j==0){
-    				differentNamespaceIndexCount++;
-    			}
+	for (UA_Int32 i = 0; i < request->nodesToBrowseSize; i++) {
+		//for(UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++){
+		UA_UInt32 j = 0;
+		do {
+			if (associatedIndices[j]
+					== request->nodesToBrowse[i].nodeId.namespaceIndex) {
+				if (differentNamespaceIndexCount == 0) {
+					differentNamespaceIndexCount++;
+				}
 				numberOfFoundIndices[j]++;
 				break;
-    		}
-    		else if(j == (differentNamespaceIndexCount - 1)){
-    			associatedIndices[j] = request->nodesToBrowse[i].nodeId.namespaceIndex;
-    			associatedIndices[j] = 1;
-    			differentNamespaceIndexCount++;
-    		}
-    	}
-    }
+			} else if (j == (differentNamespaceIndexCount - 1)) {
+				associatedIndices[j + 1] =
+						request->nodesToBrowse[i].nodeId.namespaceIndex;
+				associatedIndices[j + 1] = 1;
+				differentNamespaceIndexCount++;
+				break;
+			}
+			j++;
+		} while (j <= differentNamespaceIndexCount);
+	}
 
 	UA_UInt32 *browseDescriptionIndices;
     if(UA_Array_new((void **)&browseDescriptionIndices,request->nodesToBrowseSize,&UA_[UA_UINT32]) != UA_STATUSCODE_GOOD){
@@ -68,6 +72,7 @@ void Service_Browse(UA_Server *server, UA_Session *session,
     	    for(UA_Int32 j = 0; j < request->nodesToBrowseSize; j++){
     	    	if(request->nodesToBrowse[j].nodeId.namespaceIndex == associatedIndices[i]){
     	    		browseDescriptionIndices[n] = j;
+					n++;
     	    	}
     	    }
     	    //call read for every namespace