Skip to content
Snippets Groups Projects
Commit 1a783966 authored by Lubos Slovak's avatar Lubos Slovak
Browse files

Added a structure holding the universal system.

- The structure (us_system_t) keeps the coeficients of the
  system of functions.
- It is used in cuckoo hash table - one system per table.

fixes #621
parent 41ba4522
No related branches found
No related tags found
No related merge requests found
......@@ -39,7 +39,7 @@ typedef unsigned int uint;
//#define MEM_SLAB_CAP 3 // Cap slab_cache empty slab count (undefined = inf)
#define MEM_COLORING // Slab cache coloring
//#define USE_HASH_TABLE
#define USE_HASH_TABLE
//#define TEST_WITH_LDNS
/* Common includes.
......
......@@ -34,8 +34,8 @@
// random walk
#define NEXT_TABLE(table, count) (rand() % count)
#define HASH(key, length, exp, gen, table) \
us_hash(fnv_hash(key, length, -1), exp, table, gen)
#define HASH(system, key, length, exp, gen, table) \
us_hash(system, fnv_hash(key, length, -1), exp, table, gen)
#define STASH_ITEMS(stash) ((ck_hash_table_item_t **)(da_get_items(stash)))
......@@ -344,7 +344,8 @@ static ck_hash_table_item_t **ck_find_gen(const ck_hash_table_t *table,
// check hash tables
for (uint t = TABLE_FIRST; t <= TABLE_LAST(table->table_count); ++t) {
hash = HASH(key, length, table->table_size_exp, generation, t);
hash = HASH(&table->hash_system, key, length,
table->table_size_exp, generation, t);
if (strncmp(CZ_NAME, key, length) == 0) {
debug_ck("[hash] Hashing name 'cz' (size %u), table: %u"
......@@ -373,7 +374,7 @@ static ck_hash_table_item_t **ck_find_gen(const ck_hash_table_t *table,
}
}
// try to find in buffer
// try to find in stash
debug_ck("Searching in stash...\n");
ck_hash_table_item_t **found =
......@@ -435,8 +436,9 @@ static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
uint next_table = TABLE_FIRST;
uint32_t hash = HASH((*to_hash)->key, (*to_hash)->key_length,
table->table_size_exp, generation, next_table);
uint32_t hash = HASH(&table->hash_system, (*to_hash)->key,
(*to_hash)->key_length, table->table_size_exp,
generation, next_table);
debug_ck_hash("New hash: %u.\n", hash);
assert(hash < hashsize(table->table_size_exp));
......@@ -482,8 +484,9 @@ static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
ck_next_table(&next_table, table->table_count);
}
hash = HASH((*next)->key, (*next)->key_length,
table->table_size_exp, generation, next_table);
hash = HASH(&table->hash_system, (*next)->key,
(*next)->key_length, table->table_size_exp,
generation, next_table);
if (strncmp(CZ_NAME, (*next)->key, (*next)->key_length) == 0) {
printf("[hash] Hashing name 'cz' (size: %u), table: %u,"
......@@ -629,7 +632,7 @@ ck_hash_table_t *ck_create_table(uint items)
debug_ck("Creating hash table for %u items.\n", items);
debug_ck("Exponent: %u, number of tables: %u\n ",
table->table_size_exp, table->table_count);
debug_ck("Table size: %u items, each %lu bytes, total %lu bytes\n",
debug_ck("Table size: %u items, each %zu bytes, total %zu bytes\n",
hashsize(table->table_size_exp),
sizeof(ck_hash_table_item_t *),
hashsize(table->table_size_exp)
......@@ -675,7 +678,8 @@ ck_hash_table_t *ck_create_table(uint items)
// set the generation to 1 and initialize the universal system
CLEAR_FLAGS(&table->generation);
SET_GENERATION1(&table->generation);
us_initialize();
us_initialize(&table->hash_system);
return table;
}
......
......@@ -64,7 +64,7 @@ struct ck_hash_table_item {
* xy - generation; may be 01 (1) or 10 (2).
*/
uint8_t timestamp;
}; // size 13 B
};
typedef struct ck_hash_table_item ck_hash_table_item_t;
......@@ -133,6 +133,8 @@ struct ck_hash_table {
* both sets of functions when searching for item.
*/
uint8_t generation;
us_system_t hash_system; /*!< Universal system of hash functions. */
};
typedef struct ck_hash_table ck_hash_table_t;
......
......@@ -11,9 +11,6 @@
/*----------------------------------------------------------------------------*/
enum { GEN_COUNT = 2 };
static uint coefs[US_FNC_COUNT * GEN_COUNT];
const uint MAX_UINT_EXP = 32;
const unsigned long MAX_UINT_MY = 4294967295;
......@@ -21,21 +18,25 @@ const unsigned long MAX_UINT_MY = 4294967295;
/* Private functions */
/*----------------------------------------------------------------------------*/
static void us_generate_coefs(uint from, uint to)
static void us_generate_coefs(us_system_t *system, uint from, uint to)
{
assert(system != NULL);
for (uint i = from; i < to; ++i) {
int used = 0;
do {
// generate random odd number
coefs[i] = rand() % MAX_UINT_MY;
if (coefs[i] % 2 == 0) {
coefs[i] = (coefs[i] == 0) ? 1 : coefs[i] - 1;
system->coefs[i] = rand() % MAX_UINT_MY;
if (system->coefs[i] % 2 == 0) {
system->coefs[i] = (system->coefs[i] == 0)
? 1
: system->coefs[i] - 1;
}
// check if this coeficient is already used
uint j = from;
while (used == 0 && j < i) {
if (coefs[j++] == coefs[i]) {
if (system->coefs[j++] == system->coefs[i]) {
used = 1;
}
}
......@@ -48,31 +49,34 @@ static void us_generate_coefs(uint from, uint to)
/* Public functions */
/*----------------------------------------------------------------------------*/
void us_initialize()
void us_initialize(us_system_t *system)
{
assert(system != NULL);
assert(UINT_MAX == MAX_UINT_MY);
srand(time(NULL));
// Initialize both generations of functions by generating random odd
// numbers
us_generate_coefs(0, US_FNC_COUNT * GEN_COUNT);
us_generate_coefs(system, 0, US_FNC_COUNT * GEN_COUNT);
}
/*----------------------------------------------------------------------------*/
/*!
* \note \a generation starts from 1
*/
int us_next(uint generation)
int us_next(us_system_t *system, uint generation)
{
assert(system != NULL);
// generate new coeficients for the new generation
us_generate_coefs((generation - 1) * US_FNC_COUNT,
us_generate_coefs(system, (generation - 1) * US_FNC_COUNT,
generation * US_FNC_COUNT);
return 0;
}
/*----------------------------------------------------------------------------*/
uint32_t us_hash(uint32_t value, uint table_exp, uint fnc, uint generation)
uint32_t us_hash(const us_system_t *system, uint32_t value, uint table_exp,
uint fnc, uint generation)
{
/*
* multiplication should overflow if larger than MAX_UINT
......@@ -80,9 +84,11 @@ uint32_t us_hash(uint32_t value, uint table_exp, uint fnc, uint generation)
*
* TODO: maybe we should not rely on this
*/
assert(system != NULL);
assert(table_exp <= 32);
assert(fnc < US_FNC_COUNT);
assert(generation <= GEN_COUNT);
return ((coefs[((generation - 1) * US_FNC_COUNT) + fnc] * value)
return ((system->coefs[((generation - 1) * US_FNC_COUNT) + fnc] * value)
>> (MAX_UINT_EXP - table_exp));
}
......@@ -28,14 +28,26 @@
#include <stdint.h>
#include "common.h"
enum { US_FNC_COUNT = 4 };
enum { GEN_COUNT = 2 };
/*----------------------------------------------------------------------------*/
struct us_system {
uint coefs[US_FNC_COUNT * GEN_COUNT];
};
typedef struct us_system us_system_t;
/*----------------------------------------------------------------------------*/
/*!
* \brief Initializes the universal system by generating coeficients for all
* hash functions and all generations.
*/
void us_initialize();
void us_initialize(us_system_t *system);
/*----------------------------------------------------------------------------*/
/*!
......@@ -43,7 +55,7 @@ void us_initialize();
*
* \return 0
*/
int us_next(uint generation);
int us_next(us_system_t *system, uint generation);
/*----------------------------------------------------------------------------*/
......@@ -64,7 +76,8 @@ int us_next(uint generation);
*
* \return Hash value (32bit unsigned).
*/
uint32_t us_hash(uint32_t value, uint table_exp, uint fnc, uint generation);
uint32_t us_hash(const us_system_t *system, uint32_t value, uint table_exp,
uint fnc, uint generation);
/*----------------------------------------------------------------------------*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment