]> arthur.barton.de Git - netdata.git/commitdiff
chart and dimensions variables linked to 3 indexes: local, context and host variables
authorCosta Tsaousis <costa@tsaousis.gr>
Sun, 7 Aug 2016 11:59:17 +0000 (14:59 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Sun, 7 Aug 2016 11:59:17 +0000 (14:59 +0300)
src/health.c
src/health.h
src/rrd.c
src/rrd.h
src/web_server.c

index 47659ccdb01ec82ebfb5c68db5155ce0a2bc4cb1..2a9d771311e00b29c2aca1de31e79161a878e31c 100644 (file)
@@ -1,15 +1,31 @@
 #include "common.h"
 
+// ----------------------------------------------------------------------------
+// RRDVAR management
+
 int rrdvar_compare(void* a, void* b) {
     if(((RRDVAR *)a)->hash < ((RRDVAR *)b)->hash) return -1;
     else if(((RRDVAR *)a)->hash > ((RRDVAR *)b)->hash) return 1;
     else return strcmp(((RRDVAR *)a)->name, ((RRDVAR *)b)->name);
 }
 
-#define rrdvar_index_add(tree, rv) (RRDVAR *)avl_insert_lock(tree, (avl *)(rv))
-#define rrdvar_index_del(tree, rv) (RRDVAR *)avl_remove_lock(tree, (avl *)(rv))
+static inline RRDVAR *rrdvar_index_add(avl_tree_lock *tree, RRDVAR *rv) {
+    RRDVAR *ret = (RRDVAR *)avl_insert_lock(tree, (avl *)(rv));
+    if(ret != rv)
+        debug(D_VARIABLES, "Request to insert RRDVAR '%s' into index failed. Already exists.", rv->name);
+
+    return ret;
+}
+
+static inline RRDVAR *rrdvar_index_del(avl_tree_lock *tree, RRDVAR *rv) {
+    RRDVAR *ret = (RRDVAR *)avl_remove_lock(tree, (avl *)(rv));
+    if(!ret)
+        fatal("Request to remove RRDVAR '%s' from index failed. Not Found.", rv->name);
+
+    return ret;
+}
 
-static RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) {
+static inline RRDVAR *rrdvar_index_find(avl_tree_lock *tree, const char *name, uint32_t hash) {
     RRDVAR tmp;
     tmp.name = (char *)name;
     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
     return (RRDVAR *)avl_search_lock(tree, (avl *)&tmp);
 }
 
+static inline RRDVAR *rrdvar_create(const char *name, uint32_t hash, int type, calculated_number *value) {
+    RRDVAR *rv = calloc(1, sizeof(RRDVAR));
+    if(!rv) fatal("Cannot allocate memory for RRDVAR");
 
-RRDVAR *rrdvar_get(RRDHOST *host, RRDCONTEXT *co, RRDSET *st, const char *name) {
-    uint32_t hash = simple_hash(name);
+    rv->name = (char *)name;
+    rv->hash = (hash)?hash:simple_hash((rv->name));
+    rv->type = type;
+    rv->value = value;
 
-    RRDVAR *ret = NULL;
-    RRDVAR *rv = rrdvar_index_find(&st->variables_root_index, name, hash);
-    if(!rv) {
-        rv = calloc(1, sizeof(RRDVAR));
-        if(!rv) fatal("Cannot allocate memory for RRDVAR");
+    return rv;
+}
 
-        rv->name = strdup(name);
-        if(!rv->name) fatal("Cannot allocate memory for RRDVAR name");
+static inline void rrdvar_free(RRDVAR *rv) {
+    free(rv);
+}
 
-        rv->hash = hash;
+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) {
+    RRDVAR *rv = rrdvar_index_find(tree, name, hash);
+    if(unlikely(!rv)) {
+        debug(D_VARIABLES, "Variable '%s' not found in scope '%s'. Creating a new one.", name, scope);
 
-        ret = rrdvar_index_add(&st->variables_root_index, rv);
-        if(ret != rv) {
-            error("Duplicate RRDVAR '%s' found on chart '%s'", name, st->id);
-            free(rv->name);
-            free(rv);
-            rv = ret;
+        rv = rrdvar_create(name, hash, type, value);
+        RRDVAR *ret = rrdvar_index_add(tree, rv);
+        if(unlikely(ret != rv)) {
+            debug(D_VARIABLES, "Variable '%s' in scope '%s' already exists", name, scope);
+            rrdvar_free(rv);
+            rv = NULL;
         }
+        else
+            debug(D_VARIABLES, "Variable '%s' created in scope '%s'", name, scope);
+    }
+
+    return rv;
+}
+
+// ----------------------------------------------------------------------------
+// RRDSETVAR management
+
+#define RRDSETVAR_ID_MAX 1024
+
+RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options) {
+    RRDSETVAR *rs = (RRDSETVAR *)calloc(1, sizeof(RRDSETVAR));
+    if(!rs) fatal("Cannot allocate memory for RRDSETVAR");
+
+    char buffer[RRDSETVAR_ID_MAX + 1];
+    snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->id, variable);
+    rs->fullid = strdup(buffer);
+    if(!rs->fullid) fatal("Cannot allocate memory for RRDVASET id");
+    rs->hash_fullid = simple_hash(rs->fullid);
+
+    snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->name, variable);
+    rs->fullname = strdup(buffer);
+    if(!rs->fullname) fatal("Cannot allocate memory for RRDVASET name");
+    rs->hash_fullname = simple_hash(rs->fullname);
+
+    rs->variable = strdup(variable);
+    if(!rs->variable) fatal("Cannot allocate memory for RRDVASET variable name");
+    rs->hash_variable = simple_hash(rs->variable);
+
+    rs->type = type;
+    rs->value = value;
+    rs->options = options;
+
+    rs->local        = rrdvar_create_and_index("local",   &st->variables_root_index, rs->variable, rs->hash_variable, rs->type, rs->value);
+    rs->context      = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullid, rs->hash_fullid, rs->type, rs->value);
+    rs->host         = rrdvar_create_and_index("host",    &st->rrdhost->variables_root_index, rs->fullid, rs->hash_fullid, rs->type, rs->value);
+    rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
+    rs->host_name    = rrdvar_create_and_index("host",    &st->rrdhost->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
+
+    rs->next = st->variables;
+    st->variables = rs;
+
+    return rs;
+}
 
