]> arthur.barton.de Git - netdata.git/commitdiff
cleanup locking; ability to compile AVL with MUTEX instead of RWLOCK; disks and inter...
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Fri, 25 Dec 2015 18:50:10 +0000 (20:50 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Fri, 25 Dec 2015 18:50:10 +0000 (20:50 +0200)
src/appconfig.c
src/appconfig.h
src/apps_plugin.c
src/avl.c
src/avl.h
src/plugin_tc.c
src/proc_diskstats.c
src/proc_net_dev.c
src/rrd.c
tests/stress.sh

index 1735dbdf8655f7c6015832da5630129904c340ea..3ba7b91928e43b3dd68e81aa891632274eab4210 100755 (executable)
@@ -48,6 +48,8 @@ struct config {
        avl_tree values_index;
 
        struct config *next;
+
+       pthread_rwlock_t rwlock;
 } *config_root = NULL;
 
 
@@ -88,7 +90,11 @@ static int config_compare(void* a, void* b) {
 avl_tree config_root_index = {
                NULL,
                config_compare,
+#ifdef AVL_LOCK_WITH_MUTEX
+               PTHREAD_MUTEX_INITIALIZER
+#else
                PTHREAD_RWLOCK_INITIALIZER
+#endif
 };
 
 #define config_index_add(cfg) avl_insert(&config_root_index, (avl *)(cfg))
@@ -121,6 +127,8 @@ struct config_value *config_value_create(struct config *co, const char *name, co
 
        // no need for string termination, due to calloc()
 
+       pthread_rwlock_wrlock(&co->rwlock);
+
        struct config_value *cv2 = co->values;
        if(cv2) {
                while (cv2->next) cv2 = cv2->next;
@@ -128,6 +136,8 @@ struct config_value *config_value_create(struct config *co, const char *name, co
        }
        else co->values = cv;
 
+       pthread_rwlock_unlock(&co->rwlock);
+
        return cv;
 }
 
@@ -142,12 +152,15 @@ struct config *config_create(const char *section)
        if(!co->name) fatal("Cannot allocate config.name");
        co->hash = simple_hash(co->name);
 
+       pthread_rwlock_init(&co->rwlock, NULL);
        avl_init(&co->values_index, config_value_compare);
 
        config_index_add(co);
 
        // no need for string termination, due to calloc()
 
+       pthread_rwlock_wrlock(&config_rwlock);
+
        struct config *co2 = config_root;
        if(co2) {
                while (co2->next) co2 = co2->next;
@@ -155,6 +168,8 @@ struct config *config_create(const char *section)
        }
        else config_root = co;
 
+       pthread_rwlock_unlock(&config_rwlock);
+
        return co;
 }
 
@@ -168,15 +183,12 @@ int load_config(char *filename, int overwrite_used)
        int line = 0;
        struct config *co = NULL;
 
-       pthread_rwlock_wrlock(&config_rwlock);
-
        char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
 
        if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
        FILE *fp = fopen(filename, "r");
        if(!fp) {
                error("Cannot open file '%s'", CONFIG_DIR "/" CONFIG_FILENAME);
-               pthread_rwlock_unlock(&config_rwlock);
                return 0;
        }
 
@@ -247,7 +259,6 @@ int load_config(char *filename, int overwrite_used)
 
        fclose(fp);
 
-       pthread_rwlock_unlock(&config_rwlock);
        return 1;
 }
 
@@ -257,8 +268,6 @@ char *config_get(const char *section, const char *name, const char *default_valu
 
        debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);
 
-       pthread_rwlock_rdlock(&config_rwlock);
-
        struct config *co = config_find_section(section);
        if(!co) co = config_create(section);
 
@@ -278,7 +287,6 @@ char *config_get(const char *section, const char *name, const char *default_valu
                }
        }
 
-       pthread_rwlock_unlock(&config_rwlock);
        return(cv->value);
 }
 
