diff options
Diffstat (limited to 'database/rrdset.c')
-rw-r--r-- | database/rrdset.c | 449 |
1 files changed, 200 insertions, 249 deletions
diff --git a/database/rrdset.c b/database/rrdset.c index aabf303dee..93ea76cc64 100644 --- a/database/rrdset.c +++ b/database/rrdset.c @@ -5,95 +5,85 @@ #include <sched.h> void __rrdset_check_rdlock(RRDSET *st, const char *file, const char *function, const unsigned long line) { - debug(D_RRD_CALLS, "Checking read lock on chart '%s'", st->id); + debug(D_RRD_CALLS, "Checking read lock on chart '%s'", rrdset_id(st)); int ret = netdata_rwlock_trywrlock(&st->rrdset_rwlock); if(ret == 0) - fatal("RRDSET '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", st->id, function, line, file); + fatal("RRDSET '%s' should be read-locked, but it is not, at function %s() at line %lu of file '%s'", rrdset_id(st), function, line, file); } void __rrdset_check_wrlock(RRDSET *st, const char *file, const char *function, const unsigned long line) { - debug(D_RRD_CALLS, "Checking write lock on chart '%s'", st->id); + debug(D_RRD_CALLS, "Checking write lock on chart '%s'", rrdset_id(st)); int ret = netdata_rwlock_tryrdlock(&st->rrdset_rwlock); if(ret == 0) - fatal("RRDSET '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", st->id, function, line, file); + fatal("RRDSET '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", rrdset_id(st), function, line, file); } // ---------------------------------------------------------------------------- // RRDSET index -int rrdset_compare(void* a, void* b) { - if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1; - else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1; - else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id); +static inline void rrdset_index_add(RRDHOST *host, RRDSET *st) { + if(likely(dictionary_set(host->rrdset_root_index, rrdset_id(st), st, sizeof(RRDSET)) == st)) { + rrdset_flag_set(st, RRDSET_FLAG_INDEXED_ID); + } + else { + rrdset_flag_clear(st, RRDSET_FLAG_INDEXED_ID); + error("RRDSET: %s() attempted to index duplicate object with key '%s'", __FUNCTION__, rrdset_id(st)); + } } -static RRDSET *rrdset_index_find(RRDHOST *host, const char *id, uint32_t hash) { - RRDSET tmp; - strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX); - tmp.hash = (hash)?hash:simple_hash(tmp.id); +static inline void rrdset_index_del(RRDHOST *host, RRDSET *st) { + if(rrdset_flag_check(st, RRDSET_FLAG_INDEXED_ID)) { + if(likely(dictionary_del(host->rrdset_root_index, rrdset_id(st)) == 0)) + rrdset_flag_clear(st, RRDSET_FLAG_INDEXED_ID); + else + error("RRDSET: %s() attempted to delete non-indexed object with key '%s'", __FUNCTION__, rrdset_id(st)); + } +} - return (RRDSET *)avl_search_lock(&(host->rrdset_root_index), (avl_t *) &tmp); +static RRDSET *rrdset_index_find(RRDHOST *host, const char *id) { + return dictionary_get(host->rrdset_root_index, id); } // ---------------------------------------------------------------------------- // RRDSET name index -#define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname))) - -int rrdset_compare_name(void* a, void* b) { - RRDSET *A = rrdset_from_avlname(a); - RRDSET *B = rrdset_from_avlname(b); - - // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name); - - if(A->hash_name < B->hash_name) return -1; - else if(A->hash_name > B->hash_name) return 1; - else return strcmp(A->name, B->name); +static inline void rrdset_index_add_name(RRDHOST *host, RRDSET *st) { + if(likely(dictionary_set(host->rrdset_root_index_name, rrdset_name(st), st, sizeof(RRDSET)) == st)) { + rrdset_flag_set(st, RRDSET_FLAG_INDEXED_NAME); + } + else { + rrdset_flag_clear(st, RRDSET_FLAG_INDEXED_NAME); + error("RRDSET: %s() attempted to index duplicate object with key '%s'", __FUNCTION__, rrdset_name(st)); + } } -RRDSET *rrdset_index_add_name(RRDHOST *host, RRDSET *st) { - void *result; - // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name); - result = avl_insert_lock(&host->rrdset_root_index_name, (avl_t *) (&st->avlname)); - if(result) return rrdset_from_avlname(result); - return NULL; +static inline void rrdset_index_del_name(RRDHOST *host, RRDSET *st) { + if(rrdset_flag_check(st, RRDSET_FLAG_INDEXED_ID)) { + if(likely(dictionary_del(host->rrdset_root_index_name, rrdset_name(st)) != 0)) + rrdset_flag_clear(st, RRDSET_FLAG_INDEXED_NAME); + else + error("RRDSET: %s() attempted to delete non-index object with key '%s'", __FUNCTION__, rrdset_name(st)); + } } -RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st) { - void *result; - // fprintf(stderr, "DELETING: %s (name: %s)\n", st->id, st->name); - result = (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index_name), (avl_t *)(&st->avlname)); - if(result) return rrdset_from_avlname(result); - return NULL; +static inline RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name) { + return dictionary_get(host->rrdset_root_index_name, name); } - // ---------------------------------------------------------------------------- // RRDSET - find charts -static inline RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t hash) { - void *result = NULL; - RRDSET tmp; - tmp.name = name; - tmp.hash_name = (hash)?hash:simple_hash(tmp.name); - - result = avl_search_lock(&host->rrdset_root_index_name, (avl_t *) (&(tmp.avlname))); - if(result) return rrdset_from_avlname(result); - - return NULL; -} - inline RRDSET *rrdset_find(RRDHOST *host, const char *id) { - debug(D_RRD_CALLS, "rrdset_find() for chart '%s' in host '%s'", id, host->hostname); - RRDSET *st = rrdset_index_find(host, id, 0); + debug(D_RRD_CALLS, "rrdset_find() for chart '%s' in host '%s'", id, rrdhost_hostname(host)); + RRDSET *st = rrdset_index_find(host, id); return(st); } inline RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *id) { - debug(D_RRD_CALLS, "rrdset_find_bytype() for chart '%s.%s' in host '%s'", type, id, host->hostname); + debug(D_RRD_CALLS, "rrdset_find_bytype() for chart '%s.%s' in host '%s'", type, id, rrdhost_hostname(host)); char buf[RRD_ID_LENGTH_MAX + 1]; strncpyz(buf, type, RRD_ID_LENGTH_MAX - 1); @@ -105,8 +95,8 @@ inline RRDSET *rrdset_find_bytype(RRDHOST *host, const char *type, const char *i } inline RRDSET *rrdset_find_byname(RRDHOST *host, const char *name) { - debug(D_RRD_CALLS, "rrdset_find_byname() for chart '%s' in host '%s'", name, host->hostname); - RRDSET *st = rrdset_index_find_name(host, name, 0); + debug(D_RRD_CALLS, "rrdset_find_byname() for chart '%s' in host '%s'", name, rrdhost_hostname(host)); + RRDSET *st = rrdset_index_find_name(host, name); return(st); } @@ -129,32 +119,32 @@ char *rrdset_strncpyz_name(char *to, const char *from, size_t length) { } int rrdset_set_name(RRDSET *st, const char *name) { - if(unlikely(st->name && !strcmp(st->name, name))) + if(unlikely(!strcmp(rrdset_name(st), name))) return 1; RRDHOST *host = st->rrdhost; - debug(D_RRD_CALLS, "rrdset_set_name() old: '%s', new: '%s'", st->name?st->name:"", name); + debug(D_RRD_CALLS, "rrdset_set_name() old: '%s', new: '%s'", rrdset_name(st), name); char full_name[RRD_ID_LENGTH_MAX + 1]; char sanitized_name[CONFIG_MAX_VALUE + 1]; char new_name[CONFIG_MAX_VALUE + 1]; - snprintfz(full_name, RRD_ID_LENGTH_MAX, "%s.%s", st->type, name); + snprintfz(full_name, RRD_ID_LENGTH_MAX, "%s.%s", rrdset_type(st), name); rrdset_strncpyz_name(sanitized_name, full_name, CONFIG_MAX_VALUE); strncpyz(new_name, sanitized_name, CONFIG_MAX_VALUE); - if(rrdset_index_find_name(host, new_name, 0)) { - debug(D_RRD_CALLS, "RRDSET: chart name '%s' on host '%s' already exists.", new_name, host->hostname); - if(!strcmp(st->id, full_name) && !st->name) { + if(rrdset_index_find_name(host, new_name)) { + debug(D_RRD_CALLS, "RRDSET: chart name '%s' on host '%s' already exists.", new_name, rrdhost_hostname(host)); + if(!strcmp(rrdset_id(st), full_name) && !st->name) { unsigned i = 1; do { snprintfz(new_name, CONFIG_MAX_VALUE, "%s_%u", sanitized_name, i); i++; - } while (rrdset_index_find_name(host, new_name, 0)); + } while (rrdset_index_find_name(host, new_name)); - info("RRDSET: using name '%s' for chart '%s' on host '%s'.", new_name, full_name, host->hostname); + info("RRDSET: using name '%s' for chart '%s' on host '%s'.", new_name, full_name, rrdhost_hostname(host)); } else { return 0; } @@ -162,13 +152,12 @@ int rrdset_set_name(RRDSET *st, const char *name) { if(st->name) { rrdset_index_del_name(host, st); - st->name = strdupz(new_name); - st->hash_name = simple_hash(st->name); + string_freez(st->name); + st->name = string_strdupz(new_name); rrdsetvar_rename_all(st); } else { - st->name = strdupz(new_name); - st->hash_name = simple_hash(st->name); + st->name = string_strdupz(new_name); } rrdset_wrlock(st); @@ -177,8 +166,7 @@ int rrdset_set_name(RRDSET *st, const char *name) { rrddimvar_rename_all(rd); rrdset_unlock(st); - if(unlikely(rrdset_index_add_name(host, st) != st)) - error("RRDSET: INTERNAL ERROR: attempted to index duplicate chart name '%s'", st->name); + rrdset_index_add_name(host, st); rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_SEND); rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_IGNORE); @@ -192,12 +180,13 @@ int rrdset_set_name(RRDSET *st, const char *name) { inline void rrdset_is_obsolete(RRDSET *st) { if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_ARCHIVED))) { - info("Cannot obsolete already archived chart %s", st->name); + info("Cannot obsolete already archived chart %s", rrdset_name(st)); return; } if(unlikely(!(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) { rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE); + st->last_accessed_time = now_realtime_sec(); st->rrdhost->obsolete_charts_count++; rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); @@ -212,6 +201,7 @@ inline void rrdset_is_obsolete(RRDSET *st) { inline void rrdset_isnot_obsolete(RRDSET *st) { if(unlikely((rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE)))) { rrdset_flag_clear(st, RRDSET_FLAG_OBSOLETE); + st->last_accessed_time = now_realtime_sec(); st->rrdhost->obsolete_charts_count--; rrdset_flag_clear(st, RRDSET_FLAG_UPSTREAM_EXPOSED); @@ -239,12 +229,12 @@ inline void rrdset_update_heterogeneous_flag(RRDSET *st) { if(!rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS)) { #ifdef NETDATA_INTERNAL_CHECKS info("Dimension '%s' added on chart '%s' of host '%s' is not homogeneous to other dimensions already present (algorithm is '%s' vs '%s', multiplier is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ", divisor is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ").", - rd->name, - st->name, - host->hostname, - rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm), - rd->multiplier, multiplier, - rd->divisor, divisor + rrddim_name(rd), + rrdset_name(st), + rrdhost_hostname(host), + rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm), + rd->multiplier, multiplier, + rd->divisor, divisor ); #endif rrdset_flag_set(st, RRDSET_FLAG_HETEROGENEOUS); @@ -261,7 +251,7 @@ inline void rrdset_update_heterogeneous_flag(RRDSET *st) { // RRDSET - reset a chart void rrdset_reset(RRDSET *st) { - debug(D_RRD_CALLS, "rrdset_reset() %s", st->name); + debug(D_RRD_CALLS, "rrdset_reset() %s", rrdset_name(st)); st->last_collected_time.tv_sec = 0; st->last_collected_time.tv_usec = 0; @@ -346,9 +336,7 @@ void rrdset_free(RRDSET *st) { // ------------------------------------------------------------------------ // remove it from the indexes - if(unlikely(rrdset_index_del(host, st) != st)) - error("RRDSET: INTERNAL ERROR: attempt to remove from index chart '%s', removed a different chart.", st->id); - + rrdset_index_del(host, st); rrdset_index_del_name(host, st); // ------------------------------------------------------------------------ @@ -361,29 +349,18 @@ void rrdset_free(RRDSET *st) { /* We must free all connected alarms here in case this has been an ephemeral chart whose alarm was * created by a template. This leads to an effective memory leak, which cannot be detected since the * alarms will still be connected to the host, and freed during shutdown. */ - while(st->alarms) rrdcalc_unlink_and_free(st->rrdhost, st->alarms); - while(st->dimensions) rrddim_free(st, st->dimensions); + while(st->alarms) rrdcalc_unlink_and_free(st->rrdhost, st->alarms); + while(st->dimensions) rrddim_free(st, st->dimensions); rrdfamily_free(host, st->rrdfamily); - debug(D_RRD_CALLS, "RRDSET: Cleaning up remaining chart variables for host '%s', chart '%s'", host->hostname, st->id); - rrdvar_free_remaining_variables(host, &st->rrdvar_root_index); + debug(D_RRD_CALLS, "RRDSET: Cleaning up remaining chart variables for host '%s', chart '%s'", rrdhost_hostname(host), rrdset_id(st)); + rrdvar_free_remaining_variables(host, st->rrdvar_root_index); // ------------------------------------------------------------------------ // unlink it from the host - if(st == host->rrdset_root) { - host->rrdset_root = st->next; - } - else { - // find the previous one - RRDSET *s; - for(s = host->rrdset_root; s && s->next != st ; s = s->next) ; - - // bypass it - if(s) s->next = st->next; - else error("Request to free RRDSET '%s': cannot find it under host '%s'", st->id, host->hostname); - } + DOUBLE_LINKED_LIST_REMOVE_UNSAFE(host->rrdset_root, st, prev, next); rrdset_unlock(st); @@ -395,24 +372,28 @@ void rrdset_free(RRDSET *st) { netdata_rwlock_destroy(&st->rrdset_rwlock); + rrdset_memory_file_free(st); + rrdlabels_destroy(st->state->chart_labels); + // free directly allocated members - freez((void *)st->name); - freez(st->type); - freez(st->family); - freez(st->title); - freez(st->units); - freez(st->context); + + dictionary_destroy(st->rrddim_root_index); + dictionary_destroy(st->rrdvar_root_index); + + string_freez(st->id); + string_freez(st->name); + string_freez(st->type); + string_freez(st->family); + string_freez(st->title); + string_freez(st->units); + string_freez(st->context); + string_freez(st->plugin_name); + string_freez(st->module_name); + freez(st->cache_dir); - freez(st->plugin_name); - freez(st->module_name); - freez(st->state->old_title); - freez(st->state->old_units); - freez(st->state->old_context); - rrdlabels_destroy(st->state->chart_labels); freez(st->state); freez(st->chart_uuid); - rrdset_memory_file_free(st); freez(st); } @@ -430,7 +411,7 @@ void rrdset_delete_files(RRDSET *st) { RRDDIM *rd; rrdset_check_rdlock(st); - info("Deleting chart '%s' ('%s') from disk...", st->id, st->name); + info("Deleting chart '%s' ('%s') from disk...", rrdset_id(st), rrdset_name(st)); if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE || st->rrd_memory_mode == RRD_MEMORY_MODE_MAP) { const char *cache_filename = rrdset_cache_filename(st); @@ -440,7 +421,7 @@ void rrdset_delete_files(RRDSET *st) { error("Cannot delete chart header file '%s'", cache_filename); } else - error("Cannot find the cache filename of chart '%s'", st->id); + error("Cannot find the cache filename of chart '%s'", rrdset_id(st)); } rrddim_foreach_read(rd, st) { @@ -460,7 +441,7 @@ void rrdset_delete_obsolete_dimensions(RRDSET *st) { rrdset_check_rdlock(st); - info("Deleting dimensions of chart '%s' ('%s') from disk...", st->id, st->name); + info("Deleting dimensions of chart '%s' ('%s') from disk...", rrdset_id(st), rrdset_name(st)); rrddim_foreach_read(rd, st) { if(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE)) { @@ -490,9 +471,9 @@ static inline RRDSET *rrdset_find_on_create(RRDHOST *host, const char *fullid) { static inline void rrdset_update_permanent_labels(RRDSET *st) { if(!st->state || !st->state->chart_labels) return; - rrdlabels_add(st->state->chart_labels, "_collect_plugin", st->plugin_name, RRDLABEL_SRC_AUTO| RRDLABEL_FLAG_PERMANENT); - rrdlabels_add(st->state->chart_labels, "_collect_module", st->module_name, RRDLABEL_SRC_AUTO| RRDLABEL_FLAG_PERMANENT); - rrdlabels_add(st->state->chart_labels, "_instance_family", st->family, RRDLABEL_SRC_AUTO| RRDLABEL_FLAG_PERMANENT); + rrdlabels_add(st->state->chart_labels, "_collect_plugin", rrdset_plugin_name(st), RRDLABEL_SRC_AUTO| RRDLABEL_FLAG_PERMANENT); + rrdlabels_add(st->state->chart_labels, "_collect_module", rrdset_module_name(st), RRDLABEL_SRC_AUTO| RRDLABEL_FLAG_PERMANENT); + rrdlabels_add(st->state->chart_labels, "_instance_family",rrdset_family(st), RRDLABEL_SRC_AUTO| RRDLABEL_FLAG_PERMANENT); } RRDSET *rrdset_create_custom( @@ -549,6 +530,7 @@ RRDSET *rrdset_create_custom( char fullid[RRD_ID_LENGTH_MAX + 1]; snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); + json_fix_string(fullid); int changed_from_archived_to_active = 0; RRDSET *st = rrdset_find_on_create(host, fullid); @@ -559,11 +541,9 @@ RRDSET *rrdset_create_custom( changed_from_archived_to_active = 1; mark_rebuild |= META_CHART_ACTIVATED; } - char *old_plugin = NULL, *old_module = NULL, *old_title = NULL, *old_context = NULL, - *old_title_v = NULL, *old_context_v = NULL, *old_units_v = NULL, *old_units = NULL; - int rc; - if(unlikely(name)) + int rc; + if(unlikely(name && *name)) rc = rrdset_set_name(st, name); else rc = rrdset_set_name(st, id); @@ -580,91 +560,61 @@ RRDSET *rrdset_create_custom( mark_rebuild |= META_CHART_UPDATED; } - if (plugin && st->plugin_name) { - if (unlikely(strcmp(plugin, st->plugin_name))) { - old_plugin = st->plugin_name; - st->plugin_name = strdupz(plugin); + if(plugin && *plugin) { + STRING *old_plugin = st->plugin_name; + st->plugin_name = rrd_string_strdupz(plugin); + if (old_plugin != st->plugin_name) mark_rebuild |= META_PLUGIN_UPDATED; - } - } else { - if (plugin != st->plugin_name) { // one is NULL? - old_plugin = st->plugin_name; - st->plugin_name = plugin ? strdupz(plugin) : NULL; - mark_rebuild |= META_PLUGIN_UPDATED; - } + string_freez(old_plugin); } - if (module && st->module_name) { - if (unlikely(strcmp(module, st->module_name))) { - old_module = st->module_name; - st->module_name = strdupz(module); + if(module && *module) { + STRING *old_module = st->module_name; + st->module_name = rrd_string_strdupz(module); + if (old_module != st->module_name) mark_rebuild |= META_MODULE_UPDATED; - } - } else { - if (module != st->module_name) { - if (st->module_name && *st->module_name) { - old_module = st->module_name; - st->module_name = module ? strdupz(module) : NULL; - mark_rebuild |= META_MODULE_UPDATED; - } - } + string_freez(old_module); } - if (unlikely(title && st->state->old_title && strcmp(st->state->old_title, title))) { - char *new_title = strdupz(title); - old_title_v = st->state->old_title; - st->state->old_title = strdupz(title); - json_fix_string(new_title); - old_title = st->title; - st->title = new_title; - mark_rebuild |= META_CHART_UPDATED; + if(title && *title) { + STRING *old_title = st->title; + st->title = rrd_string_strdupz(title); + if(old_title != st->title) + mark_rebuild |= META_CHART_UPDATED; + string_freez(old_title); } - if (unlikely(units && st->state->old_units && strcmp(st->state->old_units, units))) { - char *new_units = strdupz(units); - old_units_v = st->state->old_units; - st->state->old_units = strdupz(units); - json_fix_string(new_units); - old_units= st->units; - st->units = new_units; - mark_rebuild |= META_CHART_UPDATED; + if(units && *units) { + STRING *old_units = st->units; + st->units = rrd_string_strdupz(units); + if(old_units != st->units) + mark_rebuild |= META_CHART_UPDATED; + string_freez(old_units); } + if(context && *context) { + STRING *old_context = st->context; + st->context = rrd_string_strdupz(context); + if(old_context != st->context) + mark_rebuild |= META_CHART_UPDATED; + string_freez(old_context); + } if (st->chart_type != chart_type) { st->chart_type = chart_type; mark_rebuild |= META_CHART_UPDATED; } - if (unlikely(context && st->state->old_context && strcmp(st->state->old_context, context))) { - char *new_context = strdupz(context); - old_context_v = st->state->old_context; - st->state->old_context = strdupz(context); - json_fix_string(new_context); - old_context = st->context; - st->context = new_context; - st->hash_context = simple_hash(st->context); - mark_rebuild |= META_CHART_UPDATED; - } - if (mark_rebuild) { rrdset_flag_clear(st, RRDSET_FLAG_ACLK); - freez(old_plugin); - freez(old_module); - freez(old_title); - freez(old_units); - freez(old_context); - freez(old_title_v); - freez(old_units_v); - freez(old_context_v); if (mark_rebuild != META_CHART_ACTIVATED) { - info("Collector updated metadata for chart %s", st->id); + info("Collector updated metadata for chart %s", rrdset_id(st)); sched_yield(); } } if (mark_rebuild & (META_CHART_UPDATED | META_PLUGIN_UPDATED | META_MODULE_UPDATED)) { - debug(D_METADATALOG, "CHART [%s] metadata updated", st->id); - int rc = update_chart_metadata(st->chart_uuid, st, id, name); + debug(D_METADATALOG, "CHART [%s] metadata updated", rrdset_id(st)); + rc = update_chart_metadata(st->chart_uuid, st, id, name); if (unlikely(rc)) error_report("Failed to update chart metadata in the database"); @@ -719,8 +669,7 @@ RRDSET *rrdset_create_custom( st = callocz(1, sizeof(RRDSET)); st->state = callocz(1, sizeof(*st->state)); - strcpy(st->id, fullid); - st->hash = simple_hash(st->id); + st->id = string_strdupz(fullid); // fullid is already json_fix'ed st->rrdhost = host; st->cache_dir = cache_dir; @@ -729,29 +678,23 @@ RRDSET *rrdset_create_custom( if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP) { if(!rrdset_memory_load_or_create_map_save(st, memory_mode)) { - info("Failed to use memory mode %s for chart '%s', falling back to ram", (memory_mode == RRD_MEMORY_MODE_MAP)?"map":"save", st->name); + info("Failed to use memory mode %s for chart '%s', falling back to ram", (memory_mode == RRD_MEMORY_MODE_MAP)?"map":"save", rrdset_name(st)); memory_mode = RRD_MEMORY_MODE_RAM; } } st->rrd_memory_mode = memory_mode; - st->plugin_name = plugin?strdupz(plugin):NULL; - st->module_name = module?strdupz(module):NULL; + st->plugin_name = rrd_string_strdupz(plugin); + st->module_name = rrd_string_strdupz(module); st->chart_type = chart_type; - st->type = strdupz(type); - st->family = family ? strdupz(family) : strdupz(st->type); - json_fix_string(st->family); + st->type = rrd_string_strdupz(type); + st->family = family ? rrd_string_strdupz(family) : string_dup(st->type); - st->state->is_ar_chart = strcmp(st->id, ML_ANOMALY_RATES_CHART_ID) == 0; + st->state->is_ar_chart = strcmp(rrdset_id(st), ML_ANOMALY_RATES_CHART_ID) == 0; - st->units = units ? strdupz(units) : strdupz(""); - st->state->old_units = strdupz(st->units); - json_fix_string(st->units); + st->units = rrd_string_strdupz(units); - st->context = context ? strdupz(context) : strdupz(st->id); - st->state->old_context = strdupz(st->context); - json_fix_string(st->context); - st->hash_context = simple_hash(st->context); + st->context = (context && *context) ? rrd_string_strdupz(context) : string_dup(st->id); st->priority = priority; @@ -762,8 +705,17 @@ RRDSET *rrdset_create_custom( st->gap_when_lost_iterations_above = (int) (gap_when_lost_iterations_above + 2); - avl_init_lock(&st->dimensions_index, rrddim_compare); - avl_init_lock(&st->rrdvar_root_index, rrdvar_compare); + st->rrddim_root_index = dictionary_create( + DICTIONARY_FLAG_NAME_LINK_DONT_CLONE + | DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE + | DICTIONARY_FLAG_DONT_OVERWRITE_VALUE + ); + + st->rrdvar_root_index = dictionary_create( + DICTIONARY_FLAG_NAME_LINK_DONT_CLONE + | DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE + | DICTIONARY_FLAG_DONT_OVERWRITE_VALUE + ); netdata_rwlock_init(&st->rrdset_rwlock); st->state->chart_labels = rrdlabels_create(); @@ -776,14 +728,11 @@ RRDSET *rrdset_create_custom( // could not use the name, use the id rrdset_set_name(st, id); - st->title = strdupz(title); - st->state->old_title = strdupz(st->title); - json_fix_string(st->title); + st->title = rrd_string_strdupz(title); - st->rrdfamily = rrdfamily_create(host, st->family); + st->rrdfamily = rrdfamily_create(host, rrdset_family(st)); - st->next = host->rrdset_root; - host->rrdset_root = st; + DOUBLE_LINKED_LIST_APPEND_UNSAFE(host->rrdset_root, st, prev, next); if(host->health_enabled) { rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT); @@ -793,9 +742,7 @@ RRDSET *rrdset_create_custom( rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_OPTION_DEFAULT); } - if(unlikely(rrdset_index_add(host, st) != st)) - error("RRDSET: INTERNAL ERROR: attempt to index duplicate chart '%s'", st->id); - + rrdset_index_add(host, st); rrdsetcalc_link_matching(st); rrdcalctemplate_link_matching(st); @@ -870,7 +817,7 @@ inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) { // oops! the database is in the future #ifdef NETDATA_INTERNAL_CHECKS info("RRD database for chart '%s' on host '%s' is %0.5" NETDATA_DOUBLE_MODIFIER - " secs in the future (counter #%zu, update #%zu). Adjusting it to current time.", st->id, st->rrdhost->hostname, (NETDATA_DOUBLE)-since_last_usec / USEC_PER_SEC, st->counter, st->counter_done); + " secs in the future (counter #%zu, update #%zu). Adjusting it to current time.", rrdset_id(st), rrdhost_hostname(st->rrdhost), (NETDATA_DOUBLE)-since_last_usec / USEC_PER_SEC, st->counter, st->counter_done); #endif st->last_collected_time.tv_sec = now.tv_sec - st->update_every; @@ -890,7 +837,7 @@ inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) { // oops! the database is too far behind #ifdef NETDATA_INTERNAL_CHECKS info("RRD database for chart '%s' on host '%s' is %0.5" NETDATA_DOUBLE_MODIFIER - " secs in the past (counter #%zu, update #%zu). Adjusting it to current time.", st->id, st->rrdhost->hostname, (NETDATA_DOUBLE)since_last_usec / USEC_PER_SEC, st->counter, st->counter_done); + " secs in the past (counter #%zu, update #%zu). Adjusting it to current time.", rrdset_id(st), rrdhost_hostname(st->rrdhost), (NETDATA_DOUBLE)since_last_usec / USEC_PER_SEC, st->counter, st->counter_done); #endif microseconds = (usec_t)since_last_usec; @@ -925,11 +872,11 @@ inline void rrdset_next_usec(RRDSET *st, usec_t microseconds) { } #ifdef NETDATA_INTERNAL_CHECKS - debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", st->name, microseconds); + debug(D_RRD_CALLS, "rrdset_next_usec() for chart %s with microseconds %llu", rrdset_name(st), microseconds); rrdset_debug(st, "NEXT: %llu microseconds", microseconds); if(discarded && discarded != microseconds) - info("host '%s', chart '%s': discarded data collection time of %llu usec, replaced with %llu usec, reason: '%s'", st->rrdhost->hostname, st->id, discarded, microseconds, discard_reason?discard_reason:"UNDEFINED"); + info("host '%s', chart '%s': discarded data collection time of %llu usec, replaced with %llu usec, reason: '%s'", rrdhost_hostname(st->rrdhost), rrdset_id(st), discarded, microseconds, discard_reason?discard_reason:"UNDEFINED"); #endif @@ -1081,6 +1028,8 @@ static void store_metric(RRDDIM *rd, usec_t point_end_time_ut, NETDATA_DOUBLE n, t->last_collected_ut = point_end_time_ut; store_metric_at_tier(rd, t, sp, point_end_time_ut); } + + rrdcontext_collected_rrddim(rd); } static inline size_t rrdset_done_interpolate( @@ -1114,7 +1063,7 @@ static inline size_t rrdset_done_interpolate( for( ; next_store_ut <= now_collect_ut ; last_collect_ut = next_store_ut, next_store_ut += update_every_ut, iterations-- ) { #ifdef NETDATA_INTERNAL_CHECKS - if(iterations < 0) { error("INTERNAL CHECK: %s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", st->name, first_ut, last_stored_ut, next_store_ut, now_collect_ut); } + if(iterations < 0) { error("INTERNAL CHECK: %s: iterations calculation wrapped! first_ut = %llu, last_stored_ut = %llu, next_store_ut = %llu, now_collect_ut = %llu", rrdset_name(st), first_ut, last_stored_ut, next_store_ut, now_collect_ut); } rrdset_debug(st, "last_stored_ut = %0.3" NETDATA_DOUBLE_MODIFIER " (last updated time)", (NETDATA_DOUBLE)last_stored_ut/USEC_PER_SEC); rrdset_debug(st, "next_store_ut = %0.3" NETDATA_DOUBLE_MODIFIER " (next interpolation point)", (NETDATA_DOUBLE)next_store_ut/USEC_PER_SEC); #endif @@ -1140,7 +1089,7 @@ static inline size_t rrdset_done_interpolate( NETDATA_DOUBLE_FORMAT " * (%llu - %llu)" " / (%llu - %llu)" - , rd->name + , rrddim_name(rd) , new_value , rd->calculated_value , next_store_ut, last_collect_ut @@ -1157,7 +1106,7 @@ static inline size_t rrdset_done_interpolate( #ifdef NETDATA_INTERNAL_CHECKS rrdset_debug(st, "%s: COLLECTION POINT IS SHORT " NETDATA_DOUBLE_FORMAT " - EXTRAPOLATING", - rd->name + rrddim_name(rd) , (NETDATA_DOUBLE)(next_store_ut - last_stored_ut) ); #endif @@ -1193,7 +1142,7 @@ static inline size_t rrdset_done_interpolate( rrdset_debug(st, "%s: CALC2 DEF " NETDATA_DOUBLE_FORMAT " = (((" "(" NETDATA_DOUBLE_FORMAT " - " NETDATA_DOUBLE_FORMAT ")" " * %llu" - " / %llu) + " NETDATA_DOUBLE_FORMAT, rd->name + " / %llu) + " NETDATA_DOUBLE_FORMAT, rrddim_name(rd) , new_value , rd->calculated_value, rd->last_calculated_value , (next_store_ut - first_ut) @@ -1225,7 +1174,7 @@ static inline size_t rrdset_done_interpolate( (void) ml_is_anomalous(rd, 0, false); #ifdef NETDATA_INTERNAL_CHECKS - rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING ", rd->name, current_entry); + rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING ", rrddim_name(rd), current_entry); #endif store_metric(rd, next_store_ut, NAN, SN_FLAG_NONE); @@ -1275,7 +1224,7 @@ static inline void rrdset_done_fill_the_gap(RRDSET *st) { current_entry = ((current_entry + 1) >= entries) ? 0 : current_entry + 1; #ifdef NETDATA_INTERNAL_CHECKS - rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING (FILLED THE GAP)", rd->name, current_entry); + rrdset_debug(st, "%s: STORE[%ld] = NON EXISTING (FILLED THE GAP)", rrddim_name(rd), current_entry); #endif } } @@ -1294,8 +1243,7 @@ static inline void rrdset_done_fill_the_gap(RRDSET *st) { void rrdset_done(RRDSET *st) { if(unlikely(netdata_exit)) return; - debug(D_RRD_CALLS, "rrdset_done() for chart %s", st->name); - rrdcontext_collected_rrdset(st); + debug(D_RRD_CALLS, "rrdset_done() for chart %s", rrdset_name(st)); RRDDIM *rd; @@ -1326,7 +1274,7 @@ void rrdset_done(RRDSET *st) { #endif if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_OBSOLETE))) { - error("Chart '%s' has the OBSOLETE flag set, but it is collected.", st->id); + error("Chart '%s' has the OBSOLETE flag set, but it is collected.", rrdset_id(st)); rrdset_isnot_obsolete(st); } @@ -1334,7 +1282,7 @@ void rrdset_done(RRDSET *st) { if(unlikely(st->usec_since_last_update > st->entries * update_every_ut && st->rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE && st->rrd_memory_mode != RRD_MEMORY_MODE_NONE)) { info("host '%s', chart %s: took too long to be updated (counter #%zu, update #%zu, %0.3" NETDATA_DOUBLE_MODIFIER - " secs). Resetting it.", st->rrdhost->hostname, st->name, st->counter, st->counter_done, (NETDATA_DOUBLE)st->usec_since_last_update / USEC_PER_SEC); + " secs). Resetting it.", rrdhost_hostname(st->rrdhost), rrdset_name(st), st->counter, st->counter_done, (NETDATA_DOUBLE)st->usec_since_last_update / USEC_PER_SEC); rrdset_reset(st); st->usec_since_last_update = update_every_ut; store_this_entry = 0; @@ -1382,7 +1330,7 @@ void rrdset_done(RRDSET *st) { info( "%s: too old data (last updated at %"PRId64".%"PRId64", last collected at %"PRId64".%"PRId64"). " "Resetting it. Will not store the next entry.", - st->name, + rrdset_name(st), (int64_t)st->last_updated.tv_sec, (int64_t)st->last_updated.tv_usec, (int64_t)st->last_collected_time.tv_sec, @@ -1404,7 +1352,7 @@ void rrdset_done(RRDSET *st) { info( "%s: too old data (last updated at %" PRId64 ".%" PRId64 ", last collected at %" PRId64 ".%" PRId64 "). " "Resetting it. Will not store the next entry.", - st->name, + rrdset_name(st), (int64_t)st->last_updated.tv_sec, (int64_t)st->last_updated.tv_usec, (int64_t)st->last_collected_time.tv_sec, @@ -1467,9 +1415,9 @@ after_first_database_work: if(unlikely(st->rrdhost->rrdpush_send_enabled)) rrdset_done_push(st); - if (unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) { + + if (unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) goto after_second_database_work; - } #ifdef NETDATA_INTERNAL_CHECKS rrdset_debug(st, "last_collect_ut = %0.3" NETDATA_DOUBLE_MODIFIER " (last collection time)", (NETDATA_DOUBLE)last_collect_ut/USEC_PER_SEC); @@ -1506,7 +1454,7 @@ after_first_database_work: } if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_OBSOLETE))) { - error("Dimension %s in chart '%s' has the OBSOLETE flag set, but it is collected.", rd->name, st->id); + error("Dimension %s in chart '%s' has the OBSOLETE flag set, but it is collected.", rrddim_name(rd), rrdset_id(st)); rrddim_isnot_obsolete(st, rd); } |