-        ret = rrdvar_index_add(&co->variables_root_index, rv);
-        if(ret != rv)
-            debug(D_VARIABLES, "Variable '%s' in context '%s' does not come from chart '%s'", name, co->id, st->id);
+void rrdsetvar_rename_all(RRDSET *st) {
+    // only these 2 can change name
+    // rs->context_name
+    // rs->host_name
 
-        ret = rrdvar_index_add(&host->variables_root_index, rv);
-        if(ret != rv)
-            debug(D_VARIABLES, "Variable '%s' in host '%s' does not come from chart '%s'", name, host->hostname, st->id);
+    char buffer[RRDSETVAR_ID_MAX + 1];
+    RRDSETVAR *rs, *next = st->variables;
+    while((rs = next)) {
+        next = rs->next;
+
+        snprintfz(buffer, RRDSETVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->variable);
+
+        if (strcmp(buffer, rs->fullname)) {
+            // name changed
+            if (rs->context_name) {
+                rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_name);
+                rrdvar_free(rs->context_name);
+            }
+
+            if (rs->host_name) {
+                rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host_name);
+                rrdvar_free(rs->host_name);
+            }
+
+            free(rs->fullname);
+            rs->fullname = strdup(st->name);
+            if(!rs->fullname) fatal("Cannot allocate memory for RRDSETVAR name");
+            rs->hash_fullname = simple_hash(rs->fullname);
+            rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
+            rs->host_name    = rrdvar_create_and_index("host",    &st->rrdhost->variables_root_index, rs->fullname, rs->hash_fullname, rs->type, rs->value);
+        }
+    }
+}
+
+void rrdsetvar_free(RRDSETVAR *rs) {
+    RRDSET *st = rs->rrdset;
+
+    if(rs->local) {
+        rrdvar_index_del(&st->variables_root_index, rs->local);
+        rrdvar_free(rs->local);
     }
 
-    return rv;
+    if(rs->context) {
+        rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context);
+        rrdvar_free(rs->context);
+    }
+
+    if(rs->host) {
+        rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host);
+        rrdvar_free(rs->host);
+    }
+
+    if(rs->context_name) {
+        rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_name);
+        rrdvar_free(rs->context_name);
+    }
+
+    if(rs->host_name) {
+        rrdvar_index_del(&st->rrdhost->variables_root_index, rs->host_name);
+        rrdvar_free(rs->host_name);
+    }
+
+    if(st->variables == rs) {
+        st->variables = rs->next;
+    }
+    else {
+        RRDSETVAR *t;
+        for (t = st->variables; t && t->next != rs; t = t->next);
+        if(!t) error("RRDSETVAR '%s' not found in chart '%s' variables linked list", rs->fullname, st->id);
+        else t->next = rs->next;
+    }
+
+    free(rs->fullid);
+    free(rs->fullname);
+    free(rs->variable);
+    free(rs);
+}
+
+// ----------------------------------------------------------------------------
+// RRDDIMVAR management
+
+#define RRDDIMVAR_ID_MAX 1024
+
+RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options) {
+    RRDSET *st = rd->rrdset;
+
+    if(!prefix) prefix = "";
+    if(!suffix) suffix = "";
+
+    char buffer[RRDDIMVAR_ID_MAX + 1];
+    RRDDIMVAR *rs = (RRDDIMVAR *)calloc(1, sizeof(RRDDIMVAR));
+    if(!rs) fatal("Cannot allocate memory for RRDDIMVAR");
+
+    rs->prefix = strdup(prefix);
+    if(!rs->prefix) fatal("Cannot allocate memory for RRDDIMVAR prefix");
+
+    rs->suffix = strdup(suffix);
+    if(!rs->suffix) fatal("Cannot allocate memory for RRDDIMVAR suffix");
+
+    snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->id, rs->suffix);
+    rs->id = strdup(buffer);
+    if(!rs->id) fatal("Cannot allocate memory for RRDIM id");
+    rs->hash = simple_hash(rs->id);
+
+    snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix);
+    rs->name = strdup(buffer);
+    if(!rs->name) fatal("Cannot allocate memory for RRDIM name");
+    rs->hash_name = simple_hash(rs->name);
+
+    snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->id, rs->id);
+    rs->fullidid = strdup(buffer);
+    if(!rs->fullidid) fatal("Cannot allocate memory for RRDDIMVAR fullidid");
+    rs->hash_fullidid = simple_hash(rs->fullidid);
+
+    snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->id, rs->name);
+    rs->fullidname = strdup(buffer);
+    if(!rs->fullidname) fatal("Cannot allocate memory for RRDDIMVAR fullidname");
+    rs->hash_fullidname = simple_hash(rs->fullidname);
+
+    snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->name, rs->id);
+    rs->fullnameid = strdup(buffer);
+    if(!rs->fullnameid) fatal("Cannot allocate memory for RRDDIMVAR fullnameid");
+    rs->hash_fullnameid = simple_hash(rs->fullnameid);
+
+    snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", rd->rrdset->type, rd->rrdset->name, rs->name);
+    rs->fullnamename = strdup(buffer);
+    if(!rs->fullnamename) fatal("Cannot allocate memory for RRDDIMVAR fullnamename");
+    rs->hash_fullnamename = simple_hash(rs->fullnamename);
+
+    rs->type = type;
+    rs->value = value;
+    rs->options = options;
+
+    rs->local_id     = rrdvar_create_and_index("local",   &st->variables_root_index, rs->id, rs->hash, rs->type, rs->value);
+    rs->local_name   = rrdvar_create_and_index("local",   &st->variables_root_index, rs->name, rs->hash_name, rs->type, rs->value);
+
+    rs->context_fullidid     = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullidid, rs->hash_fullidid, rs->type, rs->value);
+    rs->context_fullidname   = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
+    rs->context_fullnameid   = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
+    rs->context_fullnamename = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
+
+    rs->host_fullidid     = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidid, rs->hash_fullidid, rs->type, rs->value);
+    rs->host_fullidname   = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
+    rs->host_fullnameid   = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
+    rs->host_fullnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
+
+    rs->next = rd->variables;
+    rd->variables = rs;
+
+    return rs;
+}
+
+void rrddimvar_rename_all(RRDDIM *rd) {
+    RRDSET *st = rd->rrdset;
+
+    RRDDIMVAR *rs, *next = rd->variables;
+    while((rs = next)) {
+        next = rs->next;
+
+        if (strcmp(rd->name, rs->name)) {
+            char buffer[RRDDIMVAR_ID_MAX + 1];
+            // name changed
+
+            // name
+            if (rs->local_name) {
+                rrdvar_index_del(&st->variables_root_index, rs->local_name);
+                rrdvar_free(rs->local_name);
+            }
+            free(rs->name);
+            snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s%s%s", rs->prefix, rd->name, rs->suffix);
+            rs->name = strdup(buffer);
+            if(!rs->name) fatal("Cannot allocate memory for RRDDIMVAR name");
+            rs->hash_name = simple_hash(rs->name);
+            rs->local_name = rrdvar_create_and_index("local", &st->variables_root_index, rs->name, rs->hash_name, rs->type, rs->value);
+
+            // fullidname
+            if (rs->context_fullidname) {
+                rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullidname);
+                rrdvar_free(rs->context_fullidname);
+            }
+            if (rs->host_fullidname) {
+                rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullidname);
+                rrdvar_free(rs->host_fullidname);
+            }
+            free(rs->fullidname);
+            snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", st->type, st->id, rs->name);
+            rs->fullidname = strdup(buffer);
+            if(!rs->fullidname) fatal("Cannot allocate memory for RRDDIMVAR fullidname");
+            rs->hash_fullidname = simple_hash(rs->fullidname);
+            rs->context_fullidname = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index,
+                                                             rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
+            rs->host_fullidname = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index,
+                                                             rs->fullidname, rs->hash_fullidname, rs->type, rs->value);
+
+            // fullnameid
+            if (rs->context_fullnameid) {
+                rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullnameid);
+                rrdvar_free(rs->context_fullnameid);
+            }
+            if (rs->host_fullnameid) {
+                rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullnameid);
+                rrdvar_free(rs->host_fullnameid);
+            }
+            free(rs->fullnameid);
+            snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->id);
+            rs->fullnameid = strdup(buffer);
+            if(!rs->fullnameid) fatal("Cannot allocate memory for RRDDIMVAR fullnameid");
+            rs->hash_fullnameid = simple_hash(rs->fullnameid);
+            rs->context_fullnameid = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index,
+                                                             rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
+            rs->host_fullnameid = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index,
+                                                          rs->fullnameid, rs->hash_fullnameid, rs->type, rs->value);
+
+            // fullnamename
+            if (rs->context_fullnamename) {
+                rrdvar_index_del(&st->rrdcontext->variables_root_index, rs->context_fullnamename);
+                rrdvar_free(rs->context_fullnamename);
+            }
+            if (rs->host_fullnamename) {
+                rrdvar_index_del(&st->rrdhost->variables_root_index, rs->context_fullnamename);
+                rrdvar_free(rs->host_fullnamename);
+            }
+            free(rs->fullnamename);
+            snprintfz(buffer, RRDDIMVAR_ID_MAX, "%s.%s.%s", st->type, st->name, rs->name);
+            rs->fullnamename = strdup(buffer);
+            if(!rs->fullnamename) fatal("Cannot allocate memory for RRDDIMVAR fullnamename");
+            rs->hash_fullnamename = simple_hash(rs->fullnamename);
+            rs->context_fullnamename = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index,
+                                                             rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
+            rs->host_fullnamename = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index,
+                                                          rs->fullnamename, rs->hash_fullnamename, rs->type, rs->value);
+        }
+    }
+}
+
+void rrddimvar_free(RRDDIMVAR *rs) {
+    if(rs->local_id) {
+        rrdvar_index_del(&rs->rrddim->rrdset->variables_root_index, rs->local_id);
+        rrdvar_free(rs->local_id);
+    }
+    if(rs->local_name) {
+        rrdvar_index_del(&rs->rrddim->rrdset->variables_root_index, rs->local_name);
+        rrdvar_free(rs->local_name);
+    }
+
+    if(rs->context_fullidid) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullidid);
+        rrdvar_free(rs->context_fullidid);
+    }
+    if(rs->context_fullidname) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullidname);
+        rrdvar_free(rs->context_fullidname);
+    }
+    if(rs->context_fullnameid) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullnameid);
+        rrdvar_free(rs->context_fullnameid);
+    }
+    if(rs->context_fullnamename) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdcontext->variables_root_index, rs->context_fullnamename);
+        rrdvar_free(rs->context_fullnamename);
+    }
+
+    if(rs->host_fullidid) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullidid);
+        rrdvar_free(rs->host_fullidid);
+    }
+    if(rs->host_fullidname) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullidname);
+        rrdvar_free(rs->host_fullidname);
+    }
+    if(rs->host_fullnameid) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullnameid);
+        rrdvar_free(rs->host_fullnameid);
+    }
+    if(rs->host_fullnamename) {
+        rrdvar_index_del(&rs->rrddim->rrdset->rrdhost->variables_root_index, rs->host_fullnamename);
+        rrdvar_free(rs->host_fullnamename);
+    }
+
+    if(rs->rrddim->variables == rs) {
+        rs->rrddim->variables = rs->next;
+    }
+    else {
+        RRDDIMVAR *t;
+        for (t = rs->rrddim->variables; t && t->next != rs; t = t->next);
+        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);
+        else t->next = rs->next;
+    }
+
+    free(rs->prefix);
+    free(rs->suffix);
+    free(rs->id);
+    free(rs->name);
+    free(rs->fullidid);
+    free(rs->fullidname);
+    free(rs->fullnameid);
+    free(rs->fullnamename);
+    free(rs);
 }