@@ -288,7 +296,7 @@ long long config_get_number(const char *section, const char *name, long long val
        sprintf(buffer, "%lld", value);
 
        s = config_get(section, name, buffer);
-       if(!s) return 0;
+       if(!s) return value;
 
        return strtoll(s, NULL, 0);
 }
@@ -300,20 +308,44 @@ int config_get_boolean(const char *section, const char *name, int value)
        else s = "no";
 
        s = config_get(section, name, s);
-       if(!s) return 0;
+       if(!s) return value;
 
        if(!strcmp(s, "yes")) return 1;
        else return 0;
 }
 
+int config_get_boolean_ondemand(const char *section, const char *name, int value)
+{
+       char *s;
+
+       if(value == CONFIG_ONDEMAND_ONDEMAND)
+               s = "on demand";
+
+       else if(value == CONFIG_ONDEMAND_NO)
+               s = "no";
+
+       else
+               s = "yes";
+
+       s = config_get(section, name, s);
+       if(!s) return value;
+
+       if(!strcmp(s, "yes"))
+               return CONFIG_ONDEMAND_YES;
+       else if(!strcmp(s, "no"))
+               return CONFIG_ONDEMAND_NO;
+       else if(!strcmp(s, "on demand"))
+               return CONFIG_ONDEMAND_ONDEMAND;
+
+       return value;
+}
+
 const char *config_set(const char *section, const char *name, const char *value)
 {
        struct config_value *cv;
 
        debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
 
-       pthread_rwlock_wrlock(&config_rwlock);
-
        struct config *co = config_find_section(section);
        if(!co) co = config_create(section);
 
@@ -327,8 +359,6 @@ const char *config_set(const char *section, const char *name, const char *value)
        cv->value = strdup(value);
        if(!cv->value) fatal("Cannot allocate config.value");
 
-       pthread_rwlock_unlock(&config_rwlock);
-
        return value;
 }
 
@@ -378,6 +408,7 @@ void generate_config(BUFFER *wb, int only_changed)
                                break;
                }
 
+               pthread_rwlock_wrlock(&config_rwlock);
                for(co = config_root; co ; co = co->next) {
                        if(strcmp(co->name, "global") == 0 || strcmp(co->name, "plugins") == 0) pri = 0;
                        else if(strncmp(co->name, "plugin:", 7) == 0) pri = 1;
@@ -387,12 +418,17 @@ void generate_config(BUFFER *wb, int only_changed)
                                int used = 0;
                                int changed = 0;
                                int count = 0;
+
+                               pthread_rwlock_wrlock(&co->rwlock);
+
                                for(cv = co->values; cv ; cv = cv->next) {
                                        used += (cv->flags && CONFIG_VALUE_USED)?1:0;
                                        changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0;
                                        count++;
                                }
 
+                               pthread_rwlock_unlock(&co->rwlock);
+
                                if(!count) continue;
                                if(only_changed && !changed) continue;
 
@@ -402,6 +438,7 @@ void generate_config(BUFFER *wb, int only_changed)
 
                                buffer_sprintf(wb, "\n[%s]\n", co->name);
 
+                               pthread_rwlock_wrlock(&co->rwlock);
                                for(cv = co->values; cv ; cv = cv->next) {
 
                                        if(used && !(cv->flags & CONFIG_VALUE_USED)) {
@@ -409,8 +446,10 @@ void generate_config(BUFFER *wb, int only_changed)
                                        }
                                        buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
                                }
+                               pthread_rwlock_unlock(&co->rwlock);
                        }
                }
+               pthread_rwlock_unlock(&config_rwlock);
        }
 }
 
