示例#1
0
文件: rlite.c 项目: yodamaster/rlite
int rl_flushdb(struct rlite *db)
{
	int retval;
	rl_btree *btree;
	rl_btree_iterator *iterator = NULL;
	rl_key *key;
	void *tmp;
	RL_CALL2(rl_get_key_btree, RL_OK, RL_NOT_FOUND, db, &btree, 0);
	if (retval == RL_NOT_FOUND) {
		retval = RL_OK;
		goto cleanup;
	}

	RL_CALL(rl_btree_iterator_create, RL_OK, db, btree, &iterator);

	while ((retval = rl_btree_iterator_next(iterator, NULL, &tmp)) == RL_OK) {
		key = tmp;
		RL_CALL(rl_key_delete_value, RL_OK, db, key->type, key->value_page);
		RL_CALL(rl_multi_string_delete, RL_OK, db, key->string_page);
		rl_free(key);
	}
	if (retval != RL_END) {
		goto cleanup;
	}
	RL_CALL(rl_btree_delete, RL_OK, db, btree);
	RL_CALL(rl_delete, RL_OK, db, db->databases[db->selected_database]);
	db->databases[db->selected_database] = 0;
	RL_CALL(rl_write, RL_OK, db, &rl_data_type_header, 0, NULL);
	retval = RL_OK;
cleanup:
	return retval;
}
示例#2
0
int rl_zinterstore(rlite *db, long keys_size, unsigned char **keys, long *keys_len, double *_weights, int aggregate)
{
	unsigned char *member = NULL;
	rl_btree **btrees = NULL;
	rl_skiplist **skiplists = NULL;
	double weight = 1.0, weight_tmp;
	double *weights = NULL;
	rl_skiplist_node *node;
	rl_skiplist_iterator *skiplist_iterator = NULL;
	rl_btree_iterator *btree_iterator = NULL;
	int retval;
	long target_btree_page, target_skiplist_page;
	long multi_string_page;
	rl_btree *target_btree;
	rl_skiplist *target_skiplist;
	int found;
	void *tmp;
	double skiplist_score, tmp_score;
	long memberlen;
	unsigned char digest[20];

	if (keys_size > 1) {
		RL_MALLOC(btrees, sizeof(rl_btree *) * (keys_size - 1));
		RL_MALLOC(skiplists, sizeof(rl_skiplist *) * (keys_size - 1));
	}
	else {
		retval = RL_UNEXPECTED;
		goto cleanup;
	}
	retval = rl_key_delete_with_value(db, keys[0], keys_len[0]);
	if (retval != RL_OK && retval != RL_NOT_FOUND) {
		goto cleanup;
	}
	rl_btree *btree, *btree_tmp;
	rl_skiplist *skiplist = NULL, *skiplist_tmp;
	long i;
	// key in position 0 is the target key
	// we'll store a pivot skiplist in btree/skiplist and the others in btrees/skiplists
	// TODO: qsort instead
	RL_MALLOC(weights, sizeof(double) * (keys_size - 2));
	for (i = 1; i < keys_size; i++) {
		weight_tmp = _weights ? _weights[i - 1] : 1.0;
		RL_CALL2(rl_zset_get_objects, RL_OK, RL_WRONG_TYPE, db, keys[i], keys_len[i], NULL, &btree_tmp, NULL, &skiplist_tmp, NULL, 0, 0);
		if (retval == RL_WRONG_TYPE) {
			skiplist_tmp = NULL;
			RL_CALL(rl_set_get_objects, RL_OK, db, keys[i], keys_len[i], NULL, &btree_tmp, 0, 0);
		}
		if (i == 1) {
			btree = btree_tmp;
			skiplist = skiplist_tmp;
			weight = weight_tmp;
		}
		else if (btree_tmp->number_of_elements < btree->number_of_elements) {
			weights[i - 2] = weight;
			weight = weight_tmp;
			btrees[i - 2] = btree;
			btree = btree_tmp;
			skiplists[i - 2] = skiplist;
			skiplist = skiplist_tmp;
		}
		else {
			weights[i - 2] = weight_tmp;
			btrees[i - 2] = btree_tmp;
			skiplists[i - 2] = skiplist_tmp;
		}
	}

	RL_CALL(rl_zset_get_objects, RL_OK, db, keys[0], keys_len[0], NULL, &target_btree, &target_btree_page, &target_skiplist, &target_skiplist_page, 1, 1);

	if (skiplist) {
		RL_CALL(rl_skiplist_iterator_create, RL_OK, db, &skiplist_iterator, skiplist, 0, 0, 0);
	} else {
		RL_CALL(rl_btree_iterator_create, RL_OK, db, btree, &btree_iterator);
	}
	while ((retval = skiplist ? rl_skiplist_iterator_next(skiplist_iterator, &node) : rl_btree_iterator_next(btree_iterator, NULL, &tmp)) == RL_OK) {
		found = 1;
		if (skiplist) {
			skiplist_score = node->score * weight;
			multi_string_page = node->value;
		} else {
			skiplist_score = weight;
			multi_string_page = *(long *)tmp;
			rl_free(tmp);
		}
		for (i = 1; i < keys_size - 1; i++) {
			RL_CALL(rl_multi_string_sha1, RL_OK, db, digest, multi_string_page);

			retval = rl_btree_find_score(db, btrees[i - 1], digest, &tmp, NULL, NULL);
			if (retval == RL_NOT_FOUND) {
				found = 0;
				break;
			}
			else if (retval == RL_FOUND) {
				tmp_score = skiplist ? *(double *)tmp : 1.0;
				if (aggregate == RL_ZSET_AGGREGATE_SUM) {
					skiplist_score += tmp_score * weights[i - 1];
				}
				else if (
				    (aggregate == RL_ZSET_AGGREGATE_MIN && tmp_score * weights[i - 1] < skiplist_score) ||
				    (aggregate == RL_ZSET_AGGREGATE_MAX && tmp_score * weights[i - 1] > skiplist_score)
				) {
					skiplist_score = tmp_score * weights[i - 1];
				}
			}
			else {
				goto cleanup;
			}
		}
		if (found) {
			RL_CALL(rl_multi_string_get, RL_OK, db, multi_string_page, &member, &memberlen);
			RL_CALL(add_member, RL_OK, db, target_btree, target_btree_page, target_skiplist, target_skiplist_page, isnan(skiplist_score) ? 0.0 : skiplist_score, member, memberlen);
			rl_free(member);
			member = NULL;
		}
	}
	skiplist_iterator = NULL;
	btree_iterator = NULL;

	if (retval != RL_END) {
		goto cleanup;
	}

	retval = RL_OK;
cleanup:
	rl_free(member);
	if (skiplist_iterator) {
		rl_zset_iterator_destroy(skiplist_iterator);
	}
	if (btree_iterator) {
		rl_btree_iterator_destroy(btree_iterator);
	}
	rl_free(weights);
	rl_free(btrees);
	rl_free(skiplists);
	return retval;
}
示例#3
0
文件: rlite.c 项目: yodamaster/rlite
int rl_database_is_balanced(rlite *db, short *pages)
{
	int retval;
	void *tmp = NULL;
	rl_key *key;
	rl_btree *btree;
	rl_btree_iterator *iterator = NULL;
	retval = rl_get_key_btree(db, &btree, 0);
	if (retval == RL_NOT_FOUND) {
		retval = RL_OK;
		goto cleanup;
	}
	else if (retval != RL_OK) {
		goto cleanup;
	}

	RL_CALL(rl_btree_pages, RL_OK, db, btree, pages);
	RL_CALL(rl_btree_iterator_create, RL_OK, db, btree, &iterator);

	while ((retval = rl_btree_iterator_next(iterator, NULL, &tmp)) == RL_OK) {
		key = tmp;
		pages[key->string_page] = 1;
		pages[key->value_page] = 1;
		RL_CALL(rl_multi_string_pages, RL_OK, db, key->string_page, pages);
		if (key->type == RL_TYPE_ZSET) {
			retval = rl_zset_pages(db, key->value_page, pages);
		}
		else if (key->type == RL_TYPE_HASH) {
			retval = rl_hash_pages(db, key->value_page, pages);
		}
		else if (key->type == RL_TYPE_SET) {
			retval = rl_set_pages(db, key->value_page, pages);
		}
		else if (key->type == RL_TYPE_LIST) {
			retval = rl_llist_pages(db, key->value_page, pages);
		}
		else if (key->type == RL_TYPE_STRING) {
			retval = rl_string_pages(db, key->value_page, pages);
		}
		else {
			fprintf(stderr, "Unknown type %d\n", key->type);
			goto cleanup;
		}
		if (retval != RL_OK) {
			goto cleanup;
		}
		rl_free(tmp);
	}
	tmp = NULL;
	iterator = NULL;

	if (retval != RL_END) {
		goto cleanup;
	}

	retval = RL_OK;

cleanup:
	rl_free(tmp);
	rl_btree_iterator_destroy(iterator);
	return retval;
}
示例#4
0
文件: rlite.c 项目: yodamaster/rlite
int rl_keys(struct rlite *db, unsigned char *pattern, long patternlen, long *_len, unsigned char ***_result, long **_resultlen)
{
	int retval;
	rl_btree *btree;
	rl_btree_iterator *iterator;
	rl_key *key;
	void *tmp;
	long alloc, len;
	unsigned char **result = NULL, *keystr;
	long *resultlen = NULL, keystrlen;
	retval = rl_get_key_btree(db, &btree, 0);
	if (retval == RL_NOT_FOUND) {
		*_len = 0;
		*_result = NULL;
		*_resultlen = NULL;
		retval = RL_OK;
		goto cleanup;
	}
	else if (retval != RL_OK) {
		goto cleanup;
	}

	RL_CALL(rl_btree_iterator_create, RL_OK, db, btree, &iterator);

	len = 0;
	alloc = 16;
	RL_MALLOC(result, sizeof(unsigned char *) * alloc);
	RL_MALLOC(resultlen, sizeof(long) * alloc);
	int allkeys = patternlen == 1 && pattern[0] == '*';
	while ((retval = rl_btree_iterator_next(iterator, NULL, &tmp)) == RL_OK) {
		key = tmp;
		RL_CALL(rl_multi_string_get, RL_OK, db, key->string_page, &keystr, &keystrlen);
		if (allkeys || rl_stringmatchlen((char *)pattern, patternlen, (char *)keystr, keystrlen, 0)) {
			if (len + 1 == alloc) {
				RL_REALLOC(result, sizeof(unsigned char *) * alloc * 2)
				RL_REALLOC(resultlen, sizeof(long) * alloc * 2)
				alloc *= 2;
			}
			result[len] = keystr;
			resultlen[len] = keystrlen;
			len++;
		}
		else {
			rl_free(keystr);
		}
		rl_free(key);
	}

	if (retval != RL_END) {
		goto cleanup;
	}

	// TODO: should we realloc to shrink the result?
	*_len = len;
	*_result = result;
	*_resultlen = resultlen;

	retval = RL_OK;
cleanup:
	if (retval != RL_OK) {
		rl_free(result);
		rl_free(resultlen);
	}
	return retval;
}
示例#5
0
TEST fuzzy_hash_test_iterator(long size, long btree_node_size, int _commit)
{
	INIT();

	rl_btree_iterator *iterator = NULL;
	long *elements = malloc(sizeof(long) * size);
	long *nonelements = malloc(sizeof(long) * size);
	long *values = malloc(sizeof(long) * size);

	long btree_page = db->next_empty_page;
	RL_CALL_VERBOSE(rl_write, RL_OK, db, btree->type->btree_type, btree_page, btree);

	long i, element, value, *element_copy, *value_copy;

	long j;

	void *tmp;
	long prev_score = -1.0, score;

	for (i = 0; i < size; i++) {
		element = rand();
		value = rand();
		if (contains_element(element, elements, i)) {
			i--;
			continue;
		}
		else {
			elements[i] = element;
			element_copy = malloc(sizeof(long));
			*element_copy = element;
			values[i] = value;
			value_copy = malloc(sizeof(long));
			*value_copy = value;
			RL_CALL_VERBOSE(rl_btree_add_element, RL_OK, db, btree, btree_page, element_copy, value_copy);
			RL_CALL_VERBOSE(rl_btree_is_balanced, RL_OK, db, btree);
		}

		RL_CALL_VERBOSE(rl_btree_iterator_create, RL_OK, db, btree, &iterator);
		EXPECT_LONG(iterator->size, i + 1);

		j = 0;
		while (RL_OK == (retval = rl_btree_iterator_next(iterator, &tmp, NULL))) {
			score = *(long *)tmp;
			rl_free(tmp);
			if (j++ > 0) {
				if (prev_score >= score) {
					fprintf(stderr, "Tree is in a bad state in element %ld after adding child %ld\n", j, i);
					retval = RL_UNEXPECTED;
					goto cleanup;
				}
			}
			prev_score = score;
		}

		if (retval != RL_END) {
			rl_free(tmp);
			goto cleanup;
		}

		EXPECT_LONG(j, i + 1);
		iterator = NULL;

		if (_commit) {
			RL_CALL_VERBOSE(rl_commit, RL_OK, db);
			RL_CALL_VERBOSE(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_long_long, btree_page, &rl_btree_type_hash_long_long, &tmp, 1);
			btree = tmp;
		}
	}


	rl_btree_iterator_destroy(iterator);
	retval = 0;
cleanup:
	free(values);
	free(elements);
	free(nonelements);
	rl_close(db);
	if (retval == 0) { PASS(); } else { FAIL(); }
}