From cb7af25c09d8775d1967cb0553268075cda868d4 Mon Sep 17 00:00:00 2001 From: Costa Tsaousis Date: Mon, 19 Sep 2022 23:46:13 +0300 Subject: RRD structures managed by dictionaries (#13646) * rrdset - in progress * rrdset optimal constructor; rrdset conflict * rrdset final touches * re-organization of rrdset object members * prevent use-after-free * dictionary dfe supports also counting of iterations * rrddim managed by dictionary * rrd.h cleanup * DICTIONARY_ITEM now is referencing actual dictionary items in the code * removed rrdset linked list * Revert "removed rrdset linked list" This reverts commit 690d6a588b4b99619c2c5e10f84e8f868ae6def5. * removed rrdset linked list * added comments * Switch chart uuid to static allocation in rrdset Remove unused functions * rrdset_archive() and friends... * always create rrdfamily * enable ml_free_dimension * rrddim_foreach done with dfe * most custom rrddim loops replaced with rrddim_foreach * removed accesses to rrddim->dimensions * removed locks that are no longer needed * rrdsetvar is now managed by the dictionary * set rrdset is rrdsetvar, fixes https://github.com/netdata/netdata/pull/13646#issuecomment-1242574853 * conflict callback of rrdsetvar now properly checks if it has to reset the variable * dictionary registered callbacks accept as first parameter the DICTIONARY_ITEM * dictionary dfe now uses internal counter to report; avoided excess variables defined with dfe * dictionary walkthrough callbacks get dictionary acquired items * dictionary reference counters that can be dupped from zero * added advanced functions for get and del * rrdvar managed by dictionaries * thread safety for rrdsetvar * faster rrdvar initialization * rrdvar string lengths should match in all add, del, get functions * rrdvar internals hidden from the rest of the world * rrdvar is now acquired throughout netdata * hide the internal structures of rrdsetvar * rrdsetvar is now acquired through out netdata * rrddimvar managed by dictionary; rrddimvar linked list removed; rrddimvar structures hidden from the rest of netdata * better error handling * dont create variables if not initialized for health * dont create variables if not initialized for health again * rrdfamily is now managed by dictionaries; references of it are acquired dictionary items * type checking on acquired objects * rrdcalc renaming of functions * type checking for rrdfamily_acquired * rrdcalc managed by dictionaries * rrdcalc double free fix * host rrdvars is always needed * attempt to fix deadlock 1 * attempt to fix deadlock 2 * Remove unused variable * attempt to fix deadlock 3 * snprintfz * rrdcalc index in rrdset fix * Stop storing active charts and computing chart hashes * Remove store active chart function * Remove compute chart hash function * Remove sql_store_chart_hash function * Remove store_active_dimension function * dictionary delayed destruction * formatting and cleanup * zero dictionary base on rrdsetvar * added internal error to log delayed destructions of dictionaries * typo in rrddimvar * added debugging info to dictionary * debug info * fix for rrdcalc keys being empty * remove forgotten unlock * remove deadlock * Switch to metadata version 5 and drop chart_hash chart_hash_map chart_active dimension_active v_chart_hash * SQL cosmetic changes * do not busy wait while destroying a referenced dictionary * remove deadlock * code cleanup; re-organization; * fast cleanup and flushing of dictionaries * number formatting fixes * do not delete configured alerts when archiving a chart * rrddim obsolete linked list management outside dictionaries * removed duplicate contexts call * fix crash when rrdfamily is not initialized * dont keep rrddimvar referenced * properly cleanup rrdvar * removed some locks * Do not attempt to cleanup chart_hash / chart_hash_map * rrdcalctemplate managed by dictionary * register callbacks on the right dictionary * removed some more locks * rrdcalc secondary index replaced with linked-list; rrdcalc labels updates are now executed by health thread * when looking up for an alarm look using both chart id and chart name * host initialization a bit more modular * init rrdlabels on host update * preparation for dictionary views * improved comment * unused variables without internal checks * service threads isolation and worker info * more worker info in service thread * thread cancelability debugging with internal checks * strings data races addressed; fixes https://github.com/netdata/netdata/issues/13647 * dictionary modularization * Remove unused SQL statement definition * unit-tested thread safety of dictionaries; removed data race conditions on dictionaries and strings; dictionaries now can detect if the caller is holds a write lock and automatically all the calls become their unsafe versions; all direct calls to unsafe version is eliminated * remove worker_is_idle() from the exit of service functions, because we lose the lock time between loops * rewritten dictionary to have 2 separate locks, one for indexing and another for traversal * Update collectors/cgroups.plugin/sys_fs_cgroup.c Co-authored-by: Vladimir Kobal * Update collectors/cgroups.plugin/sys_fs_cgroup.c Co-authored-by: Vladimir Kobal * Update collectors/proc.plugin/proc_net_dev.c Co-authored-by: Vladimir Kobal * fix memory leak in rrdset cache_dir * minor dictionary changes * dont use index locks in single threaded * obsolete dict option * rrddim options and flags separation; rrdset_done() optimization to keep array of reference pointers to rrddim; * fix jump on uninitialized value in dictionary; remove double free of cache_dir * addressed codacy findings * removed debugging code * use the private refcount on dictionaries * make dictionary item desctructors work on dictionary destruction; strictier control on dictionary API; proper cleanup sequence on rrddim; * more dictionary statistics * global statistics about dictionary operations, memory, items, callbacks * dictionary support for views - missing the public API * removed warning about unused parameter * chart and context name for cloud * chart and context name for cloud, again * dictionary statistics fixed; first implementation of dictionary views - not currently used * only the master can globally delete an item * context needs netdata prefix * fix context and chart it of spins * fix for host variables when health is not enabled * run garbage collector on item insert too * Fix info message; remove extra "using" * update dict unittest for new placement of garbage collector * we need RRDHOST->rrdvars for maintaining custom host variables * Health initialization needs the host->host_uuid * split STRING to its own files; no code changes other than that * initialize health unconditionally * unit tests do not pollute the global scope with their variables * Skip initialization when creating archived hosts on startup. When a child connects it will initialize properly Co-authored-by: Stelios Fragkakis <52996999+stelfrag@users.noreply.github.com> Co-authored-by: Vladimir Kobal --- collectors/cgroups.plugin/sys_fs_cgroup.c | 23 ++++---- collectors/cgroups.plugin/tests/test_doubles.c | 8 --- collectors/cups.plugin/cups_plugin.c | 13 ++-- collectors/diskspace.plugin/plugin_diskspace.c | 6 +- collectors/plugins.d/pluginsd_parser.c | 26 ++++---- collectors/proc.plugin/ipc.c | 12 ++-- collectors/proc.plugin/proc_diskstats.c | 2 - collectors/proc.plugin/proc_interrupts.c | 4 +- collectors/proc.plugin/proc_loadavg.c | 6 +- collectors/proc.plugin/proc_mdstat.c | 1 - collectors/proc.plugin/proc_net_dev.c | 9 +-- collectors/proc.plugin/proc_net_snmp.c | 4 +- collectors/proc.plugin/proc_net_sockstat.c | 12 ++-- collectors/proc.plugin/proc_net_stat_conntrack.c | 4 +- collectors/proc.plugin/proc_net_wireless.c | 1 - collectors/proc.plugin/proc_self_mountinfo.c | 3 +- collectors/proc.plugin/proc_softirqs.c | 4 +- collectors/proc.plugin/proc_spl_kstat_zfs.c | 6 +- collectors/proc.plugin/proc_stat.c | 4 +- collectors/proc.plugin/sys_block_zram.c | 13 ++-- collectors/proc.plugin/sys_class_infiniband.c | 6 +- collectors/proc.plugin/sys_class_power_supply.c | 1 - collectors/proc.plugin/sys_fs_btrfs.c | 1 - collectors/statsd.plugin/statsd.c | 53 ++++++++++------- collectors/tc.plugin/plugin_tc.c | 75 ++++++++++++------------ 25 files changed, 145 insertions(+), 152 deletions(-) (limited to 'collectors') diff --git a/collectors/cgroups.plugin/sys_fs_cgroup.c b/collectors/cgroups.plugin/sys_fs_cgroup.c index b214b3731b..74aedf2b52 100644 --- a/collectors/cgroups.plugin/sys_fs_cgroup.c +++ b/collectors/cgroups.plugin/sys_fs_cgroup.c @@ -857,16 +857,16 @@ struct cgroup { char *filename_cpu_cfs_quota; unsigned long long cpu_cfs_quota; - RRDSETVAR *chart_var_cpu_limit; + const RRDSETVAR_ACQUIRED *chart_var_cpu_limit; NETDATA_DOUBLE prev_cpu_usage; char *filename_memory_limit; unsigned long long memory_limit; - RRDSETVAR *chart_var_memory_limit; + const RRDSETVAR_ACQUIRED *chart_var_memory_limit; char *filename_memoryswap_limit; unsigned long long memoryswap_limit; - RRDSETVAR *chart_var_memoryswap_limit; + const RRDSETVAR_ACQUIRED *chart_var_memoryswap_limit; // services RRDDIM *rd_cpu; @@ -3708,10 +3708,10 @@ cpu_limits2_err: } } -static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, unsigned long long *value, const char *chart_var_name, struct cgroup *cg) { +static inline int update_memory_limits(char **filename, const RRDSETVAR_ACQUIRED **chart_var, unsigned long long *value, const char *chart_var_name, struct cgroup *cg) { if(*filename) { if(unlikely(!*chart_var)) { - *chart_var = rrdsetvar_custom_chart_variable_create(cg->st_mem_usage, chart_var_name); + *chart_var = rrdsetvar_custom_chart_variable_add_and_acquire(cg->st_mem_usage, chart_var_name); if(!*chart_var) { error("Cannot create cgroup %s chart variable '%s'. Will not update its limit anymore.", cg->id, chart_var_name); freez(*filename); @@ -3727,7 +3727,7 @@ static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, u *filename = NULL; } else { - rrdsetvar_custom_chart_variable_set(*chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); + rrdsetvar_custom_chart_variable_set(cg->st_mem_usage, *chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); return 1; } } else { @@ -3742,11 +3742,11 @@ static inline int update_memory_limits(char **filename, RRDSETVAR **chart_var, u char *s = "max\n\0"; if(strcmp(s, buffer) == 0){ *value = UINT64_MAX; - rrdsetvar_custom_chart_variable_set(*chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); + rrdsetvar_custom_chart_variable_set(cg->st_mem_usage, *chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); return 1; } *value = str2ull(buffer); - rrdsetvar_custom_chart_variable_set(*chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); + rrdsetvar_custom_chart_variable_set(cg->st_mem_usage, *chart_var, (NETDATA_DOUBLE)(*value / (1024 * 1024))); return 1; } } @@ -3843,7 +3843,7 @@ void update_cgroup_charts(int update_every) { } if(unlikely(!cg->chart_var_cpu_limit)) { - cg->chart_var_cpu_limit = rrdsetvar_custom_chart_variable_create(cg->st_cpu, "cpu_limit"); + cg->chart_var_cpu_limit = rrdsetvar_custom_chart_variable_add_and_acquire(cg->st_cpu, "cpu_limit"); if(!cg->chart_var_cpu_limit) { error("Cannot create cgroup %s chart variable 'cpu_limit'. Will not update its limit anymore.", cg->id); if(cg->filename_cpuset_cpus) freez(cg->filename_cpuset_cpus); @@ -3868,8 +3868,6 @@ void update_cgroup_charts(int update_every) { value = (NETDATA_DOUBLE)cg->cpuset_cpus * 100; } if(likely(value)) { - rrdsetvar_custom_chart_variable_set(cg->chart_var_cpu_limit, value); - if(unlikely(!cg->st_cpu_limit)) { snprintfz(title, CHART_TITLE_MAX, "CPU Usage within the limits"); @@ -3909,14 +3907,15 @@ void update_cgroup_charts(int update_every) { cg->prev_cpu_usage = cpu_usage; + rrdsetvar_custom_chart_variable_set(cg->st_cpu, cg->chart_var_cpu_limit, value); rrdset_done(cg->st_cpu_limit); } else { - rrdsetvar_custom_chart_variable_set(cg->chart_var_cpu_limit, NAN); if(unlikely(cg->st_cpu_limit)) { rrdset_is_obsolete(cg->st_cpu_limit); cg->st_cpu_limit = NULL; } + rrdsetvar_custom_chart_variable_set(cg->st_cpu, cg->chart_var_cpu_limit, NAN); } } } diff --git a/collectors/cgroups.plugin/tests/test_doubles.c b/collectors/cgroups.plugin/tests/test_doubles.c index 7f44416255..9aa748725c 100644 --- a/collectors/cgroups.plugin/tests/test_doubles.c +++ b/collectors/cgroups.plugin/tests/test_doubles.c @@ -146,14 +146,6 @@ void netdev_rename_device_del(const char *host_device) UNUSED(host_device); } -void sql_store_chart_label(uuid_t *chart_uuid, int source_type, char *label, char *value) -{ - UNUSED(chart_uuid); - UNUSED(source_type); - UNUSED(label); - UNUSED(value); -} - void rrdcalc_update_rrdlabels(RRDSET *st) { (void)st; } diff --git a/collectors/cups.plugin/cups_plugin.c b/collectors/cups.plugin/cups_plugin.c index 77bd3e0ed8..9a200c31d1 100644 --- a/collectors/cups.plugin/cups_plugin.c +++ b/collectors/cups.plugin/cups_plugin.c @@ -137,10 +137,7 @@ getIntegerOption( return ((int)intvalue); } -static int reset_job_metrics(const char *name, void *entry, void *data) { - (void)name; - (void)data; - +static int reset_job_metrics(const DICTIONARY_ITEM *item __maybe_unused, void *entry, void *data __maybe_unused) { struct job_metrics *jm = (struct job_metrics *)entry; jm->is_collected = 0; @@ -175,8 +172,8 @@ struct job_metrics *get_job_metrics(char *dest) { return jm; } -int collect_job_metrics(const char *name, void *entry, void *data) { - (void)data; +int collect_job_metrics(const DICTIONARY_ITEM *item, void *entry, void *data __maybe_unused) { + const char *name = dictionary_acquired_item_name(item); struct job_metrics *jm = (struct job_metrics *)entry; @@ -205,7 +202,7 @@ int collect_job_metrics(const char *name, void *entry, void *data) { printf("DIMENSION pending '' absolute 1 1\n"); printf("DIMENSION held '' absolute 1 1\n"); printf("DIMENSION processing '' absolute 1 1\n"); - dictionary_del_having_write_lock(dict_dest_job_metrics, name); + dictionary_del(dict_dest_job_metrics, name); } return 0; @@ -243,7 +240,7 @@ int main(int argc, char **argv) { errno = 0; - dict_dest_job_metrics = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + dict_dest_job_metrics = dictionary_create(DICT_OPTION_SINGLE_THREADED); // ------------------------------------------------------------------------ // the main loop diff --git a/collectors/diskspace.plugin/plugin_diskspace.c b/collectors/diskspace.plugin/plugin_diskspace.c index 5bdf8bc61f..7381e1ec93 100644 --- a/collectors/diskspace.plugin/plugin_diskspace.c +++ b/collectors/diskspace.plugin/plugin_diskspace.c @@ -95,8 +95,8 @@ int mount_point_cleanup(const char *name, void *entry, int slow) { return 0; } -int mount_point_cleanup_cb(const char *name, void *entry, void *data) { - UNUSED(data); +int mount_point_cleanup_cb(const DICTIONARY_ITEM *item, void *entry, void *data __maybe_unused) { + const char *name = dictionary_acquired_item_name(item); return mount_point_cleanup(name, (struct mount_point_metadata *)entry, 0); } @@ -330,7 +330,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { , SIMPLE_PATTERN_EXACT ); - dict_mountpoints = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + dict_mountpoints = dictionary_create(DICT_OPTION_SINGLE_THREADED); } struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point); diff --git a/collectors/plugins.d/pluginsd_parser.c b/collectors/plugins.d/pluginsd_parser.c index 3dffde5acc..ce9250d568 100644 --- a/collectors/plugins.d/pluginsd_parser.c +++ b/collectors/plugins.d/pluginsd_parser.c @@ -101,15 +101,19 @@ PARSER_RC pluginsd_variable_action(void *user, RRDHOST *host, RRDSET *st, char * UNUSED(user); if (global) { - RRDVAR *rv = rrdvar_custom_host_variable_create(host, name); - if (rv) - rrdvar_custom_host_variable_set(host, rv, value); + const RRDVAR_ACQUIRED *rva = rrdvar_custom_host_variable_add_and_acquire(host, name); + if (rva) { + rrdvar_custom_host_variable_set(host, rva, value); + rrdvar_custom_host_variable_release(host, rva); + } else error("cannot find/create HOST VARIABLE '%s' on host '%s'", name, rrdhost_hostname(host)); } else { - RRDSETVAR *rs = rrdsetvar_custom_chart_variable_create(st, name); - if (rs) - rrdsetvar_custom_chart_variable_set(rs, value); + const RRDSETVAR_ACQUIRED *rsa = rrdsetvar_custom_chart_variable_add_and_acquire(st, name); + if (rsa) { + rrdsetvar_custom_chart_variable_set(st, rsa, value); + rrdsetvar_custom_chart_variable_release(st, rsa); + } else error("cannot find/create CHART VARIABLE '%s' on host '%s', chart '%s'", name, rrdhost_hostname(host), rrdset_id(st)); } @@ -127,7 +131,7 @@ PARSER_RC pluginsd_dimension_action(void *user, RRDSET *st, char *id, char *name RRDDIM *rd = rrddim_add(st, id, name, multiplier, divisor, algorithm_type); int unhide_dimension = 1; - rrddim_flag_clear(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); + rrddim_option_clear(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS); if (options && *options) { if (strstr(options, "obsolete") != NULL) rrddim_is_obsolete(st, rd); @@ -137,20 +141,20 @@ PARSER_RC pluginsd_dimension_action(void *user, RRDSET *st, char *id, char *name unhide_dimension = !strstr(options, "hidden"); if (strstr(options, "noreset") != NULL) - rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); + rrddim_option_set(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS); if (strstr(options, "nooverflow") != NULL) - rrddim_flag_set(rd, RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS); + rrddim_option_set(rd, RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS); } else rrddim_isnot_obsolete(st, rd); if (likely(unhide_dimension)) { - rrddim_flag_clear(rd, RRDDIM_FLAG_HIDDEN); + rrddim_option_clear(rd, RRDDIM_OPTION_HIDDEN); if (rrddim_flag_check(rd, RRDDIM_FLAG_META_HIDDEN)) { (void)sql_set_dimension_option(&rd->metric_uuid, NULL); rrddim_flag_clear(rd, RRDDIM_FLAG_META_HIDDEN); } } else { - rrddim_flag_set(rd, RRDDIM_FLAG_HIDDEN); + rrddim_option_set(rd, RRDDIM_OPTION_HIDDEN); if (!rrddim_flag_check(rd, RRDDIM_FLAG_META_HIDDEN)) { (void)sql_set_dimension_option(&rd->metric_uuid, "hidden"); rrddim_flag_set(rd, RRDDIM_FLAG_META_HIDDEN); diff --git a/collectors/proc.plugin/ipc.c b/collectors/proc.plugin/ipc.c index e114a05a41..e0863f6d8b 100644 --- a/collectors/proc.plugin/ipc.c +++ b/collectors/proc.plugin/ipc.c @@ -281,7 +281,7 @@ int do_ipc(int update_every, usec_t dt) { static int read_limits_next = -1; static struct ipc_limits limits; static struct ipc_status status; - static RRDVAR *arrays_max = NULL, *semaphores_max = NULL; + static const RRDVAR_ACQUIRED *arrays_max = NULL, *semaphores_max = NULL; static RRDSET *st_semaphores = NULL, *st_arrays = NULL; static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL; static char *msg_filename = NULL; @@ -352,8 +352,8 @@ int do_ipc(int update_every, usec_t dt) { } // variables - semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_max"); - arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_arrays_max"); + semaphores_max = rrdvar_custom_host_variable_add_and_acquire(localhost, "ipc_semaphores_max"); + arrays_max = rrdvar_custom_host_variable_add_and_acquire(localhost, "ipc_semaphores_arrays_max"); } struct stat stbuf; @@ -483,11 +483,7 @@ int do_ipc(int update_every, usec_t dt) { rrdset_done(st_msq_messages); rrdset_done(st_msq_bytes); - long long dimensions_num = 0; - RRDDIM *rd; - rrdset_rdlock(st_msq_messages); - rrddim_foreach_read(rd, st_msq_messages) dimensions_num++; - rrdset_unlock(st_msq_messages); + long long dimensions_num = rrdset_number_of_dimensions(st_msq_messages); if(unlikely(dimensions_num > dimensions_limit)) { info("Message queue statistics has been disabled"); diff --git a/collectors/proc.plugin/proc_diskstats.c b/collectors/proc.plugin/proc_diskstats.c index 945ca25216..554bc4f897 100644 --- a/collectors/proc.plugin/proc_diskstats.c +++ b/collectors/proc.plugin/proc_diskstats.c @@ -874,8 +874,6 @@ static void add_labels_to_disk(struct disk *d, RRDSET *st) { rrdlabels_add(st->rrdlabels, "device_type", "virtual", RRDLABEL_SRC_AUTO); break; } - - rrdcalc_update_rrdlabels(st); } int do_proc_diskstats(int update_every, usec_t dt) { diff --git a/collectors/proc.plugin/proc_interrupts.c b/collectors/proc.plugin/proc_interrupts.c index db2a20b5df..17c287425d 100644 --- a/collectors/proc.plugin/proc_interrupts.c +++ b/collectors/proc.plugin/proc_interrupts.c @@ -175,7 +175,7 @@ int do_proc_interrupts(int update_every, usec_t dt) { // calls of this function. if(unlikely(!irr->rd || strncmp(rrddim_name(irr->rd), irr->name, MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_add(st_system_interrupts, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(st_system_interrupts, irr->rd, irr->name); + rrddim_reset_name(st_system_interrupts, irr->rd, irr->name); // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { @@ -237,7 +237,7 @@ int do_proc_interrupts(int update_every, usec_t dt) { if(irr->used && (do_per_core == CONFIG_BOOLEAN_YES || irr->cpu[c].value)) { if(unlikely(!irr->cpu[c].rd)) { irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name); + rrddim_reset_name(core_st[c], irr->cpu[c].rd, irr->name); } rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value); diff --git a/collectors/proc.plugin/proc_loadavg.c b/collectors/proc.plugin/proc_loadavg.c index 8b78ecc9ef..14415ef65b 100644 --- a/collectors/proc.plugin/proc_loadavg.c +++ b/collectors/proc.plugin/proc_loadavg.c @@ -99,7 +99,7 @@ int do_proc_loadavg(int update_every, usec_t dt) { if(likely(do_all_processes)) { static RRDSET *processes_chart = NULL; static RRDDIM *rd_active = NULL; - static RRDSETVAR *rd_pidmax; + static const RRDSETVAR_ACQUIRED *rd_pidmax; if(unlikely(!processes_chart)) { processes_chart = rrdset_create_localhost( @@ -118,12 +118,12 @@ int do_proc_loadavg(int update_every, usec_t dt) { ); rd_active = rrddim_add(processes_chart, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); - rd_pidmax = rrdsetvar_custom_chart_variable_create(processes_chart, "pidmax"); + rd_pidmax = rrdsetvar_custom_chart_variable_add_and_acquire(processes_chart, "pidmax"); } else rrdset_next(processes_chart); rrddim_set_by_pointer(processes_chart, rd_active, active_processes); - rrdsetvar_custom_chart_variable_set(rd_pidmax, max_processes); + rrdsetvar_custom_chart_variable_set(processes_chart, rd_pidmax, max_processes); rrdset_done(processes_chart); } diff --git a/collectors/proc.plugin/proc_mdstat.c b/collectors/proc.plugin/proc_mdstat.c index 77b75d3139..2bfb6913f3 100644 --- a/collectors/proc.plugin/proc_mdstat.c +++ b/collectors/proc.plugin/proc_mdstat.c @@ -80,7 +80,6 @@ static inline void make_chart_obsolete(char *name, const char *id_modifier) static void add_labels_to_mdstat(struct raid *raid, RRDSET *st) { rrdlabels_add(st->rrdlabels, "device", raid->name, RRDLABEL_SRC_AUTO); rrdlabels_add(st->rrdlabels, "raid_level", raid->level, RRDLABEL_SRC_AUTO); - rrdcalc_update_rrdlabels(st); } int do_proc_mdstat(int update_every, usec_t dt) diff --git a/collectors/proc.plugin/proc_net_dev.c b/collectors/proc.plugin/proc_net_dev.c index 79572f4420..701cc00ea7 100644 --- a/collectors/proc.plugin/proc_net_dev.c +++ b/collectors/proc.plugin/proc_net_dev.c @@ -188,7 +188,7 @@ static struct netdev { RRDDIM *rd_mtu; char *filename_speed; - RRDSETVAR *chart_var_speed; + const RRDSETVAR_ACQUIRED *chart_var_speed; char *filename_duplex; char *filename_operstate; @@ -967,7 +967,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { // update the interface speed if(d->filename_speed) { if(unlikely(!d->chart_var_speed)) { - d->chart_var_speed = rrdsetvar_custom_chart_variable_create(d->st_bandwidth, "nic_speed_max"); + d->chart_var_speed = + rrdsetvar_custom_chart_variable_add_and_acquire(d->st_bandwidth, "nic_speed_max"); if(!d->chart_var_speed) { error("Cannot create interface %s chart variable 'nic_speed_max'. Will not update its speed anymore.", d->name); freez(d->filename_speed); @@ -990,8 +991,6 @@ int do_proc_net_dev(int update_every, usec_t dt) { d->filename_speed = NULL; } else { - rrdsetvar_custom_chart_variable_set(d->chart_var_speed, (NETDATA_DOUBLE) d->speed * KILOBITS_IN_A_MEGABIT); - if(d->do_speed != CONFIG_BOOLEAN_NO) { if(unlikely(!d->st_speed)) { d->st_speed = rrdset_create_localhost( @@ -1020,6 +1019,8 @@ int do_proc_net_dev(int update_every, usec_t dt) { rrddim_set_by_pointer(d->st_speed, d->rd_speed, (collected_number)d->speed * KILOBITS_IN_A_MEGABIT); rrdset_done(d->st_speed); } + + rrdsetvar_custom_chart_variable_set(d->st_bandwidth, d->chart_var_speed, (NETDATA_DOUBLE) d->speed * KILOBITS_IN_A_MEGABIT); } } } diff --git a/collectors/proc.plugin/proc_net_snmp.c b/collectors/proc.plugin/proc_net_snmp.c index b03a6ac74d..d667a06df8 100644 --- a/collectors/proc.plugin/proc_net_snmp.c +++ b/collectors/proc.plugin/proc_net_snmp.c @@ -104,7 +104,7 @@ int do_proc_net_snmp(int update_every, usec_t dt) { *arl_udp = NULL, *arl_udplite = NULL; - static RRDVAR *tcp_max_connections_var = NULL; + static const RRDVAR_ACQUIRED *tcp_max_connections_var = NULL; if(unlikely(!arl_ip)) { do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 packets", CONFIG_BOOLEAN_AUTO); @@ -216,7 +216,7 @@ int do_proc_net_snmp(int update_every, usec_t dt) { arl_expect(arl_udplite, "InCsumErrors", &snmp_root.udplite_InCsumErrors); arl_expect(arl_udplite, "IgnoredMulti", &snmp_root.udplite_IgnoredMulti); - tcp_max_connections_var = rrdvar_custom_host_variable_create(localhost, "tcp_max_connections"); + tcp_max_connections_var = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_max_connections"); } if(unlikely(!ff)) { diff --git a/collectors/proc.plugin/proc_net_sockstat.c b/collectors/proc.plugin/proc_net_sockstat.c index 994cbad7b6..db75bee1ab 100644 --- a/collectors/proc.plugin/proc_net_sockstat.c +++ b/collectors/proc.plugin/proc_net_sockstat.c @@ -27,14 +27,14 @@ static struct proc_net_sockstat { static int read_tcp_mem(void) { static char *filename = NULL; - static RRDVAR *tcp_mem_low_threshold = NULL, + static const RRDVAR_ACQUIRED *tcp_mem_low_threshold = NULL, *tcp_mem_pressure_threshold = NULL, *tcp_mem_high_threshold = NULL; if(unlikely(!tcp_mem_low_threshold)) { - tcp_mem_low_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_low"); - tcp_mem_pressure_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_pressure"); - tcp_mem_high_threshold = rrdvar_custom_host_variable_create(localhost, "tcp_mem_high"); + tcp_mem_low_threshold = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_mem_low"); + tcp_mem_pressure_threshold = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_mem_pressure"); + tcp_mem_high_threshold = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_mem_high"); } if(unlikely(!filename)) { @@ -69,7 +69,7 @@ static int read_tcp_mem(void) { static kernel_uint_t read_tcp_max_orphans(void) { static char *filename = NULL; - static RRDVAR *tcp_max_orphans_var = NULL; + static const RRDVAR_ACQUIRED *tcp_max_orphans_var = NULL; if(unlikely(!filename)) { char buffer[FILENAME_MAX + 1]; @@ -81,7 +81,7 @@ static kernel_uint_t read_tcp_max_orphans(void) { if(read_single_number_file(filename, &tcp_max_orphans) == 0) { if(unlikely(!tcp_max_orphans_var)) - tcp_max_orphans_var = rrdvar_custom_host_variable_create(localhost, "tcp_max_orphans"); + tcp_max_orphans_var = rrdvar_custom_host_variable_add_and_acquire(localhost, "tcp_max_orphans"); rrdvar_custom_host_variable_set(localhost, tcp_max_orphans_var, tcp_max_orphans); return tcp_max_orphans; diff --git a/collectors/proc.plugin/proc_net_stat_conntrack.c b/collectors/proc.plugin/proc_net_stat_conntrack.c index 642e33f8e9..3182a745a6 100644 --- a/collectors/proc.plugin/proc_net_stat_conntrack.c +++ b/collectors/proc.plugin/proc_net_stat_conntrack.c @@ -12,7 +12,7 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { static usec_t get_max_every = 10 * USEC_PER_SEC, usec_since_last_max = 0; static int read_full = 1; static char *nf_conntrack_filename, *nf_conntrack_count_filename, *nf_conntrack_max_filename; - static RRDVAR *rrdvar_max = NULL; + static const RRDVAR_ACQUIRED *rrdvar_max = NULL; unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0, ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0; @@ -50,7 +50,7 @@ int do_proc_net_stat_conntrack(int update_every, usec_t dt) { if(!do_sockets && !read_full) return 1; - rrdvar_max = rrdvar_custom_host_variable_create(localhost, "netfilter_conntrack_max"); + rrdvar_max = rrdvar_custom_host_variable_add_and_acquire(localhost, "netfilter_conntrack_max"); } if(likely(read_full)) { diff --git a/collectors/proc.plugin/proc_net_wireless.c b/collectors/proc.plugin/proc_net_wireless.c index 328ab1ca05..78d8ebbac1 100644 --- a/collectors/proc.plugin/proc_net_wireless.c +++ b/collectors/proc.plugin/proc_net_wireless.c @@ -200,7 +200,6 @@ static void configure_device(int do_status, int do_quality, int do_discarded_pac static void add_labels_to_wireless(struct netwireless *w, RRDSET *st) { rrdlabels_add(st->rrdlabels, "device", w->name, RRDLABEL_SRC_AUTO); - rrdcalc_update_rrdlabels(st); } int do_proc_net_wireless(int update_every, usec_t dt) diff --git a/collectors/proc.plugin/proc_self_mountinfo.c b/collectors/proc.plugin/proc_self_mountinfo.c index 4456d5978a..9310f2ffc1 100644 --- a/collectors/proc.plugin/proc_self_mountinfo.c +++ b/collectors/proc.plugin/proc_self_mountinfo.c @@ -227,7 +227,8 @@ struct mountinfo *mountinfo_read(int do_statvfs) { struct mountinfo *root = NULL, *last = NULL, *mi = NULL; // create a dictionary to track uniqueness - DICTIONARY *dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED|DICTIONARY_FLAG_DONT_OVERWRITE_VALUE|DICTIONARY_FLAG_NAME_LINK_DONT_CLONE); + DICTIONARY *dict = dictionary_create( + DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_NAME_LINK_DONT_CLONE); unsigned long l, lines = procfile_lines(ff); for(l = 0; l < lines ;l++) { diff --git a/collectors/proc.plugin/proc_softirqs.c b/collectors/proc.plugin/proc_softirqs.c index d6389161a2..a1c8b8ee73 100644 --- a/collectors/proc.plugin/proc_softirqs.c +++ b/collectors/proc.plugin/proc_softirqs.c @@ -155,7 +155,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { // calls of this function. if(unlikely(!irr->rd || strncmp(irr->name, rrddim_name(irr->rd), MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_add(st_system_softirqs, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(st_system_softirqs, irr->rd, irr->name); + rrddim_reset_name(st_system_softirqs, irr->rd, irr->name); // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop if(likely(do_per_core != CONFIG_BOOLEAN_NO)) { @@ -231,7 +231,7 @@ int do_proc_softirqs(int update_every, usec_t dt) { if(irr->used && (do_per_core == CONFIG_BOOLEAN_YES || irr->cpu[c].value)) { if(unlikely(!irr->cpu[c].rd)) { irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); - rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name); + rrddim_reset_name(core_st[c], irr->cpu[c].rd, irr->name); } rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value); diff --git a/collectors/proc.plugin/proc_spl_kstat_zfs.c b/collectors/proc.plugin/proc_spl_kstat_zfs.c index fae112249d..1b9ee04c10 100644 --- a/collectors/proc.plugin/proc_spl_kstat_zfs.c +++ b/collectors/proc.plugin/proc_spl_kstat_zfs.c @@ -252,8 +252,8 @@ void disable_zfs_pool_state(struct zfs_pool *pool) pool->disabled = 1; } -int update_zfs_pool_state_chart(const char *name, void *pool_p, void *update_every_p) -{ +int update_zfs_pool_state_chart(const DICTIONARY_ITEM *item, void *pool_p, void *update_every_p) { + const char *name = dictionary_acquired_item_name(item); struct zfs_pool *pool = (struct zfs_pool *)pool_p; int update_every = *(int *)update_every_p; @@ -321,7 +321,7 @@ int do_proc_spl_kstat_zfs_pool_state(int update_every, usec_t dt) snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/spl/kstat/zfs"); dirname = config_get("plugin:proc:" ZFS_PROC_POOLS, "directory to monitor", filename); - zfs_pools = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + zfs_pools = dictionary_create(DICT_OPTION_SINGLE_THREADED); do_zfs_pool_state = 1; } diff --git a/collectors/proc.plugin/proc_stat.c b/collectors/proc.plugin/proc_stat.c index 5086ff2c7d..dcc67e9ab6 100644 --- a/collectors/proc.plugin/proc_stat.c +++ b/collectors/proc.plugin/proc_stat.c @@ -481,7 +481,7 @@ int do_proc_stat(int update_every, usec_t dt) { static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked; static char *core_throttle_count_filename = NULL, *package_throttle_count_filename = NULL, *scaling_cur_freq_filename = NULL, *time_in_state_filename = NULL, *schedstat_filename = NULL, *cpuidle_name_filename = NULL, *cpuidle_time_filename = NULL; - static RRDVAR *cpus_var = NULL; + static const RRDVAR_ACQUIRED *cpus_var = NULL; static int accurate_freq_avail = 0, accurate_freq_is_used = 0; size_t cores_found = (size_t)processors; @@ -713,7 +713,7 @@ int do_proc_stat(int update_every, usec_t dt) { rrddim_hide(cpu_chart->st, "idle"); if(unlikely(core == 0 && cpus_var == NULL)) - cpus_var = rrdvar_custom_host_variable_create(localhost, "active_processors"); + cpus_var = rrdvar_custom_host_variable_add_and_acquire(localhost, "active_processors"); } else rrdset_next(cpu_chart->st); diff --git a/collectors/proc.plugin/sys_block_zram.c b/collectors/proc.plugin/sys_block_zram.c index 42c467630c..55136f502f 100644 --- a/collectors/proc.plugin/sys_block_zram.c +++ b/collectors/proc.plugin/sys_block_zram.c @@ -177,7 +177,7 @@ static void free_device(DICTIONARY *dict, const char *name) rrdset_obsolete_and_pointer_null(d->st_savings); rrdset_obsolete_and_pointer_null(d->st_alloc_efficiency); rrdset_obsolete_and_pointer_null(d->st_comp_ratio); - dictionary_del_having_write_lock(dict, name); + dictionary_del(dict, name); } // -------------------------------------------------------------------- @@ -239,13 +239,16 @@ static inline int _collect_zram_metrics(const char* name, ZRAM_DEVICE *d, int ad return 0; } -static int collect_first_zram_metrics(const char *name, void *entry, void *data) { +static int collect_first_zram_metrics(const DICTIONARY_ITEM *item, void *entry, void *data) { + const char *name = dictionary_acquired_item_name(item); + // collect without calling rrdset_next (init only) return _collect_zram_metrics(name, (ZRAM_DEVICE *)entry, 0, (DICTIONARY *)data); } -static int collect_zram_metrics(const char *name, void *entry, void *data) { - (void)name; +static int collect_zram_metrics(const DICTIONARY_ITEM *item, void *entry, void *data) { + const char *name = dictionary_acquired_item_name(item); + // collect with calling rrdset_next return _collect_zram_metrics(name, (ZRAM_DEVICE *)entry, 1, (DICTIONARY *)data); } @@ -280,7 +283,7 @@ int do_sys_block_zram(int update_every, usec_t dt) { } procfile_close(ff); - devices = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + devices = dictionary_create(DICT_OPTION_SINGLE_THREADED); device_count = init_devices(devices, (unsigned int)zram_id, update_every); if (device_count < 1) return 1; diff --git a/collectors/proc.plugin/sys_class_infiniband.c b/collectors/proc.plugin/sys_class_infiniband.c index 7e63bcbb4e..603f2eaa2c 100644 --- a/collectors/proc.plugin/sys_class_infiniband.c +++ b/collectors/proc.plugin/sys_class_infiniband.c @@ -184,7 +184,7 @@ static struct ibport { RRDSET *st_hwpackets; RRDSET *st_hwerrors; - RRDSETVAR *stv_speed; + const RRDSETVAR_ACQUIRED *stv_speed; usec_t speed_last_collected_usec; @@ -543,7 +543,7 @@ int do_sys_class_infiniband(int update_every, usec_t dt) // x4 lanes multiplier as per Documentation/ABI/stable/sysfs-class-infiniband FOREACH_COUNTER_BYTES(GEN_RRD_DIM_ADD_CUSTOM, port, 4 * 8 * port->width, 1024, RRD_ALGORITHM_INCREMENTAL) - port->stv_speed = rrdsetvar_custom_chart_variable_create(port->st_bytes, "link_speed"); + port->stv_speed = rrdsetvar_custom_chart_variable_add_and_acquire(port->st_bytes, "link_speed"); } else rrdset_next(port->st_bytes); @@ -551,7 +551,7 @@ int do_sys_class_infiniband(int update_every, usec_t dt) FOREACH_COUNTER_BYTES(GEN_RRD_DIM_SETP, port) // For link speed set only variable - rrdsetvar_custom_chart_variable_set(port->stv_speed, port->speed); + rrdsetvar_custom_chart_variable_set(port->st_bytes, port->stv_speed, port->speed); rrdset_done(port->st_bytes); } diff --git a/collectors/proc.plugin/sys_class_power_supply.c b/collectors/proc.plugin/sys_class_power_supply.c index 40731b5d5f..a8f9ac4462 100644 --- a/collectors/proc.plugin/sys_class_power_supply.c +++ b/collectors/proc.plugin/sys_class_power_supply.c @@ -114,7 +114,6 @@ void power_supply_free(struct power_supply *ps) { static void add_labels_to_power_supply(struct power_supply *ps, RRDSET *st) { rrdlabels_add(st->rrdlabels, "device", ps->name, RRDLABEL_SRC_AUTO); - rrdcalc_update_rrdlabels(st); } int do_sys_class_power_supply(int update_every, usec_t dt) { diff --git a/collectors/proc.plugin/sys_fs_btrfs.c b/collectors/proc.plugin/sys_fs_btrfs.c index 323bb69671..c43632f8ad 100644 --- a/collectors/proc.plugin/sys_fs_btrfs.c +++ b/collectors/proc.plugin/sys_fs_btrfs.c @@ -451,7 +451,6 @@ static inline int find_all_btrfs_pools(const char *path) { static void add_labels_to_btrfs(BTRFS_NODE *n, RRDSET *st) { rrdlabels_add(st->rrdlabels, "device", n->id, RRDLABEL_SRC_AUTO); rrdlabels_add(st->rrdlabels, "device_label", n->label, RRDLABEL_SRC_AUTO); - rrdcalc_update_rrdlabels(st); } int do_sys_fs_btrfs(int update_every, usec_t dt) { diff --git a/collectors/statsd.plugin/statsd.c b/collectors/statsd.plugin/statsd.c index e68640a4f7..84facd8085 100644 --- a/collectors/statsd.plugin/statsd.c +++ b/collectors/statsd.plugin/statsd.c @@ -24,9 +24,9 @@ #ifdef STATSD_MULTITHREADED // DO NOT ENABLE MULTITHREADING - IT IS NOT WELL TESTED -#define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_DONT_OVERWRITE_VALUE|DICTIONARY_FLAG_ADD_IN_FRONT +#define STATSD_DICTIONARY_OPTIONS (DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_ADD_IN_FRONT) #else -#define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_DONT_OVERWRITE_VALUE|DICTIONARY_FLAG_ADD_IN_FRONT|DICTIONARY_FLAG_SINGLE_THREADED +#define STATSD_DICTIONARY_OPTIONS (DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_ADD_IN_FRONT | DICT_OPTION_SINGLE_THREADED) #endif #define STATSD_DECIMAL_DETAIL 1000 // floating point values get multiplied by this, with the same divisor @@ -192,6 +192,7 @@ typedef struct statsd_app_chart_dimension { collected_number multiplier; // the multiplier of the dimension collected_number divisor; // the divisor of the dimension RRDDIM_FLAGS flags; // the RRDDIM flags for this dimension + RRDDIM_OPTIONS options; // the RRDDIM options for this dimension STATSD_APP_CHART_DIM_VALUE_TYPE value_type; // which value to use of the source metric @@ -371,9 +372,10 @@ static struct statsd { // -------------------------------------------------------------------------------------------------------------------- // statsd index management - add/find metrics -static void dictionary_metric_insert_callback(const char *name, void *value, void *data) { +static void dictionary_metric_insert_callback(const DICTIONARY_ITEM *item, void *value, void *data) { STATSD_INDEX *index = (STATSD_INDEX *)data; STATSD_METRIC *m = (STATSD_METRIC *)value; + const char *name = dictionary_acquired_item_name(item); debug(D_STATSD, "Creating new %s metric '%s'", index->name, name); @@ -390,9 +392,9 @@ static void dictionary_metric_insert_callback(const char *name, void *value, voi __atomic_fetch_add(&index->metrics, 1, __ATOMIC_RELAXED); } -static void dictionary_metric_delete_callback(const char *name, void *value, void *data) { +static void dictionary_metric_delete_callback(const DICTIONARY_ITEM *item, void *value, void *data) { (void)data; // STATSD_INDEX *index = (STATSD_INDEX *)data; - (void)name; + (void)item; STATSD_METRIC *m = (STATSD_METRIC *)value; if(m->type == STATSD_METRIC_TYPE_HISTOGRAM || m->type == STATSD_METRIC_TYPE_TIMER) { @@ -416,7 +418,7 @@ static inline STATSD_METRIC *statsd_find_or_add_metric(STATSD_INDEX *index, cons // no locks here, go faster // this will call the dictionary_metric_insert_callback() if an item // is inserted, otherwise it will return the existing one. - // We used the flag DICTIONARY_FLAG_DONT_OVERWRITE_VALUE to support this. + // We used the flag DICT_OPTION_DONT_OVERWRITE_VALUE to support this. STATSD_METRIC *m = dictionary_set(index->dict, name, NULL, sizeof(STATSD_METRIC)); #endif @@ -572,8 +574,8 @@ static inline void statsd_process_histogram_or_timer(STATSD_METRIC *m, const cha #define statsd_process_timer(m, value, sampling) statsd_process_histogram_or_timer(m, value, sampling, "timer") #define statsd_process_histogram(m, value, sampling) statsd_process_histogram_or_timer(m, value, sampling, "histogram") -static void dictionary_metric_set_value_insert_callback(const char *name, void *value, void *data) { - (void)name; +static void dictionary_metric_set_value_insert_callback(const DICTIONARY_ITEM *item, void *value, void *data) { + (void)item; (void)value; STATSD_METRIC *m = (STATSD_METRIC *)data; m->set.unique++; @@ -617,8 +619,8 @@ static inline void statsd_process_set(STATSD_METRIC *m, const char *value) { } } -static void dictionary_metric_dict_value_insert_callback(const char *name, void *value, void *data) { - (void)name; +static void dictionary_metric_dict_value_insert_callback(const DICTIONARY_ITEM *item, void *value, void *data) { + (void)item; (void)value; STATSD_METRIC *m = (STATSD_METRIC *)data; m->dictionary.unique++; @@ -1209,6 +1211,7 @@ static STATSD_APP_CHART_DIM *add_dimension_to_app_chart( , collected_number multiplier , collected_number divisor , RRDDIM_FLAGS flags + , RRDDIM_OPTIONS options , STATSD_APP_CHART_DIM_VALUE_TYPE value_type ) { STATSD_APP_CHART_DIM *dim = callocz(sizeof(STATSD_APP_CHART_DIM), 1); @@ -1221,6 +1224,7 @@ static STATSD_APP_CHART_DIM *add_dimension_to_app_chart( dim->divisor = divisor; dim->value_type = value_type; dim->flags = flags; + dim->options = options; if(!dim->multiplier) dim->multiplier = 1; @@ -1323,7 +1327,7 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA else if(app) { if(!strcmp(s, "dictionary")) { if(!app->dict) - app->dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + app->dict = dictionary_create(DICT_OPTION_SINGLE_THREADED); dict = app->dict; } @@ -1474,17 +1478,18 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA pattern = 1; } - char *dim_name = words[i++]; - char *type = words[i++]; - char *multiplier = words[i++]; - char *divisor = words[i++]; - char *options = words[i++]; + char *dim_name = words[i++]; + char *type = words[i++]; + char *multiplier = words[i++]; + char *divisor = words[i++]; + char *opts = words[i++]; RRDDIM_FLAGS flags = RRDDIM_FLAG_NONE; - if(options && *options) { - if(strstr(options, "hidden") != NULL) flags |= RRDDIM_FLAG_HIDDEN; - if(strstr(options, "noreset") != NULL) flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS; - if(strstr(options, "nooverflow") != NULL) flags |= RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS; + RRDDIM_OPTIONS options = RRDDIM_OPTION_NONE; + if(opts && *opts) { + if(strstr(opts, "hidden") != NULL) options |= RRDDIM_OPTION_HIDDEN; + if(strstr(opts, "noreset") != NULL) options |= RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS; + if(strstr(opts, "nooverflow") != NULL) options |= RRDDIM_OPTION_DONT_DETECT_RESETS_OR_OVERFLOWS; } if(!pattern) { @@ -1510,7 +1515,8 @@ static int statsd_readfile(const char *filename, STATSD_APP *app, STATSD_APP_CHA , (multiplier && *multiplier)?str2l(multiplier):1 , (divisor && *divisor)?str2l(divisor):1 , flags - , string2valuetype(type, line, filename) + , + options, string2valuetype(type, line, filename) ); if(pattern) @@ -1775,7 +1781,7 @@ static inline void statsd_private_chart_dictionary(STATSD_METRIC *m) { STATSD_METRIC_DICTIONARY_ITEM *t; dfe_start_read(m->dictionary.dict, t) { - if (!t->rd) t->rd = rrddim_add(m->st, t_name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); + if (!t->rd) t->rd = rrddim_add(m->st, t_dfe.name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(m->st, t->rd, (collected_number)t->count); } dfe_done(t); @@ -2130,6 +2136,7 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC , dim->multiplier , dim->divisor , dim->flags + , dim->options , dim->value_type ); @@ -2186,11 +2193,13 @@ static inline RRDDIM *statsd_add_dim_to_app_chart(STATSD_APP *app, STATSD_APP_CH dim->rd = rrddim_add(chart->st, metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm); if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags; + if(dim->options != RRDDIM_OPTION_NONE) dim->rd->options |= dim->options; return dim->rd; } dim->rd = rrddim_add(chart->st, dim->metric, dim->name, dim->multiplier, dim->divisor, dim->algorithm); if(dim->flags != RRDDIM_FLAG_NONE) dim->rd->flags |= dim->flags; + if(dim->options != RRDDIM_OPTION_NONE) dim->rd->options |= dim->options; return dim->rd; } diff --git a/collectors/tc.plugin/plugin_tc.c b/collectors/tc.plugin/plugin_tc.c index f4ef659435..393a9575d2 100644 --- a/collectors/tc.plugin/plugin_tc.c +++ b/collectors/tc.plugin/plugin_tc.c @@ -74,7 +74,7 @@ struct tc_device { // ---------------------------------------------------------------------------- // tc_class index -static void tc_class_free_callback(const char *name __maybe_unused, void *value, void *data __maybe_unused) { +static void tc_class_free_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) { // struct tc_device *d = data; struct tc_class *c = value; @@ -84,22 +84,21 @@ static void tc_class_free_callback(const char *name __maybe_unused, void *value, string_freez(c->parentid); } -static void tc_class_conflict_callback(const char *name __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) { +static bool tc_class_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) { struct tc_device *d = data; (void)d; struct tc_class *c = old_value; (void)c; struct tc_class *new_c = new_value; (void)new_c; - error("TC: class '%s' is already in device '%s'. Ignoring duplicate.", name, string2str(d->id)); + error("TC: class '%s' is already in device '%s'. Ignoring duplicate.", dictionary_acquired_item_name(item), string2str(d->id)); - tc_class_free_callback(name, new_value, data); + tc_class_free_callback(item, new_value, data); + + return true; } static void tc_class_index_init(struct tc_device *d) { if(!d->classes) { - d->classes = dictionary_create( - DICTIONARY_FLAG_DONT_OVERWRITE_VALUE - |DICTIONARY_FLAG_SINGLE_THREADED - ); + d->classes = dictionary_create(DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_SINGLE_THREADED); dictionary_register_delete_callback(d->classes, tc_class_free_callback, d); dictionary_register_conflict_callback(d->classes, tc_class_conflict_callback, d); @@ -128,12 +127,12 @@ static inline struct tc_class *tc_class_index_find(struct tc_device *d, const ch static DICTIONARY *tc_device_root_index = NULL; -static void tc_device_add_callback(const char *name __maybe_unused, void *value, void *data __maybe_unused) { +static void tc_device_add_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) { struct tc_device *d = value; tc_class_index_init(d); } -static void tc_device_free_callback(const char *name __maybe_unused, void *value, void *data __maybe_unused) { +static void tc_device_free_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) { struct tc_device *d = value; tc_class_index_destroy(d); @@ -146,10 +145,7 @@ static void tc_device_free_callback(const char *name __maybe_unused, void *value static void tc_device_index_init() { if(!tc_device_root_index) { tc_device_root_index = dictionary_create( - DICTIONARY_FLAG_DONT_OVERWRITE_VALUE - |DICTIONARY_FLAG_SINGLE_THREADED - |DICTIONARY_FLAG_ADD_IN_FRONT - ); + DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_SINGLE_THREADED | DICT_OPTION_ADD_IN_FRONT); dictionary_register_insert_callback(tc_device_root_index, tc_device_add_callback, NULL); dictionary_register_delete_callback(tc_device_root_index, tc_device_free_callback, NULL); @@ -196,7 +192,7 @@ static inline void tc_device_classes_cleanup(struct tc_device *d) { d->family_updated = false; struct tc_class *c; - dfe_start_unsafe(d->classes, c) { + dfe_start_write(d->classes, c) { if(unlikely(cleanup_every && c->unupdated >= cleanup_every)) tc_class_free(d, c); @@ -254,7 +250,7 @@ static inline void tc_device_commit(struct tc_device *d) { // prepare all classes // we set reasonable defaults for the rest of the code below - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { c->render = false; // do not render this class c->isleaf = true; // this is a leaf class c->hasparent = false; // without a parent @@ -283,7 +279,7 @@ static inline void tc_device_commit(struct tc_device *d) { error("TC: device '%s' has active both classes (%d) and qdiscs (%d). Will render only qdiscs.", string2str(d->id), updated_classes, updated_qdiscs); // set all classes to !updated - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if (unlikely(!c->isqdisc && c->updated)) c->updated = false; } @@ -307,7 +303,7 @@ static inline void tc_device_commit(struct tc_device *d) { // so, here we remove the isleaf flag from nodes in the middle // and we add the hasparent flag to leaf nodes we found their parent if(likely(!d->enabled_all_classes_qdiscs)) { - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->updated)) continue; @@ -319,7 +315,7 @@ static inline void tc_device_commit(struct tc_device *d) { // c->parentid?c->parentid:"NULL"); // find if c is leaf or not - dfe_start_unsafe(d->classes, x) { + dfe_start_read(d->classes, x) { if(unlikely(!x->updated || c == x || !x->parentid)) continue; @@ -339,7 +335,7 @@ static inline void tc_device_commit(struct tc_device *d) { dfe_done(c); } - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->updated)) continue; @@ -367,7 +363,7 @@ static inline void tc_device_commit(struct tc_device *d) { // dump all the list to see what we know if(unlikely(debug_flags & D_TC_LOOP)) { - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(c->render) debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, OK", string2str(d->name), string2str(c->id)); else debug(D_TC_LOOP, "TC: final nodes dump for '%s': class '%s', IGNORE (updated: %d, isleaf: %d, hasparent: %d, parent: '%s')", string2str(d->name?d->name:d->id), string2str(c->id), c->updated, c->isleaf, c->hasparent, string2str(c->parentid)); @@ -426,7 +422,8 @@ static inline void tc_device_commit(struct tc_device *d) { } else { rrdset_next(d->st_bytes); - if(unlikely(d->name_updated)) rrdset_set_name(d->st_bytes, string2str(d->name)); + if(unlikely(d->name_updated)) + rrdset_reset_name(d->st_bytes, string2str(d->name)); if(d->name && d->name_updated) rrdlabels_add(d->st_bytes->rrdlabels, "name", string2str(d->name), RRDLABEL_SRC_AUTO); @@ -438,13 +435,13 @@ static inline void tc_device_commit(struct tc_device *d) { // update the family } - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_bytes)) c->rd_bytes = rrddim_add(d->st_bytes, string2str(c->id), string2str(c->name?c->name:c->id), 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_bytes, c->rd_bytes, string2str(c->name)); + rrddim_reset_name(d->st_bytes, c->rd_bytes, string2str(c->name)); rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes); } @@ -491,7 +488,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", string2str(d->name?d->name:d->id)); - rrdset_set_name(d->st_packets, name); + rrdset_reset_name(d->st_packets, name); } if(d->name && d->name_updated) @@ -504,13 +501,13 @@ static inline void tc_device_commit(struct tc_device *d) { // update the family } - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_packets)) c->rd_packets = rrddim_add(d->st_packets, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_packets, c->rd_packets, string2str(c->name)); + rrddim_reset_name(d->st_packets, c->rd_packets, string2str(c->name)); rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets); } @@ -557,7 +554,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", string2str(d->name?d->name:d->id)); - rrdset_set_name(d->st_dropped, name); + rrdset_reset_name(d->st_dropped, name); } if(d->name && d->name_updated) @@ -570,13 +567,13 @@ static inline void tc_device_commit(struct tc_device *d) { // update the family } - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_dropped)) c->rd_dropped = rrddim_add(d->st_dropped, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_dropped, c->rd_dropped, string2str(c->name)); + rrddim_reset_name(d->st_dropped, c->rd_dropped, string2str(c->name)); rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped); } @@ -623,7 +620,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", string2str(d->name?d->name:d->id)); - rrdset_set_name(d->st_tokens, name); + rrdset_reset_name(d->st_tokens, name); } if(d->name && d->name_updated) @@ -636,14 +633,14 @@ static inline void tc_device_commit(struct tc_device *d) { // update the family } - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_tokens)) { c->rd_tokens = rrddim_add(d->st_tokens, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_ABSOLUTE); } else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_tokens, c->rd_tokens, string2str(c->name)); + rrddim_reset_name(d->st_tokens, c->rd_tokens, string2str(c->name)); rrddim_set_by_pointer(d->st_tokens, c->rd_tokens, c->tokens); } @@ -691,7 +688,7 @@ static inline void tc_device_commit(struct tc_device *d) { if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", string2str(d->name?d->name:d->id)); - rrdset_set_name(d->st_ctokens, name); + rrdset_reset_name(d->st_ctokens, name); } if(d->name && d->name_updated) @@ -704,13 +701,13 @@ static inline void tc_device_commit(struct tc_device *d) { // update the family } - dfe_start_unsafe(d->classes, c) { + dfe_start_read(d->classes, c) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_ctokens)) c->rd_ctokens = rrddim_add(d->st_ctokens, string2str(c->id), string2str(c->name?c->name:c->id), 1, 1, RRD_ALGORITHM_ABSOLUTE); else if(unlikely(c->name_updated)) - rrddim_set_name(d->st_ctokens, c->rd_ctokens, string2str(c->name)); + rrddim_reset_name(d->st_ctokens, c->rd_ctokens, string2str(c->name)); rrddim_set_by_pointer(d->st_ctokens, c->rd_ctokens, c->ctokens); } @@ -1146,12 +1143,12 @@ void *tc_main(void *ptr) { worker_is_busy(WORKER_TC_WORKTIME); worker_set_metric(WORKER_TC_PLUGIN_TIME, str2ll(words[1], NULL)); - size_t number_of_devices = dictionary_stats_entries(tc_device_root_index); + size_t number_of_devices = dictionary_entries(tc_device_root_index); size_t number_of_classes = 0; struct tc_device *d; - dfe_start_unsafe(tc_device_root_index, d) { - number_of_classes += dictionary_stats_entries(d->classes); + dfe_start_read(tc_device_root_index, d) { + number_of_classes += dictionary_entries(d->classes);