index 365d1e2f12bb2bb6bfd542f069beebb8cbfaba0a..5cfda99be38a1e7947357ee0a018d8613dee3632 100755 (executable)
@@ -16,6 +16,11 @@ extern char *config_get(const char *section, const char *name, const char *defau
 extern long long config_get_number(const char *section, const char *name, long long value);
 extern int config_get_boolean(const char *section, const char *name, int value);
 
+#define CONFIG_ONDEMAND_NO 0
+#define CONFIG_ONDEMAND_YES 1
+#define CONFIG_ONDEMAND_ONDEMAND 2
+extern int config_get_boolean_ondemand(const char *section, const char *name, int value);
+
 extern const char *config_set(const char *section, const char *name, const char *value);
 extern long long config_set_number(const char *section, const char *name, long long value);
 extern int config_set_boolean(const char *section, const char *name, int value);
index e81014a818cd2f077884d32f21fac70284aa4b8f..a7285c4f25c27a44acce57f165e4851a9f9845a7 100755 (executable)
@@ -831,7 +831,11 @@ int file_descriptor_iterator(avl *a) { if(a) {}; return 0; }
 avl_tree all_files_index = {
                NULL,
                file_descriptor_compare,
+#ifdef AVL_LOCK_WITH_MUTEX
+               PTHREAD_MUTEX_INITIALIZER
+#else
                PTHREAD_RWLOCK_INITIALIZER
+#endif
 };
 
 static struct file_descriptor *file_descriptor_find(const char *name, uint32_t hash) {
index 9cc72283d84dad626a883127da3031a37d423bb1..f5d67dc20f1c9a08e4b764ac522eab20f5a74d3f 100755 (executable)
--- a/src/avl.c
+++ b/src/avl.c
@@ -144,9 +144,19 @@ int _avl_insert(avl_tree* t, avl* a) {
        }
 }
 int avl_insert(avl_tree* t, avl* a) {
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_lock(&t->mutex);
+#else
        pthread_rwlock_wrlock(&t->rwlock);
+#endif
+
        int ret = _avl_insert(t, a);
+
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_unlock(&t->mutex);
+#else
        pthread_rwlock_unlock(&t->rwlock);
+#endif
        return ret;
 }
 
@@ -232,9 +242,19 @@ int _avl_remove(avl_tree* t, avl* a) {
 }
 
 int avl_remove(avl_tree* t, avl* a) {
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_lock(&t->mutex);
+#else
        pthread_rwlock_wrlock(&t->rwlock);
+#endif
+
        int ret = _avl_remove(t, a);
+
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_unlock(&t->mutex);
+#else
        pthread_rwlock_unlock(&t->rwlock);
+#endif
        return ret;
 }
 
@@ -278,9 +298,19 @@ int _avl_removeroot(avl_tree* t) {
 }
 
 int avl_removeroot(avl_tree* t) {
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_lock(&t->mutex);
+#else
        pthread_rwlock_wrlock(&t->rwlock);
+#endif
+
        int ret = _avl_removeroot(t);
+
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_unlock(&t->mutex);
+#else
        pthread_rwlock_unlock(&t->rwlock);
+#endif
        return ret;
 }
 
@@ -332,9 +362,20 @@ int _avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl* a), avl** ret) {
 }
 
 int avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl* a), avl** ret) {
-       pthread_rwlock_rdlock(&t->rwlock);
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_lock(&t->mutex);
+#else
+       pthread_rwlock_wrlock(&t->rwlock);
+#endif
+
        int ret2 = _avl_range(t, a, b, iter, ret);
+
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_unlock(&t->mutex);
+#else
        pthread_rwlock_unlock(&t->rwlock);
+#endif
+
        return ret2;
 }
 