index d4b55a5d02b802122d3c3f4479b9c3ed7520ee90..b29a2c5bfa4fdca180b73e9bafe7d15eea3a5ef4 100644 (file)
@@ -25,17 +25,98 @@ extern int rrdvar_compare(void *a, void *b);
  *
  */
 
+#define RRDVAR_TYPE_CALCULATED 1
+#define RRDVAR_TYPE_TIME_T     2
+#define RRDVAR_TYPE_COLLECTED  3
+#define RRDVAR_TYPE_TOTAL      4
+
+// the variables as stored in the variables indexes
 typedef struct rrdvar {
     avl avl;
 
     char *name;
     uint32_t hash;
 
-    calculated_number *value;
+    int type;
+    void *value;
 
     time_t last_updated;
 } RRDVAR;
 
+// variables linked to charts
+typedef struct rrdsetvar {
+    char *fullid;               // chart type.chart id.variable
+    uint32_t hash_fullid;
+
+    char *fullname;             // chart type.chart name.variable
+    uint32_t hash_fullname;
+
+    char *variable;             // variable
+    uint32_t hash_variable;
+
+    int type;
+    void *value;
+
+    uint32_t options;
+
+    RRDVAR *local;
+    RRDVAR *context;
+    RRDVAR *host;
+    RRDVAR *context_name;
+    RRDVAR *host_name;
+
+    struct rrdset *rrdset;
+
+    struct rrdsetvar *next;
+} RRDSETVAR;
+
+
+// variables linked to dimensions
+typedef struct rrddimvar {
+    char *prefix;
+    char *suffix;
+
+    char *id;                   // dimension id
+    uint32_t hash;
+
+    char *name;                 // dimension name
+    uint32_t hash_name;
+
+    char *fullidid;             // chart type.chart id.dimension id
+    uint32_t hash_fullidid;
+
+    char *fullidname;           // chart type.chart id.dimension name
+    uint32_t hash_fullidname;
+
+    char *fullnameid;           // chart type.chart name.dimension id
+    uint32_t hash_fullnameid;
+
+    char *fullnamename;         // chart type.chart name.dimension name
+    uint32_t hash_fullnamename;
+
+    int type;
+    void *value;
+
+    uint32_t options;
+
+    RRDVAR *local_id;
+    RRDVAR *local_name;
+
+    RRDVAR *context_fullidid;
+    RRDVAR *context_fullidname;
+    RRDVAR *context_fullnameid;
+    RRDVAR *context_fullnamename;
+
+    RRDVAR *host_fullidid;
+    RRDVAR *host_fullidname;
+    RRDVAR *host_fullnameid;
+    RRDVAR *host_fullnamename;
+
+    struct rrddim *rrddim;
+
+    struct rrddimvar *next;
+} RRDDIMVAR;
+
 typedef struct rrdcalc {
     avl avl;
 
@@ -55,4 +136,14 @@ typedef struct rrdcalc {
     struct rrdcalc *prev;
 } RRDCALC;
 
+#include "rrd.h"
+
+extern void rrdsetvar_rename_all(RRDSET *st);
+extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *value, uint32_t options);
+extern void rrdsetvar_free(RRDSETVAR *rs);
+
+extern void rrddimvar_rename_all(RRDDIM *rd);
+extern RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char *suffix, void *value, uint32_t options);
+extern void rrddimvar_free(RRDDIMVAR *rs);
+
 #endif //NETDATA_HEALTH_H
