+#define RRD_DEFAULT_GAP_INTERPOLATIONS 1
+
+// ----------------------------------------------------------------------------
+// globals
+
+// if not zero it gives the time (in seconds) to remove un-updated dimensions
+int rrd_delete_unupdated_dimensions = 0;
+
+int rrd_update_every = UPDATE_EVERY;
+int rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES;
+
+RRDSET *rrdset_root = NULL;
+pthread_rwlock_t rrdset_root_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+int rrd_memory_mode = RRD_MEMORY_MODE_SAVE;
+
+
+// ----------------------------------------------------------------------------
+// RRDSET index
+
+static int rrdset_iterator(avl *a) { if(a) {}; return 0; }
+
+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);
+}
+
+avl_tree rrdset_root_index = {
+ NULL,
+ rrdset_compare
+};
+
+#define rrdset_index_add(st) avl_insert(&rrdset_root_index, (avl *)(st))
+#define rrdset_index_del(st) avl_remove(&rrdset_root_index, (avl *)(st))
+
+static RRDSET *rrdset_index_find(const char *id, uint32_t hash) {
+ RRDSET *result = NULL, tmp;
+ strncpy(tmp.id, id, RRD_ID_LENGTH_MAX);
+ tmp.id[RRD_ID_LENGTH_MAX] = '\0';
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
+
+ avl_search(&(rrdset_root_index), (avl *)&tmp, rrdset_iterator, (avl **)&result);
+ return result;
+}
+
+// ----------------------------------------------------------------------------
+// RRDSET name index
+
+#define rrdset_from_avlname(avlname_ptr) ((RRDSET *)((avlname_ptr) - offsetof(RRDSET, avlname)))
+
+static int rrdset_iterator_name(avl *a) { if(a) {}; return 0; }
+
+static int rrdset_compare_name(void* a, void* b) {
+ RRDSET *A = rrdset_from_avlname(a);
+ RRDSET *B = rrdset_from_avlname(b);
+
+ // fprintf(stderr, "COMPARING: %s with %s\n", A->name, B->name);
+
+ if(A->hash_name < B->hash_name) return -1;
+ else if(A->hash_name > B->hash_name) return 1;
+ else return strcmp(A->name, B->name);
+}
+
+avl_tree rrdset_root_index_name = {
+ NULL,
+ rrdset_compare_name
+};
+
+int rrdset_index_add_name(RRDSET *st) {
+ // fprintf(stderr, "ADDING: %s (name: %s)\n", st->id, st->name);
+ return avl_insert(&rrdset_root_index_name, (avl *)(&st->avlname));
+}
+
+#define rrdset_index_del_name(st) avl_remove(&rrdset_root_index_name, (avl *)(&st->avlname))
+
+static RRDSET *rrdset_index_find_name(const char *name, uint32_t hash) {
+ void *result = NULL;
+ RRDSET tmp;
+ tmp.name = name;
+ tmp.hash_name = (hash)?hash:simple_hash(tmp.name);
+
+ // fprintf(stderr, "SEARCHING: %s\n", name);
+ avl_search(&(rrdset_root_index_name), (avl *)(&(tmp.avlname)), rrdset_iterator_name, (avl **)&result);
+ if(result) {
+ RRDSET *st = rrdset_from_avlname(result);
+ if(strcmp(st->magic, RRDSET_MAGIC))
+ error("Search for RRDSET %s returned an invalid RRDSET %s (name %s)", name, st->id, st->name);
+
+ // fprintf(stderr, "FOUND: %s\n", name);
+ return rrdset_from_avlname(result);
+ }
+ // fprintf(stderr, "NOT FOUND: %s\n", name);
+ return NULL;
+}
+
+
+// ----------------------------------------------------------------------------
+// RRDDIM index
+
+static int rrddim_iterator(avl *a) { if(a) {}; return 0; }
+
+static int rrddim_compare(void* a, void* b) {
+ if(((RRDDIM *)a)->hash < ((RRDDIM *)b)->hash) return -1;
+ else if(((RRDDIM *)a)->hash > ((RRDDIM *)b)->hash) return 1;
+ else return strcmp(((RRDDIM *)a)->id, ((RRDDIM *)b)->id);
+}
+
+#define rrddim_index_add(st, rd) avl_insert(&((st)->dimensions_index), (avl *)(rd))
+#define rrddim_index_del(st,rd ) avl_remove(&((st)->dimensions_index), (avl *)(rd))
+
+static RRDDIM *rrddim_index_find(RRDSET *st, const char *id, uint32_t hash) {
+ RRDDIM *result = NULL, tmp;
+ strncpy(tmp.id, id, RRD_ID_LENGTH_MAX);
+ tmp.id[RRD_ID_LENGTH_MAX] = '\0';
+ tmp.hash = (hash)?hash:simple_hash(tmp.id);
+
+ avl_search(&(st->dimensions_index), (avl *)&tmp, rrddim_iterator, (avl **)&result);
+ return result;
+}