@@ -349,5 +390,9 @@ int avl_search(avl_tree* t, avl* a, int (*iter)(avl* a), avl** ret) {
 void avl_init(avl_tree* t, int (*compar)(void* a, void* b)) {
        t->root = NULL;
        t->compar = compar;
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_init(&t->mutex, NULL);
+#else
        pthread_rwlock_init(&t->rwlock, NULL);
+#endif
 }
index 8071a87d6ddd456ac4a974359b82bd4d99255ebd..888eed19298a4f489c79477bc1730ec6310285f3 100755 (executable)
--- a/src/avl.h
+++ b/src/avl.h
@@ -17,6 +17,8 @@
 #ifndef _AVL_H
 #define _AVL_H 1
 
+// #define AVL_LOCK_WITH_MUTEX 1
+
 /* Data structures */
 
 /* One element of the AVL tree */
@@ -30,7 +32,12 @@ typedef struct avl {
 typedef struct avl_tree {
        avl* root;
        int (*compar)(void* a, void* b);
+
+#ifdef AVL_LOCK_WITH_MUTEX
+       pthread_mutex_t mutex;
+#else
        pthread_rwlock_t rwlock;
+#endif
 } avl_tree;
 
 /* Public methods */
index 01a93be7a1e340f37f14b78fe96564ed66c3c427..1a4be02d4452fc729ac8a6acf6e60286566fdfef 100755 (executable)
@@ -84,7 +84,11 @@ static int tc_device_compare(void* a, void* b) {
 avl_tree tc_device_root_index = {
                NULL,
                tc_device_compare,
+#ifdef AVL_LOCK_WITH_MUTEX
+               PTHREAD_MUTEX_INITIALIZER
+#else
                PTHREAD_RWLOCK_INITIALIZER
+#endif
 };
 
 #define tc_device_index_add(st) avl_insert(&tc_device_root_index, (avl *)(st))
@@ -333,7 +337,11 @@ static struct tc_device *tc_device_create(char *id)
 
                d->classes_index.root = NULL;
                d->classes_index.compar = tc_class_compare;
+#ifdef AVL_LOCK_WITH_MUTEX
+               pthread_mutex_init(&d->classes_index.mutex, NULL);
+#else
                pthread_rwlock_init(&d->classes_index.rwlock, NULL);
+#endif
 
                tc_device_index_add(d);
 
index 7322664f7ea617826b393c3ac196efd7017cc3c8..8e4da0eb3f7d581a337d3ed942c5a0e71be927be 100755 (executable)
@@ -23,15 +23,15 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
        static int enable_new_disks = -1;
        static int do_io = -1, do_ops = -1, do_mops = -1, do_iotime = -1, do_qops = -1, do_util = -1, do_backlog = -1;
 
-       if(enable_new_disks == -1)      enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
+       if(enable_new_disks == -1)      enable_new_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
 
-       if(do_io == -1)         do_io           = config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
-       if(do_ops == -1)        do_ops          = config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
-       if(do_mops == -1)       do_mops         = config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
-       if(do_iotime == -1)     do_iotime       = config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
-       if(do_qops == -1)       do_qops         = config_get_boolean("plugin:proc:/proc/diskstats", "queued operations for all disks", 1);
-       if(do_util == -1)       do_util         = config_get_boolean("plugin:proc:/proc/diskstats", "utilization percentage for all disks", 1);
-       if(do_backlog == -1)do_backlog  = config_get_boolean("plugin:proc:/proc/diskstats", "backlog for all disks", 1);
+       if(do_io == -1)         do_io           = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "bandwidth for all disks", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_ops == -1)        do_ops          = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_mops == -1)       do_mops         = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "merged operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_iotime == -1)     do_iotime       = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "i/o time for all disks", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_qops == -1)       do_qops         = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "queued operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_util == -1)       do_util         = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "utilization percentage for all disks", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_backlog == -1)do_backlog  = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "backlog for all disks", CONFIG_ONDEMAND_ONDEMAND);
 
        if(!ff) {
                char filename[FILENAME_MAX + 1];
@@ -111,17 +111,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
                backlog_ms              = strtoull(procfile_lineword(ff, l, 13), NULL, 10);     // rq_ticks
 
 
-               // do not add a disk that is completely idle
-               if(!reads && !writes && !busy_ms) continue;
-
                int def_enabled = 0;
-               int ddo_io = do_io, ddo_ops = do_ops, ddo_mops = do_mops, ddo_iotime = do_iotime, ddo_qops = do_qops, ddo_util = do_util, ddo_backlog = do_backlog;
-
-               // by default, do not add charts that do not have values
-               if(mreads == 0 && mwrites == 0) ddo_mops = 0;
-               if(readms == 0 && writems == 0) ddo_iotime = 0;
-               if(busy_ms == 0) ddo_util = 0;
-               if(backlog_ms == 0) { ddo_backlog = 0; ddo_qops = 0; }
 
                // remove slashes from disk names
                char *s;
@@ -244,19 +234,36 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
                                break;
                }
 
