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 localhost = {
.hostname = "localhost",
.rrdset_root_index_name = {
{ NULL, rrdset_compare_name },
AVL_LOCK_INITIALIZER
+ },
+ .rrdcontext_root_index = {
+ { NULL, rrdcontext_compare },
+ AVL_LOCK_INITIALIZER
}
};
+// ----------------------------------------------------------------------------
+// RRDCONTEXT index
+
+static int rrdcontext_compare(void* a, void* b) {
+ if(((RRDCONTEXT *)a)->hash < ((RRDCONTEXT *)b)->hash) return -1;
+ else if(((RRDCONTEXT *)a)->hash > ((RRDCONTEXT *)b)->hash) return 1;
+ else return strcmp(((RRDCONTEXT *)a)->id, ((RRDCONTEXT *)b)->id);
+}
+
+#define rrdcontext_index_add(host, rc) (RRDCONTEXT *)avl_insert_lock(&((host)->rrdcontext_root_index), (avl *)(rc))
+#define rrdcontext_index_del(host, rc) (RRDCONTEXT *)avl_remove_lock(&((host)->rrdcontext_root_index), (avl *)(rc))
+
+static RRDCONTEXT *rrdcontext_index_find(RRDHOST *host, const char *id, uint32_t hash) {
+ RRDCONTEXT tmp;
+ tmp.id = id;
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
+
+ return (RRDCONTEXT *)avl_search_lock(&(host->rrdcontext_root_index), (avl *) &tmp);
+}
+
+RRDCONTEXT *rrdcontext_create(const char *id) {
+ RRDCONTEXT *rc = rrdcontext_index_find(&localhost, id, 0);
+ if(!rc) {
+ rc = calloc(1, sizeof(RRDCONTEXT));
+ if(!rc) fatal("Cannot allocate RRDCONTEXT memory");
+ rc->id = strdup(id);
+ if(!rc->id) fatal("Cannot allocate RRDCONTEXT.id memory");
+ rc->hash = simple_hash(rc->id);
+ // avl_init_lock(&rc->variables_root_index, compar);
+ RRDCONTEXT *ret = rrdcontext_index_add(&localhost, rc);
+ if(ret != rc)
+ fatal("INTERNAL ERROR: Expected to INSERT RRDCONTEXT '%s' into index, but inserted '%s'.", rc->id, (ret)?ret->id:"NONE");
+ }
+
+ rc->use_count++;
+ return rc;
+}
+
+void rrdcontext_free(RRDCONTEXT *rc) {
+ rc->use_count--;
+ if(!rc->use_count) {
+ RRDCONTEXT *ret = rrdcontext_index_del(&localhost, rc);
+ if(ret != rc)
+ fatal("INTERNAL ERROR: Expected to DELETE RRDCONTEXT '%s' from index, but deleted '%s'.", rc->id, (ret)?ret->id:"NONE");
+
+ free((void *)rc->id);
+ free(rc);
+ }
+}
+
// ----------------------------------------------------------------------------
// RRDSET index
static int rrdset_compare(void* a, void* b) {
- if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1;
- else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1;
- else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id);
+ if(((RRDSET *)a)->hash < ((RRDSET *)b)->hash) return -1;
+ else if(((RRDSET *)a)->hash > ((RRDSET *)b)->hash) return 1;
+ else return strcmp(((RRDSET *)a)->id, ((RRDSET *)b)->id);
}
-#define rrdset_index_add(host, st) avl_insert_lock(&((host)->rrdset_root_index), (avl *)(st))
-#define rrdset_index_del(host, st) avl_remove_lock(&((host)->rrdset_root_index), (avl *)(st))
+#define rrdset_index_add(host, st) (RRDSET *)avl_insert_lock(&((host)->rrdset_root_index), (avl *)(st))
+#define rrdset_index_del(host, st) (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index), (avl *)(st))
static RRDSET *rrdset_index_find(RRDHOST *host, const char *id, uint32_t hash) {
- RRDSET tmp;
- strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX);
- tmp.hash = (hash)?hash:simple_hash(tmp.id);
+ RRDSET tmp;
+ strncpyz(tmp.id, id, RRD_ID_LENGTH_MAX);
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
- return (RRDSET *)avl_search_lock(&(host->rrdset_root_index), (avl *) &tmp);
+ return (RRDSET *)avl_search_lock(&(host->rrdset_root_index), (avl *) &tmp);
}
// ----------------------------------------------------------------------------
}
RRDSET *rrdset_index_add_name(RRDHOST *host, RRDSET *st) {
+ void *result;
// fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name);
- return (RRDSET *)avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname));
+ result = avl_insert_lock(&host->rrdset_root_index_name, (avl *) (&st->avlname));
+ if(result) return rrdset_from_avlname(result);
+ return NULL;
}
-#define rrdset_index_del_name(host, st) avl_remove_lock(&((host)->rrdset_root_index_name), (avl *)(&st->avlname))
+RRDSET *rrdset_index_del_name(RRDHOST *host, RRDSET *st) {
+ void *result;
+ // fprintf(stderr, "DELETING: %s (name: %s)\n", st->id, st->name);
+ return (RRDSET *)avl_remove_lock(&((host)->rrdset_root_index_name), (avl *)(&st->avlname));
+ if(result) return rrdset_from_avlname(result);
+ return NULL;
+}
static RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name, uint32_t hash) {
void *result = NULL;
rrdset_index_add(&localhost, st);
+ st->rrdcontext = rrdcontext_create(st->context);
+
pthread_rwlock_unlock(&localhost.rrdset_root_rwlock);
return(st);
rrdset_index_del(&localhost, st);
+ st->rrdcontext->use_count--;
+ if(!st->rrdcontext->use_count)
+ rrdcontext_free(st->rrdcontext);
+
if(st->mapped == RRD_MEMORY_MODE_SAVE) {
debug(D_RRD_CALLS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
savememory(st->cache_filename, st, st->memsize);
#define RRD_ID_LENGTH_MAX 1024
-#define RRDSET_MAGIC "NETDATA RRD SET FILE V017"
+#define RRDSET_MAGIC "NETDATA RRD SET FILE V018"
#define RRDDIMENSION_MAGIC "NETDATA RRD DIMENSION FILE V017"
typedef long long total_number;
#define RRDDIM_FLAG_HIDDEN 0x00000001 // this dimension will not be offered to callers
#define RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS 0x00000002 // do not offer RESET or OVERFLOW info to callers
+// ----------------------------------------------------------------------------
+// RRD CONTEXT
+
+struct rrdcontext {
+ avl avl;
+
+ const char *id;
+ uint32_t hash;
+
+ size_t use_count;
+
+ // avl_tree_lock variables_root_index;
+};
+typedef struct rrdcontext RRDCONTEXT;
+
// ----------------------------------------------------------------------------
// RRD DIMENSION
total_number collected_total; // used internally to calculate percentages
total_number last_collected_total; // used internally to calculate percentages
+ RRDCONTEXT *rrdcontext;
struct rrdset *next; // linking of rrdsets
// ------------------------------------------------------------------------
};
typedef struct rrdset RRDSET;
-// ----------------------------------------------------------------------------
-// RRD CONTEXT
-
-struct rrdcontext {
- avl avl;
-
- char *context;
-};
-typedef struct rrdcontext RRDCONTEXT;
-
-
// ----------------------------------------------------------------------------
// RRD HOST
struct rrdhost {
+ avl avl;
+
char *hostname;
RRDSET *rrdset_root;
avl_tree_lock rrdset_root_index;
avl_tree_lock rrdset_root_index_name;
+
+ avl_tree_lock rrdcontext_root_index;
+ // avl_tree_lock variables_root_index;
};
typedef struct rrdhost RRDHOST;