avl_tree values_index;
struct config *next;
+
+ pthread_rwlock_t rwlock;
} *config_root = NULL;
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))
// 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;
}
else co->values = cv;
+ pthread_rwlock_unlock(&co->rwlock);
+
return cv;
}
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;
}
else config_root = co;
+ pthread_rwlock_unlock(&config_rwlock);
+
return co;
}
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;
}
fclose(fp);
- pthread_rwlock_unlock(&config_rwlock);
return 1;
}
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);
}
}
- pthread_rwlock_unlock(&config_rwlock);
return(cv->value);
}
sprintf(buffer, "%lld", value);
s = config_get(section, name, buffer);
- if(!s) return 0;
+ if(!s) return value;
return strtoll(s, NULL, 0);
}
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);
cv->value = strdup(value);
if(!cv->value) fatal("Cannot allocate config.value");
- pthread_rwlock_unlock(&config_rwlock);
-
return 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;
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"
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;
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);
}
}