Example #1
0
/**
 * @brief Initialise the hashtable.
 *
 * Allocate the hash table entries and initialise the hash masks.
 *
 * @param hash_table Hash table to setup.
 * @param size Requested size for the hash table in number of entries.
 */
void hash_init(HashTable *hash_table, const unsigned long long size)
{
	int i, n_way;

	for (n_way = 1; n_way < HASH_N_WAY; n_way <<= 1);

	assert(hash_table != NULL);
	assert((n_way & -n_way) == n_way);

	info("< init hashtable of %llu entries>\n", size);
	if (hash_table->hash != NULL) free(hash_table->memory);
	hash_table->memory = malloc((size + n_way + 1) * sizeof (Hash));
	if (hash_table->memory == NULL) {
		fatal_error("hash_init: cannot allocate the hash table\n");
	}

	if (HASH_ALIGNED) {
		const size_t alignment = n_way * sizeof (Hash) - 1;
		hash_table->hash = (Hash*) (((size_t) hash_table->memory + alignment) & ~alignment);
		hash_table->hash_mask = size - n_way;
	} else {
		hash_table->hash = (Hash*) hash_table->memory;
		hash_table->hash_mask = size - 1;
	}

	hash_cleanup(hash_table);

	hash_table->n_lock = 256 * MAX(get_cpu_number(), 1);
	hash_table->lock_mask = hash_table->n_lock - 1;
	hash_table->n_lock += n_way + 1;
	hash_table->lock = (HashLock*) malloc(hash_table->n_lock * sizeof (HashLock));

	for (i = 0; i < hash_table->n_lock; ++i) spin_init(hash_table->lock + i);
}
Example #2
0
EC_API void ec_hash_destroy( ec_hash table )
{
	ENTERF;
	if (table)
	{
		hash_cleanup( table );
		hash_free( table );
	}
}
Example #3
0
/* bul_cleanup - cleans up global bul */
void bul_cleanup(void)
{
	hash_cleanup(&bul_hash);
}
Example #4
0
/* bul_home_cleanup - cleans up a bul 
 * @bul: binding update list to clean up
 */
void bul_home_cleanup(struct hash *bul)
{
	hash_iterate(bul, bule_cleanup, bul);	
	hash_cleanup(bul);
}
Example #5
0
void bcache_cleanup(void)
{
    pthread_rwlock_wrlock(&bc_lock);
    hash_cleanup(&bc_hash);
    pthread_rwlock_unlock(&bc_lock);
}
Example #6
0
static EcBool hash_expand( ec_hash table )
{
	EcUInt newCapacity = 0, newPrimeIndex;
	EcUInt i;
	ec_hash new_table = NULL;

	ec_hash_entry entry;

	EcAny invkey;
	EcAny invval;

	ENTERF;
#ifdef EC_DEBUG
	if (debTable)
	{
		EcUInt lf;

		if (H_CAPACITY(table))
		{
			lf  = (H_ENTRIES(table) << SHIFTAMOUNT);
			lf /= H_CAPACITY(table);
		}
		else
			lf = 0;

#if EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "**************** hash_expand ******************" );
		VADEBMESSAGE( debTable, "Current load factor: %ld [LO %ld, HI %ld]",
					  (long)lf, (long)H_LOLOAD(table), (long)H_HILOAD(table) );
#endif
	}
#endif

	ASSERT( table );
	ASSERT( !new_table );
	ASSERT( table != new_table );

#if CHECK_PRIME
	ASSERT( (H_CAPACITY(table) == 0) || isprime(H_CAPACITY(table)) );
#endif

	invkey = H_INVKEY(table);
	invval = H_INVVAL(table);

	if (H_PRIMEINDEX(table) == 0)
	{
		newPrimeIndex = FIRSTPRIME;
		ASSERT(newPrimeIndex < nprimes);
		newCapacity = primes[newPrimeIndex];
#if CHECK_PRIME
		ASSERT( isprime( newCapacity ) );
#endif

		for (i = 1; i < nprimes; i++)
		{
			if (primes[i] >= H_MINSIZE(table))
			{
				newPrimeIndex    = i;
				newCapacity      = primes[i];
				H_MINSIZE(table) = primes[i];
				break;
			}
		}
		ASSERT(newCapacity >= H_MINSIZE(table));
		ASSERT(H_MINSIZE(table) > 2);
#if CHECK_PRIME
		ASSERT( isprime( newCapacity ) );
#endif

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "*1*" );
#endif
	}
	else
	{
		EcUInt curLoad;

		newPrimeIndex = H_PRIMEINDEX(table);

		if (H_CAPACITY(table))
		{
			curLoad  = H_ENTRIES(table) << SHIFTAMOUNT;
			curLoad /= H_CAPACITY(table);
		} else
			curLoad = H_HILOAD(table) + 1;						/* capacity null => expand ! */

		if (curLoad >= H_HILOAD(table))
		{
			do
			{
				newPrimeIndex++;
				ASSERT(newPrimeIndex < nprimes);
				newCapacity = primes[newPrimeIndex];
				ASSERT(newCapacity);
#if CHECK_PRIME
				ASSERT( isprime( newCapacity ) );
#endif

				curLoad  = H_ENTRIES(table) << SHIFTAMOUNT;
				curLoad /= newCapacity;
			} while (curLoad > H_LOLOAD(table));
		}

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "*2*" );
#endif
	}

	ASSERT(newCapacity >= H_MINSIZE(table));
