@cryptotaxi247 / netdata-1 / commits / a2588ccbb

cleanup locking; ability to compile AVL with MUTEX instead of RWLOCK; disks and interfaces now have "on demand" all their options

Costa Tsaousis (ktsaou) committed Dec 25, 2015 at 20:50 UTC a2588ccbb1aec299407e390ce5bc5244504cc9c7
10 files changed +206 -70
src/appconfig.c
+52 -13
@@ -48,6 +48,8 @@ struct config {
48 avl_tree values_index;
49
50 struct config *next;
51 +
52 + pthread_rwlock_t rwlock;
53 } *config_root = NULL;
54
55
@@ -88,7 +90,11 @@ static int config_compare(void* a, void* b) {
90 avl_tree config_root_index = {
91 NULL,
92 config_compare,
93 +#ifdef AVL_LOCK_WITH_MUTEX
94 + PTHREAD_MUTEX_INITIALIZER
95 +#else
96 PTHREAD_RWLOCK_INITIALIZER
97 +#endif
98 };
99
100 #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
127
128 // no need for string termination, due to calloc()
129
130 + pthread_rwlock_wrlock(&co->rwlock);
131 +
132 struct config_value *cv2 = co->values;
133 if(cv2) {
134 while (cv2->next) cv2 = cv2->next;
@@ -128,6 +136,8 @@ struct config_value *config_value_create(struct config *co, const char *name, co
136 }
137 else co->values = cv;
138
139 + pthread_rwlock_unlock(&co->rwlock);
140 +
141 return cv;
142 }
143
@@ -142,12 +152,15 @@ struct config *config_create(const char *section)
152 if(!co->name) fatal("Cannot allocate config.name");
153 co->hash = simple_hash(co->name);
154
155 + pthread_rwlock_init(&co->rwlock, NULL);
156 avl_init(&co->values_index, config_value_compare);
157
158 config_index_add(co);
159
160 // no need for string termination, due to calloc()
161
162 + pthread_rwlock_wrlock(&config_rwlock);
163 +
164 struct config *co2 = config_root;
165 if(co2) {
166 while (co2->next) co2 = co2->next;
@@ -155,6 +168,8 @@ struct config *config_create(const char *section)
168 }
169 else config_root = co;
170
171 + pthread_rwlock_unlock(&config_rwlock);
172 +
173 return co;
174 }
175
@@ -168,15 +183,12 @@ int load_config(char *filename, int overwrite_used)
183 int line = 0;
184 struct config *co = NULL;
185
171 - pthread_rwlock_wrlock(&config_rwlock);
172 -
186 char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
187
188 if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
189 FILE *fp = fopen(filename, "r");
190 if(!fp) {
191 error("Cannot open file '%s'", CONFIG_DIR "/" CONFIG_FILENAME);
179 - pthread_rwlock_unlock(&config_rwlock);
192 return 0;
193 }
194
@@ -247,7 +259,6 @@ int load_config(char *filename, int overwrite_used)
259
260 fclose(fp);
261
250 - pthread_rwlock_unlock(&config_rwlock);
262 return 1;
263 }
264
@@ -257,8 +268,6 @@ char *config_get(const char *section, const char *name, const char *default_valu
268
269 debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);
270
260 - pthread_rwlock_rdlock(&config_rwlock);
261 -
271 struct config *co = config_find_section(section);
272 if(!co) co = config_create(section);
273
@@ -278,7 +287,6 @@ char *config_get(const char *section, const char *name, const char *default_valu
287 }
288 }
289
281 - pthread_rwlock_unlock(&config_rwlock);
290 return(cv->value);
291 }
292
@@ -288,7 +296,7 @@ long long config_get_number(const char *section, const char *name, long long val
296 sprintf(buffer, "%lld", value);
297
298 s = config_get(section, name, buffer);
291 - if(!s) return 0;
299 + if(!s) return value;
300
301 return strtoll(s, NULL, 0);
302 }
@@ -300,20 +308,44 @@ int config_get_boolean(const char *section, const char *name, int value)
308 else s = "no";
309
310 s = config_get(section, name, s);
303 - if(!s) return 0;
311 + if(!s) return value;
312
313 if(!strcmp(s, "yes")) return 1;
314 else return 0;
315 }
316
317 +int config_get_boolean_ondemand(const char *section, const char *name, int value)
318 +{
319 + char *s;
320 +
321 + if(value == CONFIG_ONDEMAND_ONDEMAND)
322 + s = "on demand";
323 +
324 + else if(value == CONFIG_ONDEMAND_NO)
325 + s = "no";
326 +
327 + else
328 + s = "yes";
329 +
330 + s = config_get(section, name, s);
331 + if(!s) return value;
332 +
333 + if(!strcmp(s, "yes"))
334 + return CONFIG_ONDEMAND_YES;
335 + else if(!strcmp(s, "no"))
336 + return CONFIG_ONDEMAND_NO;
337 + else if(!strcmp(s, "on demand"))
338 + return CONFIG_ONDEMAND_ONDEMAND;
339 +
340 + return value;
341 +}
342 +
343 const char *config_set(const char *section, const char *name, const char *value)
344 {
345 struct config_value *cv;
346
347 debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
348
315 - pthread_rwlock_wrlock(&config_rwlock);
316 -
349 struct config *co = config_find_section(section);
350 if(!co) co = config_create(section);
351
@@ -327,8 +359,6 @@ const char *config_set(const char *section, const char *name, const char *value)
359 cv->value = strdup(value);
360 if(!cv->value) fatal("Cannot allocate config.value");
361
330 - pthread_rwlock_unlock(&config_rwlock);
331 -
362 return value;
363 }
364
@@ -378,6 +408,7 @@ void generate_config(BUFFER *wb, int only_changed)
408 break;
409 }
410
411 + pthread_rwlock_wrlock(&config_rwlock);
412 for(co = config_root; co ; co = co->next) {
413 if(strcmp(co->name, "global") == 0 || strcmp(co->name, "plugins") == 0) pri = 0;
414 else if(strncmp(co->name, "plugin:", 7) == 0) pri = 1;
@@ -387,12 +418,17 @@ void generate_config(BUFFER *wb, int only_changed)
418 int used = 0;
419 int changed = 0;
420 int count = 0;
421 +
422 + pthread_rwlock_wrlock(&co->rwlock);
423 +
424 for(cv = co->values; cv ; cv = cv->next) {
425 used += (cv->flags && CONFIG_VALUE_USED)?1:0;
426 changed += (cv->flags & CONFIG_VALUE_CHANGED)?1:0;
427 count++;
428 }
429
430 + pthread_rwlock_unlock(&co->rwlock);
431 +
432 if(!count) continue;
433 if(only_changed && !changed) continue;
434
@@ -402,6 +438,7 @@ void generate_config(BUFFER *wb, int only_changed)
438
439 buffer_sprintf(wb, "\n[%s]\n", co->name);
440
441 + pthread_rwlock_wrlock(&co->rwlock);
442 for(cv = co->values; cv ; cv = cv->next) {
443
444 if(used && !(cv->flags & CONFIG_VALUE_USED)) {
@@ -409,8 +446,10 @@ void generate_config(BUFFER *wb, int only_changed)
446 }
447 buffer_sprintf(wb, "\t%s%s = %s\n", ((!(cv->flags & CONFIG_VALUE_CHANGED)) && (cv->flags & CONFIG_VALUE_USED))?"# ":"", cv->name, cv->value);
448 }
449 + pthread_rwlock_unlock(&co->rwlock);
450 }
451 }
452 + pthread_rwlock_unlock(&config_rwlock);
453 }
454 }
455
src/appconfig.h
+5
@@ -16,6 +16,11 @@ extern char *config_get(const char *section, const char *name, const char *defau
16 extern long long config_get_number(const char *section, const char *name, long long value);
17 extern int config_get_boolean(const char *section, const char *name, int value);
18
19 +#define CONFIG_ONDEMAND_NO 0
20 +#define CONFIG_ONDEMAND_YES 1
21 +#define CONFIG_ONDEMAND_ONDEMAND 2
22 +extern int config_get_boolean_ondemand(const char *section, const char *name, int value);
23 +
24 extern const char *config_set(const char *section, const char *name, const char *value);
25 extern long long config_set_number(const char *section, const char *name, long long value);
26 extern int config_set_boolean(const char *section, const char *name, int value);
src/apps_plugin.c
+4
@@ -831,7 +831,11 @@ int file_descriptor_iterator(avl *a) { if(a) {}; return 0; }
831 avl_tree all_files_index = {
832 NULL,
833 file_descriptor_compare,
834 +#ifdef AVL_LOCK_WITH_MUTEX
835 + PTHREAD_MUTEX_INITIALIZER
836 +#else
837 PTHREAD_RWLOCK_INITIALIZER
838 +#endif
839 };
840
841 static struct file_descriptor *file_descriptor_find(const char *name, uint32_t hash) {
src/avl.c
+46 -1
@@ -144,9 +144,19 @@ int _avl_insert(avl_tree* t, avl* a) {
144 }
145 }
146 int avl_insert(avl_tree* t, avl* a) {
147 +#ifdef AVL_LOCK_WITH_MUTEX
148 + pthread_mutex_lock(&t->mutex);
149 +#else
150 pthread_rwlock_wrlock(&t->rwlock);
151 +#endif
152 +
153 int ret = _avl_insert(t, a);
154 +
155 +#ifdef AVL_LOCK_WITH_MUTEX
156 + pthread_mutex_unlock(&t->mutex);
157 +#else
158 pthread_rwlock_unlock(&t->rwlock);
159 +#endif
160 return ret;
161 }
162
@@ -232,9 +242,19 @@ int _avl_remove(avl_tree* t, avl* a) {
242 }
243
244 int avl_remove(avl_tree* t, avl* a) {
245 +#ifdef AVL_LOCK_WITH_MUTEX
246 + pthread_mutex_lock(&t->mutex);
247 +#else
248 pthread_rwlock_wrlock(&t->rwlock);
249 +#endif
250 +
251 int ret = _avl_remove(t, a);
252 +
253 +#ifdef AVL_LOCK_WITH_MUTEX
254 + pthread_mutex_unlock(&t->mutex);
255 +#else
256 pthread_rwlock_unlock(&t->rwlock);
257 +#endif
258 return ret;
259 }
260
@@ -278,9 +298,19 @@ int _avl_removeroot(avl_tree* t) {
298 }
299
300 int avl_removeroot(avl_tree* t) {
301 +#ifdef AVL_LOCK_WITH_MUTEX
302 + pthread_mutex_lock(&t->mutex);
303 +#else
304 pthread_rwlock_wrlock(&t->rwlock);
305 +#endif
306 +
307 int ret = _avl_removeroot(t);
308 +
309 +#ifdef AVL_LOCK_WITH_MUTEX
310 + pthread_mutex_unlock(&t->mutex);
311 +#else
312 pthread_rwlock_unlock(&t->rwlock);
313 +#endif
314 return ret;
315 }
316
@@ -332,9 +362,20 @@ int _avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl* a), avl** ret) {
362 }
363
364 int avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl* a), avl** ret) {
335 - pthread_rwlock_rdlock(&t->rwlock);
365 +#ifdef AVL_LOCK_WITH_MUTEX
366 + pthread_mutex_lock(&t->mutex);
367 +#else
368 + pthread_rwlock_wrlock(&t->rwlock);
369 +#endif
370 +
371 int ret2 = _avl_range(t, a, b, iter, ret);
372 +
373 +#ifdef AVL_LOCK_WITH_MUTEX
374 + pthread_mutex_unlock(&t->mutex);
375 +#else
376 pthread_rwlock_unlock(&t->rwlock);
377 +#endif
378 +
379 return ret2;
380 }
381
@@ -349,5 +390,9 @@ int avl_search(avl_tree* t, avl* a, int (*iter)(avl* a), avl** ret) {
390 void avl_init(avl_tree* t, int (*compar)(void* a, void* b)) {
391 t->root = NULL;
392 t->compar = compar;
393 +#ifdef AVL_LOCK_WITH_MUTEX
394 + pthread_mutex_init(&t->mutex, NULL);
395 +#else
396 pthread_rwlock_init(&t->rwlock, NULL);
397 +#endif
398 }
src/avl.h
+7
@@ -17,6 +17,8 @@
17 #ifndef _AVL_H
18 #define _AVL_H 1
19
20 +// #define AVL_LOCK_WITH_MUTEX 1
21 +
22 /* Data structures */
23
24 /* One element of the AVL tree */
@@ -30,7 +32,12 @@ typedef struct avl {
32 typedef struct avl_tree {
33 avl* root;
34 int (*compar)(void* a, void* b);
35 +
36 +#ifdef AVL_LOCK_WITH_MUTEX
37 + pthread_mutex_t mutex;
38 +#else
39 pthread_rwlock_t rwlock;
40 +#endif
41 } avl_tree;
42
43 /* Public methods */
src/plugin_tc.c
+8
@@ -84,7 +84,11 @@ static int tc_device_compare(void* a, void* b) {
84 avl_tree tc_device_root_index = {
85 NULL,
86 tc_device_compare,
87 +#ifdef AVL_LOCK_WITH_MUTEX
88 + PTHREAD_MUTEX_INITIALIZER
89 +#else
90 PTHREAD_RWLOCK_INITIALIZER
91 +#endif
92 };
93
94 #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)
337
338 d->classes_index.root = NULL;
339 d->classes_index.compar = tc_class_compare;
340 +#ifdef AVL_LOCK_WITH_MUTEX
341 + pthread_mutex_init(&d->classes_index.mutex, NULL);
342 +#else
343 pthread_rwlock_init(&d->classes_index.rwlock, NULL);
344 +#endif
345
346 tc_device_index_add(d);
347
src/proc_diskstats.c
+34 -27
@@ -23,15 +23,15 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
23 static int enable_new_disks = -1;
24 static int do_io = -1, do_ops = -1, do_mops = -1, do_iotime = -1, do_qops = -1, do_util = -1, do_backlog = -1;
25
26 - if(enable_new_disks == -1) enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
26 + 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);
27
28 - if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
29 - if(do_ops == -1) do_ops = config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
30 - if(do_mops == -1) do_mops = config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
31 - if(do_iotime == -1) do_iotime = config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
32 - if(do_qops == -1) do_qops = config_get_boolean("plugin:proc:/proc/diskstats", "queued operations for all disks", 1);
33 - if(do_util == -1) do_util = config_get_boolean("plugin:proc:/proc/diskstats", "utilization percentage for all disks", 1);
34 - if(do_backlog == -1)do_backlog = config_get_boolean("plugin:proc:/proc/diskstats", "backlog for all disks", 1);
28 + if(do_io == -1) do_io = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "bandwidth for all disks", CONFIG_ONDEMAND_ONDEMAND);
29 + if(do_ops == -1) do_ops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
30 + if(do_mops == -1) do_mops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "merged operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
31 + if(do_iotime == -1) do_iotime = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "i/o time for all disks", CONFIG_ONDEMAND_ONDEMAND);
32 + if(do_qops == -1) do_qops = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "queued operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
33 + if(do_util == -1) do_util = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "utilization percentage for all disks", CONFIG_ONDEMAND_ONDEMAND);
34 + if(do_backlog == -1)do_backlog = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "backlog for all disks", CONFIG_ONDEMAND_ONDEMAND);
35
36 if(!ff) {
37 char filename[FILENAME_MAX + 1];
@@ -111,17 +111,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
111 backlog_ms = strtoull(procfile_lineword(ff, l, 13), NULL, 10); // rq_ticks
112
113
114 - // do not add a disk that is completely idle
115 - if(!reads && !writes && !busy_ms) continue;
116 -
114 int def_enabled = 0;
118 - 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;
119 -
120 - // by default, do not add charts that do not have values
121 - if(mreads == 0 && mwrites == 0) ddo_mops = 0;
122 - if(readms == 0 && writems == 0) ddo_iotime = 0;
123 - if(busy_ms == 0) ddo_util = 0;
124 - if(backlog_ms == 0) { ddo_backlog = 0; ddo_qops = 0; }
115
116 // remove slashes from disk names
117 char *s;
@@ -244,19 +234,36 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
234 break;
235 }
236
237 + 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;
238 +
239 // check which charts are enabled for this disk
240 {
241 char var_name[4096 + 1];
242 snprintf(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
251 - if(!config_get_boolean(var_name, "enabled", def_enabled)) continue;
252 -
253 - ddo_io = config_get_boolean(var_name, "bandwidth", ddo_io);
254 - ddo_ops = config_get_boolean(var_name, "operations", ddo_ops);
255 - ddo_mops = config_get_boolean(var_name, "merged operations", ddo_mops);
256 - ddo_iotime = config_get_boolean(var_name, "i/o time", ddo_iotime);
257 - ddo_qops = config_get_boolean(var_name, "queued operations", ddo_qops);
258 - ddo_util = config_get_boolean(var_name, "utilization percentage", ddo_util);
259 - ddo_backlog = config_get_boolean(var_name, "backlog", ddo_backlog);
243 + def_enabled = config_get_boolean_ondemand(var_name, "enabled", def_enabled);
244 + if(def_enabled == CONFIG_ONDEMAND_NO) continue;
245 + if(def_enabled == CONFIG_ONDEMAND_ONDEMAND && !reads && !writes) continue;
246 +
247 +
248 + ddo_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
249 + ddo_ops = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
250 + ddo_mops = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
251 + ddo_iotime = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
252 + ddo_qops = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
253 + ddo_util = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
254 + ddo_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
255 +
256 + // by default, do not add charts that do not have values
257 + if(ddo_io == CONFIG_ONDEMAND_ONDEMAND && !reads && !writes) ddo_io = 0;
258 + if(ddo_mops == CONFIG_ONDEMAND_ONDEMAND && mreads == 0 && mwrites == 0) ddo_mops = 0;
259 + if(ddo_iotime == CONFIG_ONDEMAND_ONDEMAND && readms == 0 && writems == 0) ddo_iotime = 0;
260 + if(ddo_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms == 0) ddo_util = 0;
261 + if(ddo_backlog == CONFIG_ONDEMAND_ONDEMAND && backlog_ms == 0) ddo_backlog = 0;
262 + if(ddo_qops == CONFIG_ONDEMAND_ONDEMAND && backlog_ms == 0) ddo_qops = 0;
263 +
264 + // for absolute values, we need to switch the setting to 'yes'
265 + // to allow it refresh from now on
266 + if(ddo_qops == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "queued operations", "yes");
267 }
268
269 RRDSET *st;
src/proc_net_dev.c
+32 -23
@@ -28,16 +28,16 @@ int do_proc_net_dev(int update_every, unsigned long long dt) {
28 ff = procfile_readall(ff);
29 if(!ff) return 0; // we return 0, so that we will retry to open it next time
30
31 - if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", 1);
32 - if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean("plugin:proc:/proc/net/dev", "enable ifb interfaces", 0);
31 + 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);
32 + if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
33
34 - if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", 1);
35 - if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/dev", "packets for all interfaces", 1);
36 - if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/dev", "errors for all interfaces", 1);
37 - if(do_drops == -1) do_drops = config_get_boolean("plugin:proc:/proc/net/dev", "drops for all interfaces", 1);
38 - if(do_fifo == -1) do_fifo = config_get_boolean("plugin:proc:/proc/net/dev", "fifo for all interfaces", 1);
39 - if(do_compressed == -1) do_compressed = config_get_boolean("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", 1);
40 - if(do_events == -1) do_events = config_get_boolean("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", 1);
34 + if(do_bandwidth == -1) do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
35 + if(do_packets == -1) do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
36 + if(do_errors == -1) do_errors = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
37 + if(do_drops == -1) do_drops = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
38 + if(do_fifo == -1) do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
39 + if(do_compressed == -1) do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
40 + 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);
41
42 uint32_t lines = procfile_lines(ff), l;
43 uint32_t words;
@@ -72,16 +72,10 @@ int do_proc_net_dev(int update_every, unsigned long long dt) {
72
73 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;
74
75 - if(rerrors == 0 && terrors == 0) ddo_errors = 0;
76 - if(rdrops == 0 && tdrops == 0) ddo_drops = 0;
77 - if(rfifo == 0 && tfifo == 0) ddo_fifo = 0;
78 - if(rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
79 - if(rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
80 -
75 int default_enable = enable_new_interfaces;
76
77 // prevent unused interfaces from creating charts
84 - if(!rbytes && !tbytes || strcmp(iface, "lo") == 0)
78 + if(strcmp(iface, "lo") == 0)
79 default_enable = 0;
80 else {
81 int len = strlen(iface);
@@ -93,13 +87,28 @@ int do_proc_net_dev(int update_every, unsigned long long dt) {
87 {
88 char var_name[512 + 1];
89 snprintf(var_name, 512, "plugin:proc:/proc/net/dev:%s", iface);
96 - if(!config_get_boolean(var_name, "enabled", default_enable)) continue;
97 -
98 - ddo_errors = config_get_boolean(var_name, "errors", ddo_errors);
99 - ddo_drops = config_get_boolean(var_name, "drops", ddo_drops);
100 - ddo_fifo = config_get_boolean(var_name, "fifo", ddo_fifo);
101 - ddo_compressed = config_get_boolean(var_name, "compressed", ddo_compressed);
102 - ddo_events = config_get_boolean(var_name, "events", ddo_events);
90 + default_enable = config_get_boolean_ondemand(var_name, "enabled", default_enable);
91 + if(default_enable == CONFIG_ONDEMAND_NO) continue;
92 + if(default_enable == CONFIG_ONDEMAND_ONDEMAND && !rbytes && !tbytes) continue;
93 +
94 + ddo_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", ddo_bandwidth);
95 + ddo_packets = config_get_boolean_ondemand(var_name, "packets", ddo_packets);
96 + ddo_errors = config_get_boolean_ondemand(var_name, "errors", ddo_errors);
97 + ddo_drops = config_get_boolean_ondemand(var_name, "drops", ddo_drops);
98 + ddo_fifo = config_get_boolean_ondemand(var_name, "fifo", ddo_fifo);
99 + ddo_compressed = config_get_boolean_ondemand(var_name, "compressed", ddo_compressed);
100 + ddo_events = config_get_boolean_ondemand(var_name, "events", ddo_events);
101 +
102 + if(ddo_bandwidth == CONFIG_ONDEMAND_ONDEMAND && rbytes == 0 && tbytes == 0) ddo_bandwidth = 0;
103 + if(ddo_errors == CONFIG_ONDEMAND_ONDEMAND && rerrors == 0 && terrors == 0) ddo_errors = 0;
104 + if(ddo_drops == CONFIG_ONDEMAND_ONDEMAND && rdrops == 0 && tdrops == 0) ddo_drops = 0;
105 + if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND && rfifo == 0 && tfifo == 0) ddo_fifo = 0;
106 + if(ddo_compressed == CONFIG_ONDEMAND_ONDEMAND && rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
107 + if(ddo_events == CONFIG_ONDEMAND_ONDEMAND && rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;
108 +
109 + // for absolute values, we need to switch the setting to 'yes'
110 + // to allow it refresh from now on
111 + if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "fifo", "yes");
112 }
113
114 RRDSET *st;
src/rrd.c
+10 -6
@@ -53,7 +53,11 @@ static int rrdset_compare(void* a, void* b) {
53 avl_tree rrdset_root_index = {
54 NULL,
55 rrdset_compare,
56 +#ifdef AVL_LOCK_WITH_MUTEX
57 + PTHREAD_MUTEX_INITIALIZER
58 +#else
59 PTHREAD_RWLOCK_INITIALIZER
60 +#endif
61 };
62
63 #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) {
94 avl_tree rrdset_root_index_name = {
95 NULL,
96 rrdset_compare_name,
97 +#ifdef AVL_LOCK_WITH_MUTEX
98 + PTHREAD_MUTEX_INITIALIZER
99 +#else
100 PTHREAD_RWLOCK_INITIALIZER
101 +#endif
102 };
103
104 int rrdset_index_add_name(RRDSET *st) {
@@ -562,6 +570,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
570 rd->counter = 0;
571
572 // append this dimension
573 + pthread_rwlock_wrlock(&st->rwlock);
574 if(!st->dimensions)
575 st->dimensions = rd;
576 else {
@@ -569,6 +578,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
578 for(; td->next; td = td->next) ;
579 td->next = rd;
580 }
581 + pthread_rwlock_unlock(&st->rwlock);
582
583 rrddim_index_add(st, rd);
584
@@ -686,10 +696,7 @@ RRDSET *rrdset_find(const char *id)
696 {
697 debug(D_RRD_CALLS, "rrdset_find() for chart %s", id);
698
689 - pthread_rwlock_rdlock(&rrdset_root_rwlock);
699 RRDSET *st = rrdset_index_find(id, 0);
691 - pthread_rwlock_unlock(&rrdset_root_rwlock);
692 -
700 return(st);
701 }
702
@@ -713,10 +720,7 @@ RRDSET *rrdset_find_byname(const char *name)
720 {
721 debug(D_RRD_CALLS, "rrdset_find_byname() for chart %s", name);
722
716 - pthread_rwlock_rdlock(&rrdset_root_rwlock);
723 RRDSET *st = rrdset_index_find_name(name, 0);
718 - pthread_rwlock_unlock(&rrdset_root_rwlock);
719 -
724 return(st);
725 }
726
tests/stress.sh
+8
@@ -22,6 +22,14 @@ update_every="$(curl "$host/netdata.conf" 2>/dev/null | grep "update every = " |
22 entries="$(curl "$host/netdata.conf" 2>/dev/null | grep "history = " | head -n 1 | cut -d '=' -f 2)"
23 [ $[ entries + 1 - 1] -eq 0 ] && entries=3600
24
25 +# to compare equal things, set the entries to 3600 max
26 +[ $entries -gt 3600 ] && entries=3600
27 +
28 +if [ $entries -ne 3600 ]
29 + then
30 + echo >&2 "You are running a test for a history of $entries entries."
31 +fi
32 +
33 modes=("average" "max")
34 formats=("jsonp" "json" "ssv" "csv" "datatable" "datasource" "tsv" "ssvcomma" "html" "array")
35 options="flip|jsonwrap"