1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177 |
- #include "stdinc.h"
- #include "dat.h"
- #include "fns.h"
- #include "xml.h"
- typedef struct HttpObj HttpObj;
- extern QLock memdrawlock;
- enum
- {
- ObjNameSize = 64,
- MaxObjs = 64
- };
- struct HttpObj
- {
- char name[ObjNameSize];
- int (*f)(HConnect*);
- };
- static HttpObj objs[MaxObjs];
- static char *webroot;
- static void listenproc(void*);
- static int estats(HConnect *c);
- static int dindex(HConnect *c);
- static int xindex(HConnect *c);
- static int xlog(HConnect *c);
- static int sindex(HConnect *c);
- static int hempty(HConnect *c);
- static int hlcacheempty(HConnect *c);
- static int hdcacheempty(HConnect *c);
- static int hicacheempty(HConnect *c);
- static int hicachekick(HConnect *c);
- static int hdcachekick(HConnect *c);
- static int hicacheflush(HConnect *c);
- static int hdcacheflush(HConnect *c);
- static int httpdobj(char *name, int (*f)(HConnect*));
- static int xgraph(HConnect *c);
- static int xset(HConnect *c);
- static int fromwebdir(HConnect *c);
- int
- httpdinit(char *address, char *dir)
- {
- fmtinstall('D', hdatefmt);
- /* fmtinstall('H', httpfmt); */
- fmtinstall('U', hurlfmt);
- if(address == nil)
- address = "tcp!*!http";
- webroot = dir;
-
- httpdobj("/stats", estats);
- httpdobj("/index", dindex);
- httpdobj("/storage", sindex);
- httpdobj("/xindex", xindex);
- httpdobj("/flushicache", hicacheflush);
- httpdobj("/flushdcache", hdcacheflush);
- httpdobj("/kickicache", hicachekick);
- httpdobj("/kickdcache", hdcachekick);
- httpdobj("/graph", xgraph);
- httpdobj("/set", xset);
- httpdobj("/log", xlog);
- httpdobj("/empty", hempty);
- httpdobj("/emptyicache", hicacheempty);
- httpdobj("/emptylumpcache", hlcacheempty);
- httpdobj("/emptydcache", hdcacheempty);
- httpdobj("/disk", hdisk);
- httpdobj("/debug", hdebug);
- httpdobj("/proc/", hproc);
- if(vtproc(listenproc, address) < 0)
- return -1;
- return 0;
- }
- static int
- httpdobj(char *name, int (*f)(HConnect*))
- {
- int i;
- if(name == nil || strlen(name) >= ObjNameSize)
- return -1;
- for(i = 0; i < MaxObjs; i++){
- if(objs[i].name[0] == '\0'){
- strcpy(objs[i].name, name);
- objs[i].f = f;
- return 0;
- }
- if(strcmp(objs[i].name, name) == 0)
- return -1;
- }
- return -1;
- }
- static HConnect*
- mkconnect(void)
- {
- HConnect *c;
- c = mallocz(sizeof(HConnect), 1);
- if(c == nil)
- sysfatal("out of memory");
- c->replog = nil;
- c->hpos = c->header;
- c->hstop = c->header;
- return c;
- }
- void httpproc(void*);
- static void
- listenproc(void *vaddress)
- {
- HConnect *c;
- char *address, ndir[NETPATHLEN], dir[NETPATHLEN];
- int ctl, nctl, data;
- address = vaddress;
- ctl = announce(address, dir);
- if(ctl < 0){
- fprint(2, "venti: httpd can't announce on %s: %r\n", address);
- return;
- }
- if(0) print("announce ctl %d dir %s\n", ctl, dir);
- for(;;){
- /*
- * wait for a call (or an error)
- */
- nctl = listen(dir, ndir);
- if(0) print("httpd listen %d %s...\n", nctl, ndir);
- if(nctl < 0){
- fprint(2, "venti: httpd can't listen on %s: %r\n", address);
- return;
- }
- data = accept(ctl, ndir);
- if(0) print("httpd accept %d...\n", data);
- if(data < 0){
- fprint(2, "venti: httpd accept: %r\n");
- close(nctl);
- continue;
- }
- if(0) print("httpd close nctl %d\n", nctl);
- close(nctl);
- c = mkconnect();
- hinit(&c->hin, data, Hread);
- hinit(&c->hout, data, Hwrite);
- vtproc(httpproc, c);
- }
- }
- void
- httpproc(void *v)
- {
- HConnect *c;
- int ok, i, n;
- c = v;
- for(;;){
- /*
- * No timeout because the signal appears to hit every
- * proc, not just us.
- */
- if(hparsereq(c, 0) < 0)
- break;
-
- for(i = 0; i < MaxObjs && objs[i].name[0]; i++){
- n = strlen(objs[i].name);
- if((objs[i].name[n-1] == '/' && strncmp(c->req.uri, objs[i].name, n) == 0)
- || (objs[i].name[n-1] != '/' && strcmp(c->req.uri, objs[i].name) == 0)){
- ok = (*objs[i].f)(c);
- goto found;
- }
- }
- ok = fromwebdir(c);
- found:
- hflush(&c->hout);
- if(c->head.closeit)
- ok = -1;
- hreqcleanup(c);
- if(ok < 0)
- break;
- }
- hreqcleanup(c);
- close(c->hin.fd);
- free(c);
- }
- char*
- hargstr(HConnect *c, char *name, char *def)
- {
- HSPairs *p;
-
- for(p=c->req.searchpairs; p; p=p->next)
- if(strcmp(p->s, name) == 0)
- return p->t;
- return def;
- }
- vlong
- hargint(HConnect *c, char *name, vlong def)
- {
- char *a;
-
- if((a = hargstr(c, name, nil)) == nil)
- return def;
- return atoll(a);
- }
- static int
- percent(ulong v, ulong total)
- {
- if(total == 0)
- total = 1;
- if(v < 1000*1000)
- return (v * 100) / total;
- total /= 100;
- if(total == 0)
- total = 1;
- return v / total;
- }
- static int
- preq(HConnect *c)
- {
- if(hparseheaders(c, 0) < 0)
- return -1;
- if(strcmp(c->req.meth, "GET") != 0
- && strcmp(c->req.meth, "HEAD") != 0)
- return hunallowed(c, "GET, HEAD");
- if(c->head.expectother || c->head.expectcont)
- return hfail(c, HExpectFail, nil);
- return 0;
- }
- int
- hsettype(HConnect *c, char *type)
- {
- Hio *hout;
- int r;
- r = preq(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- if(c->req.vermaj){
- hokheaders(c);
- hprint(hout, "Content-type: %s\r\n", type);
- if(http11(c))
- hprint(hout, "Transfer-Encoding: chunked\r\n");
- hprint(hout, "\r\n");
- }
- if(http11(c))
- hxferenc(hout, 1);
- else
- c->head.closeit = 1;
- return 0;
- }
- int
- hsethtml(HConnect *c)
- {
- return hsettype(c, "text/html; charset=utf-8");
- }
- int
- hsettext(HConnect *c)
- {
- return hsettype(c, "text/plain; charset=utf-8");
- }
- static int
- herror(HConnect *c)
- {
- int n;
- Hio *hout;
-
- hout = &c->hout;
- n = snprint(c->xferbuf, HBufSize, "<html><head><title>Error</title></head>\n<body><h1>Error</h1>\n<pre>%r</pre>\n</body></html>");
- hprint(hout, "%s %s\r\n", hversion, "400 Bad Request");
- hprint(hout, "Date: %D\r\n", time(nil));
- hprint(hout, "Server: Venti\r\n");
- hprint(hout, "Content-Type: text/html\r\n");
- hprint(hout, "Content-Length: %d\r\n", n);
- if(c->head.closeit)
- hprint(hout, "Connection: close\r\n");
- else if(!http11(c))
- hprint(hout, "Connection: Keep-Alive\r\n");
- hprint(hout, "\r\n");
- if(c->req.meth == nil || strcmp(c->req.meth, "HEAD") != 0)
- hwrite(hout, c->xferbuf, n);
- return hflush(hout);
- }
-
- int
- hnotfound(HConnect *c)
- {
- int r;
- r = preq(c);
- if(r < 0)
- return r;
- return hfail(c, HNotFound, c->req.uri);
- }
- struct {
- char *ext;
- char *type;
- } exttab[] = {
- ".html", "text/html",
- ".txt", "text/plain",
- ".xml", "text/xml",
- ".png", "image/png",
- ".gif", "image/gif",
- 0
- };
- static int
- fromwebdir(HConnect *c)
- {
- char buf[4096], *p, *ext, *type;
- int i, fd, n, defaulted;
- Dir *d;
-
- if(webroot == nil || strstr(c->req.uri, ".."))
- return hnotfound(c);
- snprint(buf, sizeof buf-20, "%s/%s", webroot, c->req.uri+1);
- defaulted = 0;
- reopen:
- if((fd = open(buf, OREAD)) < 0)
- return hnotfound(c);
- d = dirfstat(fd);
- if(d == nil){
- close(fd);
- return hnotfound(c);
- }
- if(d->mode&DMDIR){
- if(!defaulted){
- defaulted = 1;
- strcat(buf, "/index.html");
- free(d);
- close(fd);
- goto reopen;
- }
- free(d);
- return hnotfound(c);
- }
- free(d);
- p = buf+strlen(buf);
- type = "application/octet-stream";
- for(i=0; exttab[i].ext; i++){
- ext = exttab[i].ext;
- if(p-strlen(ext) >= buf && strcmp(p-strlen(ext), ext) == 0){
- type = exttab[i].type;
- break;
- }
- }
- if(hsettype(c, type) < 0){
- close(fd);
- return 0;
- }
- while((n = read(fd, buf, sizeof buf)) > 0)
- if(hwrite(&c->hout, buf, n) < 0)
- break;
- close(fd);
- hflush(&c->hout);
- return 0;
- }
- static struct
- {
- char *name;
- int *p;
- } namedints[] =
- {
- "compress", &compressblocks,
- "devnull", &writestodevnull,
- "logging", &ventilogging,
- "stats", &collectstats,
- "icachesleeptime", &icachesleeptime,
- "minicachesleeptime", &minicachesleeptime,
- "arenasumsleeptime", &arenasumsleeptime,
- "l0quantum", &l0quantum,
- "l1quantum", &l1quantum,
- "manualscheduling", &manualscheduling,
- "ignorebloom", &ignorebloom,
- "syncwrites", &syncwrites,
- "icacheprefetch", &icacheprefetch,
- 0
- };
- static int
- xset(HConnect *c)
- {
- int i, old;
- char *name, *value;
- if(hsettext(c) < 0)
- return -1;
- if((name = hargstr(c, "name", nil)) == nil || name[0] == 0){
- for(i=0; namedints[i].name; i++)
- hprint(&c->hout, "%s = %d\n", namedints[i].name, *namedints[i].p);
- hflush(&c->hout);
- return 0;
- }
- for(i=0; namedints[i].name; i++)
- if(strcmp(name, namedints[i].name) == 0)
- break;
- if(!namedints[i].name){
- hprint(&c->hout, "%s not found\n", name);
- hflush(&c->hout);
- return 0;
- }
- if((value = hargstr(c, "value", nil)) == nil || value[0] == 0){
- hprint(&c->hout, "%s = %d\n", namedints[i].name, *namedints[i].p);
- hflush(&c->hout);
- return 0;
- }
-
- old = *namedints[i].p;
- *namedints[i].p = atoll(value);
- hprint(&c->hout, "%s = %d (was %d)\n", name, *namedints[i].p, old);
- hflush(&c->hout);
- return 0;
- }
- static int
- estats(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- /*
- hprint(hout, "lump writes=%,ld\n", stats.lumpwrites);
- hprint(hout, "lump reads=%,ld\n", stats.lumpreads);
- hprint(hout, "lump cache read hits=%,ld\n", stats.lumphit);
- hprint(hout, "lump cache read misses=%,ld\n", stats.lumpmiss);
- hprint(hout, "clump disk writes=%,ld\n", stats.clumpwrites);
- hprint(hout, "clump disk bytes written=%,lld\n", stats.clumpbwrites);
- hprint(hout, "clump disk bytes compressed=%,lld\n", stats.clumpbcomp);
- hprint(hout, "clump disk reads=%,ld\n", stats.clumpreads);
- hprint(hout, "clump disk bytes read=%,lld\n", stats.clumpbreads);
- hprint(hout, "clump disk bytes uncompressed=%,lld\n", stats.clumpbuncomp);
- hprint(hout, "clump directory disk writes=%,ld\n", stats.ciwrites);
- hprint(hout, "clump directory disk reads=%,ld\n", stats.cireads);
- hprint(hout, "index disk writes=%,ld\n", stats.indexwrites);
- hprint(hout, "index disk reads=%,ld\n", stats.indexreads);
- hprint(hout, "index disk bloom filter hits=%,ld %d%% falsemisses=%,ld %d%%\n",
- stats.indexbloomhits,
- percent(stats.indexbloomhits, stats.indexreads),
- stats.indexbloomfalsemisses,
- percent(stats.indexbloomfalsemisses, stats.indexreads));
- hprint(hout, "bloom filter bits=%,ld of %,ld %d%%\n",
- stats.bloomones, stats.bloombits, percent(stats.bloomones, stats.bloombits));
- hprint(hout, "index disk reads for modify=%,ld\n", stats.indexwreads);
- hprint(hout, "index disk reads for allocation=%,ld\n", stats.indexareads);
- hprint(hout, "index block splits=%,ld\n", stats.indexsplits);
- hprint(hout, "index cache lookups=%,ld\n", stats.iclookups);
- hprint(hout, "index cache hits=%,ld %d%%\n", stats.ichits,
- percent(stats.ichits, stats.iclookups));
- hprint(hout, "index cache fills=%,ld %d%%\n", stats.icfills,
- percent(stats.icfills, stats.iclookups));
- hprint(hout, "index cache inserts=%,ld\n", stats.icinserts);
- hprint(hout, "disk cache hits=%,ld\n", stats.pchit);
- hprint(hout, "disk cache misses=%,ld\n", stats.pcmiss);
- hprint(hout, "disk cache reads=%,ld\n", stats.pcreads);
- hprint(hout, "disk cache bytes read=%,lld\n", stats.pcbreads);
- hprint(hout, "disk cache writes=%,ld\n", stats.dirtydblocks);
- hprint(hout, "disk cache writes absorbed=%,ld %d%%\n", stats.absorbedwrites,
- percent(stats.absorbedwrites, stats.dirtydblocks));
- hprint(hout, "disk cache flushes=%,ld\n", stats.dcacheflushes);
- hprint(hout, "disk cache flush writes=%,ld (%,ld per flush)\n",
- stats.dcacheflushwrites,
- stats.dcacheflushwrites/(stats.dcacheflushes ? stats.dcacheflushes : 1));
- hprint(hout, "disk writes=%,ld\n", stats.diskwrites);
- hprint(hout, "disk bytes written=%,lld\n", stats.diskbwrites);
- hprint(hout, "disk reads=%,ld\n", stats.diskreads);
- hprint(hout, "disk bytes read=%,lld\n", stats.diskbreads);
- */
- hflush(hout);
- return 0;
- }
- static int
- sindex(HConnect *c)
- {
- Hio *hout;
- Index *ix;
- Arena *arena;
- vlong clumps, cclumps, uncsize, used, size;
- int i, r, active;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- ix = mainindex;
- hprint(hout, "index=%s\n", ix->name);
- active = 0;
- clumps = 0;
- cclumps = 0;
- uncsize = 0;
- used = 0;
- size = 0;
- for(i = 0; i < ix->narenas; i++){
- arena = ix->arenas[i];
- if(arena != nil && arena->memstats.clumps != 0){
- active++;
- clumps += arena->memstats.clumps;
- cclumps += arena->memstats.cclumps;
- uncsize += arena->memstats.uncsize;
- used += arena->memstats.used;
- }
- size += arena->size;
- }
- hprint(hout, "total arenas=%,d active=%,d\n", ix->narenas, active);
- hprint(hout, "total space=%,lld used=%,lld\n", size, used + clumps * ClumpInfoSize);
- hprint(hout, "clumps=%,lld compressed clumps=%,lld data=%,lld compressed data=%,lld\n",
- clumps, cclumps, uncsize, used - clumps * ClumpSize);
- hflush(hout);
- return 0;
- }
- static void
- darena(Hio *hout, Arena *arena)
- {
- hprint(hout, "arena='%s' on %s at [%lld,%lld)\n\tversion=%d created=%d modified=%d",
- arena->name, arena->part->name, arena->base, arena->base + arena->size + 2 * arena->blocksize,
- arena->version, arena->ctime, arena->wtime);
- if(arena->memstats.sealed)
- hprint(hout, " mem=sealed");
- if(arena->diskstats.sealed)
- hprint(hout, " disk=sealed");
- hprint(hout, "\n");
- if(scorecmp(zeroscore, arena->score) != 0)
- hprint(hout, "\tscore=%V\n", arena->score);
- hprint(hout, "\twritten: clumps=%d compressed clumps=%d data=%,lld compressed data=%,lld storage=%,lld\n",
- arena->memstats.clumps, arena->memstats.cclumps, arena->memstats.uncsize,
- arena->memstats.used - arena->memstats.clumps * ClumpSize,
- arena->memstats.used + arena->memstats.clumps * ClumpInfoSize);
- hprint(hout, "\tindexed: clumps=%d compressed clumps=%d data=%,lld compressed data=%,lld storage=%,lld\n",
- arena->diskstats.clumps, arena->diskstats.cclumps, arena->diskstats.uncsize,
- arena->diskstats.used - arena->diskstats.clumps * ClumpSize,
- arena->diskstats.used + arena->diskstats.clumps * ClumpInfoSize);
- }
- static int
- hempty(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- emptylumpcache();
- emptydcache();
- emptyicache();
- hprint(hout, "emptied all caches\n");
- hflush(hout);
- return 0;
- }
- static int
- hlcacheempty(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- emptylumpcache();
- hprint(hout, "emptied lumpcache\n");
- hflush(hout);
- return 0;
- }
- static int
- hicacheempty(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- emptyicache();
- hprint(hout, "emptied icache\n");
- hflush(hout);
- return 0;
- }
- static int
- hdcacheempty(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- emptydcache();
- hprint(hout, "emptied dcache\n");
- hflush(hout);
- return 0;
- }
- static int
- hicachekick(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- kickicache();
- hprint(hout, "kicked icache\n");
- hflush(hout);
- return 0;
- }
- static int
- hdcachekick(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- kickdcache();
- hprint(hout, "kicked dcache\n");
- hflush(hout);
- return 0;
- }
- static int
- hicacheflush(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- flushicache();
- hprint(hout, "flushed icache\n");
- hflush(hout);
- return 0;
- }
- static int
- hdcacheflush(HConnect *c)
- {
- Hio *hout;
- int r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- flushdcache();
- hprint(hout, "flushed dcache\n");
- hflush(hout);
- return 0;
- }
- static int
- dindex(HConnect *c)
- {
- Hio *hout;
- Index *ix;
- int i, r;
- r = hsettext(c);
- if(r < 0)
- return r;
- hout = &c->hout;
- ix = mainindex;
- hprint(hout, "index=%s version=%d blocksize=%d tabsize=%d\n",
- ix->name, ix->version, ix->blocksize, ix->tabsize);
- hprint(hout, "\tbuckets=%d div=%d\n", ix->buckets, ix->div);
- for(i = 0; i < ix->nsects; i++)
- hprint(hout, "\tsect=%s for buckets [%lld,%lld) buckmax=%d\n", ix->smap[i].name, ix->smap[i].start, ix->smap[i].stop, ix->sects[i]->buckmax);
- for(i = 0; i < ix->narenas; i++){
- if(ix->arenas[i] != nil && ix->arenas[i]->memstats.clumps != 0){
- hprint(hout, "arena=%s at index [%lld,%lld)\n\t", ix->amap[i].name, ix->amap[i].start, ix->amap[i].stop);
- darena(hout, ix->arenas[i]);
- }
- }
- hflush(hout);
- return 0;
- }
- typedef struct Arg Arg;
- struct Arg
- {
- int index;
- int index2;
- };
- static long
- rawgraph(Stats *s, Stats *t, void *va)
- {
- Arg *a;
- USED(s);
- a = va;
- return t->n[a->index];
- }
- static long
- diffgraph(Stats *s, Stats *t, void *va)
- {
- Arg *a;
- a = va;
- return t->n[a->index] - s->n[a->index];
- }
- static long
- pctgraph(Stats *s, Stats *t, void *va)
- {
- Arg *a;
- USED(s);
- a = va;
- return percent(t->n[a->index], t->n[a->index2]);
- }
- static long
- pctdiffgraph(Stats *s, Stats *t, void *va)
- {
- Arg *a;
- a = va;
- return percent(t->n[a->index]-s->n[a->index], t->n[a->index2]-s->n[a->index2]);
- }
- static long
- xdiv(long a, long b)
- {
- if(b == 0)
- b++;
- return a/b;
- }
- static long
- divdiffgraph(Stats *s, Stats *t, void *va)
- {
- Arg *a;
- a = va;
- return xdiv(t->n[a->index] - s->n[a->index], t->n[a->index2] - s->n[a->index2]);
- }
- static long
- netbw(Stats *s)
- {
- ulong *n;
- n = s->n;
- return n[StatRpcReadBytes]+n[StatRpcWriteBytes]; /* not exactly right */
- }
- static long
- diskbw(Stats *s)
- {
- ulong *n;
- n = s->n;
- return n[StatApartReadBytes]+n[StatApartWriteBytes]
- + n[StatIsectReadBytes]+n[StatIsectWriteBytes]
- + n[StatSumReadBytes];
- }
- static long
- iobw(Stats *s)
- {
- return netbw(s)+diskbw(s);
- }
- static long
- diskgraph(Stats *s, Stats *t, void *va)
- {
- USED(va);
- return diskbw(t)-diskbw(s);
- }
- static long
- netgraph(Stats *s, Stats *t, void *va)
- {
- USED(va);
- return netbw(t)-netbw(s);
- }
- static long
- iograph(Stats *s, Stats *t, void *va)
- {
- USED(va);
- return iobw(t)-iobw(s);
- }
- static char* graphname[] =
- {
- "rpctotal",
- "rpcread",
- "rpcreadok",
- "rpcreadfail",
- "rpcreadbyte",
- "rpcreadtime",
- "rpcreadcached",
- "rpcreadcachedtime",
- "rpcreaduncached",
- "rpcreaduncachedtime",
- "rpcwrite",
- "rpcwritenew",
- "rpcwriteold",
- "rpcwritefail",
- "rpcwritebyte",
- "rpcwritetime",
- "rpcwritenewtime",
- "rpcwriteoldtime",
- "lcachehit",
- "lcachemiss",
- "lcachelookup",
- "lcachewrite",
- "lcachesize",
- "lcachestall",
- "lcachelookuptime",
-
- "dcachehit",
- "dcachemiss",
- "dcachelookup",
- "dcacheread",
- "dcachewrite",
- "dcachedirty",
- "dcachesize",
- "dcacheflush",
- "dcachestall",
- "dcachelookuptime",
- "dblockstall",
- "lumpstall",
- "icachehit",
- "icachemiss",
- "icacheread",
- "icachewrite",
- "icachefill",
- "icacheprefetch",
- "icachedirty",
- "icachesize",
- "icacheflush",
- "icachestall",
- "icachelookuptime",
- "icachelookup",
- "scachehit",
- "scacheprefetch",
- "bloomhit",
- "bloommiss",
- "bloomfalsemiss",
- "bloomlookup",
- "bloomones",
- "bloombits",
- "apartread",
- "apartreadbyte",
- "apartwrite",
- "apartwritebyte",
- "isectread",
- "isectreadbyte",
- "isectwrite",
- "isectwritebyte",
- "sumread",
- "sumreadbyte",
-
- "cigload",
- "cigloadtime",
- };
- static int
- findname(char *s)
- {
- int i;
- for(i=0; i<nelem(graphname); i++)
- if(strcmp(graphname[i], s) == 0)
- return i;
- return -1;
- }
- static void
- dotextbin(Hio *io, Graph *g)
- {
- int i, nbin;
- Statbin *b, bin[2000]; /* 32 kB, but whack is worse */
- needstack(8192); /* double check that bin didn't kill us */
- nbin = 100;
- binstats(g->fn, g->arg, g->t0, g->t1, bin, nbin);
- hprint(io, "stats\n\n");
- for(i=0; i<nbin; i++){
- b = &bin[i];
- hprint(io, "%d: nsamp=%d min=%d max=%d avg=%d\n",
- i, b->nsamp, b->min, b->max, b->avg);
- }
- }
- static int
- xgraph(HConnect *c)
- {
- char *name;
- Hio *hout;
- Memimage *m;
- int dotext;
- Graph g;
- Arg arg;
- char *graph, *a;
- name = hargstr(c, "arg", "");
- if((arg.index = findname(name)) == -1 && strcmp(name, "*") != 0){
- werrstr("unknown name %s", name);
- goto error;
- }
- a = hargstr(c, "arg2", "");
- if(a[0] && (arg.index2 = findname(a)) == -1){
- werrstr("unknown name %s", a);
- goto error;
- }
- g.arg = &arg;
- g.t0 = hargint(c, "t0", -120);
- g.t1 = hargint(c, "t1", 0);
- g.min = hargint(c, "min", -1);
- g.max = hargint(c, "max", -1);
- g.wid = hargint(c, "wid", -1);
- g.ht = hargint(c, "ht", -1);
- dotext = hargstr(c, "text", "")[0] != 0;
- g.fill = hargint(c, "fill", -1);
-
- graph = hargstr(c, "graph", "raw");
- if(strcmp(graph, "raw") == 0)
- g.fn = rawgraph;
- else if(strcmp(graph, "diskbw") == 0)
- g.fn = diskgraph;
- else if(strcmp(graph, "iobw") == 0)
- g.fn = iograph;
- else if(strcmp(graph, "netbw") == 0)
- g.fn = netgraph;
- else if(strcmp(graph, "diff") == 0)
- g.fn = diffgraph;
- else if(strcmp(graph, "pct") == 0)
- g.fn = pctgraph;
- else if(strcmp(graph, "pctdiff") == 0)
- g.fn = pctdiffgraph;
- else if(strcmp(graph, "divdiff") == 0)
- g.fn = divdiffgraph;
- else{
- werrstr("unknown graph %s", graph);
- goto error;
- }
- if(dotext){
- hsettype(c, "text/plain");
- dotextbin(&c->hout, &g);
- hflush(&c->hout);
- return 0;
- }
- m = statgraph(&g);
- if(m == nil)
- goto error;
- if(hsettype(c, "image/png") < 0)
- return -1;
- hout = &c->hout;
- writepng(hout, m);
- qlock(&memdrawlock);
- freememimage(m);
- qunlock(&memdrawlock);
- hflush(hout);
- return 0;
- error:
- return herror(c);
- }
- static int
- xloglist(HConnect *c)
- {
- if(hsettype(c, "text/html") < 0)
- return -1;
- vtloghlist(&c->hout);
- hflush(&c->hout);
- return 0;
- }
- static int
- xlog(HConnect *c)
- {
- char *name;
- VtLog *l;
- name = hargstr(c, "log", "");
- if(!name[0])
- return xloglist(c);
- l = vtlogopen(name, 0);
- if(l == nil)
- return hnotfound(c);
- if(hsettype(c, "text/html") < 0){
- vtlogclose(l);
- return -1;
- }
- vtloghdump(&c->hout, l);
- vtlogclose(l);
- hflush(&c->hout);
- return 0;
- }
- static int
- xindex(HConnect *c)
- {
- if(hsettype(c, "text/xml") < 0)
- return -1;
- xmlindex(&c->hout, mainindex, "index", 0);
- hflush(&c->hout);
- return 0;
- }
- void
- xmlindent(Hio *hout, int indent)
- {
- int i;
- for(i = 0; i < indent; i++)
- hputc(hout, '\t');
- }
- void
- xmlaname(Hio *hout, char *v, char *tag)
- {
- hprint(hout, " %s=\"%s\"", tag, v);
- }
- void
- xmlscore(Hio *hout, u8int *v, char *tag)
- {
- if(scorecmp(zeroscore, v) == 0)
- return;
- hprint(hout, " %s=\"%V\"", tag, v);
- }
- void
- xmlsealed(Hio *hout, int v, char *tag)
- {
- if(!v)
- return;
- hprint(hout, " %s=\"yes\"", tag);
- }
- void
- xmlu32int(Hio *hout, u32int v, char *tag)
- {
- hprint(hout, " %s=\"%ud\"", tag, v);
- }
- void
- xmlu64int(Hio *hout, u64int v, char *tag)
- {
- hprint(hout, " %s=\"%llud\"", tag, v);
- }
- void
- vtloghdump(Hio *h, VtLog *l)
- {
- int i;
- VtLogChunk *c;
- char *name;
-
- name = l ? l->name : "<nil>";
- hprint(h, "<html><head>\n");
- hprint(h, "<title>Venti Server Log: %s</title>\n", name);
- hprint(h, "</head><body>\n");
- hprint(h, "<b>Venti Server Log: %s</b>\n<p>\n", name);
-
- if(l){
- c = l->w;
- for(i=0; i<l->nchunk; i++){
- if(++c == l->chunk+l->nchunk)
- c = l->chunk;
- hwrite(h, c->p, c->wp-c->p);
- }
- }
- hprint(h, "</body></html>\n");
- }
- static int
- strpcmp(const void *va, const void *vb)
- {
- return strcmp(*(char**)va, *(char**)vb);
- }
- void
- vtloghlist(Hio *h)
- {
- char **p;
- int i, n;
-
- hprint(h, "<html><head>\n");
- hprint(h, "<title>Venti Server Logs</title>\n");
- hprint(h, "</head><body>\n");
- hprint(h, "<b>Venti Server Logs</b>\n<p>\n");
-
- p = vtlognames(&n);
- qsort(p, n, sizeof(p[0]), strpcmp);
- for(i=0; i<n; i++)
- hprint(h, "<a href=\"/log?log=%s\">%s</a><br>\n", p[i], p[i]);
- vtfree(p);
- hprint(h, "</body></html>\n");
- }
|