@cryptotaxi247 / netdata-1 / commits / e2389840c

chart local variables use the same structures RRDSET variables use, so they appear as family and host variables too

Costa Tsaousis (ktsaou) committed Oct 17, 2017 at 23:24 UTC e2389840cc5ff6de71e4d57b0f2bd1034912d50d
9 files changed +156 -109
src/health.h
+9 -6
@@ -11,7 +11,8 @@ typedef enum rrdvar_type {
11 RRDVAR_TYPE_COLLECTED = 3,
12 RRDVAR_TYPE_TOTAL = 4,
13 RRDVAR_TYPE_INT = 5,
14 - RRDVAR_TYPE_CALCULATED_ALLOCATED = 6 // a custom variable, allocate on purpose (ie. not inherited from charts)
14 + RRDVAR_TYPE_CALCULATED_ALLOCATED = 6 // a custom variable, allocated on purpose (ie. not inherited from charts)
15 + // used only for custom host global variables
16 } RRDVAR_TYPE;
17
18 // the variables as stored in the variables indexes
@@ -38,14 +39,17 @@ typedef struct rrdvar {
39 // these variables
40
41 typedef enum rrdvar_options {
41 - RRDVAR_OPTION_DEFAULT = (0 << 0)
42 + RRDVAR_OPTION_DEFAULT = (0 << 0),
43 + RRDVAR_OPTION_ALLOCATED = (1 << 0) // the value ptr is allocated (not a reference)
44 // future use
45 } RRDVAR_OPTIONS;
46
47 typedef struct rrdsetvar {
48 + char *variable; // variable name
49 + uint32_t hash; // variable name hash
50 +
51 char *key_fullid; // chart type.chart id.variable
52 char *key_fullname; // chart type.chart name.variable
48 - char *variable; // variable
53
54 RRDVAR_TYPE type;
55 void *value;
@@ -365,8 +369,8 @@ void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf);
369 extern RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name);
370 extern void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value);
371
368 -extern RRDVAR *rrdvar_custom_chart_variable_create(RRDSET *st, const char *name);
369 -extern void rrdvar_custom_chart_variable_set(RRDSET *st, RRDVAR *rv, calculated_number value);
372 +extern RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name);
373 +extern void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rv, calculated_number value);
374
375 extern void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock);
376
@@ -413,7 +417,6 @@ extern void rrdcalctemplate_free(RRDCALCTEMPLATE *rt);
417 extern void rrdcalctemplate_unlink_and_free(RRDHOST *host, RRDCALCTEMPLATE *rt);
418
419 extern int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data);
416 -extern int rrdvar_callback_for_all_chart_variables(RRDSET *st, int (*callback)(void *rrdvar, void *data), void *data);
420
421 #ifdef NETDATA_HEALTH_INTERNALS
422 #define RRDVAR_MAX_LENGTH 1024
src/ipc.c
+8 -10
@@ -163,10 +163,10 @@ static inline int ipc_sem_get_status(struct ipc_status *st) {
163 int do_ipc(int update_every, usec_t dt) {
164 (void)dt;
165
166 - static int initialized = 0, read_limits_next = 0;
166 + static int initialized = 0, read_limits_next = -1;
167 static struct ipc_limits limits;
168 static struct ipc_status status;
169 - static RRDVAR *arrays_max = NULL, *semaphores_max = NULL;
169 + static RRDSETVAR *arrays_max = NULL, *semaphores_max = NULL;
170 static RRDSET *st_semaphores = NULL, *st_arrays = NULL;
171 static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL;
172
@@ -185,12 +185,6 @@ int do_ipc(int update_every, usec_t dt) {
185 return 1;
186 }
187
188 - arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.arrays.max");
189 - semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc.semaphores.max");
190 -
191 - if(arrays_max) rrdvar_custom_host_variable_set(localhost, arrays_max, limits.semmni);
192 - if(semaphores_max) rrdvar_custom_host_variable_set(localhost, semaphores_max, limits.semmns);
193 -
188 // create the charts
189 if(unlikely(!st_semaphores)) {
190 st_semaphores = rrdset_create_localhost(
@@ -227,6 +221,10 @@ int do_ipc(int update_every, usec_t dt) {
221 );
222 rd_arrays = rrddim_add(st_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
223 }
224 +
225 + // variables
226 + semaphores_max = rrdsetvar_custom_chart_variable_create(st_semaphores, "ipc.semaphores.max");
227 + arrays_max = rrdsetvar_custom_chart_variable_create(st_arrays, "ipc.semaphores.arrays.max");
228 }
229
230 if(unlikely(read_limits_next < 0)) {
@@ -234,8 +232,8 @@ int do_ipc(int update_every, usec_t dt) {
232 error("Unable to fetch semaphore limits.");
233 }
234 else {
237 - if(arrays_max) rrdvar_custom_host_variable_set(localhost, arrays_max, limits.semmni);
238 - if(semaphores_max) rrdvar_custom_host_variable_set(localhost, semaphores_max, limits.semmns);
235 + if(semaphores_max) rrdsetvar_custom_chart_variable_set(semaphores_max, limits.semmns);
236 + if(arrays_max) rrdsetvar_custom_chart_variable_set(arrays_max, limits.semmni);
237
238 st_arrays->red = limits.semmni;
239 st_semaphores->red = limits.semmns;
src/plugins_d.c
+11 -3
@@ -400,7 +400,15 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
400 value = NULL;
401
402 if(value) {
403 - calculated_number v = (calculated_number)str2ld(value, NULL);
403 + char *endptr = NULL;
404 + calculated_number v = (calculated_number)str2ld(value, &endptr);
405 +
406 + if(unlikely(endptr && *endptr)) {
407 + if(endptr == value)
408 + error("PLUGINSD: '%s': the value '%s' of VARIABLE '%s' on host '%s' cannot be parsed as a number", cd->fullfilename, value, name, host->hostname);
409 + else
410 + error("PLUGINSD: '%s': the value '%s' of VARIABLE '%s' on host '%s' has leftovers: '%s'", cd->fullfilename, value, name, host->hostname, endptr);
411 + }
412
413 if(global) {
414 RRDVAR *rv = rrdvar_custom_host_variable_create(host, name);
@@ -408,8 +416,8 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
416 else error("PLUGINSD: '%s': cannot find/create HOST VARIABLE '%s' on host '%s'", cd->fullfilename, name, host->hostname);
417 }
418 else if(st) {
411 - RRDVAR *rv = rrdvar_custom_chart_variable_create(st, name);
412 - if (rv) rrdvar_custom_chart_variable_set(st, rv, v);
419 + RRDSETVAR *rs = rrdsetvar_custom_chart_variable_create(st, name);
420 + if (rs) rrdsetvar_custom_chart_variable_set(rs, v);
421 else error("PLUGINSD: '%s': cannot find/create CHART VARIABLE '%s' on host '%s', chart '%s'", cd->fullfilename, name, host->hostname, st->id);
422 }
423 else
src/rrdfamily.c
+9 -8
@@ -34,7 +34,7 @@ RRDFAMILY *rrdfamily_create(RRDHOST *host, const char *id) {
34
35 RRDFAMILY *ret = rrdfamily_index_add(host, rc);
36 if(ret != rc)
37 - fatal("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE");
37 + error("RRDFAMILY: INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE");
38 }
39
40 rc->use_count++;
@@ -46,13 +46,14 @@ void rrdfamily_free(RRDHOST *host, RRDFAMILY *rc) {
46 if(!rc->use_count) {
47 RRDFAMILY *ret = rrdfamily_index_del(host, rc);
48 if(ret != rc)
49 - fatal("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE");
50 -
51 - if(rc->rrdvar_root_index.avl_tree.root != NULL)
52 - fatal("RRDFAMILY: INTERNAL ERROR: Variables index of RRDFAMILY '%s' that is freed, is not empty.", rc->family);
53 -
54 - freez((void *)rc->family);
55 - freez(rc);
49 + error("RRDFAMILY: INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE");
50 + else {
51 + debug(D_RRD_CALLS, "RRDFAMILY: Cleaning up remaining family variables for host '%s', family '%s'", host->hostname, rc->family);
52 + rrdvar_free_remaining_variables(host, &rc->rrdvar_root_index);
53 +
54 + freez((void *) rc->family);
55 + freez(rc);
56 + }
57 }
58 }
59
src/rrdhost.c
+1
@@ -496,6 +496,7 @@ void rrdhost_free(RRDHOST *host) {
496 while(host->templates)
497 rrdcalctemplate_unlink_and_free(host, host->templates);
498
499 + debug(D_RRD_CALLS, "RRDHOST: Cleaning up remaining host variables for host '%s'", host->hostname);
500 rrdvar_free_remaining_variables(host, &host->rrdvar_root_index);
501
502 health_alarm_log_free(host);
src/rrdpush.c
+21 -29
@@ -77,35 +77,15 @@ static inline int need_to_send_chart_definition(RRDSET *st) {
77 return 0;
78 }
79
80 -static int rrdpush_sender_add_chart_variable_to_buffer_nolock(void *rrdvar_ptr, void *rrdset_ptr) {
81 - RRDVAR *rv = (RRDVAR *)rrdvar_ptr;
82 -
83 - if(unlikely(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)) {
84 - RRDSET *st = (RRDSET *)rrdset_ptr;
85 -
86 - calculated_number *value = (calculated_number *) rv->value;
87 -
88 - buffer_sprintf(
89 - st->rrdhost->rrdpush_sender_buffer
90 - , "VARIABLE CHART %s = " CALCULATED_NUMBER_FORMAT "\n"
91 - , rv->name
92 - , *value
93 - );
94 -
95 - debug(D_STREAM, "RRDVAR pushed CHART VARIABLE %s = " CALCULATED_NUMBER_FORMAT, rv->name, *value);
96 -
97 - return 1;
98 - }
99 -
100 - return 0;
101 -}
102 -
80 // sends the current chart definition
81 static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
82 + RRDHOST *host = st->rrdhost;
83 +
84 rrdset_flag_set(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
85
86 + // send the chart
87 buffer_sprintf(
108 - st->rrdhost->rrdpush_sender_buffer
88 + host->rrdpush_sender_buffer
89 , "CHART \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %ld %d \"%s %s %s\" \"%s\" \"%s\"\n"
90 , st->id
91 , st->name
@@ -123,10 +103,11 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
103 , (st->module_name)?st->module_name:""
104 );
105
106 + // send the dimensions
107 RRDDIM *rd;
108 rrddim_foreach_read(rd, st) {
109 buffer_sprintf(
129 - st->rrdhost->rrdpush_sender_buffer
110 + host->rrdpush_sender_buffer
111 , "DIMENSION \"%s\" \"%s\" \"%s\" " COLLECTED_NUMBER_FORMAT " " COLLECTED_NUMBER_FORMAT " \"%s %s\"\n"
112 , rd->id
113 , rd->name
@@ -139,11 +120,22 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
120 rd->exposed = 1;
121 }
122
142 - st->upstream_resync_time = st->last_collected_time.tv_sec + (remote_clock_resync_iterations * st->update_every);
143 -
144 - int ret = rrdvar_callback_for_all_chart_variables(st, rrdpush_sender_add_chart_variable_to_buffer_nolock, st);
145 - debug(D_STREAM, "RRDVAR sent %d VARIABLES", ret);
123 + // send the chart local custom variables
124 + RRDSETVAR *rs;
125 + for(rs = st->variables; rs ;rs = rs->next) {
126 + if(unlikely(rs->options && RRDVAR_OPTION_ALLOCATED)) {
127 + calculated_number *value = (calculated_number *) rs->value;
128 +
129 + buffer_sprintf(
130 + host->rrdpush_sender_buffer
131 + , "VARIABLE CHART %s = " CALCULATED_NUMBER_FORMAT "\n"
132 + , rs->variable
133 + , *value
134 + );
135 + }
136 + }
137
138 + st->upstream_resync_time = st->last_collected_time.tv_sec + (remote_clock_resync_iterations * st->update_every);
139 }
140
141 // sends the current chart dimensions
src/rrdset.c
+6 -5
@@ -316,6 +316,7 @@ void rrdset_free(RRDSET *st) {
316
317 rrdfamily_free(st->rrdhost, st->rrdfamily);
318
319 + debug(D_RRD_CALLS, "RRDSET: Cleaning up remaining chart variables for host '%s', chart '%s'", st->rrdhost->hostname, st->id);
320 rrdvar_free_remaining_variables(st->rrdhost, &st->rrdvar_root_index);
321
322 // ------------------------------------------------------------------------
@@ -662,11 +663,11 @@ RRDSET *rrdset_create_custom(
663 host->rrdset_root = st;
664
665 if(host->health_enabled) {
665 - rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT);
666 - rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, RRDVAR_OPTION_DEFAULT);
667 - rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, RRDVAR_OPTION_DEFAULT);
668 - rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, RRDVAR_OPTION_DEFAULT);
669 - rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_OPTION_DEFAULT);
666 + rrdsetvar_create(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_OPTION_DEFAULT);
667 + rrdsetvar_create(st, "collected_total_raw", RRDVAR_TYPE_TOTAL, &st->last_collected_total, RRDVAR_OPTION_DEFAULT);
668 + rrdsetvar_create(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, RRDVAR_OPTION_DEFAULT);
669 + rrdsetvar_create(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, RRDVAR_OPTION_DEFAULT);
670 + rrdsetvar_create(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_OPTION_DEFAULT);
671 }
672
673 if(unlikely(rrdset_index_add(host, st) != st))
src/rrdsetvar.c
+82 -23
@@ -8,29 +8,29 @@
8 static inline void rrdsetvar_free_variables(RRDSETVAR *rs) {
9 RRDSET *st = rs->rrdset;
10
11 + // ------------------------------------------------------------------------
12 // CHART
12 -
13 rrdvar_free(st->rrdhost, &st->rrdvar_root_index, rs->var_local);
14 rs->var_local = NULL;
15
16 + // ------------------------------------------------------------------------
17 // FAMILY
17 -
18 rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family);
19 rs->var_family = NULL;
20
21 - rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host);
22 - rs->var_host = NULL;
23 -
24 - // HOST
25 -
21 rrdvar_free(st->rrdhost, &st->rrdfamily->rrdvar_root_index, rs->var_family_name);
22 rs->var_family_name = NULL;
23
24 + // ------------------------------------------------------------------------
25 + // HOST
26 + rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host);
27 + rs->var_host = NULL;
28 +
29 rrdvar_free(st->rrdhost, &st->rrdhost->rrdvar_root_index, rs->var_host_name);
30 rs->var_host_name = NULL;
31
32 + // ------------------------------------------------------------------------
33 // KEYS
33 -
34 freez(rs->key_fullid);
35 rs->key_fullid = NULL;
36
@@ -39,10 +39,14 @@ static inline void rrdsetvar_free_variables(RRDSETVAR *rs) {
39 }
40
41 static inline void rrdsetvar_create_variables(RRDSETVAR *rs) {
42 - rrdsetvar_free_variables(rs);
43 -
42 RRDSET *st = rs->rrdset;
43
44 + // ------------------------------------------------------------------------
45 + // free the old ones (if any)
46 +
47 + rrdsetvar_free_variables(rs);
48 +
49 + // ------------------------------------------------------------------------
50 // KEYS
51
52 char buffer[RRDVAR_MAX_LENGTH + 1];
@@ -52,20 +56,19 @@ static inline void rrdsetvar_create_variables(RRDSETVAR *rs) {
56 snprintfz(buffer, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rs->variable);
57 rs->key_fullname = strdupz(buffer);
58
59 + // ------------------------------------------------------------------------
60 // CHART
61 + rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, rs->value);
62
57 - rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, rs->value);
58 -
63 + // ------------------------------------------------------------------------
64 // FAMILY
65 + rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
66 + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
67
61 - rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
62 - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
63 -
68 + // ------------------------------------------------------------------------
69 // HOST
65 -
66 - rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
67 - rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
68 -
70 + rs->var_host = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
71 + rs->var_host_name = rrdvar_create_and_index("host", &st->rrdhost->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
72 }
73
74 RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options) {
@@ -73,6 +76,7 @@ RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type,
76 RRDSETVAR *rs = (RRDSETVAR *)callocz(1, sizeof(RRDSETVAR));
77
78 rs->variable = strdupz(variable);
79 + rs->hash = simple_hash(rs->variable);
80 rs->type = type;
81 rs->value = value;
82 rs->options = options;
@@ -89,11 +93,9 @@ RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type,
93 void rrdsetvar_rename_all(RRDSET *st) {
94 debug(D_VARIABLES, "RRDSETVAR rename for chart id '%s' name '%s'", st->id, st->name);
95
92 - RRDSETVAR *rs, *next = st->variables;
93 - while((rs = next)) {
94 - next = rs->next;
96 + RRDSETVAR *rs;
97 + for(rs = st->variables; rs ; rs = rs->next)
98 rrdsetvar_create_variables(rs);
96 - }
99
100 rrdsetcalc_link_matching(st);
101 }
@@ -115,6 +117,63 @@ void rrdsetvar_free(RRDSETVAR *rs) {
117 rrdsetvar_free_variables(rs);
118
119 freez(rs->variable);
120 +
121 + if(rs->options & RRDVAR_OPTION_ALLOCATED)
122 + freez(rs->value);
123 +
124 freez(rs);
125 }
126
127 +// --------------------------------------------------------------------------------------------------------------------
128 +// custom chart variables
129 +
130 +RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name) {
131 + char *n = strdupz(name);
132 + rrdvar_fix_name(n);
133 + uint32_t hash = simple_hash(n);
134 +
135 + rrdset_wrlock(st);
136 +
137 + // find it
138 + RRDSETVAR *rs;
139 + for(rs = st->variables; rs ; rs = rs->next) {
140 + if(hash == rs->hash && strcmp(n, rs->variable) == 0) {
141 + rrdset_unlock(st);
142 + if(rs->options & RRDVAR_OPTION_ALLOCATED) {
143 + free(n);
144 + return rs;
145 + }
146 + else {
147 + error("RRDSETVAR: custom variable '%s' on chart '%s' of host '%s', conflicts with an internal chart variable", n, st->id, st->rrdhost->hostname);
148 + free(n);
149 + return NULL;
150 + }
151 + }
152 + }
153 +
154 + // not found, allocate one
155 +
156 + calculated_number *v = mallocz(sizeof(calculated_number));
157 + *v = NAN;
158 +
159 + rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED);
160 + rrdset_unlock(st);
161 +
162 + free(n);
163 + return rs;
164 +}
165 +
166 +void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, calculated_number value) {
167 + if(unlikely(!(rs->options & RRDVAR_OPTION_ALLOCATED))) {
168 + error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value);
169 + }
170 + else {
171 + calculated_number *v = rs->value;
172 + if(*v != value) {
173 + *v = value;
174 +
175 + // mark the chart to be sent upstream
176 + rrdset_flag_clear(rs->rrdset, RRDSET_FLAG_EXPOSED_UPSTREAM);
177 + }
178 + }
179 +}
src/rrdvar.c
+9 -25
@@ -108,23 +108,25 @@ inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, c
108 void rrdvar_free_remaining_variables(RRDHOST *host, avl_tree_lock *tree_lock) {
109 // FIXME: this is not bullet proof - avl should support some means to destroy it
110 // with a callback for each item already in the index
111 - while(host->rrdvar_root_index.avl_tree.root) {
112 - RRDVAR *rv = (RRDVAR *)tree_lock->avl_tree.root;
111 +
112 + RRDVAR *rv, *last = NULL;
113 + while((rv = (RRDVAR *)tree_lock->avl_tree.root)) {
114 + if(unlikely(rv == last)) {
115 + error("RRDVAR: INTERNAL ERROR: Cannot cleanup tree of RRDVARs");
116 + break;
117 + }
118 + last = rv;
119 rrdvar_free(host, tree_lock, rv);
120 }
121 }
122
123 // ----------------------------------------------------------------------------
118 -// CUSTOM VARIABLES
124 +// CUSTOM HOST VARIABLES
125
126 inline int rrdvar_callback_for_all_host_variables(RRDHOST *host, int (*callback)(void *rrdvar, void *data), void *data) {
127 return avl_traverse_lock(&host->rrdvar_root_index, callback, data);
128 }
129
124 -inline int rrdvar_callback_for_all_chart_variables(RRDSET *st, int (*callback)(void *rrdvar, void *data), void *data) {
125 - return avl_traverse_lock(&st->rrdhost->rrdvar_root_index, callback, data);
126 -}
127 -
130 static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *tree_lock, const char *name) {
131 calculated_number *v = callocz(1, sizeof(calculated_number));
132 *v = NAN;
@@ -150,10 +152,6 @@ RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) {
152 return rrdvar_custom_variable_create("host", &host->rrdvar_root_index, name);
153 }
154
153 -RRDVAR *rrdvar_custom_chart_variable_create(RRDSET *st, const char *name) {
154 - return rrdvar_custom_variable_create("local", &st->rrdvar_root_index, name);
155 -}
156 -
155 void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value) {
156 if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED)
157 error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value);
@@ -168,20 +166,6 @@ void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_numbe
166 }
167 }
168
171 -void rrdvar_custom_chart_variable_set(RRDSET *st, RRDVAR *rv, calculated_number value) {
172 - if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED)
173 - error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value);
174 - else {
175 - calculated_number *v = rv->value;
176 - if(*v != value) {
177 - *v = value;
178 -
179 - // mark the chart to be sent upstream
180 - rrdset_flag_clear(st, RRDSET_FLAG_EXPOSED_UPSTREAM);
181 - }
182 - }
183 -}
184 -
169 // ----------------------------------------------------------------------------
170 // RRDVAR lookup
171