index 5ba5d39a3990fa5f973015998141b3f47e7c8601..fd4cee395b01541c17d870a892023d7ade70e390 100644 (file)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -313,7 +313,10 @@ void rrdset_set_name(RRDSET *st, const char *name)
 {
        debug(D_RRD_CALLS, "rrdset_set_name() old: %s, new: %s", st->name, name);
 
-       if(st->name) rrdset_index_del_name(&localhost, st);
+       if(st->name) {
+        rrdset_index_del_name(&localhost, st);
+        rrdsetvar_rename_all(st);
+    }
 
        char b[CONFIG_MAX_VALUE + 1];
        char n[RRD_ID_LENGTH_MAX + 1];
@@ -459,6 +462,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
                st->dimensions = NULL;
                st->next = NULL;
                st->mapped = rrd_memory_mode;
+        st->variables = NULL;
        }
        else {
                st = calloc(1, size);
@@ -516,12 +520,16 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
                st->title = config_get(st->id, "title", varvalue);
        }
 
-       st->next = localhost.rrdset_root;
+    st->rrdcontext = rrdcontext_create(st->context);
+    st->rrdhost = &localhost;
+
+    st->next = localhost.rrdset_root;
     localhost.rrdset_root = st;
 
-       rrdset_index_add(&localhost, st);
+    rrdsetvar_create(st, "last_collected", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, 0);
+    rrdsetvar_create(st, "raw_total", RRDVAR_TYPE_TOTAL, &st->collected_total, 0);
 