+               int ddo_io = do_io, ddo_ops = do_ops, ddo_mops = do_mops, ddo_iotime = do_iotime, ddo_qops = do_qops, ddo_util = do_util, ddo_backlog = do_backlog;
+
                // check which charts are enabled for this disk
                {
                        char var_name[4096 + 1];
                        snprintf(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
-                       if(!config_get_boolean(var_name, "enabled", def_enabled)) continue;
-
-                       ddo_io          = config_get_boolean(var_name, "bandwidth", ddo_io);
-                       ddo_ops         = config_get_boolean(var_name, "operations", ddo_ops);
-                       ddo_mops        = config_get_boolean(var_name, "merged operations", ddo_mops);
-                       ddo_iotime      = config_get_boolean(var_name, "i/o time", ddo_iotime);
-                       ddo_qops        = config_get_boolean(var_name, "queued operations", ddo_qops);
-                       ddo_util        = config_get_boolean(var_name, "utilization percentage", ddo_util);
-                       ddo_backlog = config_get_boolean(var_name, "backlog", ddo_backlog);
+                       def_enabled = config_get_boolean_ondemand(var_name, "enabled", def_enabled);
+                       if(def_enabled == CONFIG_ONDEMAND_NO) continue;
+                       if(def_enabled == CONFIG_ONDEMAND_ONDEMAND && !reads && !writes) continue;
+
+
+                       ddo_io          = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
+                       ddo_ops         = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
+                       ddo_mops        = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
+                       ddo_iotime      = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
+                       ddo_qops        = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
+                       ddo_util        = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
+                       ddo_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
+
+                       // by default, do not add charts that do not have values
+                       if(ddo_io == CONFIG_ONDEMAND_ONDEMAND && !reads && !writes) ddo_io = 0;
+                       if(ddo_mops == CONFIG_ONDEMAND_ONDEMAND && mreads == 0 && mwrites == 0) ddo_mops = 0;
+                       if(ddo_iotime == CONFIG_ONDEMAND_ONDEMAND && readms == 0 && writems == 0) ddo_iotime = 0;
+                       if(ddo_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms == 0) ddo_util = 0;
+                       if(ddo_backlog == CONFIG_ONDEMAND_ONDEMAND && backlog_ms == 0) ddo_backlog = 0;
+                       if(ddo_qops == CONFIG_ONDEMAND_ONDEMAND && backlog_ms == 0) ddo_qops = 0;
+
+                       // for absolute values, we need to switch the setting to 'yes'
+                       // to allow it refresh from now on
+                       if(ddo_qops == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "queued operations", "yes");
                }
 
                RRDSET *st;
index ed0c2f113fc34d42204290304c01d4fc02d01b9b..ec1cabbdb6395f32d4e9e4fc597fb8b13635fdfa 100755 (executable)
@@ -28,16 +28,16 @@ int do_proc_net_dev(int update_every, unsigned long long dt) {
        ff = procfile_readall(ff);
        if(!ff) return 0; // we return 0, so that we will retry to open it next time
 
-       if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", 1);
-       if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean("plugin:proc:/proc/net/dev", "enable ifb interfaces", 0);
+       if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
+       if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
 
-       if(do_bandwidth == -1)  do_bandwidth    = config_get_boolean("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", 1);
-       if(do_packets == -1)    do_packets              = config_get_boolean("plugin:proc:/proc/net/dev", "packets for all interfaces", 1);
-       if(do_errors == -1)             do_errors               = config_get_boolean("plugin:proc:/proc/net/dev", "errors for all interfaces", 1);
-       if(do_drops == -1)              do_drops                = config_get_boolean("plugin:proc:/proc/net/dev", "drops for all interfaces", 1);
-       if(do_fifo == -1)               do_fifo                 = config_get_boolean("plugin:proc:/proc/net/dev", "fifo for all interfaces", 1);
-       if(do_compressed == -1) do_compressed   = config_get_boolean("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", 1);
-       if(do_events == -1)             do_events               = config_get_boolean("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", 1);
+       if(do_bandwidth == -1)  do_bandwidth    = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_packets == -1)    do_packets              = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_errors == -1)             do_errors               = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_drops == -1)              do_drops                = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_fifo == -1)               do_fifo                 = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_compressed == -1) do_compressed   = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
+       if(do_events == -1)             do_events               = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
 
        uint32_t lines = procfile_lines(ff), l;
        uint32_t words;
