@cryptotaxi247 / netdata-1 / commits / 30b8da7b3

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);