Exemple #1
0
int hi_rehash(hi_handle_t *hi_hndl, uint32_t new_table_size)
{
	int ret, auto_rehash;
	void *key, *data;
	uint32_t keylen;
	hi_handle_t *hi_handle;
	hi_iterator_t *iterator;

	/* create a clean handle for the new structure */
	ret = lhi_create_vanilla_hdnl(&hi_handle);
	if (ret != SUCCESS)
		return ret;

	/* we take over the original settings done
	 * by the user taken at hi_create() time */
	lhi_transform_hndl_2_hndl(hi_hndl, hi_handle);

	hi_handle->table_size = new_table_size;

	/* Allocate memory fot accounting the number of
	 * elements within every bucket in the table.  */
	ret = XMALLOC((void **) &hi_handle->bucket_size,
			hi_handle->table_size * sizeof(*hi_handle->bucket_size));
	if (ret != 0) {
		return HI_ERR_SYSTEM;
	}

	/* 0 objects in the list at start-up */
	hi_handle->no_objects = 0;

	/* Initiate mutex lock if build with thread
	 * support. */
	hi_handle->mutex_lock = NULL;
	ret = lhi_pthread_mutex_init(&hi_handle->mutex_lock, NULL);
	if (ret != 0) {
		return HI_ERR_SYSTEM;
	}

	/* Create internal data structure for
	 * list, array or rbtree */
	switch (hi_handle->coll_eng) {

		case COLL_ENG_LIST:
		case COLL_ENG_LIST_HASH:
		case COLL_ENG_LIST_MTF:
		case COLL_ENG_LIST_MTF_HASH:
			ret = lhi_create_eng_list(hi_handle);
			if (ret != SUCCESS)
				return ret;


			break;
		case COLL_ENG_ARRAY:
		case COLL_ENG_ARRAY_HASH:
		case COLL_ENG_ARRAY_DYN:
		case COLL_ENG_ARRAY_DYN_HASH:
			ret = lhi_create_eng_array(hi_handle);
			if (ret != SUCCESS)
				return ret;


			break;
		case COLL_ENG_RBTREE:
			ret = lhi_create_eng_rbtree(hi_handle);
			if (ret != SUCCESS)
				return ret;


			break;
		default:
			return HI_ERR_INTERNAL;
			break;
	}

	ret = hi_iterator_create(hi_hndl, &iterator);
	if (ret != SUCCESS)
		return ret;

	auto_rehash = hi_handle->rehash_auto;
	hi_handle->rehash_auto = 0;
	while ((ret = hi_iterator_getnext(iterator, &data, &key, &keylen)) ==
			SUCCESS) {
		ret = hi_insert(hi_handle, key, keylen, data);
		if (ret != SUCCESS) {
			hi_iterator_fini(iterator);
			hi_fini(hi_handle);

			hi_handle->rehash_auto = auto_rehash;
			return ret;
		}
	}
	hi_handle->rehash_auto = auto_rehash;
	/* verify that no error occured during iterator run */
	if (ret != HI_ERR_NODATA) {
		hi_iterator_fini(iterator);
		return ret;
	}

	hi_iterator_fini(iterator);

	/* free old hashish handle */
	lhi_fini_internal(hi_hndl);

	memcpy(hi_hndl, hi_handle, sizeof(*hi_hndl));

	return SUCCESS;
}
int hi_insert_int16_t(hi_handle_t *hi_hndl, const int16_t key, const void *data)
{
    return hi_insert(hi_hndl, (uint8_t *) &key, sizeof(int16_t), (void *)data);
}
Exemple #3
0
static void check_iterator(enum coll_eng engine, enum hash_alg hash_alg)
{
	int ret, i;
	hi_handle_t *hi_hndl;
	struct hi_init_set hi_set;
	hi_iterator_t *iterator;
	void *data_ptr = (void *) 0xdeadbeef;
	void *key;
	uint32_t keylen;

	hi_set_zero(&hi_set);
	ret = hi_set_bucket_size(&hi_set, 100);
	assert(ret == 0);
	ret = hi_set_hash_alg(&hi_set, hash_alg);
	assert(ret == 0);
	ret = hi_set_coll_eng(&hi_set, engine);
	assert(ret == 0);
	ret = hi_set_key_cmp_func(&hi_set, hi_cmp_str);
	assert(ret == 0);

	/* we need aditional arguments for ARRAY based engines */
	switch (engine) {
		case COLL_ENG_ARRAY:
		case COLL_ENG_ARRAY_HASH:
		case COLL_ENG_ARRAY_DYN:
		case COLL_ENG_ARRAY_DYN_HASH:
			ret = hi_set_coll_eng_array_size(&hi_set, 20);
			assert(ret == 0);
			break;
		default:
			break;
	};

	ret = hi_create(&hi_hndl, &hi_set);
	if (ret != 0)
		print_error(ret);
	assert(ret == 0);

	ret = hi_insert(hi_hndl, (void *) "key", sizeof("key"), "data");
	assert(ret == 0);

	ret = hi_insert(hi_hndl, (void *) "key1", sizeof("key1"), "data1");
	assert(ret == 0);

	ret = hi_insert(hi_hndl, (void *) "key2", sizeof("key2"), "data2");
	assert(ret == 0);

	ret = hi_iterator_create(hi_hndl, &iterator);
	if (ret != 0)
		return;

	for (i = 0; i < 2; i++) {
		bool got_key[] = { 0, 0, 0 };
		unsigned int j;

		for (j = 0 ; j < 3 ; j++) {
			data_ptr = NULL;
			ret = hi_iterator_getnext(iterator, &data_ptr, &key, &keylen);
			assert(ret == 0);
			assert(data_ptr);
			if (strcmp(data_ptr, "data") == 0) {
				assert(!got_key[0]);
				got_key[0] = true;
				continue;
			}
			if (strcmp(data_ptr, "data1") == 0) {
				assert(!got_key[1]);
				got_key[1] = true;
				continue;
			}
			assert (strcmp(data_ptr, "data2") == 0);
			assert(!got_key[2]);
			got_key[2] = true;
		}
		ret = hi_iterator_getnext(iterator, &data_ptr, &key, &keylen);
		assert (ret == HI_ERR_NODATA);
		ret = hi_iterator_reset(iterator);
		assert(ret == 0);
	}
	hi_iterator_fini(iterator);

	ret = hi_remove(hi_hndl, (void *) "key", sizeof("key"), &data_ptr);
	assert(ret == 0);
	ret = hi_remove(hi_hndl, (void *) "key1", sizeof("key1"), &data_ptr);
	assert(ret == 0);
	ret = hi_remove(hi_hndl, (void *) "key2", sizeof("key2"), &data_ptr);
	assert(ret == 0);

	ret = hi_fini(hi_hndl);
	assert(ret == 0);

	fputs("passed\n", stdout);
}
Exemple #4
0
static void check_insert(enum coll_eng engine, enum hash_alg hash_alg)
{
	int ret;
	hi_handle_t *hi_hndl;
	struct hi_init_set hi_set;
	void *data_ptr = (void *) 0xdeadbeef;

	hi_set_zero(&hi_set);
	ret = hi_set_bucket_size(&hi_set, 100);
	assert(ret == 0);
	ret = hi_set_hash_alg(&hi_set, hash_alg);
	assert(ret == 0);
	ret = hi_set_coll_eng(&hi_set, engine);
	assert(ret == 0);
	ret = hi_set_key_cmp_func(&hi_set, hi_cmp_str);
	assert(ret == 0);

	/* we need aditional arguments for ARRAY based engines */
	switch (engine) {
		case COLL_ENG_ARRAY:
		case COLL_ENG_ARRAY_HASH:
		case COLL_ENG_ARRAY_DYN:
		case COLL_ENG_ARRAY_DYN_HASH:
			ret = hi_set_coll_eng_array_size(&hi_set, 20);
			assert(ret == 0);
			break;
		default:
			break;
	};


	ret = hi_create(&hi_hndl, &hi_set);
	if (ret != 0)
		print_error(ret);
	assert(ret == 0);


	ret = hi_insert(hi_hndl, (void *) "key", sizeof("key"), "XX");
	assert(ret == 0);

	/* same key -> must fail */
	ret = hi_insert(hi_hndl, (void *) "key", sizeof("key"), "XX");
	assert(ret == HI_ERR_DUPKEY);


	/* key already in data structure -> must return 0 (SUCCESS) */
	ret = hi_get(hi_hndl, (void *) "key", sizeof("key"), &data_ptr);
	assert(ret == 0);
	//assert(data_ptr == NULL);

	ret = hi_remove(hi_hndl, (void *) "key", sizeof("key"), &data_ptr);
	assert(ret == 0);

	ret = hi_get(hi_hndl, (void *) "key", sizeof("key"), &data_ptr);
	assert(ret == HI_ERR_NOKEY);

	ret = hi_fini(hi_hndl);
	assert(ret == 0);

	fputs("passed\n", stdout);
}
Exemple #5
0
static void check_get_remove(enum coll_eng engine, enum hash_alg hash_alg)
{
	int ret;
	hi_handle_t *hi_hndl;
	struct hi_init_set hi_set;
	void *data_ret;

	hi_set_zero(&hi_set);
	ret = hi_set_bucket_size(&hi_set, 100);
	assert(ret == 0);
	ret = hi_set_hash_alg(&hi_set, hash_alg);
	assert(ret == 0);
	ret = hi_set_coll_eng(&hi_set, engine);
	assert(ret == 0);
	ret = hi_set_key_cmp_func(&hi_set, hi_cmp_str);
	assert(ret == 0);

	/* we need aditional arguments for ARRAY based engines */
	switch (engine) {
		case COLL_ENG_ARRAY:
		case COLL_ENG_ARRAY_HASH:
		case COLL_ENG_ARRAY_DYN:
		case COLL_ENG_ARRAY_DYN_HASH:
			ret = hi_set_coll_eng_array_size(&hi_set, 20);
			assert(ret == 0);
			break;
		default:
			break;
	};

	ret = hi_create(&hi_hndl, &hi_set);
	if (ret != 0)
		print_error(ret);
	assert(ret == 0);

	assert(hi_hndl->no_objects == 0);
	ret = hi_insert(hi_hndl, (void *) "key", sizeof("key"), "DATA");
	assert(ret == 0);
	assert(hi_hndl->no_objects == 1);
	ret = hi_insert(hi_hndl, (void *) "key2", sizeof("key2"), "DATAX");
	assert(ret == 0);
	assert(hi_hndl->no_objects == 2);
	ret = hi_insert(hi_hndl, (void *) "key3", sizeof("key3"), "DATAX");
	assert(ret == 0);
	assert(hi_hndl->no_objects == 3);

	/* key already in data structure -> must return 0 (SUCCESS) */
	ret = hi_get(hi_hndl, (void *) "key", sizeof("key"), &data_ret);
	if (ret != 0)
		print_error(ret);
	check_data(data_ret, "DATA");
	assert(hi_hndl->no_objects == 3);

	ret = hi_get(hi_hndl, (void *) "key3", sizeof("key3"), &data_ret);
	if (ret != 0)
		print_error(ret);
	check_data(data_ret, "DATAX");
	assert(hi_hndl->no_objects == 3);
	data_ret = NULL;

	ret = hi_remove(hi_hndl, (void *) "key", sizeof("key"), &data_ret);
	assert(ret == 0);
	assert(hi_hndl->no_objects == 2);
	check_data(data_ret, "DATA");
	data_ret = NULL;
	ret = hi_remove(hi_hndl, (void *) "key2", sizeof("key2"), &data_ret);
	assert(ret == 0);
	assert(hi_hndl->no_objects == 1);
	ret = hi_remove(hi_hndl, (void *) "key3", sizeof("key3"), &data_ret);
	assert(ret == 0);
	assert(hi_hndl->no_objects == 0);
	check_data(data_ret, "DATAX");

	ret = hi_fini(hi_hndl);
	assert(ret == 0);

	fputs("passed\n", stdout);
}
/* concurrent_test do the following:
 *  o It creates and removes randomly entries
 *    whithin the hash table. At the end the count
 *    must be equal to the expected
 */