-    st->rrdcontext = rrdcontext_create(st->context);
+    rrdset_index_add(&localhost, st);
 
        pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
 
@@ -594,6 +602,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
                // we have a file mapped for rd
                rd->mapped = rrd_memory_mode;
                rd->flags = 0x00000000;
+        rd->variables = NULL;
                rd->next = NULL;
                rd->name = NULL;
        }
@@ -610,6 +619,8 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
        }
        rd->memsize = size;
 
+    rd->rrdset = st;
+
        strcpy(rd->magic, RRDDIMENSION_MAGIC);
        strcpy(rd->cache_filename, fullfilename);
        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
                for(; td->next; td = td->next) ;
                td->next = rd;
        }
+
+    rrddimvar_create(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->calculated_value, 0);
+    rrddimvar_create(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->collected_value, 0);
+    rrddimvar_create(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected", &rd->last_collected_time.tv_sec, 0);
+
        pthread_rwlock_unlock(&st->rwlock);
 
        rrddim_index_add(st, rd);
@@ -667,6 +683,8 @@ void rrddim_set_name(RRDSET *st, RRDDIM *rd, const char *name)
        char varname[CONFIG_MAX_NAME + 1];
        snprintfz(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
        config_set_default(st->id, varname, name);
+
+    rrddimvar_rename_all(rd);
 }
 
 void rrddim_free(RRDSET *st, RRDDIM *rd)
@@ -685,7 +703,10 @@ void rrddim_free(RRDSET *st, RRDDIM *rd)
        else st->dimensions = rd->next;
        rd->next = NULL;
 
-       rrddim_index_del(st, rd);
+    while(rd->variables)
+        rrddimvar_free(rd->variables);
+
+    rrddim_index_del(st, rd);
 
        // free(rd->annotations);
        if(rd->mapped == RRD_MEMORY_MODE_SAVE) {
@@ -716,6 +737,9 @@ void rrdset_free_all(void)
                while(st->dimensions)
                        rrddim_free(st, st->dimensions);
 
+        while(st->variables)
+            rrdsetvar_free(st->variables);
+
                rrdset_index_del(&localhost, st);
 
         st->rrdcontext->use_count--;
index e61c58daf717ca75fd7d97272b9ab49e09121791..7a5b6674b6ece3ae75d363b50e94e851ac07bc43 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -16,7 +16,7 @@ extern int rrd_delete_unupdated_dimensions;
 #define RRD_ID_LENGTH_MAX 1024
 
 #define RRDSET_MAGIC           "NETDATA RRD SET FILE V018"
-#define RRDDIMENSION_MAGIC     "NETDATA RRD DIMENSION FILE V017"
+#define RRDDIMENSION_MAGIC     "NETDATA RRD DIMENSION FILE V018"
 
 typedef long long total_number;
 #define TOTAL_NUMBER_FORMAT "%lld"
@@ -150,6 +150,7 @@ struct rrddim {
        calculated_number stored_volume;                                // the sum of all stored values so far
 
        struct rrddim *next;                                                    // linking of dimensions within the same data set
+    struct rrdset *rrdset;
 
        // ------------------------------------------------------------------------
        // members for checking the data when loading from disk
@@ -164,6 +165,8 @@ struct rrddim {
 
        char magic[sizeof(RRDDIMENSION_MAGIC) + 1];             // a string to be saved, used to identify our data file
 
+    struct rrddimvar *variables;
+
        // ------------------------------------------------------------------------
        // the values stored in this dimension, using our floating point numbers
 
@@ -246,6 +249,8 @@ struct rrdset {
        total_number last_collected_total;                              // used internally to calculate percentages
 
     RRDCONTEXT *rrdcontext;
+    struct rrdhost *rrdhost;
+
        struct rrdset *next;                                                    // linking of rrdsets
 
        // ------------------------------------------------------------------------
@@ -265,6 +270,7 @@ struct rrdset {
     // local variables
 
     avl_tree_lock variables_root_index;
+    RRDSETVAR *variables;
 };
 typedef struct rrdset RRDSET;
 
index 1af02b3b24c5dd1244606689bcb8cfb01ff76cd5..9ef011e549d93d26f36241a587b5745bf1943f4a 100644 (file)
@@ -195,7 +195,7 @@ static inline void close_listen_sockets(void) {
 static inline int bind_to_one(const char *definition, int default_port, int listen_backlog) {
     int added = 0;
     struct addrinfo hints;
-    struct addrinfo *result, *rp;
+    struct addrinfo *result = NULL, *rp = NULL;
 
     char buffer[strlen(definition) + 1];
     strcpy(buffer, definition);
@@ -275,6 +275,8 @@ static inline int bind_to_one(const char *definition, int default_port, int list
         }
     }
 
+       freeaddrinfo(result);
+
     return added;
 }