@@ -72,16 +72,10 @@ int do_proc_net_dev(int update_every, unsigned long long dt) {
 
                int ddo_bandwidth = do_bandwidth, ddo_packets = do_packets, ddo_errors = do_errors, ddo_drops = do_drops, ddo_fifo = do_fifo, ddo_compressed = do_compressed, ddo_events = do_events;
 
-               if(rerrors == 0 && terrors == 0) ddo_errors = 0;
-               if(rdrops == 0 && tdrops == 0) ddo_drops = 0;
-               if(rfifo == 0 && tfifo == 0) ddo_fifo = 0;
-               if(rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
-               if(rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
-
                int default_enable = enable_new_interfaces;
 
                // prevent unused interfaces from creating charts
-               if(!rbytes && !tbytes || strcmp(iface, "lo") == 0)
+               if(strcmp(iface, "lo") == 0)
                        default_enable = 0;
                else {
                        int len = strlen(iface);
@@ -93,13 +87,28 @@ int do_proc_net_dev(int update_every, unsigned long long dt) {
                {
                        char var_name[512 + 1];
                        snprintf(var_name, 512, "plugin:proc:/proc/net/dev:%s", iface);
-                       if(!config_get_boolean(var_name, "enabled", default_enable)) continue;
-
-                       ddo_errors = config_get_boolean(var_name, "errors", ddo_errors);
-                       ddo_drops = config_get_boolean(var_name, "drops", ddo_drops);
-                       ddo_fifo = config_get_boolean(var_name, "fifo", ddo_fifo);
-                       ddo_compressed = config_get_boolean(var_name, "compressed", ddo_compressed);
-                       ddo_events = config_get_boolean(var_name, "events", ddo_events);
+                       default_enable = config_get_boolean_ondemand(var_name, "enabled", default_enable);
+                       if(default_enable == CONFIG_ONDEMAND_NO) continue;
+                       if(default_enable == CONFIG_ONDEMAND_ONDEMAND && !rbytes && !tbytes) continue;
+
+                       ddo_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", ddo_bandwidth);
+                       ddo_packets = config_get_boolean_ondemand(var_name, "packets", ddo_packets);
+                       ddo_errors = config_get_boolean_ondemand(var_name, "errors", ddo_errors);
+                       ddo_drops = config_get_boolean_ondemand(var_name, "drops", ddo_drops);
+                       ddo_fifo = config_get_boolean_ondemand(var_name, "fifo", ddo_fifo);
+                       ddo_compressed = config_get_boolean_ondemand(var_name, "compressed", ddo_compressed);
+                       ddo_events = config_get_boolean_ondemand(var_name, "events", ddo_events);
+
+                       if(ddo_bandwidth == CONFIG_ONDEMAND_ONDEMAND && rbytes == 0 && tbytes == 0) ddo_bandwidth = 0;
+                       if(ddo_errors == CONFIG_ONDEMAND_ONDEMAND && rerrors == 0 && terrors == 0) ddo_errors = 0;
+                       if(ddo_drops == CONFIG_ONDEMAND_ONDEMAND && rdrops == 0 && tdrops == 0) ddo_drops = 0;
+                       if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND && rfifo == 0 && tfifo == 0) ddo_fifo = 0;
+                       if(ddo_compressed == CONFIG_ONDEMAND_ONDEMAND && rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
+                       if(ddo_events == CONFIG_ONDEMAND_ONDEMAND && rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
+
+                       // for absolute values, we need to switch the setting to 'yes'
+                       // to allow it refresh from now on
+                       if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "fifo", "yes");
                }
 
                RRDSET *st;
index 3dd617a823f83bb4d5aa1774c7301fc78ed2f428..3881d51320684b32e714ef1b1e86d89dd51e0ab4 100755 (executable)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -53,7 +53,11 @@ static int rrdset_compare(void* a, void* b) {
 avl_tree rrdset_root_index = {
                NULL,
                rrdset_compare,
+#ifdef AVL_LOCK_WITH_MUTEX
+               PTHREAD_MUTEX_INITIALIZER
+#else
                PTHREAD_RWLOCK_INITIALIZER
+#endif
 };
 
 #define rrdset_index_add(st) avl_insert(&rrdset_root_index, (avl *)(st))
@@ -90,7 +94,11 @@ static int rrdset_compare_name(void* a, void* b) {
 avl_tree rrdset_root_index_name = {
                NULL,
                rrdset_compare_name,
+#ifdef AVL_LOCK_WITH_MUTEX
+               PTHREAD_MUTEX_INITIALIZER
+#else
                PTHREAD_RWLOCK_INITIALIZER
+#endif
 };
 
 int rrdset_index_add_name(RRDSET *st) {
@@ -562,6 +570,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
        rd->counter = 0;
 
        // append this dimension
+       pthread_rwlock_wrlock(&st->rwlock);
        if(!st->dimensions)
                st->dimensions = rd;
        else {
@@ -569,6 +578,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
                for(; td->next; td = td->next) ;
                td->next = rd;
        }
+       pthread_rwlock_unlock(&st->rwlock);
 
        rrddim_index_add(st, rd);
 
@@ -686,10 +696,7 @@ RRDSET *rrdset_find(const char *id)
 {
        debug(D_RRD_CALLS, "rrdset_find() for chart %s", id);
 
-       pthread_rwlock_rdlock(&rrdset_root_rwlock);
        RRDSET *st = rrdset_index_find(id, 0);
-       pthread_rwlock_unlock(&rrdset_root_rwlock);
-
        return(st);
 }
 
@@ -713,10 +720,7 @@ RRDSET *rrdset_find_byname(const char *name)
 {
        debug(D_RRD_CALLS, "rrdset_find_byname() for chart %s", name);
 
-       pthread_rwlock_rdlock(&rrdset_root_rwlock);
        RRDSET *st = rrdset_index_find_name(name, 0);
-       pthread_rwlock_unlock(&rrdset_root_rwlock);
-
        return(st);
 }
 
index 013ca70e09c8efe1d01048794ccb471b229118a9..572dc7d19c6ea546372f58fea2b4d0b267d61750 100755 (executable)
@@ -22,6 +22,14 @@ update_every="$(curl "$host/netdata.conf" 2>/dev/null | grep "update every = " |
 entries="$(curl "$host/netdata.conf" 2>/dev/null | grep "history = " | head -n 1 | cut -d '=' -f 2)"
 [ $[ entries + 1 - 1] -eq 0 ] && entries=3600
 
+# to compare equal things, set the entries to 3600 max
+[ $entries -gt 3600 ] && entries=3600
+
+if [ $entries -ne 3600 ]
+       then
+       echo >&2 "You are running a test for a history of $entries entries."
+fi
+
 modes=("average" "max")
 formats=("jsonp" "json" "ssv" "csv" "datatable" "datasource" "tsv" "ssvcomma" "html" "array")
 options="flip|jsonwrap"