static bool lookup_by_uid(const uid_t uid, struct cache_info **info) { struct cache_info prototype = { .uid = uid }; void **cache_slot = (void **) &uid_grplist_cache[prototype.uid % id_cache_size]; struct avltree_node *found_node = atomic_fetch_voidptr(cache_slot); struct cache_info *found_info; bool found = false; /* Verify that the node found in the cache array is in fact what we * want. */ if (likely(found_node)) { found_info = avltree_container_of(found_node, struct cache_info, uid_node); if (found_info->uid == uid) found = true; } if (unlikely(!found)) { found_node = avltree_lookup(&prototype.uid_node, &uid_tree); if (unlikely(!found_node)) return false; atomic_store_voidptr(cache_slot, found_node); found_info = avltree_container_of(found_node, struct cache_info, uid_node); }
static bool lookup_by_uname(const struct gsh_buffdesc *name, struct cache_info **info) { struct cache_info prototype = { .uname = *name }; struct avltree_node *found_node = avltree_lookup(&prototype.uname_node, &uname_tree); struct cache_info *found_info; void **cache_slot; if (unlikely(!found_node)) return false; found_info = avltree_container_of(found_node, struct cache_info, uname_node); /* I assume that if someone likes this user enough to look it up by name, they'll like it enough to look it up by ID later. */ cache_slot = (void **) &uid_grplist_cache[found_info->uid % id_cache_size]; atomic_store_voidptr(cache_slot, &found_info->uid_node); *info = found_info; return true; }
/** * @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; }