static void concurrent_test(int num)
{
    int i, ret;
    void *data;
    char *ptr_bucket[TEST_ITER_NO][2];
    struct drand48_data seed_data;
    unsigned long seed;
    long int rand_res;

    seed = get_proper_seed();

    /* init per thread seed */
    srand48_r(seed, &seed_data);


    /* sleep for some amount of time */
    lrand48_r(&seed_data, &rand_res);
    msleep(rand_res % 40000); /* max 4s */

    fprintf(stderr, "+%d", num);

    for (i =0; i < TEST_ITER_NO; i++) {

        int sucess;
        char *key_ptr, *data_ptr;

        /* insert at least TEST_ITER_NO data
         * sets
         */
        do {
            sucess = 1;

            random_string(KEYLEN, &key_ptr, &seed_data);
            random_string(DATALEN, &data_ptr, &seed_data);

            ptr_bucket[i][KEY] = key_ptr;
            ptr_bucket[i][DATA] = data_ptr;

            ret = hi_insert(hi_hndl, (void *) key_ptr,
                            strlen(key_ptr), (void *) data_ptr);
            if (ret < 0) {
                fprintf(stderr, "# Key (%s) already in hash\n", key_ptr);
                fprintf(stderr, "Error %s\n", ret == HI_ERR_SYSTEM ?
                        strerror(errno) : hi_strerror(ret));
                sucess = 0;
                free(key_ptr);
                free(data_ptr);
            }

        } while (!sucess);
    }

    lrand48_r(&seed_data, &rand_res);
    msleep(rand_res % 4000); /* max 4s */

    /* verify storage and cleanup */
    for (i = 0; i < TEST_ITER_NO; i++) {
        ret = hi_remove(hi_hndl, ptr_bucket[i][KEY],
                        strlen(ptr_bucket[i][KEY]), &data);
        if (ret == 0) {
            if (data != ptr_bucket[i][DATA]) {
                fprintf(stderr, "Failed: should %s - is %s\n",
                        ptr_bucket[i][DATA], (char *) data);
            }

            free(ptr_bucket[i][KEY]);
            free(ptr_bucket[i][DATA]);
        } else {
            fprintf(stderr, "# already deleted\n");
        }

    }

    fprintf(stderr, "-%d", num);
}
Exemple #7
0
/* The ending \0 of string is also a part of the key and should not be forgotten */
int hi_insert_str(hi_handle_t *hi_hndl, const char *key, const void *data)
{
	return hi_insert(hi_hndl, (uint8_t *) key, strlen(key) + 1, (void *)data);
}