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); }
struct gsh_client *get_gsh_client(sockaddr_t *client_ipaddr, bool lookup_only) { struct avltree_node *node = NULL; struct gsh_client *cl; struct server_stats *server_st; struct gsh_client v; uint8_t *addr = NULL; uint32_t ipaddr; int addr_len = 0; void **cache_slot; switch (client_ipaddr->ss_family) { case AF_INET: addr = (uint8_t *) &((struct sockaddr_in *)client_ipaddr)-> sin_addr; addr_len = 4; memcpy(&ipaddr, (uint8_t *) &((struct sockaddr_in *)client_ipaddr)-> sin_addr, sizeof(ipaddr)); break; case AF_INET6: addr = (uint8_t *) &((struct sockaddr_in6 *)client_ipaddr)-> sin6_addr; addr_len = 16; memcpy(&ipaddr, (uint8_t *) &((struct sockaddr_in6 *)client_ipaddr)-> sin6_addr, sizeof(ipaddr)); break; default: assert(0); } v.addr.addr = addr; v.addr.len = addr_len; PTHREAD_RWLOCK_rdlock(&client_by_ip.lock); /* check cache */ cache_slot = (void **) &(client_by_ip.cache[eip_cache_offsetof(&client_by_ip, ipaddr)]); node = (struct avltree_node *)atomic_fetch_voidptr(cache_slot); if (node) { if (client_ip_cmpf(&v.node_k, node) == 0) { /* got it in 1 */ LogDebug(COMPONENT_HASHTABLE_CACHE, "client_mgr cache hit slot %d\n", eip_cache_offsetof(&client_by_ip, ipaddr)); cl = avltree_container_of(node, struct gsh_client, node_k); goto out; } }
/** * @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; }