]> arthur.barton.de Git - netdata.git/blob - src/health.c
chart and dimensions variables linked to 3 indexes: local, context and host variables
[netdata.git] / src / health.c
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
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
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);
32
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
40     rv->name = (char *)name;
41     rv->hash = (hash)?hash:simple_hash((rv->name));
42     rv->type = type;
43     rv->value = value;
44
45     return rv;
46 }
47
48 static inline void rrdvar_free(RRDVAR *rv) {
49     free(rv);
50 }
51
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
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
111 void rrdsetvar_rename_all(RRDSET *st) {
112     // only these 2 can change name
113     // rs->context_name
114     // rs->host_name
115
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
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 }