]> arthur.barton.de Git - netdata.git/commitdiff
RRDCALC management completed
authorCosta Tsaousis <costa@tsaousis.gr>
Fri, 12 Aug 2016 11:04:53 +0000 (14:04 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Fri, 12 Aug 2016 11:04:53 +0000 (14:04 +0300)
src/health.c
src/health.h
src/rrd.c
src/rrd.h

index 3173781c13c94d82f918882827c781a10a1adc76..976a0c922cb31609939eb41f91106f4c3f297884 100644 (file)
@@ -47,7 +47,6 @@ static inline RRDVAR *rrdvar_create(const char *name, uint32_t hash, int type, c
 static inline void rrdvar_free(RRDHOST *host, RRDVAR *rv) {
     if(host) {
         // FIXME: we may need some kind of locking here
-        // to have mutually exclusive access with eval()
         EVAL_VARIABLE *rf;
         for (rf = host->references; rf; rf = rf->next)
             if (rf->rrdvar == rv) rf->rrdvar = NULL;
@@ -436,7 +435,9 @@ void rrddimvar_free(RRDDIMVAR *rs) {
 
 // this has to be called while the caller has locked
 // the RRDHOST
-static inline void rrdhostcalc_linked(RRDHOST *host, RRDCALC *rc) {
+static inline void rrdset_linked_optimize_rrdhost(RRDHOST *host, RRDCALC *rc) {
+    rrdhost_check_wrlock(host);
+
     // move it to be last
 
     if(!rc->next)
@@ -474,7 +475,9 @@ static inline void rrdhostcalc_linked(RRDHOST *host, RRDCALC *rc) {
 
 // this has to be called while the caller has locked
 // the RRDHOST
-static inline void rrdhostcalc_unlinked(RRDHOST *host, RRDCALC *rc) {
+static inline void rrdcalc_unlinked_optimize_rrdhost(RRDHOST *host, RRDCALC *rc) {
+    rrdhost_check_wrlock(host);
+    
     // move it to be first
 
     if(host->calculations == rc) {
@@ -502,7 +505,15 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
     rc->context = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rc->name, rc->hash, RRDVAR_TYPE_CALCULATED, &rc->value);
     rc->host    = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rc->name, rc->hash, RRDVAR_TYPE_CALCULATED, &rc->value);
 
-    rrdhostcalc_linked(st->rrdhost, rc);
+    rrdset_linked_optimize_rrdhost(st->rrdhost, rc);
+}
+
+static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) {
+    if((rc->hash_chart == st->hash && !strcmp(rc->name, st->id)) ||
+            (rc->hash_chart == st->hash_name && !strcmp(rc->name, st->name)))
+        return 1;
+
+    return 0;
 }
 
 // this has to be called while the RRDHOST is locked
@@ -514,10 +525,8 @@ void rrdsetcalc_link_matching(RRDSET *st) {
         // we stop on the first linked RRDCALC
         if(rc->rrdset != NULL) break;
 
-        if((rc->hash_chart == st->hash && !strcmp(rc->name, st->id)) ||
-                (rc->hash_chart == st->hash_name && !strcmp(rc->name, st->name))) {
+        if(rrdcalc_is_matching_this_rrdset(rc, st))
             rrdsetcalc_link(st, rc);
-        }
     }
 }
 
@@ -566,7 +575,7 @@ void rrdsetcalc_unlink(RRDCALC *rc) {
     // so that if the matching chart is found in the future
     // it will be applied automatically
 
-    rrdhostcalc_unlinked(host, rc);
+    rrdcalc_unlinked_optimize_rrdhost(host, rc);
 }
 
 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
         rc->hash_chart = simple_hash(rc->chart);
     }
 
+    rc->group = group_method;
+    rc->after = after;
+    rc->before = before;
+    rc->update_every = update_every;
+    rc->options = options;
+
+    // link it to the host
+    rc->next = host->calculations;
+    host->calculations = rc;
+
+    // link it to its chart
+    RRDSET *st;
+    for(st = host->rrdset_root; st ; st = st->next) {
+        if(rrdcalc_is_matching_this_rrdset(rc, st)) {
+            rrdsetcalc_link(st, rc);
+            break;
+        }
+    }
+
     return NULL;
 }
 
-void rrdcalc_free(RRDCALC *rc) {
+void rrdcalc_free(RRDHOST *host, RRDCALC *rc) {
     if(!rc) return;
 
+    // unlink it from RRDSET
     if(rc->rrdset) rrdsetcalc_unlink(rc);
 
+    // unlink it from RRDHOST
+    if(rc == host->calculations)
+        host->calculations = rc->next;
+
+    else if(host->calculations) {
+        RRDCALC *t, *last = host->calculations;
+
+        for(t = last->next; t ; last = t, t = t->next)
+            if(t == rc) break;
+        
+        if(last)
+            last->next = rc->next;
+        else
+            error("Cannot unlink RRDCALC '%s' from RRDHOST '%s': not found", rc->name, host->hostname);
+    }
+    else
+        error("Cannot unlink RRDCALC '%s' from RRDHOST '%s': RRDHOST does not have any calculations", rc->name, host->hostname);
+
+    freez(rc->name);
+    freez(rc->chart);
+    freez(rc->dimensions);
+
     freez(rc);
-}
\ No newline at end of file
+}
index f30e432f56090647ccf14726a4046a18fae9dc1f..9e536611ce74f5c74d99e39b31c2c35b50d49057 100644 (file)
@@ -31,6 +31,10 @@ extern int rrdvar_compare(void *a, void *b);
 #define RRDVAR_TYPE_TOTAL      4
 
 // the variables as stored in the variables indexes
+// there are 3 indexes:
+// 1. at each chart   (RRDSET.variables_root_index)
+// 2. at each context (RRDCONTEXT.variables_root_index)
+// 3. at each host    (RRDHOST.variables_root_index)
 typedef struct rrdvar {
     avl avl;
 
@@ -44,7 +48,7 @@ typedef struct rrdvar {
 } RRDVAR;
 
 // variables linked to charts
-// We link variables to point the values that are already
+// We link variables to point to the values that are already
 // calculated / processed by the normal data collection process
 // This means, there will be no speed penalty for using
 // these variables
@@ -75,7 +79,7 @@ typedef struct rrdsetvar {
 } RRDSETVAR;
 
 
-// variables linked to dimensions
+// variables linked to individual dimensions
 // We link variables to point the values that are already
 // calculated / processed by the normal data collection process
 // This means, there will be no speed penalty for using
@@ -125,17 +129,17 @@ typedef struct rrddimvar {
     struct rrddimvar *next;
 } RRDDIMVAR;
 
-// additional calculated variables
+// calculated variables (defined in health configuration)
 // These aggregate time-series data at fixed intervals
 // (defined in their update_every member below)
 // These increase the overhead of netdata.
 //
 // These calculations are allocated and linked (->next)
-// to RRDHOST.
+// under RRDHOST.
 // Then are also linked to RRDSET (of course only when the
 // chart is found, via ->rrdset_next and ->rrdset_prev).
 // This double-linked list is maintained sorted at all times
-// having as RRDSET->calculations the RRDCALC to be processed
+// having as RRDSET.calculations the RRDCALC to be processed
 // next.
 typedef struct rrdcalc {
     char *name;
@@ -192,6 +196,7 @@ typedef struct rrdcalctemplate {
     struct rrdcalctemplate *next;
 } RRDCALCTEMPLATE;
 
+
 #include "rrd.h"
 
 extern void rrdsetvar_rename_all(RRDSET *st);
index 7e34a7f5e7b70b34a5823b6a803b29c2bb2fc581..92b149595aa3e7985d64c90f64ad39fcdbbc6068 100644 (file)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -18,6 +18,9 @@ static int rrdset_compare(void* a, void* b);
 static int rrdset_compare_name(void* a, void* b);
 static int rrdcontext_compare(void* a, void* b);
 
+// ----------------------------------------------------------------------------
+// RRDHOST
+
 RRDHOST localhost = {
                .hostname = "localhost",
                .rrdset_root = NULL,
@@ -40,6 +43,24 @@ RRDHOST localhost = {
         }
 };
 
+void rrdhost_rwlock(RRDHOST *host) {
+       pthread_rwlock_wrlock(&host->rrdset_root_rwlock);
+}
+
+void rrdhost_rdlock(RRDHOST *host) {
+       pthread_rwlock_rdlock(&host->rrdset_root_rwlock);
+}
+
+void rrdhost_unlock(RRDHOST *host) {
+       pthread_rwlock_unlock(&host->rrdset_root_rwlock);
+}
+
+void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line) {
+       if(pthread_rwlock_tryrdlock(&host->rrdset_root_rwlock) == 0) {
+               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);
+       }
+}
+
 // ----------------------------------------------------------------------------
 // RRDCONTEXT index
 
index ca6165e924ba11aa3f0469acb09f24d4efaabb94..e05c4ed493d4d68bb0a4f66dbf7c7c779a0434f5 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -304,9 +304,15 @@ struct rrdhost {
     EVAL_VARIABLE *references;
 };
 typedef struct rrdhost RRDHOST;
-
 extern RRDHOST localhost;
 
+#ifdef NETDATA_INTERNAL_CHECKS
+#define rrdhost_check_wrlock(host) rrdhost_check_wrlock_int(host, __FILE__, __FUNCTION__, __LINE__)
+#else
+#define rrdhost_check_wrlock(host) (void)0
+#endif
+extern void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *function, const unsigned long line);
+
 // ----------------------------------------------------------------------------
 // RRD SET functions