@cryptotaxi247 / netdata-1 / commits / 44276ab9c

added TC qos options to control individual charts

Costa Tsaousis committed Jul 17, 2016 at 19:35 UTC 44276ab9c093410bc6a29804bbf74ca7717ae30f
1 file changed +193 -152
src/plugin_tc.c
+193 -152
@@ -15,7 +15,6 @@
15 #include "popen.h"
16 #include "plugin_tc.h"
17 #include "main.h"
18 -#include "../config.h"
18
19 #define RRD_TYPE_TC "tc"
20 #define RRD_TYPE_TC_LEN strlen(RRD_TYPE_TC)
@@ -78,6 +77,10 @@ struct tc_device {
77 char family_updated;
78
79 char enabled;
80 + char enabled_bytes;
81 + char enabled_packets;
82 + char enabled_dropped;
83 +
84 RRDSET *st_bytes;
85 RRDSET *st_packets;
86 RRDSET *st_dropped;
@@ -189,12 +192,19 @@ static inline void tc_device_classes_cleanup(struct tc_device *d) {
192 }
193
194 static inline void tc_device_commit(struct tc_device *d) {
192 - static int enable_new_interfaces = -1;
195 + static int enable_new_interfaces = -1, enable_bytes = -1, enable_packets = -1, enable_dropped = -1;
196
194 - if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean("plugin:tc", "enable new interfaces detected at runtime", 1);
197 + if(unlikely(enable_new_interfaces == -1)) {
198 + enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_YES);
199 + enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
200 + enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
201 + enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
202 + }
203
204 // we only need to add leaf classes
205 struct tc_class *c, *x;
206 + unsigned long long bytes_sum = 0, packets_sum = 0, dropped_sum = 0;
207 + int active_classes = 0;
208
209 // set all classes
210 for(c = d->classes ; c ; c = c->next) {
@@ -204,12 +214,12 @@ static inline void tc_device_commit(struct tc_device *d) {
214
215 // mark the classes as leafs and parents
216 for(c = d->classes ; c ; c = c->next) {
207 - if(!c->updated) continue;
217 + if(unlikely(!c->updated)) continue;
218
219 for(x = d->classes ; x ; x = x->next) {
210 - if(!x->updated) continue;
220 + if(unlikely(!x->updated)) continue;
221
212 - if(c == x) continue;
222 + if(unlikely(c == x)) continue;
223
224 if(x->parentid && (
225 ( c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) ||
@@ -233,9 +243,15 @@ static inline void tc_device_commit(struct tc_device *d) {
243 for(c = d->classes ; c ; c = c->next) {
244 // debug(D_TC_LOOP, "TC: Device '%s', class '%s', isLeaf=%d, HasParent=%d, Seen=%d", d->name?d->name:d->id, c->name?c->name:c->id, c->isleaf, c->hasparent, c->seen);
245 if(!c->updated) continue;
236 - if(c->isleaf && c->hasparent) break;
246 + if(c->isleaf && c->hasparent) {
247 + active_classes++;
248 + bytes_sum += c->bytes;
249 + packets_sum += c->packets;
250 + dropped_sum += c->dropped;
251 + }
252 }
238 - if(!c) {
253 +
254 + if(unlikely(!active_classes)) {
255 debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No leaf classes.", d->name?d->name:d->id);
256 tc_device_classes_cleanup(d);
257 return;
@@ -244,165 +260,182 @@ static inline void tc_device_commit(struct tc_device *d) {
260 if(unlikely(d->enabled == -1)) {
261 char var_name[CONFIG_MAX_NAME + 1];
262 snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id);
247 - d-> enabled = config_get_boolean("plugin:tc", var_name, enable_new_interfaces);
263 + d->enabled = config_get_boolean_ondemand("plugin:tc", var_name, enable_new_interfaces);
264 +
265 + snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", d->id);
266 + d->enabled_bytes = config_get_boolean_ondemand("plugin:tc", var_name, enable_bytes);
267 +
268 + snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", d->id);
269 + d->enabled_packets = config_get_boolean_ondemand("plugin:tc", var_name, enable_packets);
270 +
271 + snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", d->id);
272 + d->enabled_dropped = config_get_boolean_ondemand("plugin:tc", var_name, enable_dropped);
273 }
274
275 if(likely(d->enabled)) {
276 // --------------------------------------------------------------------
277 // bytes
278
254 - if(unlikely(!d->st_bytes)) {
255 - d->st_bytes = rrdset_find_bytype(RRD_TYPE_TC, d->id);
279 + if(d->enabled_bytes == CONFIG_ONDEMAND_YES || (d->enabled_bytes == CONFIG_ONDEMAND_ONDEMAND && bytes_sum)) {
280 + d->enabled_bytes = CONFIG_ONDEMAND_YES;
281 +
282 if(unlikely(!d->st_bytes)) {
257 - debug(D_TC_LOOP, "TC: Creating new chart for device '%s'", d->name?d->name:d->id);
258 - d->st_bytes = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, RRD_TYPE_TC ".qos", "Class Usage", "kilobits/s", 7000, rrd_update_every, RRDSET_TYPE_STACKED);
283 + d->st_bytes = rrdset_find_bytype(RRD_TYPE_TC, d->id);
284 + if(unlikely(!d->st_bytes)) {
285 + debug(D_TC_LOOP, "TC: Creating new chart for device '%s'", d->name?d->name:d->id);
286 + d->st_bytes = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, RRD_TYPE_TC ".qos", "Class Usage", "kilobits/s", 7000, rrd_update_every, RRDSET_TYPE_STACKED);
287 + }
288 }
260 - }
261 - else {
262 - debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id);
263 - rrdset_next_plugins(d->st_bytes);
289 + else {
290 + debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id);
291 + rrdset_next_plugins(d->st_bytes);
292
265 - if(unlikely(d->name_updated && d->name && strcmp(d->id, d->name) != 0)) {
266 - rrdset_set_name(d->st_bytes, d->name);
267 - d->name_updated = 0;
268 - }
293 + if(unlikely(d->name_updated && d->name && strcmp(d->id, d->name) != 0)) {
294 + rrdset_set_name(d->st_bytes, d->name);
295 + d->name_updated = 0;
296 + }
297
270 - // FIXME
271 - // update the family
272 - }
298 + // FIXME
299 + // update the family
300 + }
301
274 - for(c = d->classes ; c ; c = c->next) {
275 - if(unlikely(!c->updated)) continue;
302 + for(c = d->classes ; c ; c = c->next) {
303 + if(unlikely(!c->updated)) continue;
304
277 - c->seen++;
305 + if(c->isleaf && c->hasparent) {
306 + c->seen++;
307
279 - if(c->isleaf && c->hasparent) {
280 - if(unlikely(!c->rd_bytes)) {
281 - c->rd_bytes = rrddim_find(d->st_bytes, c->id);
308 if(unlikely(!c->rd_bytes)) {
283 - debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_bytes->id, c->id, c->name);
284 -
285 - // new class, we have to add it
286 - c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL);
309 + c->rd_bytes = rrddim_find(d->st_bytes, c->id);
310 + if(unlikely(!c->rd_bytes)) {
311 + debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_bytes->id, c->id, c->name);
312 +
313 + // new class, we have to add it
314 + c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL);
315 + }
316 + else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_bytes->id, c->id);
317 }
288 - else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_bytes->id, c->id);
289 - }
318
291 - rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes);
319 + rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes);
320
293 - // if it has a name, different to the id
294 - if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
295 - // update the rrd dimension with the new name
296 - debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_bytes->id, c->rd_bytes->id, c->name);
297 - rrddim_set_name(d->st_bytes, c->rd_bytes, c->name);
321 + // if it has a name, different to the id
322 + if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
323 + // update the rrd dimension with the new name
324 + debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_bytes->id, c->rd_bytes->id, c->name);
325 + rrddim_set_name(d->st_bytes, c->rd_bytes, c->name);
326 + }
327 }
328 }
329 + rrdset_done(d->st_bytes);
330 }
301 - rrdset_done(d->st_bytes);
331
332 // --------------------------------------------------------------------
333 // packets
334
306 - if(unlikely(!d->st_packets)) {
307 - char id[RRD_ID_LENGTH_MAX + 1];
308 - char name[RRD_ID_LENGTH_MAX + 1];
309 - snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id);
310 - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id);
335 + if(d->enabled_packets == CONFIG_ONDEMAND_YES || (d->enabled_packets == CONFIG_ONDEMAND_ONDEMAND && packets_sum)) {
336 + d->enabled_packets = CONFIG_ONDEMAND_YES;
337
312 - d->st_packets = rrdset_find_bytype(RRD_TYPE_TC, id);
338 if(unlikely(!d->st_packets)) {
314 - debug(D_TC_LOOP, "TC: Creating new _packets chart for device '%s'", d->name?d->name:d->id);
315 - d->st_packets = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010, rrd_update_every, RRDSET_TYPE_STACKED);
339 + char id[RRD_ID_LENGTH_MAX + 1];
340 + char name[RRD_ID_LENGTH_MAX + 1];
341 + snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id);
342 + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id);
343 +
344 + d->st_packets = rrdset_find_bytype(RRD_TYPE_TC, id);
345 + if(unlikely(!d->st_packets)) {
346 + debug(D_TC_LOOP, "TC: Creating new _packets chart for device '%s'", d->name?d->name:d->id);
347 + d->st_packets = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_packets", "Class Packets", "packets/s", 7010, rrd_update_every, RRDSET_TYPE_STACKED);
348 + }
349 }
317 - }
318 - else {
319 - debug(D_TC_LOOP, "TC: Updating _packets chart for device '%s'", d->name?d->name:d->id);
320 - rrdset_next_plugins(d->st_packets);
350 + else {
351 + debug(D_TC_LOOP, "TC: Updating _packets chart for device '%s'", d->name?d->name:d->id);
352 + rrdset_next_plugins(d->st_packets);
353
322 - // FIXME
323 - // update the family
324 - }
325 -
326 - for(c = d->classes ; c ; c = c->next) {
327 - if(unlikely(!c->updated)) continue;
354 + // FIXME
355 + // update the family
356 + }
357
329 - c->seen++;
358 + for(c = d->classes ; c ; c = c->next) {
359 + if(unlikely(!c->updated)) continue;
360
331 - if(c->isleaf && c->hasparent) {
332 - if(unlikely(!c->rd_packets)) {
333 - c->rd_packets = rrddim_find(d->st_packets, c->id);
361 + if(c->isleaf && c->hasparent) {
362 if(unlikely(!c->rd_packets)) {
335 - debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_packets->id, c->id, c->name);
336 -
337 - // new class, we have to add it
338 - c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
363 + c->rd_packets = rrddim_find(d->st_packets, c->id);
364 + if(unlikely(!c->rd_packets)) {
365 + debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_packets->id, c->id, c->name);
366 +
367 + // new class, we have to add it
368 + c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
369 + }
370 + else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_packets->id, c->id);
371 }
340 - else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_packets->id, c->id);
341 - }
372
343 - rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets);
373 + rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets);
374
345 - // if it has a name, different to the id
346 - if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
347 - // update the rrd dimension with the new name
348 - debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_packets->id, c->rd_packets->id, c->name);
349 - rrddim_set_name(d->st_packets, c->rd_packets, c->name);
375 + // if it has a name, different to the id
376 + if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
377 + // update the rrd dimension with the new name
378 + debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_packets->id, c->rd_packets->id, c->name);
379 + rrddim_set_name(d->st_packets, c->rd_packets, c->name);
380 + }
381 }
382 }
383 + rrdset_done(d->st_packets);
384 }
353 - rrdset_done(d->st_packets);
385
386 // --------------------------------------------------------------------
387 // dropped
388
358 - if(unlikely(!d->st_dropped)) {
359 - char id[RRD_ID_LENGTH_MAX + 1];
360 - char name[RRD_ID_LENGTH_MAX + 1];
361 - snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id);
362 - snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id);
363 -
364 - d->st_dropped = rrdset_find_bytype(RRD_TYPE_TC, id);
389 + if(d->enabled_dropped == CONFIG_ONDEMAND_YES || (d->enabled_dropped == CONFIG_ONDEMAND_ONDEMAND && dropped_sum)) {
390 + d->enabled_dropped = CONFIG_ONDEMAND_YES;
391 +
392 if(unlikely(!d->st_dropped)) {
366 - debug(D_TC_LOOP, "TC: Creating new _dropped chart for device '%s'", d->name?d->name:d->id);
367 - d->st_dropped = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s", 7020, rrd_update_every, RRDSET_TYPE_STACKED);
393 + char id[RRD_ID_LENGTH_MAX + 1];
394 + char name[RRD_ID_LENGTH_MAX + 1];
395 + snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id);
396 + snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id);
397 +
398 + d->st_dropped = rrdset_find_bytype(RRD_TYPE_TC, id);
399 + if(unlikely(!d->st_dropped)) {
400 + debug(D_TC_LOOP, "TC: Creating new _dropped chart for device '%s'", d->name?d->name:d->id);
401 + d->st_dropped = rrdset_create(RRD_TYPE_TC, id, name, d->family?d->family:d->id, RRD_TYPE_TC ".qos_dropped", "Class Dropped Packets", "packets/s", 7020, rrd_update_every, RRDSET_TYPE_STACKED);
402 + }
403 }
369 - }
370 - else {
371 - debug(D_TC_LOOP, "TC: Updating _dropped chart for device '%s'", d->name?d->name:d->id);
372 - rrdset_next_plugins(d->st_dropped);
373 -
374 - // FIXME
375 - // update the family
376 - }
404 + else {
405 + debug(D_TC_LOOP, "TC: Updating _dropped chart for device '%s'", d->name?d->name:d->id);
406 + rrdset_next_plugins(d->st_dropped);
407
378 - for(c = d->classes ; c ; c = c->next) {
379 - if(unlikely(!c->updated)) continue;
408 + // FIXME
409 + // update the family
410 + }
411
381 - c->seen++;
412 + for(c = d->classes ; c ; c = c->next) {
413 + if(unlikely(!c->updated)) continue;
414
383 - if(c->isleaf && c->hasparent) {
384 - if(unlikely(!c->rd_dropped)) {
385 - c->rd_dropped = rrddim_find(d->st_dropped, c->id);
415 + if(c->isleaf && c->hasparent) {
416 if(unlikely(!c->rd_dropped)) {
387 - debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_dropped->id, c->id, c->name);
388 -
389 - // new class, we have to add it
390 - c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
417 + c->rd_dropped = rrddim_find(d->st_dropped, c->id);
418 + if(unlikely(!c->rd_dropped)) {
419 + debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s' (name: '%s')", d->st_dropped->id, c->id, c->name);
420 +
421 + // new class, we have to add it
422 + c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRDDIM_INCREMENTAL);
423 + }
424 + else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_dropped->id, c->id);
425 }
392 - else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", d->st_dropped->id, c->id);
393 - }
426
395 - rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped);
427 + rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped);
428
397 - // if it has a name, different to the id
398 - if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
399 - // update the rrd dimension with the new name
400 - debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_dropped->id, c->rd_dropped->id, c->name);
401 - rrddim_set_name(d->st_dropped, c->rd_dropped, c->name);
429 + // if it has a name, different to the id
430 + if(unlikely(c->name_updated && c->name && strcmp(c->id, c->name) != 0)) {
431 + // update the rrd dimension with the new name
432 + debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", d->st_dropped->id, c->rd_dropped->id, c->name);
433 + rrddim_set_name(d->st_dropped, c->rd_dropped, c->name);
434 + }
435 }
436 }
437 + rrdset_done(d->st_dropped);
438 }
405 - rrdset_done(d->st_dropped);
439 }
440
441 tc_device_classes_cleanup(d);
@@ -607,9 +640,8 @@ static inline void tc_split_words(char *str, char **words, int max_words) {
640 }
641
642 pid_t tc_child_pid = 0;
610 -void *tc_main(void *ptr)
611 -{
612 - if(ptr) { ; }
643 +void *tc_main(void *ptr) {
644 + (void)ptr;
645
646 info("TC thread created with task id %d", gettid());
647
@@ -649,9 +681,9 @@ void *tc_main(void *ptr)
681
682 snprintfz(buffer, TC_LINE_MAX, "exec %s %d", config_get("plugin:tc", "script to run to get tc values", PLUGINS_DIR "/tc-qos-helper.sh"), rrd_update_every);
683 debug(D_TC_LOOP, "executing '%s'", buffer);
652 - // fp = popen(buffer, "r");
684 +
685 fp = mypopen(buffer, &tc_child_pid);
654 - if(!fp) {
686 + if(unlikely(!fp)) {
687 error("TC: Cannot popen(\"%s\", \"r\").", buffer);
688 pthread_exit(NULL);
689 return NULL;
@@ -664,6 +696,7 @@ void *tc_main(void *ptr)
696 // debug(D_TC_LOOP, "TC: read '%s'", buffer);
697
698 tc_split_words(buffer, words, MAX_WORDS);
699 +
700 if(unlikely(!words[0] || !*words[0])) {
701 // debug(D_TC_LOOP, "empty line");
702 continue;
@@ -675,13 +708,10 @@ void *tc_main(void *ptr)
708 if(unlikely(device && first_hash == CLASS_HASH && strcmp(words[0], "class") == 0)) {
709 // debug(D_TC_LOOP, "CLASS line on class id='%s', parent='%s', parentid='%s', leaf='%s', leafid='%s'", words[2], words[3], words[4], words[5], words[6]);
710
678 - // clear the last class
679 - class = NULL;
680 -
711 // words[1] : class type
712 // words[2] : N:XX
713 // words[3] : parent or root
684 - if(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0)) {
714 + if(likely(words[1] && words[2] && words[3] && (strcmp(words[3], "parent") == 0 || strcmp(words[3], "root") == 0))) {
715 //char *type = words[1]; // the class: htb, fq_codel, etc
716
717 // we are only interested for HTB classes
@@ -709,95 +739,105 @@ void *tc_main(void *ptr)
739
740 class = tc_class_add(device, id, parentid, leafid);
741 }
742 + else {
743 + // clear the last class
744 + class = NULL;
745 + }
746 }
747 else if(unlikely(first_hash == END_HASH && strcmp(words[0], "END") == 0)) {
748 // debug(D_TC_LOOP, "END line");
749
716 - if(device) {
750 + if(likely(device)) {
751 if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL) != 0)
752 error("Cannot set pthread cancel state to DISABLE.");
753
754 tc_device_commit(device);
755 // tc_device_free(device);
722 - device = NULL;
723 - class = NULL;
756
757 if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
758 error("Cannot set pthread cancel state to ENABLE.");
759 }
760 +
761 + device = NULL;
762 + class = NULL;
763 }
764 else if(unlikely(first_hash == BEGIN_HASH && strcmp(words[0], "BEGIN") == 0)) {
765 // debug(D_TC_LOOP, "BEGIN line on device '%s'", words[1]);
766
732 - if(device) {
767 + if(likely(words[1] && *words[1])) {
768 + device = tc_device_create(words[1]);
769 + }
770 + else {
771 // tc_device_free(device);
772 device = NULL;
735 - class = NULL;
773 }
774
738 - if(words[1] && *words[1]) {
739 - device = tc_device_create(words[1]);
740 - class = NULL;
741 - }
775 + class = NULL;
776 }
777 else if(unlikely(device && class && first_hash == SENT_HASH && strcmp(words[0], "Sent") == 0)) {
778 // debug(D_TC_LOOP, "SENT line '%s'", words[1]);
745 - if(words[1] && *words[1]) {
779 + if(likely(words[1] && *words[1])) {
780 class->bytes = strtoull(words[1], NULL, 10);
781 class->updated = 1;
782 }
783 + else {
784 + class->updated = 0;
785 + }
786
750 - if(words[3] && *words[3])
787 + if(likely(words[3] && *words[3]))
788 class->packets = strtoull(words[3], NULL, 10);
789
753 - if(words[6] && *words[6])
790 + if(likely(words[6] && *words[6]))
791 class->dropped = strtoull(words[6], NULL, 10);
792
756 - if(words[8] && *words[8])
793 + if(likely(words[8] && *words[8]))
794 class->overlimits = strtoull(words[8], NULL, 10);
795
759 - if(words[10] && *words[10])
796 + if(likely(words[10] && *words[10]))
797 class->requeues = strtoull(words[8], NULL, 10);
798 }
799 else if(unlikely(device && class && class->updated && first_hash == LENDED_HASH && strcmp(words[0], "lended:") == 0)) {
800 // debug(D_TC_LOOP, "LENDED line '%s'", words[1]);
764 - if(words[1] && *words[1])
801 + if(likely(words[1] && *words[1]))
802 class->lended = strtoull(words[1], NULL, 10);
803
767 - if(words[3] && *words[3])
804 + if(likely(words[3] && *words[3]))
805 class->borrowed = strtoull(words[3], NULL, 10);
806
770 - if(words[5] && *words[5])
807 + if(likely(words[5] && *words[5]))
808 class->giants = strtoull(words[5], NULL, 10);
809 }
810 else if(unlikely(device && class && class->updated && first_hash == TOKENS_HASH && strcmp(words[0], "tokens:") == 0)) {
811 // debug(D_TC_LOOP, "TOKENS line '%s'", words[1]);
775 - if(words[1] && *words[1])
812 + if(likely(words[1] && *words[1]))
813 class->tokens = strtoull(words[1], NULL, 10);
814
778 - if(words[3] && *words[3])
815 + if(likely(words[3] && *words[3]))
816 class->ctokens = strtoull(words[3], NULL, 10);
817 }
818 else if(unlikely(device && first_hash == SETDEVICENAME_HASH && strcmp(words[0], "SETDEVICENAME") == 0)) {
819 // debug(D_TC_LOOP, "SETDEVICENAME line '%s'", words[1]);
783 - if(words[1] && *words[1]) tc_device_set_device_name(device, words[1]);
820 + if(likely(words[1] && *words[1]))
821 + tc_device_set_device_name(device, words[1]);
822 }
823 else if(unlikely(device && first_hash == SETDEVICEGROUP_HASH && strcmp(words[0], "SETDEVICEGROUP") == 0)) {
824 // debug(D_TC_LOOP, "SETDEVICEGROUP line '%s'", words[1]);
787 - if(words[1] && *words[1]) tc_device_set_device_family(device, words[1]);
825 + if(likely(words[1] && *words[1]))
826 + tc_device_set_device_family(device, words[1]);
827 }
828 else if(unlikely(device && first_hash == SETCLASSNAME_HASH && strcmp(words[0], "SETCLASSNAME") == 0)) {
829 // debug(D_TC_LOOP, "SETCLASSNAME line '%s' '%s'", words[1], words[2]);
830 char *id = words[1];
831 char *path = words[2];
793 - if(id && *id && path && *path) tc_device_set_class_name(device, id, path);
832 + if(likely(id && *id && path && *path))
833 + tc_device_set_class_name(device, id, path);
834 }
835 else if(unlikely(first_hash == WORKTIME_HASH && strcmp(words[0], "WORKTIME") == 0)) {
836 // debug(D_TC_LOOP, "WORKTIME line '%s' '%s'", words[1], words[2]);
837 getrusage(RUSAGE_THREAD, &thread);
838
799 - if(!stcpu) stcpu = rrdset_find("netdata.plugin_tc_cpu");
800 - if(!stcpu) {
839 + if(unlikely(!stcpu)) stcpu = rrdset_find("netdata.plugin_tc_cpu");
840 + if(unlikely(!stcpu)) {
841 stcpu = rrdset_create("netdata", "plugin_tc_cpu", NULL, "tc.helper", NULL, "NetData TC CPU usage", "milliseconds/s", 135000, rrd_update_every, RRDSET_TYPE_STACKED);
842 rrddim_add(stcpu, "user", NULL, 1, 1000, RRDDIM_INCREMENTAL);
843 rrddim_add(stcpu, "system", NULL, 1, 1000, RRDDIM_INCREMENTAL);
@@ -808,8 +848,8 @@ void *tc_main(void *ptr)
848 rrddim_set(stcpu, "system", thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec);
849 rrdset_done(stcpu);
850
811 - if(!sttime) stcpu = rrdset_find("netdata.plugin_tc_time");
812 - if(!sttime) {
851 + if(unlikely(!sttime)) stcpu = rrdset_find("netdata.plugin_tc_time");
852 + if(unlikely(!sttime)) {
853 sttime = rrdset_create("netdata", "plugin_tc_time", NULL, "tc.helper", NULL, "NetData TC script execution", "milliseconds/run", 135001, rrd_update_every, RRDSET_TYPE_AREA);
854 rrddim_add(sttime, "run_time", "run time", 1, 1, RRDDIM_ABSOLUTE);
855 }
@@ -825,7 +865,7 @@ void *tc_main(void *ptr)
865 char *id = words[1];
866 pid_t pid = atol(id);
867
828 - if(pid) tc_child_pid = pid;
868 + if(likely(pid)) tc_child_pid = pid;
869
870 debug(D_TC_LOOP, "TC: Child PID is %d.", tc_child_pid);
871 }
@@ -834,17 +874,18 @@ void *tc_main(void *ptr)
874 // debug(D_TC_LOOP, "IGNORED line");
875 //}
876 }
877 +
878 // fgets() failed or loop broke
879 int code = mypclose(fp, tc_child_pid);
880 tc_child_pid = 0;
881
841 - if(device) {
882 + if(unlikely(device)) {
883 // tc_device_free(device);
884 device = NULL;
885 class = NULL;
886 }
887
847 - if(netdata_exit) {
888 + if(unlikely(netdata_exit)) {
889 tc_device_free_all();
890 pthread_exit(NULL);
891 return NULL;