/* * Find an event using the name and signature in the given registry. RCU read * side lock MUST be acquired before calling this function and as long as the * event reference is kept by the caller. * * On success, the event pointer is returned else NULL. */ struct ust_registry_event *ust_registry_find_event( struct ust_registry_channel *chan, char *name, char *sig) { struct lttng_ht_node_u64 *node; struct lttng_ht_iter iter; struct ust_registry_event *event = NULL; struct ust_registry_event key; assert(chan); assert(name); assert(sig); /* Setup key for the match function. */ strncpy(key.name, name, sizeof(key.name)); key.name[sizeof(key.name) - 1] = '\0'; key.signature = sig; cds_lfht_lookup(chan->ht->ht, chan->ht->hash_fct(&key, lttng_ht_seed), chan->ht->match_fct, &key, &iter.iter); node = lttng_ht_iter_get_node_u64(&iter); if (!node) { goto end; } event = caa_container_of(node, struct ust_registry_event, node); end: return event; }
/* * Lookup function in hashtable. */ void lttng_ht_lookup(struct lttng_ht *ht, void *key, struct lttng_ht_iter *iter) { assert(ht); assert(ht->ht); cds_lfht_lookup(ht->ht, ht->hash_fct(key, lttng_ht_seed), ht->match_fct, key, &iter->iter); }
UA_StatusCode UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) { hash_t nhash = hash(nodeid); struct cds_lfht_iter iter; rcu_read_lock(); /* If this fails, then the node has already been removed. */ cds_lfht_lookup(ns->ht, nhash, compare, &nodeid, &iter); if(!iter.node || cds_lfht_del(ns->ht, iter.node) != 0) { rcu_read_unlock(); return UA_STATUSCODE_BADNODEIDUNKNOWN; } struct nodeEntry *entry = (struct nodeEntry*) ((uintptr_t)iter.node - offsetof(struct nodeEntry, htn)); call_rcu(&entry->rcu_head, markDead); rcu_read_unlock(); return UA_STATUSCODE_GOOD; }
const UA_Node * UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid) { hash_t nhash = hash(nodeid); struct cds_lfht_iter iter; rcu_read_lock(); cds_lfht_lookup(ns->ht, nhash, compare, nodeid, &iter); struct nodeEntry *found_entry = (struct nodeEntry *)cds_lfht_iter_get_node(&iter); if(!found_entry) { rcu_read_unlock(); return NULL; } /* This is done within a read-lock. The node will not be marked dead within a read-lock. */ uatomic_inc(&found_entry->refcount); rcu_read_unlock(); return &found_entry->node; }
UA_StatusCode UA_NodeStore_replace(UA_NodeStore *ns, const UA_Node *oldNode, UA_Node *node, const UA_Node **inserted) { size_t nodesize; /* Copy the node into the entry. Then reset the original node. It shall no longer be used. */ switch(node->nodeClass) { case UA_NODECLASS_OBJECT: nodesize = sizeof(UA_ObjectNode); break; case UA_NODECLASS_VARIABLE: nodesize = sizeof(UA_VariableNode); break; case UA_NODECLASS_METHOD: nodesize = sizeof(UA_MethodNode); break; case UA_NODECLASS_OBJECTTYPE: nodesize = sizeof(UA_ObjectTypeNode); break; case UA_NODECLASS_VARIABLETYPE: nodesize = sizeof(UA_VariableTypeNode); break; case UA_NODECLASS_REFERENCETYPE: nodesize = sizeof(UA_ReferenceTypeNode); break; case UA_NODECLASS_DATATYPE: nodesize = sizeof(UA_DataTypeNode); break; case UA_NODECLASS_VIEW: nodesize = sizeof(UA_ViewNode); break; default: return UA_STATUSCODE_BADINTERNALERROR; } struct nodeEntry *newEntry; if(!(newEntry = UA_malloc(sizeof(struct nodeEntry) - sizeof(UA_Node) + nodesize))) return UA_STATUSCODE_BADOUTOFMEMORY; memcpy((void*)&newEntry->node, node, nodesize); cds_lfht_node_init(&newEntry->htn); newEntry->refcount = ALIVE_BIT; if(inserted) // increase the counter before adding the node newEntry->refcount++; hash_t h = hash(&node->nodeId); struct cds_lfht_iter iter; rcu_read_lock(); cds_lfht_lookup(ns->ht, h, compare, &node->nodeId, &iter); /* No node found that can be replaced */ if(!iter.node) { rcu_read_unlock(); UA_free(newEntry); return UA_STATUSCODE_BADNODEIDUNKNOWN; } struct nodeEntry *oldEntry = (struct nodeEntry*) ((uintptr_t)iter.node - offsetof(struct nodeEntry, htn)); /* The node we found is obsolete*/ if(&oldEntry->node != oldNode) { rcu_read_unlock(); UA_free(newEntry); return UA_STATUSCODE_BADINTERNALERROR; } /* The old node is replaced by a managed node. */ if(cds_lfht_replace(ns->ht, &iter, h, compare, &node->nodeId, &newEntry->htn) != 0) { /* Replacing failed. Maybe the node got replaced just before this thread tried to.*/ rcu_read_unlock(); UA_free(newEntry); return UA_STATUSCODE_BADINTERNALERROR; } /* If an entry got replaced, mark it as dead. */ call_rcu(&oldEntry->rcu_head, markDead); rcu_read_unlock(); UA_free(node); if(inserted) *inserted = &newEntry->node; return UA_STATUSCODE_GOOD; }