diff options
| author | chenzizhan <[email protected]> | 2024-07-05 15:52:54 +0800 |
|---|---|---|
| committer | chenzizhan <[email protected]> | 2024-07-05 15:52:54 +0800 |
| commit | 140bd9a51aac330f7c367b61fe7b85f7d06fefe7 (patch) | |
| tree | f9de2aa89584a2fa5ca0602e8d603e64c3c704a0 | |
| parent | d822eaa3006588210a12694dc202df3f8f6e4187 (diff) | |
renames; manifest manager(a bidict) ; cube itself as item
| -rw-r--r-- | include/fieldstat/fieldstat.h | 2 | ||||
| -rw-r--r-- | src/cube.c | 155 | ||||
| -rw-r--r-- | src/fieldstat.c | 357 | ||||
| -rw-r--r-- | src/metrics/metric.c | 2 | ||||
| -rw-r--r-- | src/metrics/metric_manifest.c | 134 | ||||
| -rw-r--r-- | src/metrics/metric_manifest.h | 31 | ||||
| -rw-r--r-- | test/test_merge.cpp | 2 |
7 files changed, 320 insertions, 363 deletions
diff --git a/include/fieldstat/fieldstat.h b/include/fieldstat/fieldstat.h index 93ac2b8..b0969cf 100644 --- a/include/fieldstat/fieldstat.h +++ b/include/fieldstat/fieldstat.h @@ -158,7 +158,7 @@ void fieldstat_reset(struct fieldstat *instance); @brief Merge the instance. The registered cubes and metrics are merged even if there are no cells added. @return 0 if success. return FS_ERR_INVALID_PARAM when the registered cubes or metrics between dest and src of the same keys has different types or configurations(like different primary metric). */ -int fieldstat_merge(struct fieldstat *instance, struct fieldstat *src); +int fieldstat_merge(struct fieldstat *instance, const struct fieldstat *src); /* -------------------------------------------------------------------------- */ /* query */ @@ -19,15 +19,8 @@ struct exdata_new_args { size_t n_tags; }; -struct cube_manager_item { - char *key; - size_t key_len; - int id; - UT_hash_handle hh; -}; - struct cube_manager { - struct cube_manager_item *head; + struct cube *hash_table; struct cube **cube; size_t cube_cnt; @@ -54,9 +47,13 @@ struct cube { size_t n_shared_tags; int primary_metric_id; + char *key; + size_t key_len; + int id; + UT_hash_handle hh; }; -static void tag_array_copy(struct fieldstat_tag *tags_dst, const struct fieldstat_tag *tags_src, size_t n_tag) +static void tag_array_copy(struct fieldstat_tag *tags_dst, const struct fieldstat_tag *tags_src, size_t n_tag) // TODO: 改成clone吧, { for (size_t i = 0; i < n_tag; i++) { tags_dst[i].key = strdup(tags_src[i].key); @@ -108,28 +105,21 @@ void add_cube_to_position(struct cube_manager *instance, struct cube *cube, int } void cube_manager_free(struct cube_manager *pthis) { - struct cube_manager_item *node = NULL; - struct cube_manager_item *tmp = NULL; - struct cube_manager_item *head = pthis->head; + struct cube *node = NULL; + struct cube *tmp = NULL; + struct cube *head = pthis->hash_table; HASH_ITER(hh, head, node, tmp) { HASH_DEL(head, node); - free(node->key); - free(node); + cube_free(node); } - for (int i = 0; i < pthis->cube_cnt; i++) { - if (pthis->cube[i] != NULL) { - cube_free(pthis->cube[i]); - } - } - free(pthis->cube); free(pthis); } struct cube_manager *cube_manager_new() { struct cube_manager *pthis = (struct cube_manager *)malloc(sizeof(struct cube_manager)); - pthis->head = NULL; + pthis->hash_table = NULL; pthis->cube = (struct cube **)calloc(DEFAULT_N_CUBE, sizeof(struct cube *)); pthis->cube_cnt = 0; @@ -138,7 +128,7 @@ struct cube_manager *cube_manager_new() { } -static void build_dynamic_cell_key(const struct fieldstat_tag tags[], size_t n_tags, char **out_key, size_t *out_key_size) +static void tag2key(const struct fieldstat_tag tags[], size_t n_tags, char **out_key, size_t *out_key_size) { if (n_tags == 0) { // use a default dummy key @@ -223,14 +213,12 @@ static void build_dynamic_cell_key(const struct fieldstat_tag tags[], size_t n_t int cube_manager_add(struct cube_manager *pthis, struct cube *cube) { - char *key; - size_t key_len; - build_dynamic_cell_key(cube->cube_identifier, cube->n_shared_tags, &key, &key_len); + char *key = cube->key; + size_t key_len = cube->key_len; - struct cube_manager_item *node = NULL; - HASH_FIND(hh, pthis->head, key, key_len, node); - if (node != NULL) { - free(key); + struct cube *old_cube = NULL; + HASH_FIND(hh, pthis->hash_table, key, key_len, old_cube); + if (old_cube != NULL) { return -1; } @@ -241,55 +229,42 @@ int cube_manager_add(struct cube_manager *pthis, struct cube *cube) } } - node = (struct cube_manager_item *)malloc(sizeof(struct cube_manager_item)); - node->key = key; - node->key_len = key_len; - node->id = id; - HASH_ADD_KEYPTR(hh, pthis->head, node->key, key_len, node); + cube->id = id; + HASH_ADD_KEYPTR(hh, pthis->hash_table, cube->key, key_len, cube); add_cube_to_position(pthis, cube, id); return id; } -void cube_manager_delete_by_key(struct cube_manager *pthis, const char *key, size_t key_len) +void cube_manager_delete(struct cube_manager *pthis, struct cube *cube) { - struct cube_manager_item *node = NULL; - HASH_FIND(hh, pthis->head, key, key_len, node); - if (node == NULL) { - return; - } - - int id = node->id; - cube_free(pthis->cube[id]); + // char *key = cube->key; + // size_t key_len = cube->key_len; + // struct cube *node = NULL; + // HASH_FIND(hh, pthis->head, key, key_len, node); + // if (node == NULL) { + // return; + // } + + int id = cube->id; + HASH_DEL(pthis->hash_table, cube); + + cube_free(cube); pthis->cube[id] = NULL; if (id == pthis->cube_cnt - 1) { pthis->cube_cnt--; } - - HASH_DEL(pthis->head, node); - free(node->key); - free(node); -} - -void cube_manager_delete(struct cube_manager *pthis, struct cube *cube) -{ - char *key; - size_t key_len; - build_dynamic_cell_key(cube->cube_identifier, cube->n_shared_tags, &key, &key_len); - - cube_manager_delete_by_key(pthis, key, key_len); - free(key); } int cube_manager_find(const struct cube_manager *pthis, const struct fieldstat_tag *identifier, size_t n_tag) { char *key; size_t key_len; - build_dynamic_cell_key(identifier, n_tag, &key, &key_len); + tag2key(identifier, n_tag, &key, &key_len); - struct cube_manager_item *node = NULL; - HASH_FIND(hh, pthis->head, key, key_len, node); + struct cube *node = NULL; + HASH_FIND(hh, pthis->hash_table, key, key_len, node); free(key); if (node == NULL) { return -1; @@ -327,27 +302,23 @@ void cube_manager_list(const struct cube_manager *pthis, int **cube_ids, int *n_ void cube_manager_calibrate(struct cube_manager *pthis, const struct cube_manager *master) { - struct cube_manager_item *node = NULL; - struct cube_manager_item *tmp = NULL; + struct cube *node_in_master, *node_in_dest, *tmp; // exist in self but not in master - HASH_ITER(hh, pthis->head, node, tmp) { - struct cube_manager_item *node_in_master = NULL; - HASH_FIND(hh, master->head, node->key, node->key_len, node_in_master); + HASH_ITER(hh, pthis->hash_table, node_in_dest, tmp) { + HASH_FIND(hh, master->hash_table, node_in_dest->key, node_in_dest->key_len, node_in_master); if (node_in_master == NULL) { - cube_manager_delete_by_key(pthis, node->key, node->key_len); + cube_manager_delete(pthis, node_in_dest); } } // exist in master but not in self - HASH_ITER(hh, master->head, node, tmp) { - struct cube_manager_item *node_in_self = NULL; - HASH_FIND(hh, pthis->head, node->key, node->key_len, node_in_self); + HASH_ITER(hh, master->hash_table, node_in_master, tmp) { + HASH_FIND(hh, pthis->hash_table, node_in_master->key, node_in_master->key_len, node_in_dest); - if (node_in_self == NULL) { - int cube_id = node->id; - cube_manager_add(pthis, cube_fork(master->cube[cube_id])); + if (node_in_dest == NULL) { + cube_manager_add(pthis, cube_fork(node_in_master)); } } } @@ -355,26 +326,26 @@ void cube_manager_calibrate(struct cube_manager *pthis, const struct cube_manage struct cube_manager *cube_manager_fork(const struct cube_manager *src) { struct cube_manager *pthis = cube_manager_new(); - struct cube_manager_item *node = NULL; - struct cube_manager_item *tmp = NULL; - HASH_ITER(hh, src->head, node, tmp) { - cube_manager_add(pthis, cube_fork(src->cube[node->id])); + struct cube *node = NULL; + struct cube *tmp = NULL; + HASH_ITER(hh, src->hash_table, node, tmp) { + cube_manager_add(pthis, cube_fork(node)); } return pthis; } void cube_manager_merge(struct cube_manager *dest, const struct cube_manager *src) { - struct cube_manager_item *node = NULL; - struct cube_manager_item *tmp = NULL; - HASH_ITER(hh, src->head, node, tmp) { - struct cube_manager_item *node_in_dest = NULL; - HASH_FIND(hh, dest->head, node->key, node->key_len, node_in_dest); + struct cube *node = NULL; + struct cube *tmp = NULL; + HASH_ITER(hh, src->hash_table, node, tmp) { + struct cube *node_in_dest = NULL; + HASH_FIND(hh, dest->hash_table, node->key, node->key_len, node_in_dest); if (node_in_dest == NULL) { - cube_manager_add(dest, cube_copy(src->cube[node->id])); + cube_manager_add(dest, cube_copy(node)); } else { - cube_merge(dest->cube[node_in_dest->id], src->cube[node->id]); + cube_merge(node_in_dest, node); } } } @@ -530,8 +501,10 @@ struct cube *cube_info_new(const struct fieldstat_tag *shared_tags, size_t n_tag } cube->n_shared_tags = n_tag; - cube->max_n_cell = max_n_cell; + tag2key(shared_tags, n_tag, &cube->key, &cube->key_len); + + cube->id = -1; return cube; } @@ -573,6 +546,7 @@ void cube_free(struct cube *cube) { } fieldstat_free_tag_array(cube->cube_identifier, cube->n_shared_tags); + free(cube->key); free(cube); } @@ -592,7 +566,7 @@ void cube_set_primary_metric(struct cube *cube, int metric_id) { struct cell *get_cell(struct cube *cube, const struct fieldstat_tag *tags, size_t n_tag,long long increment, int metric_id) { char *tag_in_string; size_t tag_len; - build_dynamic_cell_key(tags, n_tag, &tag_in_string, &tag_len); + tag2key(tags, n_tag, &tag_in_string, &tag_len); struct exdata_new_args args; args.tags = tags; args.n_tags = n_tag; @@ -634,7 +608,7 @@ struct cell *get_cell(struct cube *cube, const struct fieldstat_tag *tags, size_ int cube_histogram_record(struct cube *cube, const struct metric_manifest *manifest, const struct fieldstat_tag *tags, size_t n_tag, long long value) { assert(manifest->type == METRIC_TYPE_HISTOGRAM); - assert(manifest->id != cube->primary_metric_id); + assert(cube->sampling_mode == SAMPLING_MODE_COMPREHENSIVE || (cube->primary_metric_id != manifest->id)); struct cell *cell_data = get_cell(cube, tags, n_tag, 0, manifest->id); if (cell_data == NULL) { @@ -651,7 +625,7 @@ int cube_histogram_record(struct cube *cube, const struct metric_manifest *manif int cube_hll_add(struct cube *cube, const struct metric_manifest *manifest, const struct fieldstat_tag *tags, size_t n_tag, const char *key, size_t key_len) { assert(manifest->type == METRIC_TYPE_HLL); - assert(manifest->id != cube->primary_metric_id); + assert(cube->sampling_mode == SAMPLING_MODE_COMPREHENSIVE || (cube->primary_metric_id != manifest->id)); struct cell *cell_data = get_cell(cube, tags, n_tag, 0, manifest->id); if (cell_data == NULL) { @@ -665,7 +639,7 @@ int cube_hll_add(struct cube *cube, const struct metric_manifest *manifest, cons int cube_counter_incrby(struct cube *cube, const struct metric_manifest *manifest, const struct fieldstat_tag *tags, size_t n_tag, long long increment) { assert(manifest->type == METRIC_TYPE_COUNTER); - assert(cube->primary_metric_id != manifest->id || increment >= 0); + assert(cube->sampling_mode == SAMPLING_MODE_COMPREHENSIVE || (cube->primary_metric_id != manifest->id || increment >= 0)); struct cell *cell_data = get_cell(cube, tags, n_tag, increment, manifest->id); if (cell_data == NULL) { @@ -680,7 +654,8 @@ int cube_counter_incrby(struct cube *cube, const struct metric_manifest *manifes int cube_counter_set(struct cube *cube, const struct metric_manifest *manifest, const struct fieldstat_tag *tags, size_t n_tag, long long value) { assert(manifest->type == METRIC_TYPE_COUNTER); - assert(cube->primary_metric_id != manifest->id); + assert(cube->sampling_mode == SAMPLING_MODE_COMPREHENSIVE || (cube->primary_metric_id != manifest->id)); + struct cell *cell_data = get_cell(cube, tags, n_tag, 0, manifest->id); if (cell_data == NULL) { return FS_ERR_TOO_MANY_CELLS; @@ -793,7 +768,7 @@ const struct cell *get_cell_by_tag_list(const struct cube *cube, const struct fi const struct cell *ret = NULL; char *tag_in_string; size_t tag_len; - build_dynamic_cell_key(tags->tag, tags->n_tag, &tag_in_string, &tag_len); + tag2key(tags->tag, tags->n_tag, &tag_in_string, &tag_len); switch (cube->sampling_mode) { diff --git a/src/fieldstat.c b/src/fieldstat.c index cc57a68..df5f482 100644 --- a/src/fieldstat.c +++ b/src/fieldstat.c @@ -13,23 +13,13 @@ #include "cube.h" #include "metric_manifest.h" -#define DEFAULT_N_METRIC 32 - -struct name_set { - char *name; - UT_hash_handle hh; -}; struct fieldstat { - struct metric_manifest **manifests; - size_t manifest_size; - size_t manifest_cnt; - struct name_set *metric_name_set; + struct metric_manifest_manager *manifest_manager; struct cube_manager *cube_manager; }; - union metric_parameter *construct_parameters(enum metric_type type, ...) { union metric_parameter *paras = (union metric_parameter *)malloc(sizeof(union metric_parameter)); @@ -53,29 +43,6 @@ union metric_parameter *construct_parameters(enum metric_type type, ...) return paras; } -struct metric_manifest *metric_manifest_copy(const struct metric_manifest *src) -{ - struct metric_manifest *dest = (struct metric_manifest *)malloc(sizeof(struct metric_manifest)); - dest->name = strdup(src->name); - if (src->paras == NULL) { - dest->paras = NULL; - } else { - dest->paras = (union metric_parameter *)malloc(sizeof(union metric_parameter)); - memcpy(dest->paras, src->paras, sizeof(union metric_parameter)); - } - - dest->type = src->type; - dest->id = src->id; - - return dest; -} - -void metric_manifest_free(struct metric_manifest *manifest) { - free(manifest->name); - free(manifest->paras); - free(manifest); -} - void tag_array_copy(struct fieldstat_tag *tags_dst, const struct fieldstat_tag *tags_src, size_t n_tag) { for (size_t i = 0; i < n_tag; i++) { @@ -131,15 +98,6 @@ bool is_tag_array_same(const struct fieldstat_tag *tags1, const struct fieldstat return 0; } -bool is_metric_name_duplicate(const struct fieldstat *instance, const char *name) -{ - for (size_t i = 0; i < instance->manifest_cnt; i++) { - if (strcmp(instance->manifests[i]->name, name) == 0) { - return true; - } - } - return false; -} /* -------------------------------------------------------------------------- */ /* fieldstat */ /* -------------------------------------------------------------------------- */ @@ -148,9 +106,7 @@ struct fieldstat *fieldstat_new() { struct fieldstat *instance = calloc(1, sizeof(struct fieldstat)); - instance->manifest_size = DEFAULT_N_METRIC; - instance->manifests = calloc(instance->manifest_size, sizeof(struct metric_manifest *)); - instance->manifest_cnt = 0; + instance->manifest_manager = metric_manifest_manager_new(); instance->cube_manager = cube_manager_new(); @@ -165,17 +121,7 @@ void fieldstat_free(struct fieldstat *instance) cube_manager_free(instance->cube_manager); - for (size_t i = 0; i < instance->manifest_cnt; i++) { - metric_manifest_free(instance->manifests[i]); - } - free(instance->manifests); - - struct name_set *name_set, *tmp; - HASH_ITER(hh, instance->metric_name_set, name_set, tmp) { - HASH_DEL(instance->metric_name_set, name_set); - free(name_set->name); - free(name_set); - } + metric_manifest_manager_free(instance->manifest_manager); free(instance); } @@ -243,6 +189,7 @@ int fieldstat_create_cube(struct fieldstat *instance, const struct fieldstat_tag return ret; //ret is the cube_id } +// cppcheck-suppress [constParameterPointer, unmatchedSuppression] int fieldstat_cube_set_primary_metric(struct fieldstat *instance, int cube_id, int metric_id) { if (instance == NULL) { @@ -253,13 +200,11 @@ int fieldstat_cube_set_primary_metric(struct fieldstat *instance, int cube_id, i if (cube == NULL) { return FS_ERR_INVALID_CUBE_ID; } - if (metric_id < 0 || metric_id >= instance->manifest_cnt) { + const struct metric_manifest *manifest = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); + if (manifest == NULL) { return FS_ERR_INVALID_METRIC_ID; } - if (instance->manifests[metric_id] == NULL) { - return FS_ERR_INVALID_METRIC_ID; - } - if (instance->manifests[metric_id]->type != METRIC_TYPE_COUNTER) { + if (manifest->type != METRIC_TYPE_COUNTER) { return FS_ERR_INVALID_PARAM; } @@ -271,57 +216,22 @@ int fieldstat_cube_set_primary_metric(struct fieldstat *instance, int cube_id, i /* -------------------------------------------------------------------------- */ /* metric register */ /* -------------------------------------------------------------------------- */ - -void add_manifest_to_instance(struct fieldstat *instance, const struct metric_manifest *manifest, int metric_id) -{ - if (metric_id >= instance->manifest_size) { - instance->manifests = realloc(instance->manifests, sizeof(struct metric_manifest *) * instance->manifest_size * 2); - memset(instance->manifests + instance->manifest_size, 0, sizeof(struct metric_manifest *) * (instance->manifest_size)); - instance->manifest_size *= 2; - } - - instance->manifests[metric_id] = (struct metric_manifest *)manifest; - if (metric_id >= instance->manifest_cnt) { - instance->manifest_cnt = metric_id + 1; - } - - struct name_set *name_set = (struct name_set *)malloc(sizeof(struct name_set)); - name_set->name = strdup(manifest->name); - HASH_ADD_KEYPTR(hh, instance->metric_name_set, name_set->name, strlen(name_set->name), name_set); -} - -static int append_manifest_to_instance(struct fieldstat *instance, const struct metric_manifest *metric) -{ - int metric_id = instance->manifest_cnt; - add_manifest_to_instance(instance, metric, metric_id); - - return metric_id; -} - -bool find_metric(const struct fieldstat *instance, const char *metric_name) -{ - struct name_set *name_set; - HASH_FIND_STR(instance->metric_name_set, metric_name, name_set); - if (name_set != NULL) { - return true; - } - return false; -} - int fieldstat_register_counter(struct fieldstat *instance, const char *metric_name) { - if (find_metric(instance, metric_name)) { - return FS_ERR_INVALID_KEY; - } - struct metric_manifest *metric = malloc(sizeof(struct metric_manifest)); metric->name = strdup(metric_name); - metric->paras = construct_parameters(METRIC_TYPE_COUNTER); + metric->parameters = construct_parameters(METRIC_TYPE_COUNTER); metric->type = METRIC_TYPE_COUNTER; - int id = append_manifest_to_instance(instance, metric); - metric->id = id; + int id = metric_manifest_manager_add(instance->manifest_manager, metric); + if (id < 0) { + free(metric->name); + free(metric->parameters); + free(metric); + return FS_ERR_INVALID_KEY; + } + metric->id = id; return id; } @@ -330,18 +240,21 @@ int fieldstat_register_hll(struct fieldstat *instance, const char *metric_name, if (precision < 4 || precision > 18) { return FS_ERR_INVALID_PARAM; } - if (find_metric(instance, metric_name)) { - return FS_ERR_INVALID_KEY; - } struct metric_manifest *metric = malloc(sizeof(struct metric_manifest)); metric->name = strdup(metric_name); - metric->paras = construct_parameters(METRIC_TYPE_HLL, precision); + metric->parameters = construct_parameters(METRIC_TYPE_HLL, precision); metric->type = METRIC_TYPE_HLL; - int id = append_manifest_to_instance(instance, metric); - metric->id = id; + int id = metric_manifest_manager_add(instance->manifest_manager, metric); + if (id < 0) { + free(metric->name); + free(metric->parameters); + free(metric); + return FS_ERR_INVALID_KEY; + } + metric->id = id; return id; } @@ -358,16 +271,20 @@ int fieldstat_register_hist(struct fieldstat *instance, const char *metric_name, { return FS_ERR_INVALID_PARAM; } - if (find_metric(instance, metric_name)) { - return FS_ERR_INVALID_KEY; - } + struct metric_manifest *metric = malloc(sizeof(struct metric_manifest)); metric->name = strdup(metric_name); - metric->paras = construct_parameters(METRIC_TYPE_HISTOGRAM, lowest_trackable_value, highest_trackable_value, significant_figures); + metric->parameters = construct_parameters(METRIC_TYPE_HISTOGRAM, lowest_trackable_value, highest_trackable_value, significant_figures); metric->type = METRIC_TYPE_HISTOGRAM; - int id = append_manifest_to_instance(instance, metric); + int id = metric_manifest_manager_add(instance->manifest_manager, metric); + if (id < 0) { + free(metric->name); + free(metric->parameters); + free(metric); + return FS_ERR_INVALID_KEY; + } metric->id = id; return id; @@ -376,132 +293,96 @@ int fieldstat_register_hist(struct fieldstat *instance, const char *metric_name, /* -------------------------------------------------------------------------- */ /* metric operation */ /* -------------------------------------------------------------------------- */ -int check_before_add(const struct fieldstat *instance, int cube_id, int metric_id, enum metric_type type) -{ - if (instance == NULL) { - return FS_ERR_NULL_HANDLER; - } - if (cube_manager_get_cube_by_id(instance->cube_manager, cube_id) == NULL) { +// cppcheck-suppress [constParameterPointer, unmatchedSuppression] +int fieldstat_counter_incrby(struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, long long increment) +{ + struct cube *cube = cube_manager_get_cube_by_id(instance->cube_manager, cube_id); + if (cube == NULL) { return FS_ERR_INVALID_CUBE_ID; } - - if (metric_id < 0 || metric_id >= instance->manifest_cnt) { - return FS_ERR_INVALID_METRIC_ID; - } - const struct metric_manifest *metric = instance->manifests[metric_id]; - if (metric == NULL || metric->type != type) { + const struct metric_manifest *manifest = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); + if (manifest == NULL || manifest->type != METRIC_TYPE_COUNTER) { return FS_ERR_INVALID_METRIC_ID; } - - return FS_OK; -} - -int fieldstat_counter_incrby(struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, long long increment) -{ - int ret = check_before_add(instance, cube_id, metric_id, METRIC_TYPE_COUNTER); - if (ret != FS_OK) { - return ret; - } - - struct cube *cube = cube_manager_get_cube_by_id(instance->cube_manager, cube_id); - const struct metric_manifest *manifest = instance->manifests[metric_id]; return cube_counter_incrby(cube, manifest, tags, n_tag, increment); - } +// cppcheck-suppress [constParameterPointer, unmatchedSuppression] int fieldstat_counter_set(struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, long long value) { - int ret = check_before_add(instance, cube_id, metric_id, METRIC_TYPE_COUNTER); - if (ret != FS_OK) { - return ret; - } struct cube *cube = cube_manager_get_cube_by_id(instance->cube_manager, cube_id); - const struct metric_manifest *manifest = instance->manifests[metric_id]; + if (cube == NULL) { + return FS_ERR_INVALID_CUBE_ID; + } + const struct metric_manifest *manifest = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); + if (manifest == NULL || manifest->type != METRIC_TYPE_COUNTER) { + return FS_ERR_INVALID_METRIC_ID; + } return cube_counter_set(cube, manifest, tags, n_tag, value); } +// cppcheck-suppress [constParameterPointer, unmatchedSuppression] int fieldstat_hll_add(struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, const char *key, size_t key_len) { - int ret = check_before_add(instance, cube_id, metric_id, METRIC_TYPE_HLL); - if (ret != FS_OK) { - return ret; - } - struct cube *cube = cube_manager_get_cube_by_id(instance->cube_manager, cube_id); - const struct metric_manifest *manifest = instance->manifests[metric_id]; + if (cube == NULL) { + return FS_ERR_INVALID_CUBE_ID; + } + const struct metric_manifest *manifest = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); + if (manifest == NULL || manifest->type != METRIC_TYPE_HLL) { + return FS_ERR_INVALID_METRIC_ID; + } return cube_hll_add(cube, manifest, tags, n_tag, key, key_len); } +// cppcheck-suppress [constParameterPointer, unmatchedSuppression] int fieldstat_hist_record(struct fieldstat *instance, int cube_id, int metric_id, const struct fieldstat_tag *tags, size_t n_tag, long long value) { - int ret = check_before_add(instance, cube_id, metric_id, METRIC_TYPE_HISTOGRAM); - if (ret != FS_OK) { - return ret; - } - struct cube *cube = cube_manager_get_cube_by_id(instance->cube_manager, cube_id); - const struct metric_manifest *manifest = instance->manifests[metric_id]; + if (cube == NULL) { + return FS_ERR_INVALID_CUBE_ID; + } + const struct metric_manifest *manifest = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); + if (manifest == NULL || manifest->type != METRIC_TYPE_HISTOGRAM) { + return FS_ERR_INVALID_METRIC_ID; + } return cube_histogram_record(cube, manifest, tags, n_tag, value); } -int fieldstat_merge(struct fieldstat *instance, struct fieldstat *src) +int fieldstat_merge(struct fieldstat *instance, const struct fieldstat *src) { if (instance == NULL || src == NULL) { return FS_ERR_NULL_HANDLER; } - int metric_len_src = src->manifest_cnt; - int metric_len_dst = instance->manifest_cnt; - int len_min = metric_len_src < metric_len_dst ? metric_len_src : metric_len_dst; + size_t n_metric_src = 0; + const struct metric_manifest **list_src = metric_manifest_manager_list(src->manifest_manager, &n_metric_src); + size_t n_metric_dst = 0; + const struct metric_manifest **list_dst = metric_manifest_manager_list(instance->manifest_manager, &n_metric_dst); + int len_min = n_metric_src < n_metric_dst ? n_metric_src : n_metric_dst; for (int i = 0; i < len_min; i++) { - const struct metric_manifest *metric_src = src->manifests[i]; - const struct metric_manifest *metric_dst = instance->manifests[i]; - if (metric_src->type != metric_dst->type || - strcmp(metric_src->name, metric_dst->name) != 0 - ) { - assert(0); + if (list_src[i]->type != list_dst[i]->type) { + return FS_ERR_INVALID_PARAM; + } + if (strcmp(list_src[i]->name, list_dst[i]->name) != 0) { return FS_ERR_INVALID_PARAM; } } - for (int i = metric_len_dst; i < metric_len_src; i++) { - const struct metric_manifest *metric_src = src->manifests[i]; - append_manifest_to_instance(instance, metric_manifest_copy(metric_src)); + for (int i = n_metric_dst; i < n_metric_src; i++) { + metric_manifest_manager_add(instance->manifest_manager, metric_manifest_copy(list_src[i])); } + cube_manager_merge(instance->cube_manager, src->cube_manager); return FS_OK; } -void metric_name_set_callibrate(struct fieldstat *instance, const struct fieldstat *master) -{ - struct name_set *name_set_master, *tmp, *name_set_dest; - // name in dest but not in master - HASH_ITER(hh, instance->metric_name_set, name_set_dest, tmp) { - HASH_FIND_STR(master->metric_name_set, name_set_dest->name, name_set_master); - if (name_set_master == NULL) { - HASH_DEL(instance->metric_name_set, name_set_dest); - free(name_set_dest->name); - free(name_set_dest); - } - } - - // name in master but not in dest - HASH_ITER(hh, master->metric_name_set, name_set_master, tmp) { - HASH_FIND_STR(instance->metric_name_set, name_set_master->name, name_set_dest); - if (name_set_dest == NULL) { - name_set_dest = (struct name_set *)malloc(sizeof(struct name_set)); - name_set_dest->name = strdup(name_set_master->name); - HASH_ADD_KEYPTR(hh, instance->metric_name_set, name_set_dest->name, strlen(name_set_dest->name), name_set_dest); - } - } -} - struct fieldstat *fieldstat_fork(const struct fieldstat *instance) { if (instance == NULL) { @@ -510,60 +391,16 @@ struct fieldstat *fieldstat_fork(const struct fieldstat *instance) struct fieldstat *new_instance = calloc(1, sizeof(struct fieldstat)); new_instance->cube_manager = cube_manager_fork(instance->cube_manager); - new_instance->manifests = calloc(instance->manifest_size, sizeof(struct metric_manifest *)); - new_instance->manifest_size = instance->manifest_size; - new_instance->manifest_cnt = instance->manifest_cnt; - - for (size_t i = 0; i < instance->manifest_cnt; i++) { - new_instance->manifests[i] = metric_manifest_copy(instance->manifests[i]); - } - metric_name_set_callibrate(new_instance, instance); + new_instance->manifest_manager = metric_manifest_manager_copy(instance->manifest_manager); return new_instance; } -void calibrate_metrics_in_instance(const struct fieldstat *master, struct fieldstat *replica) -{ - if (replica->manifest_size < master->manifest_size) { - replica->manifests = (struct metric_manifest **)realloc(replica->manifests, sizeof(struct metric_manifest *) * master->manifest_size); - memset(replica->manifests + replica->manifest_size, 0, sizeof(struct metric_manifest *) * (master->manifest_size - replica->manifest_size)); - replica->manifest_size = master->manifest_size; - } - - size_t longer_arr_len = master->manifest_cnt > replica->manifest_cnt ? master->manifest_cnt : replica->manifest_cnt; - for (size_t i = 0; i < longer_arr_len; i++) { - const struct metric_manifest *metric_master = i >= master->manifest_cnt ? NULL : master->manifests[i]; - struct metric_manifest *metric_target = i >= replica->manifest_cnt ? NULL : replica->manifests[i]; - if (metric_master == NULL && metric_target == NULL) { - continue; - } - if (metric_master == NULL && metric_target != NULL) { - metric_manifest_free(metric_target); - replica->manifests[i] = NULL; - continue; - } - if (metric_master != NULL && metric_target == NULL) { - replica->manifests[i] = metric_manifest_copy(metric_master); - continue; - } - - if (metric_master->type != metric_target->type || strcmp(metric_master->name, metric_target->name) != 0) { - metric_manifest_free(metric_target); - replica->manifests[i] = metric_manifest_copy(metric_master); - continue; - } - - // metric same, no need to do anything - } - - replica->manifest_cnt = master->manifest_cnt; - metric_name_set_callibrate(replica, master); -} - int fieldstat_calibrate(const struct fieldstat *master, struct fieldstat *replica) { cube_manager_calibrate(replica->cube_manager, master->cube_manager); - calibrate_metrics_in_instance(master, replica); + metric_manifest_manager_free(replica->manifest_manager); + replica->manifest_manager = metric_manifest_manager_copy(master->manifest_manager); return FS_OK; } @@ -578,20 +415,18 @@ void fieldstat_get_cubes(const struct fieldstat *instance, int **cube_ids, int * void fieldstat_get_metrics(const struct fieldstat *instance, int **metric_id_out, size_t *n_metric) { - int *tmp_ids = (int *)malloc(sizeof(int) * instance->manifest_cnt); - *metric_id_out = tmp_ids; - int cnt = 0; - for (int i = 0; i < instance->manifest_cnt; i++) { - if (instance->manifests[i] != NULL) { - tmp_ids[cnt] = i; - cnt ++; - } - } - if (cnt == 0) { - free(tmp_ids); + const struct metric_manifest **list = metric_manifest_manager_list(instance->manifest_manager, n_metric); + if (*n_metric == 0) { *metric_id_out = NULL; + return; + } + + int *tmp_ids = (int *)malloc(sizeof(int) * (*n_metric)); + *metric_id_out = tmp_ids; + + for (int i = 0; i < *n_metric; i++) { + tmp_ids[i] = list[i]->id; } - *n_metric = cnt; } struct fieldstat_tag_list *fieldstat_get_shared_tags(const struct fieldstat *instance, int cube_id) @@ -680,10 +515,7 @@ void fieldstat_tag_list_arr_free(struct fieldstat_tag_list *tag_list, size_t n_c const char *fieldstat_get_metric_name(const struct fieldstat *instance, int metric_id) { - if (metric_id < 0 || metric_id >= instance->manifest_cnt) { - return NULL; - } - const struct metric_manifest *metric = instance->manifests[metric_id]; + const struct metric_manifest *metric = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); if (metric == NULL) { return NULL; } @@ -693,10 +525,7 @@ const char *fieldstat_get_metric_name(const struct fieldstat *instance, int metr enum metric_type fieldstat_get_metric_type(const struct fieldstat *instance, int metric_id) { - if (instance == NULL || metric_id < 0 || metric_id >= instance->manifest_cnt) { - return (enum metric_type)(-1); - } - const struct metric_manifest *metric = instance->manifests[metric_id]; + const struct metric_manifest *metric = metric_manifest_manager_get_by_id(instance->manifest_manager, metric_id); if (metric == NULL) { return (enum metric_type)(-1); } diff --git a/src/metrics/metric.c b/src/metrics/metric.c index d66444e..fc7c68b 100644 --- a/src/metrics/metric.c +++ b/src/metrics/metric.c @@ -260,7 +260,7 @@ static const struct metric_scheme g_metric_scheme_table[] = { struct metric *metric_new(const struct metric_manifest *manifest) { struct metric *pthis = (struct metric *)calloc(1, sizeof(struct metric)); - pthis->data = g_metric_scheme_table[manifest->type].new(manifest->paras); + pthis->data = g_metric_scheme_table[manifest->type].new(manifest->parameters); pthis->type = manifest->type; return pthis; diff --git a/src/metrics/metric_manifest.c b/src/metrics/metric_manifest.c new file mode 100644 index 0000000..fd03209 --- /dev/null +++ b/src/metrics/metric_manifest.c @@ -0,0 +1,134 @@ + +#include "metric_manifest.h" + +#define DEFAULT_N_METRIC 32 + +struct metric_manifest; // defined in metric_manifest.h + +struct metric_manifest_manager { + struct metric_manifest *hash_table; + + struct metric_manifest **manifests; + size_t manifest_size; + size_t manifest_cnt; +}; + +struct metric_manifest_manager *metric_manifest_manager_new() { + struct metric_manifest_manager *ret = calloc(1, sizeof(struct metric_manifest_manager)); + + ret->manifest_size = DEFAULT_N_METRIC; + ret->manifests = calloc(DEFAULT_N_METRIC, sizeof(struct metric_manifest *)); + ret->manifest_cnt = 0; + + return ret; +} + +void metric_manifest_manager_free(struct metric_manifest_manager *pthis) { + struct metric_manifest *cur, *tmp; + HASH_ITER(hh, pthis->hash_table, cur, tmp) { + HASH_DEL(pthis->hash_table, cur); + } + + for (size_t i = 0; i < pthis->manifest_cnt; i++) { + metric_manifest_free(pthis->manifests[i]); + } + free(pthis->manifests); + free(pthis); +} + +const struct metric_manifest* metric_manifest_manager_get_by_id(const struct metric_manifest_manager *pthis, int metric_id) { + if (metric_id >= pthis->manifest_cnt || metric_id < 0) { + return NULL; + } + return pthis->manifests[metric_id]; +} + +const struct metric_manifest* metric_manifest_manager_get_by_name(const struct metric_manifest_manager *pthis, const char *name) { + struct metric_manifest *manifest = NULL; + HASH_FIND_STR(pthis->hash_table, name, manifest); + return manifest; +} + +void add_manifest_to_position(struct metric_manifest_manager *pthis, struct metric_manifest *manifest, int metric_id) +{ + if (metric_id >= pthis->manifest_size) { + pthis->manifests = realloc(pthis->manifests, sizeof(struct metric_manifest *) * pthis->manifest_size * 2); + memset(pthis->manifests + pthis->manifest_size, 0, sizeof(struct metric_manifest *) * (pthis->manifest_size)); + pthis->manifest_size *= 2; + } + + pthis->manifests[metric_id] = manifest; + if (metric_id >= pthis->manifest_cnt) { + pthis->manifest_cnt = metric_id + 1; + } + + HASH_ADD_KEYPTR(hh, pthis->hash_table, manifest->name, strlen(manifest->name), manifest); +} + +int metric_manifest_manager_add(struct metric_manifest_manager *pthis, struct metric_manifest *manifest) { + struct metric_manifest *tmp; + HASH_FIND_STR(pthis->hash_table, manifest->name, tmp); + if (tmp != NULL) { + return -1; + } + + int id = pthis->manifest_cnt; + add_manifest_to_position(pthis, manifest, id); + + manifest->id = id; + return id; +} + +const struct metric_manifest **metric_manifest_manager_list(const struct metric_manifest_manager *pthis, size_t *n_manifest) { + *n_manifest = pthis->manifest_cnt; + return (const struct metric_manifest **)pthis->manifests; +} + +bool metric_manifest_manager_equal(const struct metric_manifest_manager *pthis, const struct metric_manifest_manager *other) { + if (pthis->manifest_cnt != other->manifest_cnt) { + return false; + } + + for (size_t i = 0; i < pthis->manifest_cnt; i++) { + if (pthis->manifests[i]->type != other->manifests[i]->type) { + return false; + } + if (strcmp(pthis->manifests[i]->name, other->manifests[i]->name) != 0) { + return false; + } + } + + return true; +} + +void metric_manifest_free(struct metric_manifest *manifest) { + free(manifest->name); + free(manifest->parameters); + free(manifest); +} + +struct metric_manifest *metric_manifest_copy(const struct metric_manifest *src) +{ + struct metric_manifest *dest = (struct metric_manifest *)malloc(sizeof(struct metric_manifest)); + dest->name = strdup(src->name); + if (src->parameters == NULL) { + dest->parameters = NULL; + } else { + dest->parameters = (union metric_parameter *)malloc(sizeof(union metric_parameter)); + memcpy(dest->parameters, src->parameters, sizeof(union metric_parameter)); + } + + dest->type = src->type; + dest->id = src->id; + + return dest; +} + +struct metric_manifest_manager *metric_manifest_manager_copy(const struct metric_manifest_manager *pthis) { + struct metric_manifest_manager *ret = metric_manifest_manager_new(); + for (size_t i = 0; i < pthis->manifest_cnt; i++) { + struct metric_manifest *manifest = metric_manifest_copy(pthis->manifests[i]); + metric_manifest_manager_add(ret, manifest); + } + return ret; +} diff --git a/src/metrics/metric_manifest.h b/src/metrics/metric_manifest.h index 83d9ad7..632b314 100644 --- a/src/metrics/metric_manifest.h +++ b/src/metrics/metric_manifest.h @@ -1,23 +1,42 @@ #pragma once -struct para_hdr{ +#include "uthash.h" +#include "fieldstat.h" + +struct histogram_parameters { long long lowest_trackable_value; long long highest_trackable_value; int significant_figures; }; -struct para_hll { +struct hll_parameters { char precision; }; union metric_parameter { - struct para_hdr hdr; - struct para_hll hll; + struct histogram_parameters hdr; + struct hll_parameters hll; }; struct metric_manifest { int id; char *name; - union metric_parameter *paras; + union metric_parameter *parameters; enum metric_type type; -};
\ No newline at end of file + + UT_hash_handle hh; +}; + +struct metric_manifest *metric_manifest_copy(const struct metric_manifest *src); +void metric_manifest_free(struct metric_manifest *pthis); + +struct metric_manifest_manager; + +struct metric_manifest_manager *metric_manifest_manager_new(); +void metric_manifest_manager_free(struct metric_manifest_manager *pthis); +int metric_manifest_manager_add(struct metric_manifest_manager *pthis, struct metric_manifest *manifest); +struct metric_manifest_manager *metric_manifest_manager_copy(const struct metric_manifest_manager *pthis); + +const struct metric_manifest **metric_manifest_manager_list(const struct metric_manifest_manager *pthis, size_t *n_manifest); +const struct metric_manifest*metric_manifest_manager_get_by_id(const struct metric_manifest_manager *pthis, int metric_id); +const struct metric_manifest*metric_manifest_manager_get_by_name(const struct metric_manifest_manager *pthis, const char *name);
\ No newline at end of file diff --git a/test/test_merge.cpp b/test/test_merge.cpp index 8f88c80..42f87e0 100644 --- a/test/test_merge.cpp +++ b/test/test_merge.cpp @@ -517,7 +517,7 @@ TEST(unit_test_merge, primary_metric_id_different) int metric_primary_dst = fieldstat_register_counter(instance_dst, "primary"); fieldstat_cube_set_primary_metric(instance_dst, cube_id_dst, metric_primary_dst); - ASSERT_DEBUG_DEATH(fieldstat_merge(instance_dst, instance), ".*"); + EXPECT_EQ(fieldstat_merge(instance_dst, instance), FS_ERR_INVALID_PARAM); fieldstat_free(instance); fieldstat_free(instance_dst); |
