/** * * Key_Locate: Locate a buffer key in the hash table, as a rbt node. * * This function is for internal use only * * @param ht the hashtable to be used. * @param buffkey a pointeur to an object of type hash_buffer_t which describe the key location in memory. * @param hashval hash value associated with the key (in order to avoid computing it a second time) * @param rbt_value rbt value associated with the key (in order to avoid computing it a second time) * @param ppnode if successfull,will point to the pointer to the rbt node to be used * * @return HASHTABLE_SUCCESS if successfull\n. * @return HASHTABLE_NO_SUCH_KEY if key was not found * */ static int Key_Locate(hash_table_t * ht, hash_buffer_t * buffkey, unsigned int hashval, int rbt_value, struct rbt_node **ppnode) { struct rbt_head *tete_rbt; hash_data_t *pdata = NULL; struct rbt_node *pn; int found = 0; /* Sanity check */ if(ht == NULL || buffkey == NULL || ppnode == NULL) return HASHTABLE_ERROR_INVALID_ARGUMENT; /* Find the head of the rbt */ tete_rbt = &(ht->array_rbt[hashval]); /* I get the node with this value that is located on the left (first with this value in the rbtree) */ RBT_FIND_LEFT(tete_rbt, pn, rbt_value); /* Find was successfull ? */ if(pn == NULL) return HASHTABLE_ERROR_NO_SUCH_KEY; /* For each entry with this value, compare the key value */ while((pn != 0) && (RBT_VALUE(pn) == rbt_value)) { pdata = (hash_data_t *) RBT_OPAQ(pn); /* Verify the key value : this function returns 0 if key are indentical */ if(!ht->parameter.compare_key(buffkey, &(pdata->buffkey))) { found = 1; break; /* exit the while loop */ } RBT_INCREMENT(pn); } /* while */ /* We didn't find anything */ if(!found) return HASHTABLE_ERROR_NO_SUCH_KEY; /* Key was found */ *ppnode = pn; return HASHTABLE_SUCCESS; } /* Key_Locate */
/** * @brief Locate a key within a partition * * This function traverses the red-black tree within a hash table * partition and returns, if one exists, a pointer to a node matching * the supplied key. * * @param[in] ht The hashtable to be used * @param[in] key The key to look up * @param[in] index Index into RBT array * @param[in] rbthash Hash in red-black tree * @param[out] node On success, the found node, NULL otherwise * * @retval HASHTABLE_SUCCESS if successfull * @retval HASHTABLE_NO_SUCH_KEY if key was not found */ static hash_error_t key_locate(struct hash_table *ht, const struct gsh_buffdesc *key, uint32_t index, uint64_t rbthash, struct rbt_node **node) { /* The current partition */ struct hash_partition *partition = &(ht->partitions[index]); /* The root of the red black tree matching this index */ struct rbt_head *root = NULL; /* A pair of buffer descriptors locating key and value for this entry */ struct hash_data *data = NULL; /* The node in the red-black tree currently being traversed */ struct rbt_node *cursor = NULL; /* true if we have located the key */ int found = false; *node = NULL; if (partition->cache) { void **cache_slot = (void **) &(partition->cache[cache_offsetof(ht, rbthash)]); cursor = atomic_fetch_voidptr(cache_slot); LogFullDebug(COMPONENT_HASHTABLE_CACHE, "hash %s index %" PRIu32 " slot %d", (cursor) ? "hit" : "miss", index, cache_offsetof(ht, rbthash)); if (cursor) { data = RBT_OPAQ(cursor); if (ht->parameter. compare_key((struct gsh_buffdesc *)key, &(data->key)) == 0) { goto out; } } } root = &(ht->partitions[index].rbt); /* The lefmost occurrence of the value is the one from which we may start iteration to visit all nodes containing a value. */ RBT_FIND_LEFT(root, cursor, rbthash); if (cursor == NULL) { if (isFullDebug(COMPONENT_HASHTABLE) && isFullDebug(ht->parameter.ht_log_component)) LogFullDebug(ht->parameter.ht_log_component, "Key not found: rbthash = %" PRIu64, rbthash); return HASHTABLE_ERROR_NO_SUCH_KEY; } while ((cursor != NULL) && (RBT_VALUE(cursor) == rbthash)) { data = RBT_OPAQ(cursor); if (ht->parameter. compare_key((struct gsh_buffdesc *)key, &(data->key)) == 0) { if (partition->cache) { void **cache_slot = (void **) &(partition-> cache[cache_offsetof(ht, rbthash)]); atomic_store_voidptr(cache_slot, cursor); } found = true; break; } RBT_INCREMENT(cursor); } if (!found) { if (isFullDebug(COMPONENT_HASHTABLE) && isFullDebug(ht->parameter.ht_log_component)) LogFullDebug(ht->parameter.ht_log_component, "Matching hash found, but no matching key."); return HASHTABLE_ERROR_NO_SUCH_KEY; } out: *node = cursor; return HASHTABLE_SUCCESS; }