@cryptotaxi247 / netdata-1 / commits / dd4b84630

chart and dimensions variables linked to 3 indexes: local, context and host variables

Costa Tsaousis committed Aug 7, 2016 at 14:59 UTC dd4b84630650c98211f2289e369c65aff1a3ce3f
5 files changed +513 -34
src/health.c
+382 -26
@@ -1,15 +1,31 @@
1 #include "common.h"
2
3 +// ----------------------------------------------------------------------------
4 +// RRDVAR management
5 +
6 int rrdvar_compare(void* a, void* b) {
7 if(((RRDVAR *)a)->hash < ((RRDVAR *)b)->hash) return -1;
8 else if(((RRDVAR *)a)->hash > ((RRDVAR *)b)->hash) return 1;
9 else return strcmp(((RRDVAR *)a)->name, ((RRDVAR *)b)->name);
10 }
11
9 -#define rrdvar_index_add(tree, rv) (RRDVAR *)avl_insert_lock(tree, (avl *)(rv))
10 -#define rrdvar_index_del(tree, rv) (RRDVAR *)avl_remove_lock(tree, (avl *)(rv))
12 +static inline RRDVAR *rrdvar_index_add(avl_tree_lock *tree, RRDVAR *rv) {
13 + RRDVAR *ret = (RRDVAR *)avl_insert_lock(tree, (avl *)(rv));
14 + if(ret != rv)
15 + debug(D_VARIABLES, "Request to insert RRDVAR '%s' into index failed. Already exists.", rv->name);
16 +
17 + return ret;
18 +}
19 +
20 +static inline RRDVAR *rrdvar_index_del(avl_tree_lock *tree, RRDVAR *rv) {
21 + RRDVAR *ret = (RRDVAR *)avl_remove_lock(tree, (avl *)(rv));
22 + if(!ret)
23 + fatal("Request to remove RRDVAR '%s' from index failed. Not Found.", rv->name);
24 +
25 + return ret;
26 +}
27
12 -static RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) {
28 +static inline RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) {
29 RRDVAR tmp;
30 tmp.name = (char *)name;
31 tmp.hash = (hash)?hash:simple_hash(tmp.name);
@@ -17,37 +33,377 @@ static RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t
33 return (RRDVAR *)avl_search_lock(tree, (avl *)&tmp);
34 }
35
36 +static inline RRDVAR *rrdvar_create(const char *name, uint32_t hash, int type, calculated_number *value) {
37 + RRDVAR *rv = calloc(1, sizeof(RRDVAR));
38 + if(!rv) fatal("Cannot allocate memory for RRDVAR");
39
21 -RRDVAR *rrdvar_get(RRDHOST *host, RRDCONTEXT *co, RRDSET *st, const char *name) {
22 - uint32_t hash = simple_hash(name);
40 + rv->name = (char *)name;
41 + rv->hash = (hash)?hash:simple_hash((rv->name));
42 + rv->type = type;
43 + rv->value = value;
44
24 - RRDVAR *ret = NULL;
25 - RRDVAR *rv = rrdvar_index_find(&st->variables_root_index, name, hash);
26 - if(!rv) {
27 - rv = calloc(1, sizeof(RRDVAR));
28 - if(!rv) fatal("Cannot allocate memory for RRDVAR");
45 + return rv;
46 +}
47
30 - rv->name = strdup(name);
31 - if(!rv->name) fatal("Cannot allocate memory for RRDVAR name");
48 +static inline void rrdvar_free(RRDVAR *rv) {
49 + free(rv);
50 +}
51
33 - rv->hash = hash;
52 +static inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, uint32_t hash, int type, calculated_number *value) {
53 + RRDVAR *rv = rrdvar_index_find(tree, name, hash);
54 + if(unlikely(!rv)) {
55 + debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", name, scope);
56
35 - ret = rrdvar_index_add(&st->variables_root_index, rv);
36 - if(ret != rv) {
37 - error("Duplicate RRDVAR '%s' found on chart '%s'", name, st->id);
38 - free(rv->name);
39 - free(rv);
40 - rv = ret;
57 + rv = rrdvar_create(name, hash, type, value);
58 + RRDVAR *ret = rrdvar_index_add(tree, rv);
59 + if(unlikely(ret != rv)) {
60 + debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", name, scope);
61 + rrdvar_free(rv);
62 + rv = NULL;
63 }
64 + else
65 + debug(D_VARIABLES, "Variable '%s' created in scope '%s'", name, scope);
66 + }
67 +
68 + return rv;
69 +}
70 +
71 +// ----------------------------------------------------------------------------
72 +// RRDSETVAR management
73 +
74 +#define RRDSETVAR_ID_MAX 1024
75 +
76 +RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) {
77 + RRDSETVAR *rs = (RRDSETVAR *)calloc(1, sizeof(RRDSETVAR));
78 + if(!rs) fatal("Cannot allocate memory for RRDSETVAR");
79 +
80 + char buffer[RRDSETVAR_ID_MAX + 1];
81 + snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->id, variable);
82 + rs->fullid = strdup(buffer);
83 + if(!rs->fullid) fatal("Cannot allocate memory for RRDVASET id");
84 + rs->hash_fullid = simple_hash(rs->fullid);
85 +
86 + snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->name, variable);
87 + rs->fullname = strdup(buffer);
88 + if(!rs->fullname) fatal("Cannot allocate memory for RRDVASET name");
89 + rs->hash_fullname = simple_hash(rs->fullname);
90 +
91 + rs->variable = strdup(variable);
92 + if(!rs->variable) fatal("Cannot allocate memory for RRDVASET variable name");
93 + rs->hash_variable = simple_hash(rs->variable);
94 +
95 + rs->type = type;
96 + rs->value = value;
97 + rs->options = options;
98 +
99 + rs->local = rrdvar_create_and_index("local", &st->variables_root_index, rs->variable, rs->hash_variable, rs->type, rs->value);
100 + rs->context = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullid, rs->hash_fullid, rs->type, rs->value);
101 + rs->host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullid, rs->hash_fullid, rs->type, rs->value);
102 + rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
103 + rs->host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
104 +
105 + rs->next = st->variables;
106 + st->variables = rs;
107 +
108 + return rs;
109 +}
110
43 - ret = rrdvar_index_add(&co->variables_root_index, rv);
44 - if(ret != rv)
45 - debug(D_VARIABLES, "Variable '%s' in context '%s' does not come from chart '%s'", name, co->id, st->id);
111 +void rrdsetvar_rename_all(RRDSET *st) {
112 + // only these 2 can change name
113 + // rs->context_name
114 + // rs->host_name
115
47 - ret = rrdvar_index_add(&host->variables_root_index, rv);
48 - if(ret != rv)
49 - debug(D_VARIABLES, "Variable '%s' in host '%s' does not come from chart '%s'", name, host->hostname, st->id);
116 + char buffer[RRDSETVAR_ID_MAX + 1];
117 + RRDSETVAR *rs, *next = st->variables;
118 + while((rs = next)) {
119 + next = rs->next;
120 +
121 + snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->variable);
122 +
123 + if (strcmp(buffer, rs->fullname)) {
124 + // name changed
125 + if (rs->context_name) {
126 + rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_name);
127 + rrdvar_free(rs->context_name);
128 + }
129 +
130 + if (rs->host_name) {
131 + rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host_name);
132 + rrdvar_free(rs->host_name);
133 + }
134 +
135 + free(rs->fullname);
136 + rs->fullname = strdup(st->name);
137 + if(!rs->fullname) fatal("Cannot allocate memory for RRDSETVAR name");
138 + rs->hash_fullname = simple_hash(rs->fullname);
139 + rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
140 + rs->host_name = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
141 + }
142 + }
143 +}
144 +
145 +void rrdsetvar_free(RRDSETVAR *rs) {
146 + RRDSET *st = rs->rrdset;
147 +
148 + if(rs->local) {
149 + rrdvar_index_del(&st->variables_root_index, rs->local);
150 + rrdvar_free(rs->local);
151 }
152
52 - return rv;
153 + if(rs->context) {
154 + rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context);
155 + rrdvar_free(rs->context);
156 + }
157 +
158 + if(rs->host) {
159 + rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host);
160 + rrdvar_free(rs->host);
161 + }
162 +
163 + if(rs->context_name) {
164 + rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_name);
165 + rrdvar_free(rs->context_name);
166 + }
167 +
168 + if(rs->host_name) {
169 + rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host_name);
170 + rrdvar_free(rs->host_name);
171 + }
172 +
173 + if(st->variables == rs) {
174 + st->variables = rs->next;
175 + }
176 + else {
177 + RRDSETVAR *t;
178 + for (t = st->variables; t && t->next != rs; t = t->next);
179 + if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->fullname, st->id);
180 + else t->next = rs->next;
181 + }
182 +
183 + free(rs->fullid);
184 + free(rs->fullname);
185 + free(rs->variable);
186 + free(rs);
187 +}
188 +
189 +// ----------------------------------------------------------------------------
190 +// RRDDIMVAR management
191 +
192 +#define RRDDIMVAR_ID_MAX 1024
193 +
194 +RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) {
195 + RRDSET *st = rd->rrdset;
196 +
197 + if(!prefix) prefix = "";
198 + if(!suffix) suffix = "";
199 +
200 + char buffer[RRDDIMVAR_ID_MAX + 1];
201 + RRDDIMVAR *rs = (RRDDIMVAR *)calloc(1, sizeof(RRDDIMVAR));
202 + if(!rs) fatal("Cannot allocate memory for RRDDIMVAR");
203 +
204 + rs->prefix = strdup(prefix);
205 + if(!rs->prefix) fatal("Cannot allocate memory for RRDDIMVAR prefix");
206 +
207 + rs->suffix = strdup(suffix);
208 + if(!rs->suffix) fatal("Cannot allocate memory for RRDDIMVAR suffix");
209 +
210 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->id, rs->suffix);
211 + rs->id = strdup(buffer);
212 + if(!rs->id) fatal("Cannot allocate memory for RRDIM id");
213 + rs->hash = simple_hash(rs->id);
214 +
215 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix);
216 + rs->name = strdup(buffer);
217 + if(!rs->name) fatal("Cannot allocate memory for RRDIM name");
218 + rs->hash_name = simple_hash(rs->name);
219 +
220 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->id, rs->id);
221 + rs->fullidid = strdup(buffer);
222 + if(!rs->fullidid) fatal("Cannot allocate memory for RRDDIMVAR fullidid");
223 + rs->hash_fullidid = simple_hash(rs->fullidid);
224 +
225 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->id, rs->name);
226 + rs->fullidname = strdup(buffer);
227 + if(!rs->fullidname) fatal("Cannot allocate memory for RRDDIMVAR fullidname");
228 + rs->hash_fullidname = simple_hash(rs->fullidname);
229 +
230 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->name, rs->id);
231 + rs->fullnameid = strdup(buffer);
232 + if(!rs->fullnameid) fatal("Cannot allocate memory for RRDDIMVAR fullnameid");
233 + rs->hash_fullnameid = simple_hash(rs->fullnameid);
234 +
235 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->name, rs->name);
236 + rs->fullnamename = strdup(buffer);
237 + if(!rs->fullnamename) fatal("Cannot allocate memory for RRDDIMVAR fullnamename");
238 + rs->hash_fullnamename = simple_hash(rs->fullnamename);
239 +
240 + rs->type = type;
241 + rs->value = value;
242 + rs->options = options;
243 +
244 + rs->local_id = rrdvar_create_and_index("local", &st->variables_root_index, rs->id, rs->hash, rs->type, rs->value);
245 + rs->local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->name, rs->hash_name, rs->type, rs->value);
246 +
247 + rs->context_fullidid = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullidid, rs->hash_fullidid, rs->type, rs->value);
248 + rs->context_fullidname = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
249 + rs->context_fullnameid = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
250 + rs->context_fullnamename = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
251 +
252 + rs->host_fullidid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidid, rs->hash_fullidid, rs->type, rs->value);
253 + rs->host_fullidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
254 + rs->host_fullnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
255 + rs->host_fullnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
256 +
257 + rs->next = rd->variables;
258 + rd->variables = rs;
259 +
260 + return rs;
261 +}
262 +
263 +void rrddimvar_rename_all(RRDDIM *rd) {
264 + RRDSET *st = rd->rrdset;
265 +
266 + RRDDIMVAR *rs, *next = rd->variables;
267 + while((rs = next)) {
268 + next = rs->next;
269 +
270 + if (strcmp(rd->name, rs->name)) {
271 + char buffer[RRDDIMVAR_ID_MAX + 1];
272 + // name changed
273 +
274 + // name
275 + if (rs->local_name) {
276 + rrdvar_index_del(&st->variables_root_index, rs->local_name);
277 + rrdvar_free(rs->local_name);
278 + }
279 + free(rs->name);
280 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix);
281 + rs->name = strdup(buffer);
282 + if(!rs->name) fatal("Cannot allocate memory for RRDDIMVAR name");
283 + rs->hash_name = simple_hash(rs->name);
284 + rs->local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->name, rs->hash_name, rs->type, rs->value);
285 +
286 + // fullidname
287 + if (rs->context_fullidname) {
288 + rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullidname);
289 + rrdvar_free(rs->context_fullidname);
290 + }
291 + if (rs->host_fullidname) {
292 + rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullidname);
293 + rrdvar_free(rs->host_fullidname);
294 + }
295 + free(rs->fullidname);
296 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", st->type, st->id, rs->name);
297 + rs->fullidname = strdup(buffer);
298 + if(!rs->fullidname) fatal("Cannot allocate memory for RRDDIMVAR fullidname");
299 + rs->hash_fullidname = simple_hash(rs->fullidname);
300 + rs->context_fullidname = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index,
301 + rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
302 + rs->host_fullidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index,
303 + rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
304 +
305 + // fullnameid
306 + if (rs->context_fullnameid) {
307 + rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullnameid);
308 + rrdvar_free(rs->context_fullnameid);
309 + }
310 + if (rs->host_fullnameid) {
311 + rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullnameid);
312 + rrdvar_free(rs->host_fullnameid);
313 + }
314 + free(rs->fullnameid);
315 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->id);
316 + rs->fullnameid = strdup(buffer);
317 + if(!rs->fullnameid) fatal("Cannot allocate memory for RRDDIMVAR fullnameid");
318 + rs->hash_fullnameid = simple_hash(rs->fullnameid);
319 + rs->context_fullnameid = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index,
320 + rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
321 + rs->host_fullnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index,
322 + rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
323 +
324 + // fullnamename
325 + if (rs->context_fullnamename) {
326 + rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullnamename);
327 + rrdvar_free(rs->context_fullnamename);
328 + }
329 + if (rs->host_fullnamename) {
330 + rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullnamename);
331 + rrdvar_free(rs->host_fullnamename);
332 + }
333 + free(rs->fullnamename);
334 + snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->name);
335 + rs->fullnamename = strdup(buffer);
336 + if(!rs->fullnamename) fatal("Cannot allocate memory for RRDDIMVAR fullnamename");
337 + rs->hash_fullnamename = simple_hash(rs->fullnamename);
338 + rs->context_fullnamename = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index,
339 + rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
340 + rs->host_fullnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index,
341 + rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
342 + }
343 + }
344 +}
345 +
346 +void rrddimvar_free(RRDDIMVAR *rs) {
347 + if(rs->local_id) {
348 + rrdvar_index_del(&rs->rrddim->rrdset->variables_root_index, rs->local_id);
349 + rrdvar_free(rs->local_id);
350 + }
351 + if(rs->local_name) {
352 + rrdvar_index_del(&rs->rrddim->rrdset->variables_root_index, rs->local_name);
353 + rrdvar_free(rs->local_name);
354 + }
355 +
356 + if(rs->context_fullidid) {
357 + rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullidid);
358 + rrdvar_free(rs->context_fullidid);
359 + }
360 + if(rs->context_fullidname) {
361 + rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullidname);
362 + rrdvar_free(rs->context_fullidname);
363 + }
364 + if(rs->context_fullnameid) {
365 + rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullnameid);
366 + rrdvar_free(rs->context_fullnameid);
367 + }
368 + if(rs->context_fullnamename) {
369 + rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullnamename);
370 + rrdvar_free(rs->context_fullnamename);
371 + }
372 +
373 + if(rs->host_fullidid) {
374 + rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullidid);
375 + rrdvar_free(rs->host_fullidid);
376 + }
377 + if(rs->host_fullidname) {
378 + rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullidname);
379 + rrdvar_free(rs->host_fullidname);
380 + }
381 + if(rs->host_fullnameid) {
382 + rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullnameid);
383 + rrdvar_free(rs->host_fullnameid);
384 + }
385 + if(rs->host_fullnamename) {
386 + rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullnamename);
387 + rrdvar_free(rs->host_fullnamename);
388 + }
389 +
390 + if(rs->rrddim->variables == rs) {
391 + rs->rrddim->variables = rs->next;
392 + }
393 + else {
394 + RRDDIMVAR *t;
395 + for (t = rs->rrddim->variables; t && t->next != rs; t = t->next);
396 + if(!t) error("RRDDIMVAR '%s' not found in dimension '%s.%s/%s' variables linked list", rs->name, rs->rrddim->rrdset->type, rs->rrddim->rrdset->id, rs->rrddim->id);
397 + else t->next = rs->next;
398 + }
399 +
400 + free(rs->prefix);
401 + free(rs->suffix);
402 + free(rs->id);
403 + free(rs->name);
404 + free(rs->fullidid);
405 + free(rs->fullidname);
406 + free(rs->fullnameid);
407 + free(rs->fullnamename);
408 + free(rs);
409 }
src/health.h
+92 -1
@@ -25,17 +25,98 @@ extern int rrdvar_compare(void *a, void *b);
25 *
26 */
27
28 +#define RRDVAR_TYPE_CALCULATED 1
29 +#define RRDVAR_TYPE_TIME_T 2
30 +#define RRDVAR_TYPE_COLLECTED 3
31 +#define RRDVAR_TYPE_TOTAL 4
32 +
33 +// the variables as stored in the variables indexes
34 typedef struct rrdvar {
35 avl avl;
36
37 char *name;
38 uint32_t hash;
39
34 - calculated_number *value;
40 + int type;
41 + void *value;
42
43 time_t last_updated;
44 } RRDVAR;
45
46 +// variables linked to charts
47 +typedef struct rrdsetvar {
48 + char *fullid; // chart type.chart id.variable
49 + uint32_t hash_fullid;
50 +
51 + char *fullname; // chart type.chart name.variable
52 + uint32_t hash_fullname;
53 +
54 + char *variable; // variable
55 + uint32_t hash_variable;
56 +
57 + int type;
58 + void *value;
59 +
60 + uint32_t options;
61 +
62 + RRDVAR *local;
63 + RRDVAR *context;
64 + RRDVAR *host;
65 + RRDVAR *context_name;
66 + RRDVAR *host_name;
67 +
68 + struct rrdset *rrdset;
69 +
70 + struct rrdsetvar *next;
71 +} RRDSETVAR;
72 +
73 +
74 +// variables linked to dimensions
75 +typedef struct rrddimvar {
76 + char *prefix;
77 + char *suffix;
78 +
79 + char *id; // dimension id
80 + uint32_t hash;
81 +
82 + char *name; // dimension name
83 + uint32_t hash_name;
84 +
85 + char *fullidid; // chart type.chart id.dimension id
86 + uint32_t hash_fullidid;
87 +
88 + char *fullidname; // chart type.chart id.dimension name
89 + uint32_t hash_fullidname;
90 +
91 + char *fullnameid; // chart type.chart name.dimension id
92 + uint32_t hash_fullnameid;
93 +
94 + char *fullnamename; // chart type.chart name.dimension name
95 + uint32_t hash_fullnamename;
96 +
97 + int type;
98 + void *value;
99 +
100 + uint32_t options;
101 +
102 + RRDVAR *local_id;
103 + RRDVAR *local_name;
104 +
105 + RRDVAR *context_fullidid;
106 + RRDVAR *context_fullidname;
107 + RRDVAR *context_fullnameid;
108 + RRDVAR *context_fullnamename;
109 +
110 + RRDVAR *host_fullidid;
111 + RRDVAR *host_fullidname;
112 + RRDVAR *host_fullnameid;
113 + RRDVAR *host_fullnamename;
114 +
115 + struct rrddim *rrddim;
116 +
117 + struct rrddimvar *next;
118 +} RRDDIMVAR;
119 +
120 typedef struct rrdcalc {
121 avl avl;
122
@@ -55,4 +136,14 @@ typedef struct rrdcalc {
136 struct rrdcalc *prev;
137 } RRDCALC;
138
139 +#include "rrd.h"
140 +
141 +extern void rrdsetvar_rename_all(RRDSET *st);
142 +extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options);
143 +extern void rrdsetvar_free(RRDSETVAR *rs);
144 +
145 +extern void rrddimvar_rename_all(RRDDIM *rd);
146 +extern RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options);
147 +extern void rrddimvar_free(RRDDIMVAR *rs);
148 +
149 #endif //NETDATA_HEALTH_H
src/rrd.c
+29 -5
@@ -313,7 +313,10 @@ void rrdset_set_name(RRDSET *st, const char *name)
313 {
314 debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name);
315
316 - if(st->name) rrdset_index_del_name(&localhost, st);
316 + if(st->name) {
317 + rrdset_index_del_name(&localhost, st);
318 + rrdsetvar_rename_all(st);
319 + }
320
321 char b[CONFIG_MAX_VALUE + 1];
322 char n[RRD_ID_LENGTH_MAX + 1];
@@ -459,6 +462,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
462 st->dimensions = NULL;
463 st->next = NULL;
464 st->mapped = rrd_memory_mode;
465 + st->variables = NULL;
466 }
467 else {
468 st = calloc(1, size);
@@ -516,12 +520,16 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
520 st->title = config_get(st->id, "title", varvalue);
521 }
522
519 - st->next = localhost.rrdset_root;
523 + st->rrdcontext = rrdcontext_create(st->context);
524 + st->rrdhost = &localhost;
525 +
526 + st->next = localhost.rrdset_root;
527 localhost.rrdset_root = st;
528
522 - rrdset_index_add(&localhost, st);
529 + rrdsetvar_create(st, "last_collected", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, 0);
530 + rrdsetvar_create(st, "raw_total", RRDVAR_TYPE_TOTAL, &st->collected_total, 0);
531
524 - st->rrdcontext = rrdcontext_create(st->context);
532 + rrdset_index_add(&localhost, st);
533
534 pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
535
@@ -594,6 +602,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
602 // we have a file mapped for rd
603 rd->mapped = rrd_memory_mode;
604 rd->flags = 0x00000000;
605 + rd->variables = NULL;
606 rd->next = NULL;
607 rd->name = NULL;
608 }
@@ -610,6 +619,8 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
619 }
620 rd->memsize = size;
621
622 + rd->rrdset = st;
623 +
624 strcpy(rd->magic, RRDDIMENSION_MAGIC);
625 strcpy(rd->cache_filename, fullfilename);
626 strncpyz(rd->id, id, RRD_ID_LENGTH_MAX);
@@ -653,6 +664,11 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
664 for(; td->next; td = td->next) ;
665 td->next = rd;
666 }
667 +
668 + rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->calculated_value, 0);
669 + rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->collected_value, 0);
670 + rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected", &rd->last_collected_time.tv_sec, 0);
671 +
672 pthread_rwlock_unlock(&st->rwlock);
673
674 rrddim_index_add(st, rd);
@@ -667,6 +683,8 @@ void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name)
683 char varname[CONFIG_MAX_NAME + 1];
684 snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
685 config_set_default(st->id, varname, name);
686 +
687 + rrddimvar_rename_all(rd);
688 }
689
690 void rrddim_free(RRDSET *st, RRDDIM *rd)
@@ -685,7 +703,10 @@ void rrddim_free(RRDSET *st, RRDDIM *rd)
703 else st->dimensions = rd->next;
704 rd->next = NULL;
705
688 - rrddim_index_del(st, rd);
706 + while(rd->variables)
707 + rrddimvar_free(rd->variables);
708 +
709 + rrddim_index_del(st, rd);
710
711 // free(rd->annotations);
712 if(rd->mapped == RRD_MEMORY_MODE_SAVE) {
@@ -716,6 +737,9 @@ void rrdset_free_all(void)
737 while(st->dimensions)
738 rrddim_free(st, st->dimensions);
739
740 + while(st->variables)
741 + rrdsetvar_free(st->variables);
742 +
743 rrdset_index_del(&localhost, st);
744
745 st->rrdcontext->use_count--;
src/rrd.h
+7 -1
@@ -16,7 +16,7 @@ extern int rrd_delete_unupdated_dimensions;
16 #define RRD_ID_LENGTH_MAX 1024
17
18 #define RRDSET_MAGIC "NETDATA RRD SET FILE V018"
19 -#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V017"
19 +#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V018"
20
21 typedef long long total_number;
22 #define TOTAL_NUMBER_FORMAT "%lld"
@@ -150,6 +150,7 @@ struct rrddim {
150 calculated_number stored_volume; // the sum of all stored values so far
151
152 struct rrddim *next; // linking of dimensions within the same data set
153 + struct rrdset *rrdset;
154
155 // ------------------------------------------------------------------------
156 // members for checking the data when loading from disk
@@ -164,6 +165,8 @@ struct rrddim {
165
166 char magic[sizeof(RRDDIMENSION_MAGIC) + 1]; // a string to be saved, used to identify our data file
167
168 + struct rrddimvar *variables;
169 +
170 // ------------------------------------------------------------------------
171 // the values stored in this dimension, using our floating point numbers
172
@@ -246,6 +249,8 @@ struct rrdset {
249 total_number last_collected_total; // used internally to calculate percentages
250
251 RRDCONTEXT *rrdcontext;
252 + struct rrdhost *rrdhost;
253 +
254 struct rrdset *next; // linking of rrdsets
255
256 // ------------------------------------------------------------------------
@@ -265,6 +270,7 @@ struct rrdset {
270 // local variables
271
272 avl_tree_lock variables_root_index;
273 + RRDSETVAR *variables;
274 };
275 typedef struct rrdset RRDSET;
276
src/web_server.c
+3 -1
@@ -195,7 +195,7 @@ static inline void close_listen_sockets(void) {
195 static inline int bind_to_one(const char *definition, int default_port, int listen_backlog) {
196 int added = 0;
197 struct addrinfo hints;
198 - struct addrinfo *result, *rp;
198 + struct addrinfo *result = NULL, *rp = NULL;
199
200 char buffer[strlen(definition) + 1];
201 strcpy(buffer, definition);
@@ -275,6 +275,8 @@ static inline int bind_to_one(const char *definition, int default_port, int list
275 }
276 }
277
278 + freeaddrinfo(result);
279 +
280 return added;
281 }
282