tstats helper - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit f0f4401f0cfc654646bdf21849627ebcbd5d82b5
parent d72054aa270d6f3d539e830ef9892138a255872a
Author: rsc 
Date:   Fri, 23 Apr 2004 05:12:11 +0000

stats helper

Diffstat:
  A src/cmd/auxstats/Darwin.c           |     250 +++++++++++++++++++++++++++++++
  A src/cmd/auxstats/FreeBSD.c          |     262 +++++++++++++++++++++++++++++++
  A src/cmd/auxstats/Linux.c            |     177 +++++++++++++++++++++++++++++++
  A src/cmd/auxstats/NetBSD.c           |      10 ++++++++++
  A src/cmd/auxstats/OpenBSD.c          |      10 ++++++++++
  A src/cmd/auxstats/SunOS.c            |      10 ++++++++++
  A src/cmd/auxstats/core               |       0 
  A src/cmd/auxstats/dat.h              |       9 +++++++++
  A src/cmd/auxstats/main.c             |     123 +++++++++++++++++++++++++++++++
  A src/cmd/auxstats/mkfile             |      15 +++++++++++++++

10 files changed, 866 insertions(+), 0 deletions(-)
---
diff --git a/src/cmd/auxstats/Darwin.c b/src/cmd/auxstats/Darwin.c
t@@ -0,0 +1,250 @@
+/*
+ * No idea whether this will work.  It does compile.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "dat.h"
+
+void xloadavg(int);
+void xcpu(int);
+void xswap(int);
+void xsysctl(int);
+void xnet(int);
+void xkvm(int);
+
+void (*statfn[])(int) =
+{
+        xkvm,
+        xloadavg,
+        xswap,
+        xcpu,
+        xsysctl,
+        xnet,
+        0
+};
+
+static kvm_t *kvm;
+
+static struct nlist nl[] = {
+        { "_ifnet" },
+        { "_cp_time" },
+        { "" },
+};
+
+void
+kvminit(void)
+{
+        char buf[_POSIX2_LINE_MAX];
+
+        if(kvm)
+                return;
+        kvm = kvm_openfiles(nil, nil, nil, OREAD, buf);
+        if(kvm == nil)
+                return;
+        if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){
+                kvm = nil;
+                return;
+        }
+}
+
+void
+xkvm(int first)
+{
+        if(first)
+                kvminit();
+}
+
+int
+kread(ulong addr, char *buf, int size)
+{
+        if(kvm_read(kvm, addr, buf, size) != size){
+                memset(buf, 0, size);
+                return -1;
+        }
+        return size;
+}
+
+void
+xnet(int first)
+{
+        ulong out, in, outb, inb, err;
+        static ulong ifnetaddr;
+        ulong addr;
+        struct ifnet ifnet;
+        struct ifnethead ifnethead;
+        char name[16];
+
+        if(first)
+                return;
+
+        if(ifnetaddr == 0){
+                ifnetaddr = nl[0].n_value;
+                if(ifnetaddr == 0)
+                        return;
+        }
+
+        if(kread(ifnetaddr, (char*)&ifnethead, sizeof ifnethead) < 0)
+                return;
+
+        out = in = outb = inb = err = 0;
+        addr = (ulong)TAILQ_FIRST(&ifnethead);
+        while(addr){
+                if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
+                || kread((ulong)ifnet.if_name, name, 16) < 0)
+                        return;
+                name[15] = 0;
+                addr = (ulong)TAILQ_NEXT(&ifnet, if_link);
+                out += ifnet.if_opackets;
+                in += ifnet.if_ipackets;
+                outb += ifnet.if_obytes;
+                inb += ifnet.if_ibytes;
+                err += ifnet.if_oerrors+ifnet.if_ierrors;
+        }
+        Bprint(&bout, "etherin %lud\n", in);
+        Bprint(&bout, "etherout %lud\n", out);
+        Bprint(&bout, "etherinb %lud\n", inb);
+        Bprint(&bout, "etheroutb %lud\n", outb);
+        Bprint(&bout, "ethererr %lud\n", err);
+        Bprint(&bout, "ether %lud\n", in+out);
+        Bprint(&bout, "etherb %lud\n", inb+outb);
+}
+
+
+int
+rsys(char *name, char *buf, int len)
+{
+        size_t l;
+
+        l = len;
+        if(sysctlbyname(name, buf, &l, nil, 0) < 0)
+                return -1;
+        buf[l] = 0;
+        return l;
+}
+
+vlong
+isys(char *name)
+{
+        ulong u;
+        size_t l;
+
+        l = sizeof u;
+        if(sysctlbyname(name, &u, &l, nil, 0) < 0)
+                return 0;
+        return u;
+}
+
+void
+xsysctl(int first)
+{
+        static int pgsize;
+        vlong t;
+
+        if(first){
+                pgsize = isys("vm.stats.vm.v_page_size");
+                if(pgsize == 0)
+                        pgsize = 4096;
+        }
+        if((t = isys("vm.stats.vm.v_page_count")) != 0)
+                Bprint(&bout, "mem %lld %lld\n", 
+                        isys("vm.stats.vm.v_active_count")*pgsize, 
+                        t*pgsize);
+        Bprint(&bout, "context %lld 1000\n", isys("vm.stats.sys.v_swtch"));
+        Bprint(&bout, "syscall %lld 1000\n", isys("vm.stats.sys.v_syscall"));
+        Bprint(&bout, "intr %lld 1000\n", isys("vm.stats.sys.v_intr")+isys("vm.stats.sys.v_trap"));
+        Bprint(&bout, "fault %lld 1000\n", isys("vm.stats.vm.v_vm_faults"));
+        Bprint(&bout, "fork %lld 1000\n", isys("vm.stats.vm.v_forks")
+                +isys("vm.stats.vm.v_rforks")
+                +isys("vm.stats.vm.v_vforks"));
+}
+
+void
+xcpu(int first)
+{
+#if 0
+        static int stathz;
+        ulong x[20];
+        struct clockinfo *ci;
+        int n;
+
+        if(first){
+                if(rsys("kern.clockrate", (char*)&x, sizeof x) < sizeof ci)
+                        stathz = 128;
+                else{
+                        ci = (struct clockinfo*)x;
+                        stathz = ci->stathz;
+                }
+                return;
+        }
+
+        if((n=rsys("kern.cp_time", (char*)x, sizeof x)) < 5*sizeof(ulong))
+                return;
+
+        Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz);
+        Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz);
+        Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz);
+        Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz);
+#endif
+}
+
+void
+xloadavg(int first)
+{
+        double l[3];
+
+        if(first)
+                return;
+
+        if(getloadavg(l, 3) < 0)
+                return;
+        Bprint(&bout, "load %d 1000\n", (int)(l[0]*1000.0));
+}
+
+void
+xswap(int first)
+{
+#if 0
+        static struct kvm_swap s;
+        static ulong pgin, pgout;
+        int i, o;
+        static int pgsize;
+
+        if(first){
+                pgsize = getpagesize();
+                if(pgsize == 0)
+                        pgsize = 4096;
+                return;
+        }
+
+        if(kvm == nil)
+                return;
+
+        i = isys("vm.stats.vm.v_swappgsin");
+        o = isys("vm.stats.vm.v_swappgsout");
+        if(i != pgin || o != pgout){
+                pgin = i;
+                pgout = o;
+                kvm_getswapinfo(kvm, &s, 1, 0);
+        }
+
+
+        Bprint(&bout, "swap %lld %lld\n", s.ksw_used*(vlong)pgsize, s.ksw_total*(vlong)pgsize);
+#endif
+}
+
diff --git a/src/cmd/auxstats/FreeBSD.c b/src/cmd/auxstats/FreeBSD.c
t@@ -0,0 +1,262 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "dat.h"
+
+void xapm(int);
+void xloadavg(int);
+void xcpu(int);
+void xswap(int);
+void xsysctl(int);
+void xnet(int);
+void xkvm(int);
+
+void (*statfn[])(int) =
+{
+        xkvm,
+        xapm,
+        xloadavg,
+        xswap,
+        xcpu,
+        xsysctl,
+        xnet,
+        0
+};
+
+static kvm_t *kvm;
+
+static struct nlist nl[] = {
+        { "_ifnet" },
+        { "_cp_time" },
+        { "" },
+};
+
+void
+kvminit(void)
+{
+        char buf[_POSIX2_LINE_MAX];
+
+        if(kvm)
+                return;
+        kvm = kvm_openfiles(nil, nil, nil, OREAD, buf);
+        if(kvm == nil)
+                return;
+        if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){
+                kvm = nil;
+                return;
+        }
+}
+
+void
+xkvm(int first)
+{
+        if(first)
+                kvminit();
+}
+
+int
+kread(ulong addr, char *buf, int size)
+{
+        if(kvm_read(kvm, addr, buf, size) != size){
+                memset(buf, 0, size);
+                return -1;
+        }
+        return size;
+}
+
+void
+xnet(int first)
+{
+        ulong out, in, outb, inb, err;
+        static ulong ifnetaddr;
+        ulong addr;
+        struct ifnet ifnet;
+        struct ifnethead ifnethead;
+        char name[16];
+        int n;
+
+        if(first)
+                return;
+
+        if(ifnetaddr == 0){
+                ifnetaddr = nl[0].n_value;
+                if(ifnetaddr == 0)
+                        return;
+        }
+
+        if(kread(ifnetaddr, (char*)&ifnethead, sizeof ifnethead) < 0)
+                return;
+
+        out = in = outb = inb = err = 0;
+        addr = (ulong)TAILQ_FIRST(&ifnethead);
+        while(addr){
+                if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
+                || kread((ulong)ifnet.if_name, name, 16) < 0)
+                        return;
+                name[15] = 0;
+                addr = (ulong)TAILQ_NEXT(&ifnet, if_link);
+                out += ifnet.if_opackets;
+                in += ifnet.if_ipackets;
+                outb += ifnet.if_obytes;
+                inb += ifnet.if_ibytes;
+                err += ifnet.if_oerrors+ifnet.if_ierrors;
+        }
+        Bprint(&bout, "etherin %lud 1000\n", in);
+        Bprint(&bout, "etherout %lud 1000\n", out);
+        Bprint(&bout, "etherinb %lud 1000000\n", inb);
+        Bprint(&bout, "etheroutb %lud 1000000\n", outb);
+        Bprint(&bout, "ethererr %lud 1000\n", err);
+        Bprint(&bout, "ether %lud 1000\n", in+out);
+        Bprint(&bout, "etherb %lud 1000000\n", inb+outb);
+}
+
+void
+xapm(int first)
+{
+        static int fd;
+        struct apm_info ai;
+
+        if(first){
+                fd = open("/dev/apm", OREAD);
+                return;
+        }
+
+        if(ioctl(fd, APMIO_GETINFO, &ai) < 0)
+                return;
+
+        if(ai.ai_batt_life <= 100)
+                Bprint(&bout, "battery =%d 100\n", ai.ai_batt_life);
+}
+
+int
+rsys(char *name, char *buf, int len)
+{
+        size_t l;
+
+        l = len;
+        if(sysctlbyname(name, buf, &l, nil, 0) < 0)
+                return -1;
+        buf[l] = 0;
+        return l;
+}
+
+vlong
+isys(char *name)
+{
+        ulong u;
+        size_t l;
+
+        l = sizeof u;
+        if(sysctlbyname(name, &u, &l, nil, 0) < 0)
+                return -1;
+        return u;
+}
+
+void
+xsysctl(int first)
+{
+        static int pgsize;
+
+        if(first){
+                pgsize = isys("vm.stats.vm.v_page_size");
+                if(pgsize == 0)
+                        pgsize = 4096;
+        }
+
+        Bprint(&bout, "mem =%lld %lld\n", 
+                isys("vm.stats.vm.v_active_count")*pgsize, 
+                isys("vm.stats.vm.v_page_count")*pgsize);
+        Bprint(&bout, "context %lld 1000\n", isys("vm.stats.sys.v_swtch"));
+        Bprint(&bout, "syscall %lld 1000\n", isys("vm.stats.sys.v_syscall"));
+        Bprint(&bout, "intr %lld 1000\n", isys("vm.stats.sys.v_intr")+isys("vm.stats.sys.v_trap"));
+        Bprint(&bout, "fault %lld 1000\n", isys("vm.stats.vm.v_vm_faults"));
+        Bprint(&bout, "fork %lld 1000\n", isys("vm.stats.vm.v_forks")
+                +isys("vm.stats.vm.v_rforks")
+                +isys("vm.stats.vm.v_vforks"));
+}
+
+void
+xcpu(int first)
+{
+        static int stathz;
+        ulong x[20];
+        struct clockinfo *ci;
+        int n;
+
+        if(first){
+                if(rsys("kern.clockrate", (char*)&x, sizeof x) < sizeof ci)
+                        stathz = 128;
+                else{
+                        ci = (struct clockinfo*)x;
+                        stathz = ci->stathz;
+                }
+                return;
+        }
+
+        if((n=rsys("kern.cp_time", (char*)x, sizeof x)) < 5*sizeof(ulong))
+                return;
+
+        Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz);
+        Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz);
+        Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz);
+        Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz);
+}
+
+void
+xloadavg(int first)
+{
+        double l[3];
+
+        if(first)
+                return;
+
+        if(getloadavg(l, 3) < 0)
+                return;
+        Bprint(&bout, "load =%d 1000\n", (int)(l[0]*1000.0));
+}
+
+void
+xswap(int first)
+{
+        static struct kvm_swap s;
+        static ulong pgin, pgout;
+        int i, o;
+        static int pgsize;
+
+        if(first){
+                pgsize = getpagesize();
+                if(pgsize == 0)
+                        pgsize = 4096;
+                return;
+        }
+
+        if(kvm == nil)
+                return;
+
+        i = isys("vm.stats.vm.v_swappgsin");
+        o = isys("vm.stats.vm.v_swappgsout");
+        if(i != pgin || o != pgout){
+                pgin = i;
+                pgout = o;
+                kvm_getswapinfo(kvm, &s, 1, 0);
+        }
+
+
+        Bprint(&bout, "swap =%lld %lld\n", s.ksw_used*(vlong)pgsize, s.ksw_total*(vlong)pgsize);
+}
+
diff --git a/src/cmd/auxstats/Linux.c b/src/cmd/auxstats/Linux.c
t@@ -0,0 +1,177 @@
+#include 
+#include 
+#include 
+#include "dat.h"
+
+void xapm(int);
+void xloadavg(int);
+void xmeminfo(int);
+void xnet(int);
+void xstat(int);
+
+void (*statfn[])(int) =
+{
+        xapm,
+        xloadavg,
+        xmeminfo,
+        xnet,
+        xstat,
+        0
+};
+
+void
+xapm(int first)
+{
+        static int fd = -1;
+
+        if(first){
+                fd = open("/proc/apm", OREAD);
+                return;
+        }
+        readfile(fd);
+        tokens(0);
+        if(ntok >= 7 && atoi(tok[6]) != -1)
+                Bprint(&bout, "battery =%d 100\n", atoi(tok[6]));
+}
+        
+void
+xloadavg(int first)
+{
+        static int fd = -1;
+
+        if(first){
+                fd = open("/proc/loadavg", OREAD);
+                return;
+        }
+
+        readfile(fd);
+        tokens(0);
+        if(ntok >= 1)
+                Bprint(&bout, "load =%d 1000\n", (int)(atof(tok[0])*1000));
+}
+
+void
+xmeminfo(int first)
+{
+        int i;
+        vlong tot, used;
+        static int fd = -1;
+
+        if(first){
+                fd = open("/proc/meminfo", OREAD);
+                return;
+        }
+
+        readfile(fd);
+        for(i=0; i= 5){
+                        Bprint(&bout, "user %lld 100\n", atoll(tok[1]));
+                        Bprint(&bout, "sys %lld 100\n", atoll(tok[3]));
+                        Bprint(&bout, "cpu %lld 100\n", atoll(tok[1])+atoll(tok[3]));
+                        Bprint(&bout, "idle %lld\n", atoll(tok[4]));
+                }
+        /*
+                if(strcmp(tok[0], "page") == 0 && ntok >= 3){
+                        Bprint(&bout, "pagein %lld 500\n", atoll(tok[1]));
+                        Bprint(&bout, "pageout %lld 500\n", atoll(tok[2]));
+                        Bprint(&bout, "page %lld 1000\n", atoll(tok[1])+atoll(tok[2]));
+                }
+                if(strcmp(tok[0], "swap") == 0 && ntok >= 3){
+                        Bprint(&bout, "swapin %lld 500\n", atoll(tok[1]));
+                        Bprint(&bout, "swapout %lld 500\n", atoll(tok[2]));
+                        Bprint(&bout, "swap %lld 1000\n", atoll(tok[1])+atoll(tok[2]));
+                }
+        */
+                if(strcmp(tok[0], "intr") == 0)
+                        Bprint(&bout, "interrupt %lld 1000\n", atoll(tok[1]));
+                if(strcmp(tok[0], "ctxt") == 0)
+                        Bprint(&bout, "context %lld 1000\n", atoll(tok[1]));
+                if(strcmp(tok[0], "processes") == 0)
+                        Bprint(&bout, "fork %lld 1000\n", atoll(tok[1]));
+        }
+}
+
diff --git a/src/cmd/auxstats/NetBSD.c b/src/cmd/auxstats/NetBSD.c
t@@ -0,0 +1,10 @@
+#include 
+#include 
+#include 
+#include "dat.h"
+
+void (*statfn[])(int) = 
+{
+        0
+};
+
diff --git a/src/cmd/auxstats/OpenBSD.c b/src/cmd/auxstats/OpenBSD.c
t@@ -0,0 +1,10 @@
+#include 
+#include 
+#include 
+#include "dat.h"
+
+void (*statfn[])(int) = 
+{
+        0
+};
+
diff --git a/src/cmd/auxstats/SunOS.c b/src/cmd/auxstats/SunOS.c
t@@ -0,0 +1,10 @@
+#include 
+#include 
+#include 
+#include "dat.h"
+
+void (*statfn[])(int) = 
+{
+        0
+};
+
diff --git a/src/cmd/auxstats/core b/src/cmd/auxstats/core
Binary files differ.
diff --git a/src/cmd/auxstats/dat.h b/src/cmd/auxstats/dat.h
t@@ -0,0 +1,9 @@
+extern Biobuf bout;
+extern void (*statfn[])(int);
+extern char buf[];
+extern char *line[];
+extern char *tok[];
+extern int nline, ntok;
+
+void readfile(int);
+void tokens(int);
diff --git a/src/cmd/auxstats/main.c b/src/cmd/auxstats/main.c
t@@ -0,0 +1,123 @@
+#include 
+#include 
+#include 
+#include "dat.h"
+
+Biobuf bout;
+
+void
+usage(void)
+{
+        fprint(2, "usage: auxstats [system [executable]]\n");
+        exits("usage");
+}
+
+int pid;
+
+void
+notifyf(void *v, char *msg)
+{
+        USED(v);
+
+        if(strcmp(msg, "child") == 0)
+                noted(NCONT);
+        postnote(PNPROC, pid, msg);
+        exits(nil);
+}
+
+void
+main(int argc, char **argv)
+{
+        char *sys, *exe;
+        int i;
+        Waitmsg *w;
+
+        ARGBEGIN{
+        default:
+                usage();
+        }ARGEND
+
+        notify(notifyf);
+
+        sys = nil;
+        exe = nil;
+        if(argc > 0)
+                sys = argv[0];
+        if(argc > 1)
+                exe = argv[1];
+        if(argc > 2)
+                usage();
+
+        if(sys){
+                if(exe == nil)
+                        exe = "auxstats";
+                for(;;){
+                        switch(pid = fork()){
+                        case -1:
+                                sysfatal("fork: %r");
+                        case 0:
+                                rfork(RFNOTEG);
+                                execlp("ssh", "ssh", "-C", sys, exe, nil);
+                                _exit(12);
+                        default:
+                                if((w = wait()) == nil)
+                                        sysfatal("wait: %r");
+                                if(w->pid != pid)
+                                        sysfatal("wait got wrong pid");
+                                if(atoi(w->msg) == 12)
+                                        sysfatal("exec ssh failed");
+                                free(w);
+                                fprint(2, "stats: %s hung up; sleeping 60\n", sys);
+                                sleep(60*1000);
+                                fprint(2, "stats: redialing %s\n", sys);
+                                break;
+                        }
+                }
+        }
+
+        for(i=0; statfn[i]; i++)
+                statfn[i](1);
+
+        Binit(&bout, 1, OWRITE);
+        for(;;){
+                Bflush(&bout);
+                sleep(900);
+                for(i=0; statfn[i]; i++)
+                        statfn[i](0);
+        }
+}
+
+char buf[16384];
+char *line[100];
+char *tok[100];
+int nline, ntok;
+
+void
+readfile(int fd)
+{
+        int n;
+
+        if(fd == -1){
+                nline = 0;
+                return;
+        }
+
+        seek(fd, 0, 0);
+        n = read(fd, buf, sizeof buf-1);
+        if(n < 0)
+                n = 0;
+        buf[n] = 0;
+
+        nline = getfields(buf, line, nelem(line), 0, "\n");
+}
+
+void
+tokens(int i)
+{
+        if(i >= nline){
+                ntok = 0;
+                return;
+        }
+        ntok = tokenize(line[i], tok, nelem(tok));
+}
+
diff --git a/src/cmd/auxstats/mkfile b/src/cmd/auxstats/mkfile
t@@ -0,0 +1,15 @@
+<$PLAN9/src/mkhdr
+
+TARG=auxstats
+
+OFILES=\
+        $SYSNAME.$O\
+        main.$O\
+
+HFILES=\
+        dat.h\
+
+SHORTLIB=bio 9
+
+<$PLAN9/src/mkone
+