コード例 #1
0
ファイル: mevent.c プロジェクト: bigml/mevent
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);
}
コード例 #2
0
ファイル: hash.c プロジェクト: Arkhont/samba
/* 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;
}