Pārlūkot izejas kodu

replace list of namespaces with a single nodestore for all namespaces

Julius Pfrommer 10 gadi atpakaļ
vecāks
revīzija
8e2c4c89dc

+ 2 - 3
CMakeLists.txt

@@ -20,7 +20,6 @@ set(lib_sources src/ua_types.c
                 src/util/ua_util.c
                 src/util/ua_list.c
                 src/util/ua_base64.c
-                src/server/ua_namespace.c
                 src/server/ua_server.c
                 src/server/ua_securechannel_manager.c
                 src/server/ua_session_manager.c
@@ -94,9 +93,9 @@ configure_file("src/ua_config.h.in" "${PROJECT_BINARY_DIR}/src_generated/ua_conf
 option(ENABLE_MULTITHREADING "Enable multithreading" OFF)
 if(ENABLE_MULTITHREADING)
     find_package(Threads REQUIRED)
-    list(APPEND lib_sources src/server/ua_namespace_concurrent.c)
+    list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
 else()
-    list(APPEND lib_sources src/server/ua_namespace.c)
+    list(APPEND lib_sources src/server/ua_nodestore.c)
 endif(ENABLE_MULTITHREADING)
 
 add_library(open62541 ${lib_sources}) # we can add more files to lib_sources later on

+ 28 - 26
src/server/ua_namespace.c

@@ -1,6 +1,6 @@
-#include "ua_namespace.h"
+#include "ua_nodestore.h"
 
-struct UA_Namespace {
+struct UA_NodeStore {
     const UA_Node **entries;
     UA_UInt32       size;
     UA_UInt32       count;
@@ -39,9 +39,9 @@ static INLINE UA_Int16 higher_prime_index(hash_t n) {
 }
 
 /* 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) {
-    const int32_t         nblocks = len / 4;
-    const uint32_t       *blocks;
+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;
@@ -49,7 +49,7 @@ static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len) {
     static const uint32_t r2 = 13;
     static const uint32_t m  = 5;
     static const uint32_t n  = 0xe6546b64;
-    hash_t hash = len;
+    hash_t hash = seed;
 
     if(data == UA_NULL)
         return 0;
@@ -96,23 +96,24 @@ static INLINE hash_t hash(const UA_NodeId *n) {
     switch(n->identifierType) {
     case UA_NODEIDTYPE_NUMERIC:
         /*  Knuth's multiplicative hashing */
-        return n->identifier.numeric * 2654435761;   // mod(2^32) is implicit
+        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);
+        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));
+        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);
+        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_Namespace *ns, const UA_Node **entry) {
+static INLINE void clear_entry(UA_NodeStore *ns, const UA_Node **entry) {
     const UA_Node *node;
     if(entry == UA_NULL || *entry == UA_NULL)
         return;
@@ -152,6 +153,7 @@ static INLINE void clear_entry(UA_Namespace *ns, const UA_Node **entry) {
         break;
 
     default:
+        UA_assert(UA_FALSE);
         break;
     }
     entry = UA_NULL;
@@ -160,7 +162,7 @@ static INLINE void clear_entry(UA_Namespace *ns, const UA_Node **entry) {
 
 /* 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_Int32 find_entry(const UA_Namespace *ns, const UA_NodeId *nodeid, const UA_Node ***entry) {
+static INLINE UA_Int32 find_entry(const UA_NodeStore *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);
@@ -203,7 +205,7 @@ static INLINE UA_Int32 find_entry(const UA_Namespace *ns, const UA_NodeId *nodei
    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_Int32 expand(UA_Namespace *ns) {
+static UA_Int32 expand(UA_NodeStore *ns) {
     const UA_Node **nentries;
     int32_t nsize;
     UA_UInt32       nindex;
@@ -246,10 +248,10 @@ static UA_Int32 expand(UA_Namespace *ns) {
 /* Exported functions */
 /**********************/
 
-UA_Int32 UA_Namespace_new(UA_Namespace **result) {
-    UA_Namespace *ns;
+UA_Int32 UA_NodeStore_new(UA_NodeStore **result) {
+    UA_NodeStore *ns;
     UA_UInt32     sizePrimeIndex, size;
-    if(UA_alloc((void **)&ns, sizeof(UA_Namespace)) != UA_SUCCESS)
+    if(UA_alloc((void **)&ns, sizeof(UA_NodeStore)) != UA_SUCCESS)
         return UA_ERR_NO_MEMORY;
 
     sizePrimeIndex = higher_prime_index(32);
@@ -262,12 +264,12 @@ UA_Int32 UA_Namespace_new(UA_Namespace **result) {
     /* set entries to zero */
     memset(ns->entries, 0, size * sizeof(UA_Node *));
 
-    *ns     = (UA_Namespace) {ns->entries, size, 0, sizePrimeIndex };
+    *ns     = (UA_NodeStore) {ns->entries, size, 0, sizePrimeIndex };
     *result = ns;
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_delete(UA_Namespace *ns) {
+UA_Int32 UA_NodeStore_delete(UA_NodeStore *ns) {
     UA_UInt32       size    = ns->size;
     const UA_Node **entries = ns->entries;
 
@@ -279,7 +281,7 @@ UA_Int32 UA_Namespace_delete(UA_Namespace *ns) {
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
+UA_Int32 UA_NodeStore_insert(UA_NodeStore *ns, UA_Node **node, UA_Byte flags) {
     if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL)
         return UA_ERROR;
 
@@ -291,7 +293,7 @@ UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
     const UA_Node **entry;
     UA_Int32 found = find_entry(ns, &(*node)->nodeId, &entry);
 
-    if(flags & UA_NAMESPACE_INSERT_UNIQUE) {
+    if(flags & UA_NODESTORE_INSERT_UNIQUE) {
         if(found == UA_SUCCESS)
             return UA_ERROR;    /* There is already an entry for that nodeid */
         else
@@ -302,14 +304,14 @@ UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
         *entry = *node;
     }
 
-    if(!(flags & UA_NAMESPACE_INSERT_GETMANAGED))
+    if(!(flags & UA_NODESTORE_INSERT_GETMANAGED))
         *node = UA_NULL;
 
     ns->count++;
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_get(const UA_Namespace *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
+UA_Int32 UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
     const UA_Node **entry;
     if(ns == UA_NULL || nodeid == UA_NULL || managedNode == UA_NULL)
         return UA_ERROR;
@@ -321,12 +323,12 @@ UA_Int32 UA_Namespace_get(const UA_Namespace *ns, const UA_NodeId *nodeid, const
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_remove(UA_Namespace *ns, const UA_NodeId *nodeid) {
+UA_Int32 UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) {
     const UA_Node **entry;
     if(find_entry(ns, nodeid, &entry) != UA_SUCCESS)
         return UA_ERROR;
 
-    // Check before if deleting the node makes the UA_Namespace inconsistent.
+    // Check before if deleting the node makes the UA_NodeStore inconsistent.
     clear_entry(ns, entry);
 
     /* Downsize the hashmap if it is very empty */
@@ -336,7 +338,7 @@ UA_Int32 UA_Namespace_remove(UA_Namespace *ns, const UA_NodeId *nodeid) {
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_iterate(const UA_Namespace *ns, UA_Namespace_nodeVisitor visitor) {
+UA_Int32 UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor) {
     if(ns == UA_NULL || visitor == UA_NULL)
         return UA_ERROR;
 
@@ -348,6 +350,6 @@ UA_Int32 UA_Namespace_iterate(const UA_Namespace *ns, UA_Namespace_nodeVisitor v
     return UA_SUCCESS;
 }
 
-void UA_Namespace_releaseManagedNode(const UA_Node *managed) {
+void UA_NodeStore_releaseManagedNode(const UA_Node *managed) {
     ;
 }

+ 21 - 21
src/server/ua_namespace.h

@@ -1,5 +1,5 @@
-#ifndef UA_NAMESPACE_H_
-#define UA_NAMESPACE_H_
+#ifndef UA_NODESTORE_H_
+#define UA_NODESTORE_H_
 
 #include "ua_types.h"
 #include "ua_types_generated.h"
@@ -7,13 +7,13 @@
 /**
    @ingroup server
 
-   @defgroup namespace Namespace
+   @defgroup nodestore NodeStore
 
-   @brief The namespace is the central storage for nodes in the UA address
-   space. Internally, the namespace is realised as hash-map where nodes are
+   @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 namespace are immutable. To change the content of a node, it
+   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
@@ -22,46 +22,46 @@
    @{
  */
 
-/** @brief UA_Namespace datastructure. Mainly a hashmap to UA_Nodes */
-struct UA_Namespace;
-typedef struct UA_Namespace UA_Namespace;
+/** @brief UA_NodeStore datastructure. Mainly a hashmap to UA_Nodes */
+struct UA_NodeStore;
+typedef struct UA_NodeStore UA_NodeStore;
 
 /** @brief Create a new namespace */
-UA_Int32 UA_Namespace_new(UA_Namespace **result);
+UA_Int32 UA_NodeStore_new(UA_NodeStore **result);
 
 /** @brief Delete the namespace and all nodes in it */
-UA_Int32 UA_Namespace_delete(UA_Namespace *ns);
+UA_Int32 UA_NodeStore_delete(UA_NodeStore *ns);
 
-#define UA_NAMESPACE_INSERT_UNIQUE 1
-#define UA_NAMESPACE_INSERT_GETMANAGED 2
+#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_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags);
+UA_Int32 UA_NodeStore_insert(UA_NodeStore *ns, UA_Node **node, UA_Byte flags);
 
 /** @brief Remove a node from the namespace. Always succeeds, even if the node
     was not found. */
-UA_Int32 UA_Namespace_remove(UA_Namespace *ns, const UA_NodeId *nodeid);
+UA_Int32 UA_NodeStore_remove(UA_NodeStore *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_Int32 UA_Namespace_get(const UA_Namespace *ns, const UA_NodeId *nodeid,
+UA_Int32 UA_NodeStore_get(const UA_NodeStore *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_Namespace_releaseManagedNode(const UA_Node *managed);
+void UA_NodeStore_releaseManagedNode(const UA_Node *managed);
 
 /** @brief A function that can be evaluated on all entries in a namespace via
-    UA_Namespace_iterate. Note that the visitor is read-only on the nodes. */
-typedef void (*UA_Namespace_nodeVisitor)(const UA_Node *node);
+    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. */
-UA_Int32 UA_Namespace_iterate(const UA_Namespace *ns, UA_Namespace_nodeVisitor visitor);
+UA_Int32 UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor);
 
 /// @} /* end of group */
 
-#endif /* UA_NAMESPACE_H_ */
+#endif /* UA_NODESTORE_H_ */

+ 39 - 37
src/server/ua_namespace_concurrent.c

@@ -1,4 +1,4 @@
-#include "ua_namespace.h"
+#include "ua_nodestore.h"
 
 #include <urcu.h>
 #include <urcu/compiler.h> // for caa_container_of
@@ -6,14 +6,14 @@
 #include <urcu/rculfhash.h>
 
 #define ALIVE_BIT (1 << 15) /* Alive bit in the readcount */
-typedef struct UA_Namespace_Entry {
+typedef struct UA_NodeStore_Entry {
     struct cds_lfht_node htn;      /* contains next-ptr for urcu-hashmap */
     struct rcu_head      rcu_head; /* For call-rcu */
     UA_UInt16 readcount;           /* Counts the amount of readers on it [alive-bit, 15 counter-bits] */
     UA_Node   node;                /* Might be cast from any _bigger_ UA_Node* type. Allocate enough memory! */
-} UA_Namespace_Entry;
+} UA_NodeStore_Entry;
 
-struct UA_Namespace {
+struct UA_NodeStore {
     struct cds_lfht *ht; /* Hash table */
 };
 
@@ -24,14 +24,14 @@ struct UA_Namespace {
 typedef UA_UInt32 hash_t;
 
 /* 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) {
+static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len, UA_UInt32 seed) {
     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 = len;
+    hash_t hash = seed;
 
     if(data == UA_NULL) return 0;
 
@@ -74,29 +74,30 @@ static inline hash_t hash_array(const UA_Byte *data, UA_UInt32 len) {
     return hash;
 }
 
-static inline hash_t hash(const UA_NodeId *n) {
+static INLINE hash_t hash(const UA_NodeId *n) {
     switch(n->identifierType) {
     case UA_NODEIDTYPE_NUMERIC:
         /*  Knuth's multiplicative hashing */
-        return n->identifier.numeric * 2654435761;   // mod(2^32) is implicit
+        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);
+        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));
+        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);
+        return hash_array((UA_Byte *)n->identifier.byteString.data, n->identifier.byteString.length, n->namespaceIndex);
 
     default:
+        UA_assert(UA_FALSE);
         return 0;
     }
 }
 
-/*************/
-/* UA_Namespace */
-/*************/
+/****************/
+/* UA_NodeStore */
+/****************/
 
 static inline void node_deleteMembers(const UA_Node *node) {
     switch(node->nodeClass) {
@@ -133,6 +134,7 @@ static inline void node_deleteMembers(const UA_Node *node) {
         break;
 
     default:
+        UA_assert(UA_FALSE);
         break;
     }
 }
@@ -140,7 +142,7 @@ static inline void node_deleteMembers(const UA_Node *node) {
 /* We are in a rcu_read lock. So the node will not be freed under our feet. */
 static int compare(struct cds_lfht_node *htn, const void *orig) {
     UA_NodeId *origid = (UA_NodeId *)orig;
-    UA_NodeId *newid  = &((UA_Namespace_Entry *)htn)->node.nodeId;   /* The htn is first in the entry structure. */
+    UA_NodeId *newid  = &((UA_NodeStore_Entry *)htn)->node.nodeId;   /* The htn is first in the entry structure. */
 
     return UA_NodeId_equal(newid, origid) == UA_EQUAL;
 }
@@ -150,7 +152,7 @@ static int compare(struct cds_lfht_node *htn, const void *orig) {
    section) increased the readcount, we only need to wait for the readcount
    to reach zero. */
 static void markDead(struct rcu_head *head) {
-    UA_Namespace_Entry *entry = caa_container_of(head, UA_Namespace_Entry, rcu_head);
+    UA_NodeStore_Entry *entry = caa_container_of(head, UA_NodeStore_Entry, rcu_head);
     if(uatomic_sub_return(&entry->readcount, ALIVE_BIT) > 0)
         return;
 
@@ -160,11 +162,11 @@ static void markDead(struct rcu_head *head) {
 }
 
 /* Free the entry if it is dead and nobody uses it anymore */
-void UA_Namespace_releaseManagedNode(const UA_Node *managed) {
+void UA_NodeStore_releaseManagedNode(const UA_Node *managed) {
     if(managed == UA_NULL)
         return;
 
-    UA_Namespace_Entry *entry = caa_container_of(managed, UA_Namespace_Entry, node); // pointer to the first entry
+    UA_NodeStore_Entry *entry = caa_container_of(managed, UA_NodeStore_Entry, node); // pointer to the first entry
     if(uatomic_sub_return(&entry->readcount, 1) > 0)
         return;
 
@@ -173,9 +175,9 @@ void UA_Namespace_releaseManagedNode(const UA_Node *managed) {
     return;
 }
 
-UA_Int32 UA_Namespace_new(UA_Namespace **result, UA_UInt32 namespaceIndex) {
-    UA_Namespace *ns;
-    if(UA_alloc((void **)&ns, sizeof(UA_Namespace)) != UA_SUCCESS)
+UA_Int32 UA_NodeStore_new(UA_NodeStore **result, UA_UInt32 namespaceIndex) {
+    UA_NodeStore *ns;
+    if(UA_alloc((void **)&ns, sizeof(UA_NodeStore)) != UA_SUCCESS)
         return UA_ERR_NO_MEMORY;
 
     /* 32 is the minimum size for the hashtable. */
@@ -190,7 +192,7 @@ UA_Int32 UA_Namespace_new(UA_Namespace **result, UA_UInt32 namespaceIndex) {
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_delete(UA_Namespace *ns) {
+UA_Int32 UA_NodeStore_delete(UA_NodeStore *ns) {
     if(ns == UA_NULL)
         return UA_ERROR;
 
@@ -203,7 +205,7 @@ UA_Int32 UA_Namespace_delete(UA_Namespace *ns) {
     while(iter.node != UA_NULL) {
         found_htn = cds_lfht_iter_get_node(&iter);
         if(!cds_lfht_del(ht, found_htn)) {
-            UA_Namespace_Entry *entry = caa_container_of(found_htn, UA_Namespace_Entry, htn);
+            UA_NodeStore_Entry *entry = caa_container_of(found_htn, UA_NodeStore_Entry, htn);
             call_rcu(&entry->rcu_head, markDead);
         }
         cds_lfht_next(ht, &iter);
@@ -217,7 +219,7 @@ UA_Int32 UA_Namespace_delete(UA_Namespace *ns) {
         return UA_ERROR;
 }
 
-UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
+UA_Int32 UA_NodeStore_insert(UA_NodeStore *ns, UA_Node **node, UA_Byte flags) {
     if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL || (*node)->nodeId.namespaceIndex !=
        ns->namespaceIndex)
         return UA_ERROR;
@@ -261,19 +263,19 @@ UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
         return UA_ERROR;
     }
 
-    UA_Namespace_Entry *entry;
-    if(UA_alloc((void **)&entry, sizeof(UA_Namespace_Entry) - sizeof(UA_Node) + nodesize))
+    UA_NodeStore_Entry *entry;
+    if(UA_alloc((void **)&entry, sizeof(UA_NodeStore_Entry) - sizeof(UA_Node) + nodesize))
         return UA_ERR_NO_MEMORY;
     memcpy(&entry->node, *node, nodesize);
 
     cds_lfht_node_init(&entry->htn);
     entry->readcount = ALIVE_BIT;
-    if(flags & UA_NAMESPACE_INSERT_GETMANAGED)
+    if(flags & UA_NODESTORE_INSERT_GETMANAGED)
         entry->readcount++;
 
     hash_t nhash = hash(&(*node)->nodeId);
     struct cds_lfht_node *result;
-    if(flags & UA_NAMESPACE_INSERT_UNIQUE) {
+    if(flags & UA_NODESTORE_INSERT_UNIQUE) {
         rcu_read_lock();
         result = cds_lfht_add_unique(ns->ht, nhash, compare, &entry->node.nodeId, &entry->htn);
         rcu_read_unlock();
@@ -288,14 +290,14 @@ UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
         result = cds_lfht_add_replace(ns->ht, nhash, compare, &(*node)->nodeId, &entry->htn);
         /* If an entry got replaced, mark it as dead. */
         if(result) {
-            UA_Namespace_Entry *entry = caa_container_of(result, UA_Namespace_Entry, htn);
+            UA_NodeStore_Entry *entry = caa_container_of(result, UA_NodeStore_Entry, htn);
             call_rcu(&entry->rcu_head, markDead);      /* Queue this for the next time when no readers are on the entry.*/
         }
         rcu_read_unlock();
     }
 
     UA_free((UA_Node *)*node);     /* The old node is replaced by a managed node. */
-    if(flags & UA_NAMESPACE_INSERT_GETMANAGED)
+    if(flags & UA_NODESTORE_INSERT_GETMANAGED)
         *node = &entry->node;
     else
         *node = UA_NULL;
@@ -303,7 +305,7 @@ UA_Int32 UA_Namespace_insert(UA_Namespace *ns, UA_Node **node, UA_Byte flags) {
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_remove(UA_Namespace *ns, const UA_NodeId *nodeid) {
+UA_Int32 UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) {
     hash_t nhash = hash(nodeid);
     struct cds_lfht_iter iter;
 
@@ -317,20 +319,20 @@ UA_Int32 UA_Namespace_remove(UA_Namespace *ns, const UA_NodeId *nodeid) {
         return UA_ERROR;
     }
 
-    UA_Namespace_Entry *entry = caa_container_of(found_htn, UA_Namespace_Entry, htn);
+    UA_NodeStore_Entry *entry = caa_container_of(found_htn, UA_NodeStore_Entry, htn);
     call_rcu(&entry->rcu_head, markDead);
     rcu_read_unlock();
 
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_get(const UA_Namespace *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
+UA_Int32 UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
     hash_t nhash = hash(nodeid);
     struct cds_lfht_iter iter;
 
     rcu_read_lock();
     cds_lfht_lookup(ns->ht, nhash, compare, nodeid, &iter);
-    UA_Namespace_Entry *found_entry = (UA_Namespace_Entry *)cds_lfht_iter_get_node(&iter);
+    UA_NodeStore_Entry *found_entry = (UA_NodeStore_Entry *)cds_lfht_iter_get_node(&iter);
 
     if(!found_entry) {
         rcu_read_unlock();
@@ -345,7 +347,7 @@ UA_Int32 UA_Namespace_get(const UA_Namespace *ns, const UA_NodeId *nodeid, const
     return UA_SUCCESS;
 }
 
-UA_Int32 UA_Namespace_iterate(const UA_Namespace *ns, UA_Namespace_nodeVisitor visitor) {
+UA_Int32 UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor) {
     if(ns == UA_NULL || visitor == UA_NULL)
         return UA_ERROR;
 
@@ -355,12 +357,12 @@ UA_Int32 UA_Namespace_iterate(const UA_Namespace *ns, UA_Namespace_nodeVisitor v
     rcu_read_lock();
     cds_lfht_first(ht, &iter);
     while(iter.node != UA_NULL) {
-        UA_Namespace_Entry *found_entry = (UA_Namespace_Entry *)cds_lfht_iter_get_node(&iter);
+        UA_NodeStore_Entry *found_entry = (UA_NodeStore_Entry *)cds_lfht_iter_get_node(&iter);
         uatomic_inc(&found_entry->readcount);
         const UA_Node      *node = &found_entry->node;
         rcu_read_unlock();
         visitor(node);
-        UA_Namespace_releaseManagedNode((UA_Node *)node);
+        UA_NodeStore_releaseManagedNode((UA_Node *)node);
         rcu_read_lock();
         cds_lfht_next(ht, &iter);
     }

+ 119 - 157
src/server/ua_server.c

@@ -6,10 +6,7 @@ UA_Int32 UA_Server_deleteMembers(UA_Server *server) {
     UA_ApplicationDescription_delete(&server->description);
     UA_SecureChannelManager_delete(server->secureChannelManager);
     UA_SessionManager_delete(server->sessionManager);
-    for(UA_UInt32 i = 0;i < server->namespacesSize;i++)
-        UA_Namespace_delete(server->namespaces[i].namespace);
-
-    UA_free(server->namespaces);
+    UA_NodeStore_delete(server->nodestore);
     UA_free(server);
     return UA_SUCCESS;
 }
@@ -37,109 +34,98 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
         UA_borrowed_.types[i].deleteMembers = (UA_Int32 (*)(void *))phantom_delete;
     }
 
-    // create namespaces
-    server->namespacesSize = 2;
-    UA_alloc((void **)&server->namespaces, sizeof(UA_IndexedNamespace)*2);
-
-    UA_Namespace_new(&server->namespaces[0].namespace);
-    server->namespaces[0].namespaceIndex = 0;
-    UA_Namespace *ns0 = server->namespaces[0].namespace;
-    //C2UA_STRING("http://opcfoundation.org/UA/"));
-
-    UA_Namespace_new(&server->namespaces[1].namespace);
-    server->namespaces[1].namespaceIndex = 1;
-    //UA_Namespace *ns1 = server->namespaces[1].namespace;
-    //C2UA_STRING("http://localhost:16664/open62541/"));
+    UA_NodeStore_new(&server->nodestore);
+    //ns0: C2UA_STRING("http://opcfoundation.org/UA/"));
+    //ns1: C2UA_STRING("http://localhost:16664/open62541/"));
 
     /**************/
     /* References */
     /**************/
 
     // ReferenceType Ids
-    UA_NodeId RefTypeId_References = NS0NODEID(31);
-    UA_NodeId RefTypeId_NonHierarchicalReferences  = NS0NODEID(32);
-    UA_NodeId RefTypeId_HierarchicalReferences     = NS0NODEID(33);
-    UA_NodeId RefTypeId_HasChild                   = NS0NODEID(34);
-    UA_NodeId RefTypeId_Organizes                  = NS0NODEID(35);
-    UA_NodeId RefTypeId_HasEventSource             = NS0NODEID(36);
-    UA_NodeId RefTypeId_HasModellingRule           = NS0NODEID(37);
-    UA_NodeId RefTypeId_HasEncoding                = NS0NODEID(38);
-    UA_NodeId RefTypeId_HasDescription             = NS0NODEID(39);
-    UA_NodeId RefTypeId_HasTypeDefinition          = NS0NODEID(40);
-    UA_NodeId RefTypeId_GeneratesEvent             = NS0NODEID(41);
-    UA_NodeId RefTypeId_Aggregates                 = NS0NODEID(44);
-    UA_NodeId RefTypeId_HasSubtype                 = NS0NODEID(45);
-    UA_NodeId RefTypeId_HasProperty                = NS0NODEID(46);
-    UA_NodeId RefTypeId_HasComponent               = NS0NODEID(47);
-    UA_NodeId RefTypeId_HasNotifier                = NS0NODEID(48);
-    UA_NodeId RefTypeId_HasOrderedComponent        = NS0NODEID(49);
-    UA_NodeId RefTypeId_HasModelParent             = NS0NODEID(50);
-    UA_NodeId RefTypeId_FromState                  = NS0NODEID(51);
-    UA_NodeId RefTypeId_ToState = NS0NODEID(52);
-    UA_NodeId RefTypeId_HasCause                   = NS0NODEID(53);
-    UA_NodeId RefTypeId_HasEffect                  = NS0NODEID(54);
-    UA_NodeId RefTypeId_HasHistoricalConfiguration = NS0NODEID(56);
-
-#define ADDINVERSEREFERENCE(NODE, REFTYPE, TARGET_NODEID)       \
-    static struct UA_ReferenceNode NODE##ReferenceNode;         \
-    UA_ReferenceNode_init(&NODE##ReferenceNode);                \
-    NODE##ReferenceNode.referenceTypeId       = REFTYPE;        \
-    NODE##ReferenceNode.isInverse             = UA_TRUE;        \
-    NODE##ReferenceNode.targetId.nodeId       = TARGET_NODEID;  \
-    NODE##ReferenceNode.targetId.namespaceUri = UA_STRING_NULL; \
-    NODE##ReferenceNode.targetId.serverIndex  = 0;              \
-    AddReference((UA_Node *)NODE, &NODE##ReferenceNode, ns0)
-
+    UA_ExpandedNodeId RefTypeId_References; NS0EXPANDEDNODEID(RefTypeId_References, 31);
+    UA_ExpandedNodeId RefTypeId_NonHierarchicalReferences; NS0EXPANDEDNODEID(RefTypeId_NonHierarchicalReferences, 32);
+    UA_ExpandedNodeId RefTypeId_HierarchicalReferences; NS0EXPANDEDNODEID(RefTypeId_HierarchicalReferences, 33);
+    UA_ExpandedNodeId RefTypeId_HasChild; NS0EXPANDEDNODEID(RefTypeId_HasChild, 34);
+    UA_ExpandedNodeId RefTypeId_Organizes; NS0EXPANDEDNODEID(RefTypeId_Organizes, 35);
+    UA_ExpandedNodeId RefTypeId_HasEventSource; NS0EXPANDEDNODEID(RefTypeId_HasEventSource, 36);
+    UA_ExpandedNodeId RefTypeId_HasModellingRule; NS0EXPANDEDNODEID(RefTypeId_HasModellingRule, 37);
+    UA_ExpandedNodeId RefTypeId_HasEncoding; NS0EXPANDEDNODEID(RefTypeId_HasEncoding, 38);
+    UA_ExpandedNodeId RefTypeId_HasDescription; NS0EXPANDEDNODEID(RefTypeId_HasDescription, 39);
+    UA_ExpandedNodeId RefTypeId_HasTypeDefinition; NS0EXPANDEDNODEID(RefTypeId_HasTypeDefinition, 40);
+    UA_ExpandedNodeId RefTypeId_GeneratesEvent; NS0EXPANDEDNODEID(RefTypeId_GeneratesEvent, 41);
+    UA_ExpandedNodeId RefTypeId_Aggregates; NS0EXPANDEDNODEID(RefTypeId_Aggregates, 44);
+    UA_ExpandedNodeId RefTypeId_HasSubtype; NS0EXPANDEDNODEID(RefTypeId_HasSubtype, 45);
+    UA_ExpandedNodeId RefTypeId_HasProperty; NS0EXPANDEDNODEID(RefTypeId_HasProperty, 46);
+    UA_ExpandedNodeId RefTypeId_HasComponent; NS0EXPANDEDNODEID(RefTypeId_HasComponent, 47);
+    UA_ExpandedNodeId RefTypeId_HasNotifier; NS0EXPANDEDNODEID(RefTypeId_HasNotifier, 48);
+    UA_ExpandedNodeId RefTypeId_HasOrderedComponent; NS0EXPANDEDNODEID(RefTypeId_HasOrderedComponent, 49);
+    UA_ExpandedNodeId RefTypeId_HasModelParent; NS0EXPANDEDNODEID(RefTypeId_HasModelParent, 50);
+    UA_ExpandedNodeId RefTypeId_FromState; NS0EXPANDEDNODEID(RefTypeId_FromState, 51);
+    UA_ExpandedNodeId RefTypeId_ToState; NS0EXPANDEDNODEID(RefTypeId_ToState, 52);
+    UA_ExpandedNodeId RefTypeId_HasCause; NS0EXPANDEDNODEID(RefTypeId_HasCause, 53);
+    UA_ExpandedNodeId RefTypeId_HasEffect; NS0EXPANDEDNODEID(RefTypeId_HasEffect, 54);
+    UA_ExpandedNodeId RefTypeId_HasHistoricalConfiguration; NS0EXPANDEDNODEID(RefTypeId_HasHistoricalConfiguration, 56);
+
+#define ADDREFERENCE(NODE, REFTYPE, INVERSE, TARGET_NODEID) do { \
+    static struct UA_ReferenceNode NODE##REFTYPE##TARGET_NODEID;    \
+    UA_ReferenceNode_init(&NODE##REFTYPE##TARGET_NODEID);       \
+    NODE##REFTYPE##TARGET_NODEID.referenceTypeId = REFTYPE.nodeId;     \
+    NODE##REFTYPE##TARGET_NODEID.isInverse       = INVERSE; \
+    NODE##REFTYPE##TARGET_NODEID.targetId = TARGET_NODEID; \
+    AddReference(server->nodestore, (UA_Node *)NODE, &NODE##REFTYPE##TARGET_NODEID); \
+    } while(0)
+    
     UA_ReferenceTypeNode *references;
     UA_ReferenceTypeNode_new(&references);
-    references->nodeId    = RefTypeId_References;
+    references->nodeId    = RefTypeId_References.nodeId;
     references->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(references->browseName, "References");
     UA_LOCALIZEDTEXT_STATIC(references->displayName, "References");
     UA_LOCALIZEDTEXT_STATIC(references->description, "References");
     references->isAbstract = UA_TRUE;
     references->symmetric  = UA_TRUE;
-    UA_Namespace_insert(ns0, (UA_Node**)&references, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&references, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hierarchicalreferences;
     UA_ReferenceTypeNode_new(&hierarchicalreferences);
-    hierarchicalreferences->nodeId    = RefTypeId_HierarchicalReferences;
+    hierarchicalreferences->nodeId    = RefTypeId_HierarchicalReferences.nodeId;
     hierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hierarchicalreferences->browseName, "HierarchicalReferences");
     UA_LOCALIZEDTEXT_STATIC(hierarchicalreferences->displayName, "HierarchicalReferences");
     UA_LOCALIZEDTEXT_STATIC(hierarchicalreferences->description, "HierarchicalReferences");
     hierarchicalreferences->isAbstract = UA_TRUE;
     hierarchicalreferences->symmetric  = UA_FALSE;
-    ADDINVERSEREFERENCE(hierarchicalreferences, RefTypeId_HasSubtype, RefTypeId_References);
-    UA_Namespace_insert(ns0, (UA_Node**)&hierarchicalreferences, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hierarchicalreferences, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_References);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hierarchicalreferences, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *nonhierarchicalreferences;
     UA_ReferenceTypeNode_new(&nonhierarchicalreferences);
-    nonhierarchicalreferences->nodeId    = RefTypeId_NonHierarchicalReferences;
+    nonhierarchicalreferences->nodeId    = RefTypeId_NonHierarchicalReferences.nodeId;
     nonhierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(nonhierarchicalreferences->browseName, "NonHierarchicalReferences");
     UA_LOCALIZEDTEXT_STATIC(nonhierarchicalreferences->displayName, "NonHierarchicalReferences");
     UA_LOCALIZEDTEXT_STATIC(nonhierarchicalreferences->description, "NonHierarchicalReferences");
     nonhierarchicalreferences->isAbstract = UA_TRUE;
     nonhierarchicalreferences->symmetric  = UA_FALSE;
-    ADDINVERSEREFERENCE(nonhierarchicalreferences, RefTypeId_HasSubtype, RefTypeId_References);
-    UA_Namespace_insert(ns0, (UA_Node**)&nonhierarchicalreferences, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(nonhierarchicalreferences, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_References);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&nonhierarchicalreferences, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *haschild;
     UA_ReferenceTypeNode_new(&haschild);
-    haschild->nodeId    = RefTypeId_HasChild;
+    haschild->nodeId    = RefTypeId_HasChild.nodeId;
     haschild->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(haschild->browseName, "HasChild");
     UA_LOCALIZEDTEXT_STATIC(haschild->displayName, "HasChild");
     UA_LOCALIZEDTEXT_STATIC(haschild->description, "HasChild");
     haschild->isAbstract = UA_TRUE;
     haschild->symmetric  = UA_FALSE;
-    ADDINVERSEREFERENCE(haschild, RefTypeId_HasSubtype, RefTypeId_HierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&haschild, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(haschild, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&haschild, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *organizes;
     UA_ReferenceTypeNode_new(&organizes);
-    organizes->nodeId    = RefTypeId_Organizes;
+    organizes->nodeId    = RefTypeId_Organizes.nodeId;
     organizes->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(organizes->browseName, "Organizes");
     UA_LOCALIZEDTEXT_STATIC(organizes->displayName, "Organizes");
@@ -147,12 +133,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     organizes->isAbstract = UA_FALSE;
     organizes->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(organizes->inverseName, "OrganizedBy");
-    ADDINVERSEREFERENCE(organizes, RefTypeId_HasSubtype, RefTypeId_HierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&organizes, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(organizes, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&organizes, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *haseventsource;
     UA_ReferenceTypeNode_new(&haseventsource);
-    haseventsource->nodeId    = RefTypeId_HasEventSource;
+    haseventsource->nodeId    = RefTypeId_HasEventSource.nodeId;
     haseventsource->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(haseventsource->browseName, "HasEventSource");
     UA_LOCALIZEDTEXT_STATIC(haseventsource->displayName, "HasEventSource");
@@ -160,12 +146,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     haseventsource->isAbstract = UA_FALSE;
     haseventsource->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(haseventsource->inverseName, "EventSourceOf");
-    ADDINVERSEREFERENCE(haseventsource, RefTypeId_HasSubtype, RefTypeId_HierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&haseventsource, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(haseventsource, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&haseventsource, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasmodellingrule;
     UA_ReferenceTypeNode_new(&hasmodellingrule);
-    hasmodellingrule->nodeId    = RefTypeId_HasModellingRule;
+    hasmodellingrule->nodeId    = RefTypeId_HasModellingRule.nodeId;
     hasmodellingrule->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasmodellingrule->browseName, "HasModellingRule");
     UA_LOCALIZEDTEXT_STATIC(hasmodellingrule->displayName, "HasModellingRule");
@@ -173,12 +159,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasmodellingrule->isAbstract = UA_FALSE;
     hasmodellingrule->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasmodellingrule->inverseName, "ModellingRuleOf");
-    ADDINVERSEREFERENCE(hasmodellingrule, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasmodellingrule, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasmodellingrule, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasmodellingrule, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasencoding;
     UA_ReferenceTypeNode_new(&hasencoding);
-    hasencoding->nodeId    = RefTypeId_HasEncoding;
+    hasencoding->nodeId    = RefTypeId_HasEncoding.nodeId;
     hasencoding->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasencoding->browseName, "HasEncoding");
     UA_LOCALIZEDTEXT_STATIC(hasencoding->displayName, "HasEncoding");
@@ -186,12 +172,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasencoding->isAbstract = UA_FALSE;
     hasencoding->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasencoding->inverseName, "EncodingOf");
-    ADDINVERSEREFERENCE(hasencoding, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasencoding, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasencoding, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasencoding, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasdescription;
     UA_ReferenceTypeNode_new(&hasdescription);
-    hasdescription->nodeId    = RefTypeId_HasDescription;
+    hasdescription->nodeId    = RefTypeId_HasDescription.nodeId;
     hasdescription->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasdescription->browseName, "HasDescription");
     UA_LOCALIZEDTEXT_STATIC(hasdescription->displayName, "HasDescription");
@@ -199,12 +185,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasdescription->isAbstract = UA_FALSE;
     hasdescription->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasdescription->inverseName, "DescriptionOf");
-    ADDINVERSEREFERENCE(hasdescription, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasdescription, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasdescription, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasdescription, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hastypedefinition;
     UA_ReferenceTypeNode_new(&hastypedefinition);
-    hastypedefinition->nodeId    = RefTypeId_HasTypeDefinition;
+    hastypedefinition->nodeId    = RefTypeId_HasTypeDefinition.nodeId;
     hastypedefinition->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hastypedefinition->browseName, "HasTypeDefinition");
     UA_LOCALIZEDTEXT_STATIC(hastypedefinition->displayName, "HasTypeDefinition");
@@ -212,12 +198,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hastypedefinition->isAbstract = UA_FALSE;
     hastypedefinition->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hastypedefinition->inverseName, "TypeDefinitionOf");
-    ADDINVERSEREFERENCE(hastypedefinition, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&hastypedefinition, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hastypedefinition, RefTypeId_HasSubtype, UA_TRUE,  RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hastypedefinition, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *generatesevent;
     UA_ReferenceTypeNode_new(&generatesevent);
-    generatesevent->nodeId    = RefTypeId_GeneratesEvent;
+    generatesevent->nodeId    = RefTypeId_GeneratesEvent.nodeId;
     generatesevent->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(generatesevent->browseName, "GeneratesEvent");
     UA_LOCALIZEDTEXT_STATIC(generatesevent->displayName, "GeneratesEvent");
@@ -225,24 +211,24 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     generatesevent->isAbstract = UA_FALSE;
     generatesevent->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(generatesevent->inverseName, "GeneratedBy");
-    ADDINVERSEREFERENCE(generatesevent, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&generatesevent, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(generatesevent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&generatesevent, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *aggregates;
     UA_ReferenceTypeNode_new(&aggregates);
-    aggregates->nodeId    = RefTypeId_Aggregates;
+    aggregates->nodeId    = RefTypeId_Aggregates.nodeId;
     aggregates->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(aggregates->browseName, "Aggregates");
     UA_LOCALIZEDTEXT_STATIC(aggregates->displayName, "Aggregates");
     UA_LOCALIZEDTEXT_STATIC(aggregates->description, "Aggregates");
     aggregates->isAbstract = UA_TRUE;
     aggregates->symmetric  = UA_FALSE;
-    ADDINVERSEREFERENCE(aggregates, RefTypeId_HasSubtype, RefTypeId_HasChild);
-    UA_Namespace_insert(ns0, (UA_Node**)&aggregates, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(aggregates, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasChild);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&aggregates, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hassubtype;
     UA_ReferenceTypeNode_new(&hassubtype);
-    hassubtype->nodeId    = RefTypeId_HasSubtype;
+    hassubtype->nodeId    = RefTypeId_HasSubtype.nodeId;
     hassubtype->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hassubtype->browseName, "HasSubtype");
     UA_LOCALIZEDTEXT_STATIC(hassubtype->displayName, "HasSubtype");
@@ -250,12 +236,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hassubtype->isAbstract = UA_FALSE;
     hassubtype->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hassubtype->inverseName, "SubtypeOf");
-    ADDINVERSEREFERENCE(hassubtype, RefTypeId_HasSubtype, RefTypeId_HasChild);
-    UA_Namespace_insert(ns0, (UA_Node**)&hassubtype, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hassubtype, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasChild);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hassubtype, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasproperty;
     UA_ReferenceTypeNode_new(&hasproperty);
-    hasproperty->nodeId    = RefTypeId_HasProperty;
+    hasproperty->nodeId    = RefTypeId_HasProperty.nodeId;
     hasproperty->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasproperty->browseName, "HasProperty");
     UA_LOCALIZEDTEXT_STATIC(hasproperty->displayName, "HasProperty");
@@ -263,12 +249,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasproperty->isAbstract = UA_FALSE;
     hasproperty->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasproperty->inverseName, "PropertyOf");
-    ADDINVERSEREFERENCE(hasproperty, RefTypeId_HasSubtype, RefTypeId_Aggregates);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasproperty, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasproperty, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_Aggregates);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasproperty, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hascomponent;
     UA_ReferenceTypeNode_new(&hascomponent);
-    hascomponent->nodeId    = RefTypeId_HasComponent;
+    hascomponent->nodeId    = RefTypeId_HasComponent.nodeId;
     hascomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hascomponent->browseName, "HasComponent");
     UA_LOCALIZEDTEXT_STATIC(hascomponent->displayName, "HasComponent");
@@ -276,12 +262,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hascomponent->isAbstract = UA_FALSE;
     hascomponent->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hascomponent->inverseName, "ComponentOf");
-    ADDINVERSEREFERENCE(hascomponent, RefTypeId_HasSubtype, RefTypeId_Aggregates);
-    UA_Namespace_insert(ns0, (UA_Node**)&hascomponent, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hascomponent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_Aggregates);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hascomponent, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasnotifier;
     UA_ReferenceTypeNode_new(&hasnotifier);
-    hasnotifier->nodeId    = RefTypeId_HasNotifier;
+    hasnotifier->nodeId    = RefTypeId_HasNotifier.nodeId;
     hasnotifier->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasnotifier->browseName, "HasNotifier");
     UA_LOCALIZEDTEXT_STATIC(hasnotifier->displayName, "HasNotifier");
@@ -289,12 +275,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasnotifier->isAbstract = UA_FALSE;
     hasnotifier->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasnotifier->inverseName, "NotifierOf");
-    ADDINVERSEREFERENCE(hasnotifier, RefTypeId_HasSubtype, RefTypeId_HasEventSource);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasnotifier, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasnotifier, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasEventSource);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasnotifier, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasorderedcomponent;
     UA_ReferenceTypeNode_new(&hasorderedcomponent);
-    hasorderedcomponent->nodeId    = RefTypeId_HasOrderedComponent;
+    hasorderedcomponent->nodeId    = RefTypeId_HasOrderedComponent.nodeId;
     hasorderedcomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasorderedcomponent->browseName, "HasOrderedComponent");
     UA_LOCALIZEDTEXT_STATIC(hasorderedcomponent->displayName, "HasOrderedComponent");
@@ -302,12 +288,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasorderedcomponent->isAbstract = UA_FALSE;
     hasorderedcomponent->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasorderedcomponent->inverseName, "OrderedComponentOf");
-    ADDINVERSEREFERENCE(hasorderedcomponent, RefTypeId_HasSubtype, RefTypeId_HasComponent);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasorderedcomponent, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasorderedcomponent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasComponent);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasorderedcomponent, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hasmodelparent;
     UA_ReferenceTypeNode_new(&hasmodelparent);
-    hasmodelparent->nodeId    = RefTypeId_HasModelParent;
+    hasmodelparent->nodeId    = RefTypeId_HasModelParent.nodeId;
     hasmodelparent->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hasmodelparent->browseName, "HasModelParent");
     UA_LOCALIZEDTEXT_STATIC(hasmodelparent->displayName, "HasModelParent");
@@ -315,12 +301,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hasmodelparent->isAbstract = UA_FALSE;
     hasmodelparent->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hasmodelparent->inverseName, "ModelParentOf");
-    ADDINVERSEREFERENCE(hasmodelparent, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&hasmodelparent, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hasmodelparent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasmodelparent, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *fromstate;
     UA_ReferenceTypeNode_new(&fromstate);
-    fromstate->nodeId    = RefTypeId_FromState;
+    fromstate->nodeId    = RefTypeId_FromState.nodeId;
     fromstate->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(fromstate->browseName, "FromState");
     UA_LOCALIZEDTEXT_STATIC(fromstate->displayName, "FromState");
@@ -328,12 +314,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     fromstate->isAbstract = UA_FALSE;
     fromstate->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(fromstate->inverseName, "ToTransition");
-    ADDINVERSEREFERENCE(fromstate, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&fromstate, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(fromstate, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&fromstate, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *tostate;
     UA_ReferenceTypeNode_new(&tostate);
-    tostate->nodeId    = RefTypeId_ToState;
+    tostate->nodeId    = RefTypeId_ToState.nodeId;
     tostate->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(tostate->browseName, "ToState");
     UA_LOCALIZEDTEXT_STATIC(tostate->displayName, "ToState");
@@ -341,12 +327,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     tostate->isAbstract = UA_FALSE;
     tostate->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(tostate->inverseName, "FromTransition");
-    ADDINVERSEREFERENCE(tostate, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&tostate, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(tostate, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&tostate, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hascause;
     UA_ReferenceTypeNode_new(&hascause);
-    hascause->nodeId    = RefTypeId_HasCause;
+    hascause->nodeId    = RefTypeId_HasCause.nodeId;
     hascause->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hascause->browseName, "HasCause");
     UA_LOCALIZEDTEXT_STATIC(hascause->displayName, "HasCause");
@@ -354,12 +340,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hascause->isAbstract = UA_FALSE;
     hascause->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hascause->inverseName, "MayBeCausedBy");
-    ADDINVERSEREFERENCE(hascause, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&hascause, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hascause, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hascause, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *haseffect;
     UA_ReferenceTypeNode_new(&haseffect);
-    haseffect->nodeId    = RefTypeId_HasEffect;
+    haseffect->nodeId    = RefTypeId_HasEffect.nodeId;
     haseffect->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(haseffect->browseName, "HasEffect");
     UA_LOCALIZEDTEXT_STATIC(haseffect->displayName, "HasEffect");
@@ -367,12 +353,12 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     haseffect->isAbstract = UA_FALSE;
     haseffect->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(haseffect->inverseName, "MayBeEffectedBy");
-    ADDINVERSEREFERENCE(haseffect, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-    UA_Namespace_insert(ns0, (UA_Node**)&haseffect, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(haseffect, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&haseffect, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *hashistoricalconfiguration;
     UA_ReferenceTypeNode_new(&hashistoricalconfiguration);
-    hashistoricalconfiguration->nodeId    = RefTypeId_HasHistoricalConfiguration;
+    hashistoricalconfiguration->nodeId    = RefTypeId_HasHistoricalConfiguration.nodeId;
     hashistoricalconfiguration->nodeClass = UA_NODECLASS_REFERENCETYPE;
     UA_QUALIFIEDNAME_STATIC(hashistoricalconfiguration->browseName, "HasHistoricalConfiguration");
     UA_LOCALIZEDTEXT_STATIC(hashistoricalconfiguration->displayName, "HasHistoricalConfiguration");
@@ -380,8 +366,8 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     hashistoricalconfiguration->isAbstract = UA_FALSE;
     hashistoricalconfiguration->symmetric  = UA_FALSE;
     UA_LOCALIZEDTEXT_STATIC(hashistoricalconfiguration->inverseName, "HistoricalConfigurationOf");
-    ADDINVERSEREFERENCE(hashistoricalconfiguration, RefTypeId_HasSubtype, RefTypeId_Aggregates);
-    UA_Namespace_insert(ns0, (UA_Node**)&hashistoricalconfiguration, UA_NAMESPACE_INSERT_UNIQUE);
+    ADDREFERENCE(hashistoricalconfiguration, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_Aggregates);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hashistoricalconfiguration, UA_NODESTORE_INSERT_UNIQUE);
 
 
     // ObjectTypes (Ids only)
@@ -406,15 +392,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_QUALIFIEDNAME_STATIC(folderType->browseName, "FolderType");
     UA_LOCALIZEDTEXT_STATIC(folderType->displayName, "FolderType");
     UA_LOCALIZEDTEXT_STATIC(folderType->description, "FolderType");
-    UA_Namespace_insert(ns0, (UA_Node**)&folderType, UA_NAMESPACE_INSERT_UNIQUE);
-
-#define ADDREFERENCE(NODE, REFTYPE, INVERSE, TARGET_NODEID)      \
-    static struct UA_ReferenceNode NODE##REFTYPE##TARGET_NODEID; \
-    UA_ReferenceNode_init(&NODE##REFTYPE##TARGET_NODEID);        \
-    NODE##REFTYPE##TARGET_NODEID.referenceTypeId = REFTYPE;      \
-    NODE##REFTYPE##TARGET_NODEID.isInverse       = INVERSE;      \
-    NODE##REFTYPE##TARGET_NODEID.targetId = TARGET_NODEID;       \
-    AddReference((UA_Node *)NODE, &NODE##REFTYPE##TARGET_NODEID, ns0)
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&folderType, UA_NODESTORE_INSERT_UNIQUE);
 
     // Root
     UA_ObjectNode *root;
@@ -429,7 +407,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     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_Namespace_insert(ns0, (UA_Node**)&root, UA_NAMESPACE_INSERT_UNIQUE | UA_NAMESPACE_INSERT_GETMANAGED);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&root, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
 
     // Objects
     UA_ObjectNode *objects;
@@ -441,7 +419,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_LOCALIZEDTEXT_STATIC(objects->description, "Objects");
     ADDREFERENCE(objects, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
     ADDREFERENCE(objects, RefTypeId_Organizes, UA_FALSE, ObjId_Server);
-    UA_Namespace_insert(ns0, (UA_Node**)&objects, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&objects, UA_NODESTORE_INSERT_UNIQUE);
 
     // Types
     UA_ObjectNode *types;
@@ -452,7 +430,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_LOCALIZEDTEXT_STATIC(types->displayName, "Types");
     UA_LOCALIZEDTEXT_STATIC(types->description, "Types");
     ADDREFERENCE(types, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
-    UA_Namespace_insert(ns0, (UA_Node**)&types, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&types, UA_NODESTORE_INSERT_UNIQUE);
 
     // Views
     UA_ObjectNode *views;
@@ -463,7 +441,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_LOCALIZEDTEXT_STATIC(views->displayName, "Views");
     UA_LOCALIZEDTEXT_STATIC(views->description, "Views");
     ADDREFERENCE(views, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
-    UA_Namespace_insert(ns0, (UA_Node**)&views, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&views, UA_NODESTORE_INSERT_UNIQUE);
 
     // Server
     UA_ObjectNode *servernode;
@@ -477,16 +455,16 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     ADDREFERENCE(servernode, RefTypeId_HasComponent, UA_FALSE, ObjId_NamespaceArray);
     ADDREFERENCE(servernode, RefTypeId_HasProperty, UA_FALSE, ObjId_ServerStatus);
     ADDREFERENCE(servernode, RefTypeId_HasProperty, UA_FALSE, ObjId_ServerArray);
-    UA_Namespace_insert(ns0, (UA_Node**)&servernode, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&servernode, UA_NODESTORE_INSERT_UNIQUE);
 
     // NamespaceArray
     UA_VariableNode *namespaceArray;
     UA_VariableNode_new(&namespaceArray);
     namespaceArray->nodeId    = ObjId_NamespaceArray.nodeId;
     namespaceArray->nodeClass = UA_NODECLASS_VARIABLE; //FIXME: this should go into _new?
-    UA_QUALIFIEDNAME_STATIC(namespaceArray->browseName, "NamespaceArray");
-    UA_LOCALIZEDTEXT_STATIC(namespaceArray->displayName, "NamespaceArray");
-    UA_LOCALIZEDTEXT_STATIC(namespaceArray->description, "NamespaceArray");
+    UA_QUALIFIEDNAME_STATIC(namespaceArray->browseName, "NodeStoreArray");
+    UA_LOCALIZEDTEXT_STATIC(namespaceArray->displayName, "NodeStoreArray");
+    UA_LOCALIZEDTEXT_STATIC(namespaceArray->description, "NodeStoreArray");
     UA_Array_new((void **)&namespaceArray->value.data, 2, &UA_.types[UA_STRING]);
     namespaceArray->value.vt = &UA_.types[UA_STRING];
     namespaceArray->value.arrayLength = 2;
@@ -502,7 +480,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     namespaceArray->valueRank       = 1;
     namespaceArray->minimumSamplingInterval = 1.0;
     namespaceArray->historizing     = UA_FALSE;
-    UA_Namespace_insert(ns0, (UA_Node**)&namespaceArray, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&namespaceArray, UA_NODESTORE_INSERT_UNIQUE);
 
     // ServerStatus
     UA_VariableNode *serverstatus;
@@ -528,7 +506,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     serverstatus->value.vt          = &UA_.types[UA_SERVERSTATUSDATATYPE]; // gets encoded as an extensionobject
     serverstatus->value.arrayLength = 1;
     serverstatus->value.data        = status;
-    UA_Namespace_insert(ns0, (UA_Node**)&serverstatus, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&serverstatus, UA_NODESTORE_INSERT_UNIQUE);
 
     // State (Component of ServerStatus)
     UA_VariableNode *state;
@@ -542,11 +520,10 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     state->value.arrayDimensionsLength = 1; // added to ensure encoding in readreponse
     state->value.arrayLength = 1;
     state->value.data = &status->state; // points into the other object.
-    UA_Namespace_insert(ns0, (UA_Node**)&state, UA_NAMESPACE_INSERT_UNIQUE);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&state, UA_NODESTORE_INSERT_UNIQUE);
 
     //TODO: free(namespaceArray->value.data) later or forget it
 
-
     /* UA_VariableNode* v = (UA_VariableNode*)np; */
     /* UA_Array_new((void**)&v->value.data, 2, &UA_.types[UA_STRING]); */
     /* v->value.vt = &UA_.types[UA_STRING]; */
@@ -558,22 +535,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     /* v->valueRank = 1; */
     /* v->minimumSamplingInterval = 1.0; */
     /* v->historizing = UA_FALSE; */
-    /* UA_Namespace_insert(ns0,np); */
-
-    /*******************/
-    /* Namespace local */
-    /*******************/
-
-    UA_Namespace_releaseManagedNode((const UA_Node *)root);
+    /* UA_NodeStore_insert(server->nodestore,np); */
 
-#if defined(DEBUG) && defined(VERBOSE)
-    uint32_t i;
-    for(i = 0; i < ns0->size; i++) {
-    if(ns0->entries[i].node != UA_NULL) {
-        printf("application_init - entries[%d]={", i);
-        UA_Node_print(ns0->entries[i].node, stdout);
-        printf("}\n");
-    }
-    }
-#endif
+    UA_NodeStore_releaseManagedNode((const UA_Node *)root);
 }

+ 5 - 11
src/server/ua_server.h

@@ -3,26 +3,20 @@
 
 #include "ua_types.h"
 #include "ua_types_generated.h"
-#include "ua_namespace.h"
+#include "ua_nodestore.h"
 #include "ua_securechannel_manager.h"
 #include "ua_session_manager.h"
 #include "util/ua_log.h"
 
 /**
-   @defgroup server
+   @defgroup server Server
  */
 
-typedef struct UA_IndexedNamespace {
-    UA_UInt32 namespaceIndex;
-    UA_Namespace *namespace;
-} UA_IndexedNamespace;
-
 typedef struct UA_Server {
     UA_ApplicationDescription description;
-    UA_SecureChannelManager  *secureChannelManager;
-    UA_SessionManager   *sessionManager;
-    UA_UInt32 namespacesSize;
-    UA_IndexedNamespace *namespaces;
+    UA_SecureChannelManager *secureChannelManager;
+    UA_SessionManager *sessionManager;
+    UA_NodeStore *nodestore;
     UA_Logger logger;
 } UA_Server;
 

+ 5 - 33
src/server/ua_services_attribute.c

@@ -37,22 +37,8 @@ static UA_DataValue service_read_node(UA_Server *server, const UA_ReadValueId *i
     UA_DataValue v;
     UA_DataValue_init(&v);
 
-    UA_Namespace *ns = UA_NULL;
-    for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
-        if(server->namespaces[i].namespaceIndex == id->nodeId.namespaceIndex) {
-            ns = server->namespaces[i].namespace;
-            break;
-        }
-    }
-
-    if(ns == UA_NULL) {
-    v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-    v.status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
-    return v;
-    }
-
     UA_Node const *node   = UA_NULL;
-    UA_Int32       result = UA_Namespace_get(ns, &(id->nodeId), &node);
+    UA_Int32       result = UA_NodeStore_get(server->nodestore, &(id->nodeId), &node);
     if(result != UA_SUCCESS || node == UA_NULL) {
         v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
         v.status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -215,7 +201,7 @@ static UA_DataValue service_read_node(UA_Server *server, const UA_ReadValueId *i
         break;
     }
 
-    UA_Namespace_releaseManagedNode(node);
+    UA_NodeStore_releaseManagedNode(node);
 
     if(retval != UA_SUCCESS) {
         v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
@@ -253,23 +239,9 @@ UA_Int32 Service_Read(UA_Server *server, UA_Session *session, const UA_ReadReque
 
 UA_Int32 Service_Write_writeNode(UA_Server *server, UA_WriteValue *writeValue,
                                  UA_StatusCode *result) {
-    UA_Int32      retval = UA_SUCCESS;
-
-    UA_Namespace *ns     = UA_NULL;
-    for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
-        if(server->namespaces[i].namespaceIndex == writeValue->nodeId.namespaceIndex) {
-            ns = server->namespaces[i].namespace;
-            break;
-        }
-    }
-
-    if(ns == UA_NULL) {
-    *result = UA_STATUSCODE_BADNODEIDINVALID;
-    return UA_ERROR;
-    }
-
+    UA_Int32 retval = UA_SUCCESS;
     const UA_Node *node;
-    if(UA_Namespace_get(ns, &writeValue->nodeId, &node) != UA_SUCCESS)
+    if(UA_NodeStore_get(server->nodestore, &writeValue->nodeId, &node) != UA_SUCCESS)
         return UA_ERROR;
 
     switch(writeValue->attributeId) {
@@ -404,7 +376,7 @@ UA_Int32 Service_Write_writeNode(UA_Server *server, UA_WriteValue *writeValue,
         break;
     }
 
-    UA_Namespace_releaseManagedNode(node);
+    UA_NodeStore_releaseManagedNode(node);
     return retval;
 
 }

+ 2 - 3
src/server/ua_services_internal.h

@@ -3,8 +3,7 @@
  * internally as well (with a simplified API as no access rights are checked).
  */
 
-#include "ua_namespace.h"
-#include "ua_types.h"
+#include "ua_nodestore.h"
 #include "ua_types_generated.h"
 
 /* @brief Add a reference (and the inverse reference to the target node).
@@ -13,4 +12,4 @@
  * @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_Node *node, UA_ReferenceNode *reference, UA_Namespace *targetns);
+UA_Int32 AddReference(UA_NodeStore *targetns, UA_Node *node, UA_ReferenceNode *reference);

+ 11 - 35
src/server/ua_services_nodemanagement.c

@@ -1,6 +1,6 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
-#include "ua_namespace.h"
+#include "ua_nodestore.h"
 #include "ua_services_internal.h"
 #include "ua_session.h"
 
@@ -16,43 +16,19 @@ static UA_AddNodesResult addSingleNode(UA_Server *server, UA_AddNodesItem *item)
     UA_AddNodesResult_init(&result);
 
     // TODO: search for namespaceUris and not only ns-ids.
-    UA_Namespace *parent_ns = UA_NULL;
-    for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
-        if(server->namespaces[i].namespaceIndex == item->parentNodeId.nodeId.namespaceIndex) {
-            parent_ns = server->namespaces[i].namespace;
-            break;
-        }
-    }
-
-    if(parent_ns == UA_NULL) {
-    result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
-    return result;
-    }
+    /* UA_Boolean    nodeid_isnull = UA_NodeId_isNull(&item->requestedNewNodeId.nodeId); */
 
-    UA_Namespace *ns = UA_NULL;
-    UA_Boolean    nodeid_isnull = UA_NodeId_isNull(&item->requestedNewNodeId.nodeId);
-
-    if(nodeid_isnull) ns = parent_ns;
-    else {
-        for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
-            if(server->namespaces[i].namespaceIndex == item->requestedNewNodeId.nodeId.namespaceIndex) {
-                parent_ns = server->namespaces[i].namespace;
-                break;
-            }
-        }
-    }
-
-    if(ns == UA_NULL || item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
-    result.statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
-    return result;
+    if(item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
+        result.statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
+        return result;
     }
 
     UA_Int32       status = UA_SUCCESS;
     const UA_Node *parent;
-    CHECKED_ACTION(UA_Namespace_get(parent_ns, &item->parentNodeId.nodeId, &parent),
+    CHECKED_ACTION(UA_NodeStore_get(server->nodestore, &item->parentNodeId.nodeId, &parent),
                    result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
 
-    /* if(!nodeid_isnull && Namespace_contains(ns, &item->requestedNewNodeId.nodeId)) { */
+    /* if(!nodeid_isnull && NodeStore_contains(ns, &item->requestedNewNodeId.nodeId)) { */
     /*  result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; */
     /*  goto ret; */
     /* } */
@@ -76,7 +52,7 @@ static UA_AddNodesResult addSingleNode(UA_Server *server, UA_AddNodesItem *item)
      */
 
 ret:
-    UA_Namespace_releaseManagedNode(parent);
+    UA_NodeStore_releaseManagedNode(parent);
     return result;
 }
 
@@ -129,7 +105,7 @@ static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
     return retval;
 }
 
-UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, UA_Namespace *targetns) {
+UA_Int32 AddReference(UA_NodeStore *targetns, UA_Node *node, UA_ReferenceNode *reference) {
     UA_Int32 retval = AddSingleReference(node, reference);
     UA_Node *targetnode;
     UA_ReferenceNode inversereference;
@@ -137,7 +113,7 @@ UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, UA_Namespace *
         return retval;
 
     // Do a copy every time?
-    if(UA_Namespace_get(targetns, &reference->targetId.nodeId, (const UA_Node **)&targetnode) != UA_SUCCESS)
+    if(UA_NodeStore_get(targetns, &reference->targetId.nodeId, (const UA_Node **)&targetnode) != UA_SUCCESS)
         return UA_ERROR;
 
     inversereference.referenceTypeId       = reference->referenceTypeId;
@@ -146,7 +122,7 @@ UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, UA_Namespace *
     inversereference.targetId.namespaceUri = UA_STRING_NULL;
     inversereference.targetId.serverIndex  = 0;
     retval = AddSingleReference(targetnode, &inversereference);
-    UA_Namespace_releaseManagedNode(targetnode);
+    UA_NodeStore_releaseManagedNode(targetnode);
 
     return retval;
 }

+ 13 - 28
src/server/ua_services_view.c

@@ -1,11 +1,11 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 
-UA_Int32 Service_Browse_getReferenceDescription(UA_Namespace *ns, UA_ReferenceNode *reference,
+UA_Int32 Service_Browse_getReferenceDescription(UA_NodeStore *ns, UA_ReferenceNode *reference,
                                                 UA_UInt32 nodeClassMask, UA_UInt32 resultMask,
                                                 UA_ReferenceDescription *referenceDescription) {
     const UA_Node *foundNode;
-    if(UA_Namespace_get(ns, &reference->targetId.nodeId, &foundNode) != UA_SUCCESS)
+    if(UA_NodeStore_get(ns, &reference->targetId.nodeId, &foundNode) != UA_SUCCESS)
         return UA_ERROR;
 
     UA_NodeId_copy(&foundNode->nodeId, &referenceDescription->nodeId.nodeId);
@@ -52,7 +52,7 @@ UA_Int32 Service_Browse_getReferenceDescription(UA_Namespace *ns, UA_ReferenceNo
         }
     }
 
-    UA_Namespace_releaseManagedNode(foundNode);
+    UA_NodeStore_releaseManagedNode(foundNode);
     return UA_SUCCESS;
 }
 
@@ -63,7 +63,7 @@ struct SubRefTypeId {
 };
 SLIST_HEAD(SubRefTypeIdList, SubRefTypeId);
 
-UA_UInt32 walkReferenceTree(UA_Namespace *ns, const UA_ReferenceTypeNode *current,
+UA_UInt32 walkReferenceTree(UA_NodeStore *ns, const UA_ReferenceTypeNode *current,
                             struct SubRefTypeIdList *list) {
     // insert the current referencetype
     struct SubRefTypeId *element;
@@ -78,10 +78,10 @@ UA_UInt32 walkReferenceTree(UA_Namespace *ns, const UA_ReferenceTypeNode *curren
         if(current->references[i].referenceTypeId.identifier.numeric == 45 /* HasSubtype */ &&
            current->references[i].isInverse == UA_FALSE) {
             const UA_Node *node;
-            if(UA_Namespace_get(ns, &current->references[i].targetId.nodeId, &node) == UA_SUCCESS
+            if(UA_NodeStore_get(ns, &current->references[i].targetId.nodeId, &node) == UA_SUCCESS
                && node->nodeClass == UA_NODECLASS_REFERENCETYPE) {
                 count += walkReferenceTree(ns, (UA_ReferenceTypeNode *)node, list);
-                UA_Namespace_releaseManagedNode(node);
+                UA_NodeStore_releaseManagedNode(node);
             }
         }
     }
@@ -89,7 +89,7 @@ UA_UInt32 walkReferenceTree(UA_Namespace *ns, const UA_ReferenceTypeNode *curren
 }
 
 /* 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_Namespace *ns, UA_NodeId *rootReferenceType,
+static UA_Int32 findSubReferenceTypes(UA_NodeStore *ns, UA_NodeId *rootReferenceType,
                                       UA_NodeId **ids, UA_UInt32 *idcount) {
     struct SubRefTypeIdList list;
     UA_UInt32 count;
@@ -97,11 +97,11 @@ static UA_Int32 findSubReferenceTypes(UA_Namespace *ns, UA_NodeId *rootReference
 
     // walk the tree
     const UA_ReferenceTypeNode *root;
-    if(UA_Namespace_get(ns, rootReferenceType, (const UA_Node **)&root) != UA_SUCCESS ||
+    if(UA_NodeStore_get(ns, rootReferenceType, (const UA_Node **)&root) != UA_SUCCESS ||
        root->nodeClass != UA_NODECLASS_REFERENCETYPE)
         return UA_ERROR;
     count = walkReferenceTree(ns, root, &list);
-    UA_Namespace_releaseManagedNode((const UA_Node *)root);
+    UA_NodeStore_releaseManagedNode((const UA_Node *)root);
 
     // copy results into an array
     UA_alloc((void **)ids, sizeof(UA_NodeId)*count);
@@ -135,14 +135,14 @@ static INLINE UA_Boolean Service_Browse_returnReference(UA_BrowseDescription *br
 }
 
 /* Return results to a single browsedescription. */
-static void Service_Browse_getBrowseResult(UA_Namespace         *ns,
+static void Service_Browse_getBrowseResult(UA_NodeStore         *ns,
                                            UA_BrowseDescription *browseDescription,
                                            UA_UInt32             maxReferences,
                                            UA_BrowseResult      *browseResult) {
     const UA_Node *node;
     UA_NodeId     *relevantReferenceTypes;
     UA_UInt32      relevantReferenceTypesCount = 0;
-    if(UA_Namespace_get(ns, &browseDescription->nodeId, &node) != UA_SUCCESS) {
+    if(UA_NodeStore_get(ns, &browseDescription->nodeId, &node) != UA_SUCCESS) {
         browseResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return;
     }
@@ -198,7 +198,7 @@ static void Service_Browse_getBrowseResult(UA_Namespace         *ns,
         // Todo. Set the Statuscode and the continuation point.
     }
 
-    UA_Namespace_releaseManagedNode(node);
+    UA_NodeStore_releaseManagedNode(node);
     UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesCount, &UA_.types[UA_NODEID]);
 }
 
@@ -213,23 +213,8 @@ UA_Int32 Service_Browse(UA_Server *server, UA_Session *session,
     response->resultsSize = request->nodesToBrowseSize;
 
     for(UA_Int32 i = 0;i < request->nodesToBrowseSize;i++) {
-        UA_Namespace *ns = UA_NULL;
-
-        for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
-            if(server->namespaces[i].namespaceIndex ==
-               request->nodesToBrowse[i].nodeId.namespaceIndex) {
-                ns = server->namespaces[i].namespace;
-                break;
-            }
-        }
-
-        if(ns == UA_NULL) {
-        response->results[i].statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
-        continue;
-        }
-
         // Service_Browse_getBrowseResult has no return value. All errors are resolved internally.
-        Service_Browse_getBrowseResult(ns, &request->nodesToBrowse[i],
+        Service_Browse_getBrowseResult(server->nodestore, &request->nodesToBrowse[i],
                                        request->requestedMaxReferencesPerNode,
                                        &response->results[i]);
     }