summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchenzizhan <[email protected]>2024-04-19 17:26:37 +0800
committerchenzizhan <[email protected]>2024-04-19 17:26:37 +0800
commitba621ef1c677e1a5ad6ffab6dcd4d771916cd27e (patch)
tree2cc49f3a0ccd269eb1e155c5947e0961eaa00dc0
parentd1375c9ce15ea764272a658072666b0ed519dc94 (diff)
TSG-20709 : wrap when add topk and cause a very big topk entry is viewed as dying cell
-rw-r--r--src/tags/cell_manager.c4
-rw-r--r--src/tags/cell_manager.h2
-rw-r--r--src/tags/heavy_keeper.c34
-rw-r--r--src/tags/heavy_keeper.h6
-rw-r--r--src/tags/sorted_set.c56
-rw-r--r--src/tags/sorted_set.h14
6 files changed, 63 insertions, 53 deletions
diff --git a/src/tags/cell_manager.c b/src/tags/cell_manager.c
index 7c3b61e..67e0cbf 100644
--- a/src/tags/cell_manager.c
+++ b/src/tags/cell_manager.c
@@ -152,7 +152,7 @@ long long cell_manager_get_count_by_tag(const struct cell_manager *pthis, const
return -1;
}
- unsigned int count = 0;
+ unsigned long long int count = 0;
int ret = heavy_keeper_query_one(pthis->topk_tag_id_map, tag, &count, NULL);
if (ret == -1) {
return -1;
@@ -191,7 +191,7 @@ int cell_manager_add_cell(struct cell_manager *pthis, const struct tag_hash_key
return pthis->next_cell_id++;
}
-int cell_manager_add_cell_topk(struct cell_manager *pthis, const struct tag_hash_key *tag, unsigned int count, int *popped_cell_id)
+int cell_manager_add_cell_topk(struct cell_manager *pthis, const struct tag_hash_key *tag, unsigned long long int count, int *popped_cell_id)
{
int ret = heavy_keeper_add(pthis->topk_tag_id_map, tag, count, pthis->next_cell_id, popped_cell_id);
if (ret == -1) { // didn't add
diff --git a/src/tags/cell_manager.h b/src/tags/cell_manager.h
index eea3bc3..479e444 100644
--- a/src/tags/cell_manager.h
+++ b/src/tags/cell_manager.h
@@ -20,7 +20,7 @@ int cell_manager_find(const struct cell_manager *pthis, const struct tag_hash_ke
int cell_manager_get_cardinality(const struct cell_manager *pthis);
int cell_manager_add_cell(struct cell_manager *pthis, const struct tag_hash_key *tag);
-int cell_manager_add_cell_topk(struct cell_manager *pthis, const struct tag_hash_key *tag, unsigned int count, int *popped_cell_id);
+int cell_manager_add_cell_topk(struct cell_manager *pthis, const struct tag_hash_key *tag, unsigned long long int count, int *popped_cell_id);
int cell_manager_delete_cell(struct cell_manager *pthis, const struct tag_hash_key *tag);
void cell_manager_merge_topk(struct cell_manager *dest, const struct cell_manager *src,
diff --git a/src/tags/heavy_keeper.c b/src/tags/heavy_keeper.c
index 894eead..f866484 100644
--- a/src/tags/heavy_keeper.c
+++ b/src/tags/heavy_keeper.c
@@ -25,7 +25,7 @@
struct Bucket {
unsigned int finger_print;
- unsigned count; // the actual count, sum of all uuid_hash_node->count
+ unsigned long long count; // the actual count, sum of all uuid_hash_node->count
};
struct heavy_keeper {
@@ -120,7 +120,7 @@ void heavy_keeper_free(struct heavy_keeper *hk) {
/*********************************add and query*************************************/
/***********************************************************************************/
-bool if_need_to_decay(struct heavy_keeper *hk, struct Bucket *bucket, unsigned count) {
+bool if_need_to_decay(struct heavy_keeper *hk, struct Bucket *bucket, unsigned long long count) {
if (bucket->count == 0) {
return true;
}
@@ -156,9 +156,9 @@ struct Bucket *map_flow_id_hash_to_bucket(struct heavy_keeper *hk, int array_ind
return &(hk->sketch[array_index * w + Hsh]);
}
-unsigned count_add(unsigned a, unsigned b) {
- if (a > UINT32_MAX - b) {
- return UINT32_MAX;
+unsigned long long count_add(unsigned long long a, unsigned long long b) {
+ if (a > UINT64_MAX - b) {
+ return UINT64_MAX;
}
return a + b;
}
@@ -170,7 +170,7 @@ unsigned my_max(unsigned a, unsigned b) {
return b;
}
-static int heavy_keeper_add_by_recording_popped_data(struct heavy_keeper *heavy_keeper, const struct tag_hash_key *tag, unsigned int count, int cell_id, int *popped_id_out)
+static int heavy_keeper_add_by_recording_popped_data(struct heavy_keeper *heavy_keeper, const struct tag_hash_key *tag, unsigned long long int count, int cell_id, int *popped_id_out)
{
if (count == 0) {
int cell_id_old = sorted_set_get_cell_id(heavy_keeper->top_K_heap, tag);
@@ -194,7 +194,7 @@ static int heavy_keeper_add_by_recording_popped_data(struct heavy_keeper *heavy_
struct sorted_set *summary = heavy_keeper->top_K_heap;
unsigned nMin = sorted_set_get_min_count(summary);
- unsigned maxv = 0;
+ unsigned long long maxv = 0;
unsigned int FP = tag_hash_key_cal_hash_val(tag, FP_HASH_KEY);
for (int j = 0; j < heavy_keeper->params.array_num; j++) {
@@ -225,7 +225,7 @@ static int heavy_keeper_add_by_recording_popped_data(struct heavy_keeper *heavy_
}
}
- unsigned int tmp_cnt = sorted_set_get_count(summary, tag);
+ unsigned long long int tmp_cnt = sorted_set_get_count(summary, tag);
if (tmp_cnt == 0) { // the flow is not in sorted set
if ((maxv - nMin <= count && maxv != nMin) || sorted_set_cardinality(summary) != heavy_keeper->K) {
assert(cell_id >= 0);
@@ -257,7 +257,7 @@ static int heavy_keeper_add_by_recording_popped_data(struct heavy_keeper *heavy_
return -1;
}
-int heavy_keeper_add(struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned int count, int cell_id, int *popped_id_out)
+int heavy_keeper_add(struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned long long int count, int cell_id, int *popped_id_out)
{
*popped_id_out = -1;
heavy_keeper_add_by_recording_popped_data(hk, tag, count, cell_id, popped_id_out);
@@ -284,7 +284,7 @@ struct tag_hash_key *heavy_keeper_get_true_pst_tag(const struct heavy_keeper *hk
struct heavy_keeper_result *heavy_keeper_query(const struct heavy_keeper *hk) {
size_t query_entry_num = sorted_set_cardinality(hk->top_K_heap);
struct heavy_keeper_result *stats = (struct heavy_keeper_result *)malloc(sizeof(struct heavy_keeper_result));
- stats->count = (unsigned *)malloc(query_entry_num * sizeof(unsigned));
+ stats->count = (unsigned long long *)malloc(query_entry_num * sizeof(unsigned long long));
stats->tags = (struct tag_hash_key **)malloc(query_entry_num * sizeof(struct tag_hash_key *));
stats->cell_id = (int *)malloc(query_entry_num * sizeof(int));
stats->n_key = query_entry_num;
@@ -298,10 +298,10 @@ size_t heavy_keeper_get_cardinality(const struct heavy_keeper *hk) {
return sorted_set_cardinality(hk->top_K_heap);
}
-int heavy_keeper_query_one(const struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned int *count_out, int *cell_id_out)
+int heavy_keeper_query_one(const struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned long long int *count_out, int *cell_id_out)
{
if (count_out != NULL) {
- unsigned int count = sorted_set_get_count(hk->top_K_heap, tag);
+ unsigned long long int count = sorted_set_get_count(hk->top_K_heap, tag);
if (count == 0) {
*count_out = 0;
return -1;
@@ -346,11 +346,11 @@ static void heavy_keeper_merge_sketch(struct heavy_keeper *dest, const struct he
}
}
-unsigned find_maxv_in_sketch(struct heavy_keeper *hk, const struct tag_hash_key *tag) {
+unsigned long long find_maxv_in_sketch(struct heavy_keeper *hk, const struct tag_hash_key *tag) {
struct Bucket *bucket;
unsigned fp = tag_hash_key_cal_hash_val(tag, FP_HASH_KEY);
- unsigned maxv = 0;
+ unsigned long long maxv = 0;
for (int array_id = 0; array_id < hk->params.array_num; array_id++) {
bucket = map_flow_id_hash_to_bucket(hk, array_id, tag, tag_hash_key_cal_hash_val(tag, FP_HASH_KEY)); // hk->sketch is the merge of two. So just check one
@@ -421,7 +421,7 @@ void heavy_keeper_merge_sorted_set_recording_id_details(struct heavy_keeper *des
int size_src = sorted_set_cardinality(ss_src);
int max_size = size_dest > size_src ? size_dest : size_src;
- unsigned *count_arr = (unsigned *)malloc(max_size * sizeof(unsigned));
+ unsigned long long *count_arr = (unsigned long long *)malloc(max_size * sizeof(unsigned long long));
// struct tag_hash_key **tag_arr = (struct tag_hash_key **)malloc(max_size * sizeof(struct tag_hash_key *));
struct tag_hash_key **tag_arr = (struct tag_hash_key **)calloc(max_size, sizeof(struct tag_hash_key *));
int *cell_id_arr_dst = (int *)malloc(size_dest * sizeof(int));
@@ -435,7 +435,7 @@ void heavy_keeper_merge_sorted_set_recording_id_details(struct heavy_keeper *des
/* ------------------------------ merge dest ------------------------------ */
for (int i = 0; i < size_dest; i++) {
- unsigned maxv = find_maxv_in_sketch(dest, tag_arr[i]);
+ unsigned long long maxv = find_maxv_in_sketch(dest, tag_arr[i]);
assert(tag_arr[i] != NULL);
assert(cell_id_arr_dst[i] >= 0);
sorted_set_insert(new_rec, tag_arr[i], maxv, cell_id_arr_dst[i]);
@@ -465,7 +465,7 @@ void heavy_keeper_merge_sorted_set_recording_id_details(struct heavy_keeper *des
continue;
}
- unsigned maxv = find_maxv_in_sketch(dest, tag_src); // the dest heavy keeper has been merged, so the maxv is the maxv in the merged sketch, instead of the dest sketch
+ unsigned long long maxv = find_maxv_in_sketch(dest, tag_src); // the dest heavy keeper has been merged, so the maxv is the maxv in the merged sketch, instead of the dest sketch
int popped_id = -1;
int now_idx = next_idx;
int find_id = find_next_unused_cell_id(cell_id_arr_dst, size_dest, last_find_id, &now_idx);
diff --git a/src/tags/heavy_keeper.h b/src/tags/heavy_keeper.h
index 216d8f6..688911b 100644
--- a/src/tags/heavy_keeper.h
+++ b/src/tags/heavy_keeper.h
@@ -18,7 +18,7 @@ extern "C"{
struct heavy_keeper_result {
size_t n_key; // number of result
struct tag_hash_key **tags;
- unsigned *count; // count[i] is the metric count of the corresponding flow id
+ unsigned long long *count; // count[i] is the metric count of the corresponding flow id
int *cell_id;
};
@@ -52,7 +52,7 @@ void heavy_keeper_reset(struct heavy_keeper *hk);
// tag: the pointer to the tag, user should alloc it. Its memory will be freed by heavy keeper, so don't free it after calling heavy_keeper_add.
// return -1 when the key is not inserted to the heavy keeper(not fail). popped_id_out is -1 if not popped. any other value >= 0 means the id of the popped member.
// the cube id will give the key if the key is new, in which case return 0, if the key is already in the heavy keeper, return 1.
-int heavy_keeper_add(struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned int count, int cube_id, int *popped_id_out);
+int heavy_keeper_add(struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned long long int count, int cube_id, int *popped_id_out);
/**
* @brief Query the top-K flows.The flow id with bigger count ranks at smaller index.
@@ -61,7 +61,7 @@ int heavy_keeper_add(struct heavy_keeper *hk, const struct tag_hash_key *tag, un
*/
struct heavy_keeper_result *heavy_keeper_query(const struct heavy_keeper *hk);
-int heavy_keeper_query_one(const struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned int *count_out, int *cube_id_out);
+int heavy_keeper_query_one(const struct heavy_keeper *hk, const struct tag_hash_key *tag, unsigned long long int *count_out, int *cube_id_out);
size_t heavy_keeper_get_cardinality(const struct heavy_keeper *hk);
/**
diff --git a/src/tags/sorted_set.c b/src/tags/sorted_set.c
index 2f9dd7a..df6002e 100644
--- a/src/tags/sorted_set.c
+++ b/src/tags/sorted_set.c
@@ -58,9 +58,9 @@ void entry_data_destroy(struct entry_data *entry_data)
free(entry_data);
}
-unsigned sorted_set_entry_get_count(const heap_entry *entry)
+unsigned long long sorted_set_entry_get_count(const heap_entry *entry)
{
- unsigned count = *(unsigned *)entry->key;
+ unsigned long long count = *(unsigned long long *)entry->key;
if (count == 0) {
return 0;
}
@@ -86,7 +86,7 @@ struct entry_data *sorted_set_entry_get_data(const heap_entry *entry)
*/
bool sorted_set_entry_dying(const heap_entry *entry)
{
- unsigned count = *(unsigned *)entry->key;
+ unsigned long long count = *(unsigned long long *)entry->key;
return count == 0;
}
@@ -156,21 +156,21 @@ heap_entry *sorted_set_find_entry(const struct sorted_set *ss, const struct tag_
return (heap_entry *)s->val;
}
-void sorted_set_entry_set_key(struct sorted_set *ss, heap_entry *entry, unsigned count)
+void sorted_set_entry_set_key(struct sorted_set *ss, heap_entry *entry, unsigned long long count)
{
- *(unsigned *)(entry->key) = count;
+ *(unsigned long long *)(entry->key) = count;
adjust_heap_node(ss->heap, entry);
}
-unsigned sorted_set_pop_and_record_popped_back(struct sorted_set *ss, int *popped_cell_id)
+unsigned long long sorted_set_pop_and_record_popped_back(struct sorted_set *ss, int *popped_cell_id)
{
struct hash_node *hash_tbl = ss->hash_tbl;
heap_entry *entry = (heap_entry *)pop_heap(ss->heap);
if (entry == NULL) {
return 0;
}
- unsigned count_ret = sorted_set_entry_get_count(entry);
+ unsigned long long count_ret = sorted_set_entry_get_count(entry);
struct entry_data *tmp_data = sorted_set_entry_get_data(entry);
struct hash_node *s = NULL;
@@ -197,10 +197,10 @@ unsigned sorted_set_pop_and_record_popped_back(struct sorted_set *ss, int *poppe
return count_ret;
}
-unsigned sorted_set_pop(struct sorted_set *ss)
+unsigned long long sorted_set_pop(struct sorted_set *ss)
{
int dummy;
- unsigned count_ret = sorted_set_pop_and_record_popped_back(ss, &dummy);
+ unsigned long long count_ret = sorted_set_pop_and_record_popped_back(ss, &dummy);
return count_ret;
}
@@ -210,10 +210,15 @@ bool sorted_set_check_is_full(const struct sorted_set *ss)
return ss->heap->cur_size >= ss->heap->max_size;
}
-void sorted_set_insert_to_available_heap(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned cnt, int cell_id)
+void sorted_set_insert_to_available_heap(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long cnt, int cell_id)
{
- cnt += 1; // sorted set will let the count start from 1, 0 for dying entry.
- unsigned *tmp_cnt = (unsigned *)malloc(sizeof(unsigned));
+ // cnt += 1; // sorted set will let the count start from 1, 0 for dying entry.
+ if (cnt >= UINT64_MAX) {
+ cnt = UINT64_MAX;
+ } else {
+ cnt += 1; // sorted set will let the count start from 1, 0 for dying entry.
+ }
+ unsigned long long *tmp_cnt = (unsigned long long*)malloc(sizeof(unsigned long long));
*tmp_cnt = cnt;
struct entry_data *tmp_data = entry_data_construct(tag, cell_id);
heap_entry *node = (heap_entry *)malloc(sizeof(heap_entry));
@@ -232,7 +237,7 @@ void sorted_set_insert_to_available_heap(struct sorted_set *ss, const struct tag
ss->n_living_entry++;
}
-int sorted_set_insert(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned cnt, int cell_id)
+int sorted_set_insert(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long cnt, int cell_id)
{
assert(cell_id >= 0);
assert(tag != NULL);
@@ -249,7 +254,7 @@ int sorted_set_insert(struct sorted_set *ss, const struct tag_hash_key *tag, uns
return 1;
}
-int sorted_set_insert_and_record_popped_back(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned cnt, int cell_id, int *popped_user_data)
+int sorted_set_insert_and_record_popped_back(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long cnt, int cell_id, int *popped_user_data)
{
assert(cell_id >= 0);
assert(tag != NULL);
@@ -262,7 +267,12 @@ int sorted_set_insert_and_record_popped_back(struct sorted_set *ss, const struct
if (!sorted_set_entry_dying(entry)) {
return -1;
}
- sorted_set_entry_set_key(ss, entry, cnt + 1); // count 0 for dying entry.
+ if (cnt >= UINT64_MAX) {
+ cnt = UINT64_MAX;
+ } else {
+ cnt += 1; // sorted set will let the count start from 1, 0 for dying entry.
+ }
+ sorted_set_entry_set_key(ss, entry, cnt); // count 0 for dying entry.
struct entry_data *data = sorted_set_entry_get_data(entry);
data->cell_id = cell_id;
ss->n_living_entry++;
@@ -285,7 +295,7 @@ int sorted_set_insert_and_record_popped_back(struct sorted_set *ss, const struct
return popped ? 2 : 1;
}
-unsigned sorted_set_get_min_count(const struct sorted_set *ss)
+unsigned long long sorted_set_get_min_count(const struct sorted_set *ss)
{
heap *heap = ss->heap;
if (heap->cur_size == 0) {
@@ -293,14 +303,14 @@ unsigned sorted_set_get_min_count(const struct sorted_set *ss)
}
const heap_entry *ret = (heap_entry *)(heap->nodes[0]);
- unsigned int count = *(unsigned int *)ret->key;
+ unsigned long long count = *(unsigned long long *)ret->key;
if (count == 0) {
return 0;
}
return count - 1; // sorted set will let the count start from 1, 0 for dying entry.
}
-unsigned sorted_set_get_count(const struct sorted_set *ss, const struct tag_hash_key *tag)
+unsigned long long sorted_set_get_count(const struct sorted_set *ss, const struct tag_hash_key *tag)
{
if (sorted_set_cardinality(ss) == 0) {
return 0;
@@ -334,7 +344,7 @@ int sorted_set_cardinality(const struct sorted_set *ss)
return ss->n_living_entry;
}
-int sorted_set_incrby(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned count)
+int sorted_set_incrby(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long count)
{
heap_entry *entry = sorted_set_find_entry(ss, tag);
if (entry == NULL) {
@@ -345,7 +355,7 @@ int sorted_set_incrby(struct sorted_set *ss, const struct tag_hash_key *tag, uns
}
typedef struct {
- unsigned key;
+ unsigned long long key;
struct entry_data *val;
} tmp_heap_node;
@@ -363,7 +373,7 @@ int cmp_tmp_heap_node(const void *a, const void *b)
}
}
-void sorted_set_dump(const struct sorted_set *ss, unsigned *scores_out, struct tag_hash_key **tags_out, int *user_data_out)
+void sorted_set_dump(const struct sorted_set *ss, unsigned long long *scores_out, struct tag_hash_key **tags_out, int *user_data_out)
{
struct minheap *h = ss->heap;
tmp_heap_node *tmp_nodes = (tmp_heap_node *)malloc(sizeof(tmp_heap_node) * h->cur_size);
@@ -416,14 +426,14 @@ void sorted_set_reset(struct sorted_set *ss)
struct hash_node *h_node, *tmp;
HASH_ITER(hh, tbl, h_node, tmp) {
heap_entry *entry = (heap_entry *)h_node->val;
- *(unsigned *)entry->key = 0;
+ *(unsigned long long *)entry->key = 0;
}
heap *heap = ss->heap;
heap_entry *entry;
for (int i = 0; i < heap->cur_size; i++) {
entry = (heap_entry *)heap->nodes[i];
- *(unsigned *)entry->key = 0;
+ *(unsigned long long *)entry->key = 0;
}
ss->n_living_entry = 0;
diff --git a/src/tags/sorted_set.h b/src/tags/sorted_set.h
index 6a079a8..4403c7b 100644
--- a/src/tags/sorted_set.h
+++ b/src/tags/sorted_set.h
@@ -28,33 +28,33 @@ void sorted_set_free(struct sorted_set *ss);
* @param tag the pointer to the tag, user should alloc it, when the entry is popped out, the tag will be freed. If the tag is not inserted to the sorted set, user should free it.
* @return 0 if the entry is not inserted because the sorted set is full and the score of the entry is less than the minimum score in the sorted set. Otherwise, return 1.
*/
-int sorted_set_insert(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned cnt, int cell_id);
+int sorted_set_insert(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long cnt, int cell_id);
/*
@return -1 if the entry already exist. 0 if the entry is not inserted because the sorted set is full. return 2 if some data is popped out. Otherwise, return 1 if the entry is inserted successfully and sorted set not full.
@param popped_user_data user should alloc it, popped_user_data_size is equal to the size of the user data memory.
*/
-int sorted_set_insert_and_record_popped_back(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned cnt, int cell_id, int *popped_user_data);
+int sorted_set_insert_and_record_popped_back(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long cnt, int cell_id, int *popped_user_data);
/**
* @brief pop out the minumum-score entry from the sorted set.
* @param ss the sorted set
* @return the score of the minimum-score member. return 0 if the sorted set is empty.
*/
-unsigned sorted_set_pop(struct sorted_set *ss);
+unsigned long long sorted_set_pop(struct sorted_set *ss);
/**
* @brief Increase the score of the given member.
* @param score By the value of which increase member.
*/
-int sorted_set_incrby(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned count);
+int sorted_set_incrby(struct sorted_set *ss, const struct tag_hash_key *tag, unsigned long long count);
/**
* @brief get the minimum score from the sorted set.
* @param ss the sorted set
* @return the score of the minimum-score member
*/
-unsigned sorted_set_get_min_count(const struct sorted_set *ss);
+unsigned long long sorted_set_get_min_count(const struct sorted_set *ss);
/**
* @brief find the how many elements the sorted set contains.
@@ -65,7 +65,7 @@ int sorted_set_cardinality(const struct sorted_set *ss);
* @brief Get the score of the given key string.
* @return the score of the member. return 0 if the member is not in the sorted set.
*/
-unsigned sorted_set_get_count(const struct sorted_set *ss, const struct tag_hash_key *tag);
+unsigned long long sorted_set_get_count(const struct sorted_set *ss, const struct tag_hash_key *tag);
int sorted_set_get_cell_id(const struct sorted_set *ss, const struct tag_hash_key *tag);
/**
* @brief Get all the contents in sorted order from small to big.
@@ -73,7 +73,7 @@ int sorted_set_get_cell_id(const struct sorted_set *ss, const struct tag_hash_ke
* @param tags_out the tags of the entries. User should alloc it and make sure the buffer is long enough. Don't free the content.
* @param user_data_out the user data of the entries. User should alloc it and make sure the buffer is long enough. Its content is the pointer to the user data in the sorted set. Don't free the content.
*/
-void sorted_set_dump(const struct sorted_set *ss, unsigned *scores_out, struct tag_hash_key **tags_out, int *user_data_out);
+void sorted_set_dump(const struct sorted_set *ss, unsigned long long *scores_out, struct tag_hash_key **tags_out, int *user_data_out);
struct sorted_set *sorted_set_copy(const struct sorted_set *ss);