#if CHECK_PRIME
	ASSERT( isprime( newCapacity ) );
#endif

	if (! H_ENTRYBASE(table))
	{
		H_ENTRYBASE(table) = (ec_hash_entry) ec_malloc( sizeof(struct ec_hash_entry_struct) * newCapacity );
		if (! H_ENTRYBASE(table)) return FALSE;

		H_CAPACITY(table)   = newCapacity;
		H_PRIMEINDEX(table) = newPrimeIndex;

		/* IMPORTANT: initialize new slots */
		for (i = 0; i < newCapacity; i++)
		{
			EC_HASH_ENTRY_KEY(H_ENTRY(table, i))   = invkey;
			EC_HASH_ENTRY_VALUE(H_ENTRY(table, i)) = invval;
		}

#if CHECK_PRIME
		ASSERT( isprime(H_CAPACITY(table)) );
#endif
		return TRUE;
	}
	else
	{
		EcBool old_xfer;

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "Expanding table to %ld elements", (long)newCapacity );
#endif
		ASSERT( !new_table );
		new_table = hash_alloc();

		ASSERT( !H_ENTRYBASE(new_table) );
		H_DEF(new_table)        = H_DEF(table);
		H_ENTRIES(new_table)    = 0;
		H_CAPACITY(new_table)   = 0;
		H_PRIMEINDEX(new_table) = 0;
		H_ENTRYBASE(new_table)  = 0;
/* 		new_table.loLoad     = (1 << SHIFTAMOUNT); */     /* BUG CORRECTED */
/* 		new_table.hiLoad     = (1 << SHIFTAMOUNT); */
		H_MINSIZE(new_table) = H_MINSIZE(table);
 		H_LOLOAD(new_table)  = H_LOLOAD(table);
 		H_HILOAD(new_table)  = H_HILOAD(table);

		H_ENTRYBASE(new_table) = (ec_hash_entry) ec_malloc( sizeof(struct ec_hash_entry_struct) * newCapacity );
		if (! H_ENTRYBASE(new_table)) return FALSE;

		H_ENTRIES(new_table)    = 0;
		H_CAPACITY(new_table)   = newCapacity;
		H_PRIMEINDEX(new_table) = newPrimeIndex;

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "newCapacity: %ld, newPrimeIndex: %ld", (long)newCapacity, (long)newPrimeIndex );
#endif

		/* IMPORTANT: initialize new slots */
		for (i = 0; i < newCapacity; i++)
		{
			EC_HASH_ENTRY_KEY(H_ENTRY(new_table, i))   = invkey;
			EC_HASH_ENTRY_VALUE(H_ENTRY(new_table, i)) = invval;
		}

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "oldTable   capacity: %ld  entries: %ld\n", (long)H_CAPACITY(table), (long)H_ENTRIES(table) );
#endif
		/* fill new table with old values */
		ASSERT( table != new_table );
		old_xfer = xfer_only;
		xfer_only = TRUE;
		for (i = 0; i < H_CAPACITY(table); i++)
		{
			entry = H_ENTRY(table, i);
			if (EC_HASH_ENTRY_KEY(entry) != invkey)
			{
				ec_hash_set( new_table,
						   EC_HASH_ENTRY_KEY(entry),
						   EC_HASH_ENTRY_VALUE(entry) );
			}
		}
		xfer_only = old_xfer;

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "newTable   capacity: %ld  entries: %ld\n", (long)H_CAPACITY(new_table), (long)H_ENTRIES(new_table) );
#endif
		ASSERT( H_ENTRIES(table) == H_ENTRIES(new_table) );

		/* free old table contents */
		hash_cleanup( table );

		/* move new table to old one */
		memcpy( table, new_table, sizeof(struct ec_hash_struct) );

		/* free new table space (not contents !) */
		hash_free( new_table );
		new_table = NULL;

#if EC_DEBUG && EC_HAS_VARARGS_MACRO
		VADEBMESSAGE( debTable, "Table   capacity: %ld  entries: %ld\n", (long)H_CAPACITY(table), (long)H_ENTRIES(table) );
#endif
#if CHECK_PRIME
		ASSERT( isprime(H_CAPACITY(table)) );
#endif
		return TRUE;
	}

	return FALSE;
}