Changeset 7388

Show
Ignore:
Timestamp:
09/01/11 23:54:29 (22 months ago)
Author:
jow
Message:

modules/admin-full: rework realtime stats to start luci-bwc on demand, kill daemon after ten seconds of inactivity

Location:
luci/trunk/modules/admin-full
Files:
1 removed
2 modified

Legend:

Unmodified
Added
Removed
  • luci/trunk/modules/admin-full/luasrc/controller/admin/status.lua

    r7362 r7388  
    7070    local iface = path[#path] 
    7171 
    72     local fs = require "luci.fs" 
    73     if fs.access("/var/lib/luci-bwc/if/%s" % iface) then 
    74         luci.http.prepare_content("application/json") 
     72    luci.http.prepare_content("application/json") 
    7573 
    76         local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface) 
    77         if bwc then 
    78             luci.http.write("[") 
     74    local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface) 
     75    if bwc then 
     76        luci.http.write("[") 
    7977 
    80             while true do 
    81                 local ln = bwc:read("*l") 
    82                 if not ln then break end 
    83                 luci.http.write(ln) 
    84             end 
    85  
    86             luci.http.write("]") 
    87             bwc:close() 
     78        while true do 
     79            local ln = bwc:read("*l") 
     80            if not ln then break end 
     81            luci.http.write(ln) 
    8882        end 
    8983 
    90         return 
     84        luci.http.write("]") 
     85        bwc:close() 
    9186    end 
    92  
    93     luci.http.status(404, "No data available") 
    9487end 
    9588 
    9689function action_load() 
    97     local fs = require "luci.fs" 
    98     if fs.access("/var/lib/luci-bwc/load") then 
    99         luci.http.prepare_content("application/json") 
     90    luci.http.prepare_content("application/json") 
    10091 
    101         local bwc = io.popen("luci-bwc -l 2>/dev/null") 
    102         if bwc then 
    103             luci.http.write("[") 
     92    local bwc = io.popen("luci-bwc -l 2>/dev/null") 
     93    if bwc then 
     94        luci.http.write("[") 
    10495 
    105             while true do 
    106                 local ln = bwc:read("*l") 
    107                 if not ln then break end 
    108                 luci.http.write(ln) 
    109             end 
    110  
    111             luci.http.write("]") 
    112             bwc:close() 
     96        while true do 
     97            local ln = bwc:read("*l") 
     98            if not ln then break end 
     99            luci.http.write(ln) 
    113100        end 
    114101 
    115         return 
     102        luci.http.write("]") 
     103        bwc:close() 
    116104    end 
    117  
    118     luci.http.status(404, "No data available") 
    119105end 
    120106 
    121107function action_connections() 
    122     local fs  = require "luci.fs" 
    123108    local sys = require "luci.sys" 
    124109 
     
    128113    luci.http.write_json(sys.net.conntrack()) 
    129114 
    130     if fs.access("/var/lib/luci-bwc/connections") then 
    131         local bwc = io.popen("luci-bwc -c 2>/dev/null") 
    132         if bwc then 
    133             luci.http.write(", statistics: [") 
     115    local bwc = io.popen("luci-bwc -c 2>/dev/null") 
     116    if bwc then 
     117        luci.http.write(", statistics: [") 
    134118 
    135             while true do 
    136                 local ln = bwc:read("*l") 
    137                 if not ln then break end 
    138                 luci.http.write(ln) 
    139             end 
     119        while true do 
     120            local ln = bwc:read("*l") 
     121            if not ln then break end 
     122            luci.http.write(ln) 
     123        end 
    140124 
    141             luci.http.write("]") 
    142             bwc:close() 
    143         end 
     125        luci.http.write("]") 
     126        bwc:close() 
    144127    end 
    145128 
  • luci/trunk/modules/admin-full/src/luci-bwc.c

    r6959 r7388  
    2626#include <errno.h> 
    2727#include <unistd.h> 
     28#include <signal.h> 
    2829 
    2930#include <sys/stat.h> 
     
    3435#define STEP_COUNT  60 
    3536#define STEP_TIME   1 
     37#define TIMEOUT     10 
     38 
     39#define PID_PATH    "/var/run/luci-bwc.pid" 
    3640 
    3741#define DB_PATH     "/var/lib/luci-bwc" 
     
    9195#define ntohll htonll 
    9296 
     97static int readpid(void) 
     98{ 
     99    int fd; 
     100    int pid = -1; 
     101    char buf[9] = { 0 }; 
     102 
     103    if ((fd = open(PID_PATH, O_RDONLY)) > -1) 
     104    { 
     105        if (read(fd, buf, sizeof(buf))) 
     106        { 
     107            buf[8] = 0; 
     108            pid = atoi(buf); 
     109        } 
     110 
     111        close(fd); 
     112    } 
     113 
     114    return pid; 
     115} 
     116 
     117static int writepid(void) 
     118{ 
     119    int fd; 
     120    int wlen; 
     121    char buf[9] = { 0 }; 
     122 
     123    if ((fd = open(PID_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0600)) > -1) 
     124    { 
     125        wlen = snprintf(buf, sizeof(buf), "%i", getpid()); 
     126        write(fd, buf, wlen); 
     127        close(fd); 
     128 
     129        return 0; 
     130    } 
     131 
     132    return -1; 
     133} 
     134 
     135static int timeout = TIMEOUT; 
     136static int countdown = -1; 
     137 
     138static void reset_countdown(int sig) 
     139{ 
     140    countdown = timeout; 
     141 
     142} 
     143 
    93144 
    94145static int init_directory(char *path) 
     
    134185 
    135186    return -1; 
     187} 
     188 
     189static inline uint64_t timeof(void *entry) 
     190{ 
     191    return ((struct traffic_entry *)entry)->time; 
    136192} 
    137193 
     
    149205        if ((map != NULL) && (map != MAP_FAILED)) 
    150206        { 
    151             memmove(map, map + esize, esize * (STEP_COUNT-1)); 
    152             memcpy(map + esize * (STEP_COUNT-1), entry, esize); 
     207            if (timeof(entry) > timeof(map + esize * (STEP_COUNT-1))) 
     208            { 
     209                memmove(map, map + esize, esize * (STEP_COUNT-1)); 
     210                memcpy(map + esize * (STEP_COUNT-1), entry, esize); 
     211            } 
    153212 
    154213            munmap(map, esize * STEP_COUNT); 
     
    278337} 
    279338 
    280 static int run_daemon(int nofork) 
     339static int run_daemon(char *progname) 
    281340{ 
    282341    FILE *info; 
     
    287346    char ifname[16]; 
    288347 
     348    struct sigaction sa; 
     349 
    289350    struct stat s; 
    290351    const char *ipc = stat("/proc/net/nf_conntrack", &s) 
    291352        ? "/proc/net/ip_conntrack" : "/proc/net/nf_conntrack"; 
    292353 
    293     if (!nofork) 
    294     { 
    295         switch (fork()) 
    296         { 
    297             case -1: 
    298                 perror("fork()"); 
    299                 return -1; 
    300  
    301             case 0: 
    302                 if (chdir("/") < 0) 
    303                 { 
    304                     perror("chdir()"); 
    305                     exit(1); 
    306                 } 
    307  
    308                 close(0); 
    309                 close(1); 
    310                 close(2); 
    311                 break; 
    312  
    313             default: 
    314                 exit(0); 
    315         } 
    316     } 
    317  
     354    switch (fork()) 
     355    { 
     356        case -1: 
     357            perror("fork()"); 
     358            return -1; 
     359 
     360        case 0: 
     361            if (chdir("/") < 0) 
     362            { 
     363                perror("chdir()"); 
     364                exit(1); 
     365            } 
     366 
     367            close(0); 
     368            close(1); 
     369            close(2); 
     370            break; 
     371 
     372        default: 
     373            return 0; 
     374    } 
     375 
     376    /* setup USR1 signal handler to reset timer */ 
     377    sa.sa_handler = reset_countdown; 
     378    sa.sa_flags   = SA_RESTART; 
     379    sigemptyset(&sa.sa_mask); 
     380    sigaction(SIGUSR1, &sa, NULL); 
     381 
     382    /* write pid */ 
     383    if (writepid()) 
     384    { 
     385        fprintf(stderr, "Failed to write pid file: %s\n", strerror(errno)); 
     386        return 1; 
     387    } 
    318388 
    319389    /* go */ 
    320     while (1) 
    321     { 
     390    for (reset_countdown(0); countdown >= 0; countdown--) 
     391    { 
     392        /* alter progname for ps, top */ 
     393        sprintf(progname, "luci-bwc %d", countdown); 
     394 
    322395        if ((info = fopen("/proc/net/dev", "r")) != NULL) 
    323396        { 
     
    378451        sleep(STEP_TIME); 
    379452    } 
    380 } 
    381  
    382 static int run_dump_ifname(const char *ifname) 
     453 
     454    unlink(PID_PATH); 
     455 
     456    return 0; 
     457} 
     458 
     459static int check_daemon(char *progname) 
     460{ 
     461    int pid; 
     462 
     463    if ((pid = readpid()) < 0 || kill(pid, 0) < 0) 
     464    { 
     465        /* daemon ping failed, try to start it up */ 
     466        if (run_daemon(progname)) 
     467        { 
     468            fprintf(stderr, 
     469                "Failed to ping daemon and unable to start it up: %s\n", 
     470                strerror(errno)); 
     471 
     472            return 1; 
     473        } 
     474    } 
     475    else if (kill(pid, SIGUSR1)) 
     476    { 
     477        fprintf(stderr, "Failed to send signal: %s\n", strerror(errno)); 
     478        return 1; 
     479    } 
     480 
     481    return 0; 
     482} 
     483 
     484static int run_dump_ifname(char *progname, const char *ifname) 
    383485{ 
    384486    int i; 
     
    388490 
    389491    snprintf(path, sizeof(path), DB_IF_FILE, ifname); 
     492 
     493    if (check_daemon(progname)) 
     494    { 
     495        return 1; 
     496    } 
    390497 
    391498    if (mmap_file(path, sizeof(struct traffic_entry), &m)) 
     
    415522} 
    416523 
    417 static int run_dump_conns(void) 
     524static int run_dump_conns(char *progname) 
    418525{ 
    419526    int i; 
     
    424531    snprintf(path, sizeof(path), DB_CN_FILE); 
    425532 
     533    if (check_daemon(progname)) 
     534    { 
     535        return 1; 
     536    } 
     537 
    426538    if (mmap_file(path, sizeof(struct conn_entry), &m)) 
    427539    { 
     
    448560} 
    449561 
    450 static int run_dump_load(void) 
     562static int run_dump_load(char *progname) 
    451563{ 
    452564    int i; 
     
    457569    snprintf(path, sizeof(path), DB_LD_FILE); 
    458570 
     571    if (check_daemon(progname)) 
     572    { 
     573        return 1; 
     574    } 
     575 
    459576    if (mmap_file(path, sizeof(struct load_entry), &m)) 
    460577    { 
     
    485602{ 
    486603    int opt; 
    487     int daemon = 0; 
    488     int nofork = 0; 
    489  
    490     while ((opt = getopt(argc, argv, "dfi:cl")) > -1) 
     604 
     605    while ((opt = getopt(argc, argv, "t:i:cl")) > -1) 
    491606    { 
    492607        switch (opt) 
    493608        { 
    494             case 'd': 
    495                 daemon = 1; 
    496                 break; 
    497  
    498             case 'f': 
    499                 nofork = 1; 
     609            case 't': 
     610                timeout = atoi(optarg); 
    500611                break; 
    501612 
    502613            case 'i': 
    503614                if (optarg) 
    504                     return run_dump_ifname(optarg); 
     615                    return run_dump_ifname(argv[0], optarg); 
    505616                break; 
    506617 
    507618            case 'c': 
    508                 return run_dump_conns(); 
     619                return run_dump_conns(argv[0]); 
    509620 
    510621            case 'l': 
    511                 return run_dump_load(); 
     622                return run_dump_load(argv[0]); 
    512623 
    513624            default: 
     
    516627    } 
    517628 
    518     if (daemon) 
    519         return run_daemon(nofork); 
    520  
    521     else 
    522         fprintf(stderr, 
    523             "Usage:\n" 
    524             "   %s -d [-f]\n" 
    525             "   %s -i ifname\n" 
    526             "   %s -c\n" 
    527             "   %s -l\n", 
    528                 argv[0], argv[0], argv[0], argv[0] 
    529         ); 
     629    fprintf(stderr, 
     630        "Usage:\n" 
     631        "   %s [-t timeout] -i ifname\n" 
     632        "   %s [-t timeout] -c\n" 
     633        "   %s [-t timeout] -l\n", 
     634            argv[0], argv[0], argv[0] 
     635    ); 
    530636 
    531637    return 1;