X-Git-Url: https://arthur.barton.de/gitweb/?a=blobdiff_plain;f=src%2Fappconfig.c;h=3ba7b91928e43b3dd68e81aa891632274eab4210;hb=a2588ccbb1aec299407e390ce5bc5244504cc9c7;hp=0f957e40e87b3ece815e634b4275df88f49c6266;hpb=537e212e1d9e9d64c250d43f39791e9ff30159af;p=netdata.git diff --git a/src/appconfig.c b/src/appconfig.c index 0f957e40..3ba7b919 100755 --- a/src/appconfig.c +++ b/src/appconfig.c @@ -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; } @@ -353,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; @@ -362,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" @@ -370,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; @@ -387,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); } }