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

create unique namespace entry and check membership

the functionality is required for the addnode service
Julius Pfrommer лет назад: 10
Родитель
Сommit
f69da45e52
2 измененных файлов с 50 добавлено и 8 удалено
  1. 43 8
      src/ua_namespace.c
  2. 7 0
      src/ua_namespace.h

+ 43 - 8
src/ua_namespace.c

@@ -230,14 +230,10 @@ static inline void clear_slot(Namespace * ns, Namespace_Entry * slot) {
 
 static inline UA_Int32 find_slot(const Namespace * ns, Namespace_Entry ** slot, const UA_NodeId * nodeid) {
 	hash_t h = hash(nodeid);
-	hash_t index, hash2;
-	UA_UInt32 size;
-	Namespace_Entry *entry;
-
-	size = ns->size;
-	index = mod(h, ns);
+	hash_t index = mod(h, ns);
+	UA_UInt32 size = ns->size;
+	Namespace_Entry *entry = &ns->entries[index];
 
-	entry = &ns->entries[index];
 	if(entry == UA_NULL)
 		return UA_ERROR;
 	if(UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
@@ -245,7 +241,7 @@ static inline UA_Int32 find_slot(const Namespace * ns, Namespace_Entry ** slot,
 		return UA_SUCCESS;
 	}
 
-	hash2 = mod_m2(h, ns);
+	hash_t hash2 = mod_m2(h, ns);
 	for(;;) {
 		index += hash2;
 		if(index >= size)
@@ -406,6 +402,45 @@ UA_Int32 Namespace_insert(Namespace * ns, UA_Node * node) {
 	return UA_SUCCESS;
 }
 
+UA_Int32 Namespace_insertUnique(Namespace * ns, UA_Node * node, UA_NodeId * new_nodeid) {
+	if(ns->size * 3 <= ns->count * 4) {
+		if(expand(ns) != UA_SUCCESS)
+			return UA_ERROR;
+	}
+
+	// find unoccupied numeric nodeid
+	new_nodeid->identifier.numeric = ns->count;
+	Namespace_Entry *slot = UA_NULL;
+
+	hash_t h = hash(new_nodeid);
+	hash_t hash2 = mod_m2(h, ns);
+	UA_UInt32 size = ns->size;
+
+	// change integer pseudo-randomly until a free slot is found
+	while(1) {
+		if(find_slot(ns, &slot, new_nodeid) != UA_SUCCESS)
+			break;
+		new_nodeid->identifier.numeric += hash2;
+		if(new_nodeid->identifier.numeric >= size)
+			new_nodeid->identifier.numeric -= size;
+	}
+
+#ifdef MULTITHREADING
+	if(UA_alloc((void **)&slot->lock, sizeof(pthread_rwlock_t)) != UA_SUCCESS)
+		return UA_ERR_NO_MEMORY;
+	pthread_rwlock_init((pthread_rwlock_t *) slot->lock, NULL);
+#endif
+
+	slot->node = node;
+	ns->count++;
+	return UA_SUCCESS;
+}
+
+UA_Int32 Namespace_contains(Namespace * ns, UA_NodeId * nodeid) {
+	Namespace_Entry *slot;
+	return find_slot(ns, &slot, nodeid);
+}
+
 UA_Int32 Namespace_get(Namespace const *ns, const UA_NodeId * nodeid, UA_Node const **result, Namespace_Lock ** lock) {
 	Namespace_Entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS)

+ 7 - 0
src/ua_namespace.h

@@ -60,9 +60,16 @@ void Namespace_delete(Namespace * ns);
 /** @brief Insert a new node into the namespace */
 UA_Int32 Namespace_insert(Namespace * ns, UA_Node * node);
 
+/** @brief Find an unused (numeric) NodeId in the namespace, create a slot under
+ * the NodeId and return both */
+UA_Int32 Namespace_insertUnique(Namespace * ns, UA_Node * node, UA_NodeId * new_nodeid); 
+
 /** @brief Remove a node from the namespace */
 void Namespace_remove(Namespace * ns, UA_NodeId * nodeid);
 
+/** @brief Tests whether the namespace contains an entry for a given NodeId */
+UA_Int32 Namespace_contains(Namespace * ns, UA_NodeId * nodeid);
+
 /** @brief Retrieve a node (read-only) from the namespace. Nodes are identified
 	by their NodeId. After the Node is no longer used, the lock needs to be
 	released. */