struct event_entry* find_entry_in_table(struct mevent *evt, const unsigned char *key, size_t ksize) { uint32_t h; struct event_chain *c; h = hash(key, ksize) % evt->hashlen; c = evt->table + h; return find_in_chain(c, key, ksize); }
/* This is the core routine which searches the hashtable for an entry. * On error, no locks are held and -ve is returned. * Otherwise, hinfo is filled in (and the optional tinfo). * If not found, the return value is 0. * If found, the return value is the offset, and *rec is the record. */ tdb_off_t find_and_lock(struct tdb_context *tdb, struct tdb_data key, int ltype, struct hash_info *h, struct tdb_used_record *rec, struct traverse_info *tinfo) { uint32_t i, group; tdb_off_t hashtable; enum TDB_ERROR ecode; h->h = tdb_hash(tdb, key.dptr, key.dsize); h->hash_used = 0; group = use_bits(h, TDB_TOPLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS); h->home_bucket = use_bits(h, TDB_HASH_GROUP_BITS); h->hlock_start = hlock_range(group, &h->hlock_range); ecode = tdb_lock_hashes(tdb, h->hlock_start, h->hlock_range, ltype, TDB_LOCK_WAIT); if (ecode != TDB_SUCCESS) { return ecode; } hashtable = offsetof(struct tdb_header, hashtable); if (tinfo) { tinfo->toplevel_group = group; tinfo->num_levels = 1; tinfo->levels[0].entry = 0; tinfo->levels[0].hashtable = hashtable + (group << TDB_HASH_GROUP_BITS) * sizeof(tdb_off_t); tinfo->levels[0].total_buckets = 1 << TDB_HASH_GROUP_BITS; } while (h->hash_used <= 64) { /* Read in the hash group. */ h->group_start = hashtable + group * (sizeof(tdb_off_t) << TDB_HASH_GROUP_BITS); ecode = tdb_read_convert(tdb, h->group_start, &h->group, sizeof(h->group)); if (ecode != TDB_SUCCESS) { goto fail; } /* Pointer to another hash table? Go down... */ if (is_subhash(h->group[h->home_bucket])) { hashtable = (h->group[h->home_bucket] & TDB_OFF_MASK) + sizeof(struct tdb_used_record); if (tinfo) { /* When we come back, use *next* bucket */ tinfo->levels[tinfo->num_levels-1].entry += h->home_bucket + 1; } group = use_bits(h, TDB_SUBLEVEL_HASH_BITS - TDB_HASH_GROUP_BITS); h->home_bucket = use_bits(h, TDB_HASH_GROUP_BITS); if (tinfo) { tinfo->levels[tinfo->num_levels].hashtable = hashtable; tinfo->levels[tinfo->num_levels].total_buckets = 1 << TDB_SUBLEVEL_HASH_BITS; tinfo->levels[tinfo->num_levels].entry = group << TDB_HASH_GROUP_BITS; tinfo->num_levels++; } continue; } /* It's in this group: search (until 0 or all searched) */ for (i = 0, h->found_bucket = h->home_bucket; i < (1 << TDB_HASH_GROUP_BITS); i++, h->found_bucket = ((h->found_bucket+1) % (1 << TDB_HASH_GROUP_BITS))) { tdb_bool_err berr; if (is_subhash(h->group[h->found_bucket])) continue; if (!h->group[h->found_bucket]) break; berr = match(tdb, h, &key, h->group[h->found_bucket], rec); if (berr < 0) { ecode = berr; goto fail; } if (berr) { if (tinfo) { tinfo->levels[tinfo->num_levels-1].entry += h->found_bucket; } return h->group[h->found_bucket] & TDB_OFF_MASK; } } /* Didn't find it: h indicates where it would go. */ return 0; } return find_in_chain(tdb, key, hashtable, h, rec, tinfo); fail: tdb_unlock_hashes(tdb, h->hlock_start, h->hlock_range, ltype); return ecode; }