]> arthur.barton.de Git - netdata.git/blobdiff - src/appconfig.c
cleanup locking; ability to compile AVL with MUTEX instead of RWLOCK; disks and inter...
[netdata.git] / src / appconfig.c
index 94002fe4c0bed74c7f4c2457fcba58405111b928..3ba7b91928e43b3dd68e81aa891632274eab4210 100755 (executable)
@@ -48,6 +48,8 @@ struct config {
        avl_tree values_index;
 
        struct config *next;
+
+       pthread_rwlock_t rwlock;
 } *config_root = NULL;
 
 
@@ -87,7 +89,12 @@ static int config_compare(void* a, void* b) {
 
 avl_tree config_root_index = {
                NULL,
-               config_compare
+               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))
@@ -120,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;
@@ -127,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;
 }
 
@@ -141,12 +152,15 @@ struct config *config_create(const char *section)
        if(!co->name) fatal("Cannot allocate config.name");
        co->hash = simple_hash(co->name);
 
-       co->values_index.compar = config_value_compare;
+       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;
@@ -154,6 +168,8 @@ struct config *config_create(const char *section)
        }
        else config_root = co;
 
+       pthread_rwlock_unlock(&config_rwlock);
+
        return co;
 }
 
@@ -167,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;
        }
 
@@ -246,7 +259,6 @@ int load_config(char *filename, int overwrite_used)
 
        fclose(fp);
 
-       pthread_rwlock_unlock(&config_rwlock);
        return 1;
 }
 
@@ -256,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);
 
@@ -277,7 +287,6 @@ char *config_get(const char *section, const char *name, const char *default_valu
                }
        }
 
-       pthread_rwlock_unlock(&config_rwlock);
        return(cv->value);
 }
 
@@ -287,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);
 }
@@ -299,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);
 
@@ -326,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;
 }
 
@@ -352,7 +383,7 @@ int config_set_boolean(const char *section, const char *name, int value)
        return value;
 }
 
-void generate_config(struct web_buffer *wb, int only_changed)
+void generate_config(BUFFER *wb, int only_changed)
 {
        int i, pri;
        struct config *co;
@@ -361,7 +392,7 @@ void generate_config(struct web_buffer *wb, int only_changed)
        for(i = 0; i < 3 ;i++) {
                switch(i) {
                        case 0:
-                               web_buffer_strcat(wb,
+                               buffer_strcat(wb,
                                        "# NetData Configuration\n"
                                        "# You can uncomment and change any of the options below.\n"
                                        "# The value shown in the commented settings, is the default value.\n"
@@ -369,14 +400,15 @@ void generate_config(struct web_buffer *wb, int only_changed)
                                break;
 
                        case 1:
-                               web_buffer_strcat(wb, "\n\n# per plugin configuration\n");
+                               buffer_strcat(wb, "\n\n# per plugin configuration\n");
                                break;
 
                        case 2:
-                               web_buffer_strcat(wb, "\n\n# per chart configuration\n");
+                               buffer_strcat(wb, "\n\n# per chart configuration\n");
                                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;
@@ -386,30 +418,38 @@ void generate_config(struct web_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;
 
                                if(!used) {
-                                       web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX+1, "\n# node '%s' is not used.", co->name);
+                                       buffer_sprintf(wb, "\n# node '%s' is not used.", co->name);
                                }
 
-                               web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX+1, "\n[%s]\n", co->name);
+                               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)) {
-                                               web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX + 1, "\n\t# option '%s' is not used.\n", cv->name);
+                                               buffer_sprintf(wb, "\n\t# option '%s' is not used.\n", cv->name);
                                        }
-                                       web_buffer_snprintf(wb, CONFIG_FILE_LINE_MAX + 1, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
+                                       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);
        }
 }