示例#1
0
/**
 * Save a hashtable to disk
 *
 * @param table         Hashtable to save
 * @param filename      Filename to write hashtable into
 * @param keywrite      Pointer to function that writes a single key
 * @param valuewrite    Pointer to function that writes a single value
 * @return              Number of entries written or -1 on error
 */
int
hashtable_save(HASHTABLE *table, char *filename,
               int (*keywrite)(int, void*),
               int (*valuewrite)(int, void*))
{
    int fd, rval = 0;
    HASHITERATOR *iter;
    void *key, *value;

    if ((fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)
    {
        return -1;
    }
    if (write(fd, "HASHTABLE", 7) != 7)     // Magic number
    {
        close(fd);
        return -1;
    }
    write(fd, &rval, sizeof(rval)); // Write zero counter, will be overrwriten at end
    if ((iter = hashtable_iterator(table)) != NULL)
    {
        while ((key = hashtable_next(iter)) != NULL)
        {
            if (!(*keywrite)(fd, key))
            {
                close(fd);
                hashtable_iterator_free(iter);
                return -1;
            }
            if ((value = hashtable_fetch(table, key)) == NULL ||
                (*valuewrite)(fd, value) == 0)
            {
                close(fd);
                hashtable_iterator_free(iter);
                return -1;
            }
            rval++;
        }
    }

    /* Now go back and write the count of entries */
    if (lseek(fd, 7L, SEEK_SET) != -1)
    {
        write(fd, &rval, sizeof(rval));
    }

    close(fd);
    hashtable_iterator_free(iter);
    return rval;
}
示例#2
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
}
示例#3
0
/**
 * Fetch the authentication data for a particular user from the users table
 *
 * @param users The MySQL users table
 * @param key	The key with user@host
 * @return	The authentication data or NULL on error
 */
char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key) {
	if (key == NULL)
		return NULL;
        atomic_add(&users->stats.n_fetches, 1);
        return hashtable_fetch(users->data, key);
}
示例#4
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;
}