3 // ----------------------------------------------------------------------------
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);
12 static inline RRDVAR *rrdvar_index_add(avl_tree_lock *tree, RRDVAR *rv) {
13 RRDVAR *ret = (RRDVAR *)avl_insert_lock(tree, (avl *)(rv));
15 debug(D_VARIABLES, "Request to insert RRDVAR '%s' into index failed. Already exists.", rv->name);
20 static inline RRDVAR *rrdvar_index_del(avl_tree_lock *tree, RRDVAR *rv) {
21 RRDVAR *ret = (RRDVAR *)avl_remove_lock(tree, (avl *)(rv));
23 fatal("Request to remove RRDVAR '%s' from index failed. Not Found.", rv->name);
28 static inline RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) {
30 tmp.name = (char *)name;
31 tmp.hash = (hash)?hash:simple_hash(tmp.name);
33 return (RRDVAR *)avl_search_lock(tree, (avl *)&tmp);
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");
40 rv->name = (char *)name;
41 rv->hash = (hash)?hash:simple_hash((rv->name));
48 static inline void rrdvar_free(RRDVAR *rv) {
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);
55 debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", name, scope);
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);
65 debug(D_VARIABLES, "Variable '%s' created in scope '%s'", name, scope);
71 // ----------------------------------------------------------------------------
72 // RRDSETVAR management
74 #define RRDSETVAR_ID_MAX 1024
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");
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);
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);
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);
97 rs->options = options;
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);
105 rs->next = st->variables;
111 void rrdsetvar_rename_all(RRDSET *st) {
112 // only these 2 can change name
116 char buffer[RRDSETVAR_ID_MAX + 1];
117 RRDSETVAR *rs, *next = st->variables;
121 snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->variable);
123 if (strcmp(buffer, rs->fullname)) {
125 if (rs->context_name) {
126 rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_name);
127 rrdvar_free(rs->context_name);
131 rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host_name);
132 rrdvar_free(rs->host_name);
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);
145 void rrdsetvar_free(RRDSETVAR *rs) {
146 RRDSET *st = rs->rrdset;
149 rrdvar_index_del(&st->variables_root_index, rs->local);
150 rrdvar_free(rs->local);
154 rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context);
155 rrdvar_free(rs->context);
159 rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host);
160 rrdvar_free(rs->host);
163 if(rs->context_name) {
164 rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_name);
165 rrdvar_free(rs->context_name);
169 rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host_name);
170 rrdvar_free(rs->host_name);
173 if(st->variables == rs) {
174 st->variables = rs->next;
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;
189 // ----------------------------------------------------------------------------
190 // RRDDIMVAR management
192 #define RRDDIMVAR_ID_MAX 1024
194 RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) {
195 RRDSET *st = rd->rrdset;
197 if(!prefix) prefix = "";
198 if(!suffix) suffix = "";
200 char buffer[RRDDIMVAR_ID_MAX + 1];
201 RRDDIMVAR *rs = (RRDDIMVAR *)calloc(1, sizeof(RRDDIMVAR));
202 if(!rs) fatal("Cannot allocate memory for RRDDIMVAR");
204 rs->prefix = strdup(prefix);
205 if(!rs->prefix) fatal("Cannot allocate memory for RRDDIMVAR prefix");
207 rs->suffix = strdup(suffix);
208 if(!rs->suffix) fatal("Cannot allocate memory for RRDDIMVAR suffix");
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);
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);
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);
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);
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);
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);
242 rs->options = options;
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);
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);
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);
257 rs->next = rd->variables;
263 void rrddimvar_rename_all(RRDDIM *rd) {
264 RRDSET *st = rd->rrdset;
266 RRDDIMVAR *rs, *next = rd->variables;
270 if (strcmp(rd->name, rs->name)) {
271 char buffer[RRDDIMVAR_ID_MAX + 1];
275 if (rs->local_name) {
276 rrdvar_index_del(&st->variables_root_index, rs->local_name);
277 rrdvar_free(rs->local_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);
287 if (rs->context_fullidname) {
288 rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullidname);
289 rrdvar_free(rs->context_fullidname);
291 if (rs->host_fullidname) {
292 rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullidname);
293 rrdvar_free(rs->host_fullidname);
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);
306 if (rs->context_fullnameid) {
307 rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullnameid);
308 rrdvar_free(rs->context_fullnameid);
310 if (rs->host_fullnameid) {
311 rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullnameid);
312 rrdvar_free(rs->host_fullnameid);
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);
325 if (rs->context_fullnamename) {
326 rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullnamename);
327 rrdvar_free(rs->context_fullnamename);
329 if (rs->host_fullnamename) {
330 rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullnamename);
331 rrdvar_free(rs->host_fullnamename);
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);
346 void rrddimvar_free(RRDDIMVAR *rs) {
348 rrdvar_index_del(&rs->rrddim->rrdset->variables_root_index, rs->local_id);
349 rrdvar_free(rs->local_id);
352 rrdvar_index_del(&rs->rrddim->rrdset->variables_root_index, rs->local_name);
353 rrdvar_free(rs->local_name);
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);
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);
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);
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);
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);
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);
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);
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);
390 if(rs->rrddim->variables == rs) {
391 rs->rrddim->variables = rs->next;
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;
405 free(rs->fullidname);
406 free(rs->fullnameid);
407 free(rs->fullnamename);