RRDCALC management completed
Costa Tsaousis committed
Aug 12, 2016 at 14:04 UTC
f3ce8bcde83d2e2fc9c22ab7e49ddf0fb7c0c396
4 files changed
+99
-16
src/health.c
+61
-10
@@ -47,7 +47,6 @@ static inline RRDVAR *rrdvar_create(const char *name, uint32_t hash, int type, c
47
static inline void rrdvar_free(RRDHOST *host, RRDVAR *rv) {
48
if(host) {
49
// FIXME: we may need some kind of locking here
50
- // to have mutually exclusive access with eval()
50
EVAL_VARIABLE *rf;
51
for (rf = host->references; rf; rf = rf->next)
52
if (rf->rrdvar == rv) rf->rrdvar = NULL;
@@ -436,7 +435,9 @@ void rrddimvar_free(RRDDIMVAR *rs) {
435
436
// this has to be called while the caller has locked
437
// the RRDHOST
439
-static inline void rrdhostcalc_linked(RRDHOST *host, RRDCALC *rc) {
438
+static inline void rrdset_linked_optimize_rrdhost(RRDHOST *host, RRDCALC *rc) {
439
+ rrdhost_check_wrlock(host);
440
+
441
// move it to be last
442
443
if(!rc->next)
@@ -474,7 +475,9 @@ static inline void rrdhostcalc_linked(RRDHOST *host, RRDCALC *rc) {
475
476
// this has to be called while the caller has locked
477
// the RRDHOST
477
-static inline void rrdhostcalc_unlinked(RRDHOST *host, RRDCALC *rc) {
478
+static inline void rrdcalc_unlinked_optimize_rrdhost(RRDHOST *host, RRDCALC *rc) {
479
+ rrdhost_check_wrlock(host);
480
+
481
// move it to be first
482
483
if(host->calculations == rc) {
@@ -502,7 +505,15 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
505
rc->context = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rc->name, rc->hash, RRDVAR_TYPE_CALCULATED, &rc->value);
506
rc->host = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rc->name, rc->hash, RRDVAR_TYPE_CALCULATED, &rc->value);
507
505
- rrdhostcalc_linked(st->rrdhost, rc);
508
+ rrdset_linked_optimize_rrdhost(st->rrdhost, rc);
509
+}
510
+
511
+static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) {
512
+ if((rc->hash_chart == st->hash && !strcmp(rc->name, st->id)) ||
513
+ (rc->hash_chart == st->hash_name && !strcmp(rc->name, st->name)))
514
+ return 1;
515
+
516
+ return 0;
517
}
518
519
// this has to be called while the RRDHOST is locked
@@ -514,10 +525,8 @@ void rrdsetcalc_link_matching(RRDSET *st) {
525
// we stop on the first linked RRDCALC
526
if(rc->rrdset != NULL) break;
527
517
- if((rc->hash_chart == st->hash && !strcmp(rc->name, st->id)) ||
518
- (rc->hash_chart == st->hash_name && !strcmp(rc->name, st->name))) {
528
+ if(rrdcalc_is_matching_this_rrdset(rc, st))
529
rrdsetcalc_link(st, rc);
520
- }
530
}
531
}
532
@@ -566,7 +575,7 @@ void rrdsetcalc_unlink(RRDCALC *rc) {
575
// so that if the matching chart is found in the future
576
// it will be applied automatically
577
569
- rrdhostcalc_unlinked(host, rc);
578
+ rrdcalc_unlinked_optimize_rrdhost(host, rc);
579
}
580
581
RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const char *chart, const char *dimensions, int group_method, uint32_t after, uint32_t before, int update_every, uint32_t options) {
@@ -595,13 +604,55 @@ RRDCALC *rrdcalc_create(RRDHOST *host, const char *name, const char *chart, cons
604
rc->hash_chart = simple_hash(rc->chart);
605
}
606
607
+ rc->group = group_method;
608
+ rc->after = after;
609
+ rc->before = before;
610
+ rc->update_every = update_every;
611
+ rc->options = options;
612
+
613
+ // link it to the host
614
+ rc->next = host->calculations;
615
+ host->calculations = rc;
616
+
617
+ // link it to its chart
618
+ RRDSET *st;
619
+ for(st = host->rrdset_root; st ; st = st->next) {
620
+ if(rrdcalc_is_matching_this_rrdset(rc, st)) {
621
+ rrdsetcalc_link(st, rc);
622
+ break;
623
+ }
624
+ }
625
+
626
return NULL;
627
}
628
601
-void rrdcalc_free(RRDCALC *rc) {
629
+void rrdcalc_free(RRDHOST *host, RRDCALC *rc) {
630
if(!rc) return;
631
632
+ // unlink it from RRDSET
633
if(rc->rrdset) rrdsetcalc_unlink(rc);
634
635
+ // unlink it from RRDHOST
636
+ if(rc == host->calculations)
637
+ host->calculations = rc->next;
638
+
639
+ else if(host->calculations) {
640
+ RRDCALC *t, *last = host->calculations;
641
+
642
+ for(t = last->next; t ; last = t, t = t->next)
643
+ if(t == rc) break;
644
+
645
+ if(last)
646
+ last->next = rc->next;
647
+ else
648
+ error("Cannot unlink RRDCALC '%s' from RRDHOST '%s': not found", rc->name, host->hostname);
649
+ }
650
+ else
651
+ error("Cannot unlink RRDCALC '%s' from RRDHOST '%s': RRDHOST does not have any calculations", rc->name, host->hostname);
652
+
653
+ freez(rc->name);
654
+ freez(rc->chart);
655
+ freez(rc->dimensions);
656
+
657
freez(rc);
607
-}
\ No newline at end of file
658
+}
src/health.h
+10
-5
@@ -31,6 +31,10 @@ extern int rrdvar_compare(void *a, void *b);
31
#define RRDVAR_TYPE_TOTAL 4
32
33
// the variables as stored in the variables indexes
34
+// there are 3 indexes:
35
+// 1. at each chart (RRDSET.variables_root_index)
36
+// 2. at each context (RRDCONTEXT.variables_root_index)
37
+// 3. at each host (RRDHOST.variables_root_index)
38
typedef struct rrdvar {
39
avl avl;
40
@@ -44,7 +48,7 @@ typedef struct rrdvar {
48
} RRDVAR;
49
50
// variables linked to charts
47
-// We link variables to point the values that are already
51
+// We link variables to point to the values that are already
52
// calculated / processed by the normal data collection process
53
// This means, there will be no speed penalty for using
54
// these variables
@@ -75,7 +79,7 @@ typedef struct rrdsetvar {
79
} RRDSETVAR;
80
81
78
-// variables linked to dimensions
82
+// variables linked to individual dimensions
83
// We link variables to point the values that are already
84
// calculated / processed by the normal data collection process
85
// This means, there will be no speed penalty for using
@@ -125,17 +129,17 @@ typedef struct rrddimvar {
129
struct rrddimvar *next;
130
} RRDDIMVAR;
131
128
-// additional calculated variables
132
+// calculated variables (defined in health configuration)
133
// These aggregate time-series data at fixed intervals
134
// (defined in their update_every member below)
135
// These increase the overhead of netdata.
136
//
137
// These calculations are allocated and linked (->next)
134
-// to RRDHOST.
138
+// under RRDHOST.
139
// Then are also linked to RRDSET (of course only when the
140
// chart is found, via ->rrdset_next and ->rrdset_prev).
141
// This double-linked list is maintained sorted at all times
138
-// having as RRDSET->calculations the RRDCALC to be processed
142
+// having as RRDSET.calculations the RRDCALC to be processed
143
// next.
144
typedef struct rrdcalc {
145
char *name;
@@ -192,6 +196,7 @@ typedef struct rrdcalctemplate {
196
struct rrdcalctemplate *next;
197
} RRDCALCTEMPLATE;
198
199
+
200
#include "rrd.h"
201
202
extern void rrdsetvar_rename_all(RRDSET *st);
src/rrd.c
+21
@@ -18,6 +18,9 @@ static int rrdset_compare(void* a, void* b);
18
static int rrdset_compare_name(void* a, void* b);
19
static int rrdcontext_compare(void* a, void* b);
20
21
+// ----------------------------------------------------------------------------
22
+// RRDHOST
23
+
24
RRDHOST localhost = {
25
.hostname = "localhost",
26
.rrdset_root = NULL,
@@ -40,6 +43,24 @@ RRDHOST localhost = {
43
}
44
};
45
46
+void rrdhost_rwlock(RRDHOST *host) {
47
+ pthread_rwlock_wrlock(&host->rrdset_root_rwlock);
48
+}
49
+
50
+void rrdhost_rdlock(RRDHOST *host) {
51
+ pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
52
+}
53
+
54
+void rrdhost_unlock(RRDHOST *host) {
55
+ pthread_rwlock_unlock(&host->rrdset_root_rwlock);
56
+}
57
+
58
+void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
59
+ if(pthread_rwlock_tryrdlock(&host->rrdset_root_rwlock) == 0) {
60
+ fatal("RRDHOST '%s' should be write-locked, but it is not, at function %s() at line %lu of file '%s'", host->hostname, function, line, file);
61
+ }
62
+}
63
+
64
// ----------------------------------------------------------------------------
65
// RRDCONTEXT index
66
src/rrd.h
+7
-1
@@ -304,9 +304,15 @@ struct rrdhost {
304
EVAL_VARIABLE *references;
305
};
306
typedef struct rrdhost RRDHOST;
307
-
307
extern RRDHOST localhost;
308
309
+#ifdef NETDATA_INTERNAL_CHECKS
310
+#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__)
311
+#else
312
+#define rrdhost_check_wrlock(host) (void)0
313
+#endif
314
+extern void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line);
315
+
316
// ----------------------------------------------------------------------------
317
// RRD SET functions
318