Ejemplo n.º 1
0
void hashtable_set(hashtable_t* input, const void* key, size_t key_length, void* value)
{
	//fprintf(stderr,"store(%s,%p)\n",key,value);
	uint32_t hashcode=_hashtable_function(key, key_length);
	uint32_t bucket=hashcode%input->size;
	hashelement_t* element=input->buckets[bucket];
#ifdef HASHTABLE_REORDER_ON_ACCESS
	hashelement_t* previous_element=NULL;
#endif
#ifdef HASHTABLE_GATHER_STATS
	unsigned int num_hits=1;
#endif
	while(element!=NULL)
	{
		if(element->key_length==key_length && memcmp(element->key,key,key_length)==0)
		{
			element->value=value;
#ifdef HASHTABLE_GATHER_STATS
			input->num_hits_per_access+=num_hits;
			input->num_accesses++;
#endif
#ifdef HASHTABLE_REORDER_ON_ACCESS
			if(previous_element!=NULL)
			{
				previous_element->next_in_bucket=element->next_in_bucket;
				element->next_in_bucket=input->buckets[bucket];
				input->buckets[bucket]=element;
			}
#endif
			return;
		}
#ifdef HASHTABLE_GATHER_STATS
		num_hits++;
#endif
#ifdef HASHTABLE_REORDER_ON_ACCESS
		previous_element=element;
#endif
		element=element->next_in_bucket;
	}
#ifdef HASHTABLE_GATHER_STATS
	input->num_hits_per_access+=num_hits;
	input->num_accesses++;
#endif
	element = (hashelement_t*)MALLOC(sizeof(hashelement_t));
	element->hashcode=hashcode;
#ifdef HASHTABLE_CENTRALIZE_KEYS
	if(input==_hashtable_key_repository)
	{
		element->key=key;
	}
	else
	{
		if(_hashtable_key_repository==NULL)
			_hashtable_key_repository=hashtable_new();
		char* repository_key=hashtable_fetch(_hashtable_key_repository, key, key_length);
		if(repository_key==NULL)
		{
			repository_key=MALLOC(key_length);
			memcpy(repository_key,key,key_length);
			hashtable_store(_hashtable_key_repository, repository_key, key_length, repository_key);
		}
		element->key=repository_key;
	}
#else
	element->key=MALLOC(key_length);
	memcpy(element->key,key,key_length);
#endif
	element->key_length=key_length;
	element->value=value;
	element->next_in_bucket=input->buckets[bucket];
	input->buckets[bucket]=element;
	input->length++;
#ifdef HASHTABLE_INCREASE_SIZE
	if(input->length/input->size>input->max_average_collisions)hashtable_resize(input, (size_t)(input->size*(input->resize_factor)+1));//+input->size);
#endif
}
Ejemplo n.º 2
0
/* main */
int main(int argc, char *argv[])
{
    struct hashtable           * hashtable;
    struct hashtable_iterator    iter;
    struct hashtable_entry       entry;
    void * valuepointer;
    int valueint, seed = 0, stringcount = 0, stringlength, key_bytes = 0,
        value_bytes = 0, entrynumber, collisions = 0, delete_count;
    char * source, * destination, * value;

    diag("02b-hashtable");
    plan(4);
    hashtable = hashtable_new();
    srand(seed);  /* TODO: get a portable seed from for example current time */
    while (stringcount<STRINGCOUNT) { /* nondeterministic because of collisions */
        char * key = random_string(MAXKEYLENGTH);
        /* create a value consisting of the key reversed followed by */
        /* the original key, for example 'abc' -> 'cbaabc' */
        stringlength = strlen(key);
        value = (char *) malloc(2 * stringlength + 1);
        destination=value+stringlength;
        * destination -- = '\0';
        for (source=key; stringlength-->0; ) {
            * destination -- = * source ++;
        }
        strcat( value, key );
        /* test whether the key is already in the hashtable */
        if ( hashtable_fetch(hashtable, key, strlen(key), & valuepointer, & valueint) ) {
            /* it is already in the hash table, free these values */
            free(key);
            free(value);
            ++ collisions;
        }
        else {
            /* it is not already in the hash table, add it */
            hashtable_store(hashtable, key, strlen(key), value, strlen(value));
            key_bytes   += strlen(key);
            value_bytes += strlen(value);
            ++ stringcount;
        }
    }
    is_ii( stringcount, STRINGCOUNT, "created a hash with 5000 entries");
    srand(seed);

    /* Test 2 - iterate the entries and delete them */
    hashtable_iterator_init(hashtable, & iter);
    delete_count = 0;
    while (hashtable_iterator_next(& iter, & entry)) {
        key_bytes   -= strlen(entry.keypointer);
        value_bytes -= strlen(entry.valuepointer);
        /* fprintf(stderr,"iter A '%s' => '%s'\n", (char *) entry.keypointer, (char *) entry.valuepointer); */
        free(entry.keypointer);
        free(entry.valuepointer);
        ++delete_count;
    }
    is_ii(delete_count, stringcount, "iterate 5000 entries and delete");

    /* Test 3 - verify total number of bytes in keys */
    is_ii(key_bytes, 0, "all bytes in keys reclaimed");

    /* Test 4 - verify total number of bytes in keys */
    is_ii(value_bytes, 0, "all bytes in values reclaimed");

    /* Cannot test this internally, but Valgrind should show that no */
    /* bytes remain allocated on the heap. */
    hashtable_free(hashtable);
    return 0;
}