added support for /sbin/tc - is not complete yet - it is disabled.
Costa Tsaousis (ktsaou) committed
Mar 24, 2014 at 00:54 UTC
30b8da7b3592f72b0274a4c0e36555ee8d4d51b6
1 file changed
+129
-3
netdata.c
+129
-3
@@ -47,6 +47,7 @@
47
#define D_PROCNETDEV_LOOP 0x00000020
48
#define D_RRD_STATS 0x00000040
49
#define D_WEB_CLIENT_ACCESS 0x00000080
50
+#define D_TC_LOOP 0x00000100
51
52
#define CT_APPLICATION_JSON 1
53
#define CT_TEXT_PLAIN 2
@@ -58,7 +59,7 @@
59
#define CT_TEXT_XSL 8
60
61
// configuration
61
-#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
62
+#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS|D_TC_LOOP)
63
//#define DEBUG 0xffffffff
64
//#define DEBUG (0)
65
@@ -1516,8 +1517,10 @@ void *proc_main(void *ptr)
1517
usec = usecdiff(&now, &last);
1518
debug(D_PROCNETDEV_LOOP, "PROCNETDEV: Last loop took %llu usec.", usec);
1519
1520
+ // BEGIN -- the job to be done
1521
do_proc_net_dev(usec);
1522
do_proc_diskstats(usec);
1523
+ // END -- the job is done
1524
1525
// find the time to sleep in order to wait exactly update_every seconds
1526
gettimeofday(&tmp, NULL);
@@ -1541,6 +1544,126 @@ void *proc_main(void *ptr)
1544
return NULL;
1545
}
1546
1547
+#define PIPE_READ 0
1548
+#define PIPE_WRITE 1
1549
+#define TC_SHOW_MAX 65536
1550
+
1551
+void *tc_main(void *ptr)
1552
+{
1553
+ return NULL;
1554
+
1555
+ char buffer[TC_SHOW_MAX+1] = "";
1556
+ struct timeval last, now, tmp;
1557
+ int pipefd[2];
1558
+ long i, len;
1559
+
1560
+ gettimeofday(&last, NULL);
1561
+ last.tv_sec -= update_every;
1562
+
1563
+ for(;1;) {
1564
+ unsigned long long usec, susec;
1565
+ gettimeofday(&now, NULL);
1566
+
1567
+ // calculate the time it took for a full loop
1568
+ usec = usecdiff(&now, &last);
1569
+ debug(D_TC_LOOP, "TC: Last loop took %llu usec.", usec);
1570
+
1571
+
1572
+
1573
+ // BEGIN -- the job to be done
1574
+
1575
+ /* --- BEGIN OF OLD VERSION ---
1576
+ // this works!
1577
+ // it is simpler...
1578
+ // but it is 2-3 times slower than the current implementation!
1579
+ // I guess the difference is that popen first runs /bin/sh.
1580
+
1581
+ FILE *fp = popen("/sbin/tc -s -d qdisc show", "r");
1582
+
1583
+ char *p;
1584
+ while((p = fgets(buffer, TC_SHOW_MAX, fp))) {
1585
+ buffer[TC_SHOW_MAX] = '\0';
1586
+ debug(D_TC_LOOP, "TC: read '%s'", p);
1587
+ }
1588
+ pclose(fp);
1589
+
1590
+ --- END OF OLD VERSION --- */
1591
+
1592
+ if(pipe(pipefd) != 0) {
1593
+ error("TC: Cannot create pipe for tc. TC will be disabled.");
1594
+ return NULL;
1595
+ }
1596
+
1597
+ pid_t pid = fork();
1598
+ if(pid == -1) {
1599
+ error("TC: cannot fork child. TC will be disabled.");
1600
+ return NULL;
1601
+ }
1602
+ else if(pid == 0) {
1603
+ // the child
1604
+
1605
+ // close the read fd of the pipe
1606
+ close(pipefd[PIPE_READ]);
1607
+
1608
+ // attach the pipe to stdout and stderr
1609
+ if(dup2(pipefd[PIPE_WRITE], STDOUT_FILENO) == -1) {
1610
+ error("TC: cannot attach pipe write to stdout.");
1611
+ exit(1);
1612
+ }
1613
+ if(dup2(pipefd[PIPE_WRITE], STDERR_FILENO) == -1) {
1614
+ error("TC: cannot attach pipe write to stderr.");
1615
+ exit(1);
1616
+ }
1617
+
1618
+ // execute tc to get the output
1619
+ execl("/sbin/tc", "-s", "-d", "qdisc", "show", NULL);
1620
+ exit(0);
1621
+ }
1622
+ // the parent
1623
+
1624
+ // close the write fd of the pipe
1625
+ close(pipefd[PIPE_WRITE]);
1626
+
1627
+ // read data from the pipe
1628
+ i = 1;
1629
+ len = 0;
1630
+ while(i > 0 && len < TC_SHOW_MAX) {
1631
+ debug(D_TC_LOOP, "TC: Reading from pipe...");
1632
+ i = read(pipefd[PIPE_READ], &buffer[len], TC_SHOW_MAX - len);
1633
+ if(i > 0) len += i;
1634
+ // debug(D_TC_LOOP, "TC READ: '%s'", buffer);
1635
+ }
1636
+ buffer[len] = '\0';
1637
+ debug(D_TC_LOOP, "TC: Completed reading %d bytes.", len);
1638
+ close(pipefd[PIPE_READ]);
1639
+
1640
+ // END -- the job is done
1641
+
1642
+
1643
+
1644
+ // find the time to sleep in order to wait exactly update_every seconds
1645
+ gettimeofday(&tmp, NULL);
1646
+ usec = usecdiff(&tmp, &now);
1647
+ debug(D_TC_LOOP, "TC: This loop took %llu usec.", usec);
1648
+
1649
+ if(usec < (update_every * 1000000)) susec = (update_every * 1000000) - usec;
1650
+ else susec = 0;
1651
+
1652
+ // make sure we will wait at least 100ms
1653
+ if(susec < 100000) susec = 100000;
1654
+
1655
+ debug(D_TC_LOOP, "TC: Sleeping for %llu usec.", susec);
1656
+ usleep(susec);
1657
+
1658
+ // copy now to last
1659
+ last.tv_sec = now.tv_sec;
1660
+ last.tv_usec = now.tv_usec;
1661
+ }
1662
+
1663
+ return NULL;
1664
+}
1665
+
1666
+
1667
int main(int argc, char **argv)
1668
{
1669
int i, daemon = 0;
@@ -1608,19 +1731,22 @@ int main(int argc, char **argv)
1731
silent = 1;
1732
}
1733
1611
- pthread_t p_proc;
1612
- int r_proc;
1734
+ pthread_t p_proc, p_tc;
1735
+ int r_proc, r_tc;
1736
1737
// spawn a child to collect data
1738
r_proc = pthread_create(&p_proc, NULL, proc_main, NULL);
1739
+ r_tc = pthread_create(&p_tc, NULL, tc_main, NULL);
1740
1741
// the main process - the web server listener
1742
//sleep(1);
1743
socket_listen_main(NULL);
1744
1745
// wait for the childs to finish
1746
+ pthread_join(p_tc, NULL);
1747
pthread_join(p_proc, NULL);
1748
1749
+ printf("TC thread returns: %d\n", r_tc);
1750
printf("PROC NET DEV thread returns: %d\n", r_proc);
1751
1752
exit(0);