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"