1368c31abSDavid du Colombier #include "stdinc.h" 2368c31abSDavid du Colombier #include "dat.h" 3368c31abSDavid du Colombier #include "fns.h" 4368c31abSDavid du Colombier #include "xml.h" 5368c31abSDavid du Colombier 6368c31abSDavid du Colombier typedef struct HttpObj HttpObj; 7368c31abSDavid du Colombier extern QLock memdrawlock; 8368c31abSDavid du Colombier 9368c31abSDavid du Colombier enum 10368c31abSDavid du Colombier { 11368c31abSDavid du Colombier ObjNameSize = 64, 12368c31abSDavid du Colombier MaxObjs = 64 13368c31abSDavid du Colombier }; 14368c31abSDavid du Colombier 15368c31abSDavid du Colombier struct HttpObj 16368c31abSDavid du Colombier { 17368c31abSDavid du Colombier char name[ObjNameSize]; 18368c31abSDavid du Colombier int (*f)(HConnect*); 19368c31abSDavid du Colombier }; 20368c31abSDavid du Colombier 21368c31abSDavid du Colombier static HttpObj objs[MaxObjs]; 22368c31abSDavid du Colombier 23368c31abSDavid du Colombier static char *webroot; 24368c31abSDavid du Colombier 25368c31abSDavid du Colombier static void listenproc(void*); 26368c31abSDavid du Colombier static int estats(HConnect *c); 27368c31abSDavid du Colombier static int dindex(HConnect *c); 28368c31abSDavid du Colombier static int xindex(HConnect *c); 29368c31abSDavid du Colombier static int xlog(HConnect *c); 30368c31abSDavid du Colombier static int sindex(HConnect *c); 31368c31abSDavid du Colombier static int hempty(HConnect *c); 32368c31abSDavid du Colombier static int hlcacheempty(HConnect *c); 33368c31abSDavid du Colombier static int hdcacheempty(HConnect *c); 34368c31abSDavid du Colombier static int hicacheempty(HConnect *c); 35368c31abSDavid du Colombier static int hicachekick(HConnect *c); 36368c31abSDavid du Colombier static int hdcachekick(HConnect *c); 37368c31abSDavid du Colombier static int hicacheflush(HConnect *c); 38368c31abSDavid du Colombier static int hdcacheflush(HConnect *c); 39368c31abSDavid du Colombier static int httpdobj(char *name, int (*f)(HConnect*)); 40368c31abSDavid du Colombier static int xgraph(HConnect *c); 41368c31abSDavid du Colombier static int xset(HConnect *c); 42368c31abSDavid du Colombier static int fromwebdir(HConnect *c); 43368c31abSDavid du Colombier 44368c31abSDavid du Colombier int 45368c31abSDavid du Colombier httpdinit(char *address, char *dir) 46368c31abSDavid du Colombier { 47368c31abSDavid du Colombier fmtinstall('D', hdatefmt); 48368c31abSDavid du Colombier /* fmtinstall('H', httpfmt); */ 49368c31abSDavid du Colombier fmtinstall('U', hurlfmt); 50368c31abSDavid du Colombier 51368c31abSDavid du Colombier if(address == nil) 52368c31abSDavid du Colombier address = "tcp!*!http"; 53368c31abSDavid du Colombier webroot = dir; 54368c31abSDavid du Colombier 55368c31abSDavid du Colombier httpdobj("/stats", estats); 56368c31abSDavid du Colombier httpdobj("/index", dindex); 57368c31abSDavid du Colombier httpdobj("/storage", sindex); 58368c31abSDavid du Colombier httpdobj("/xindex", xindex); 59368c31abSDavid du Colombier httpdobj("/flushicache", hicacheflush); 60368c31abSDavid du Colombier httpdobj("/flushdcache", hdcacheflush); 61368c31abSDavid du Colombier httpdobj("/kickicache", hicachekick); 62368c31abSDavid du Colombier httpdobj("/kickdcache", hdcachekick); 63368c31abSDavid du Colombier httpdobj("/graph", xgraph); 64368c31abSDavid du Colombier httpdobj("/set", xset); 65368c31abSDavid du Colombier httpdobj("/log", xlog); 66368c31abSDavid du Colombier httpdobj("/empty", hempty); 67368c31abSDavid du Colombier httpdobj("/emptyicache", hicacheempty); 68368c31abSDavid du Colombier httpdobj("/emptylumpcache", hlcacheempty); 69368c31abSDavid du Colombier httpdobj("/emptydcache", hdcacheempty); 70368c31abSDavid du Colombier httpdobj("/disk", hdisk); 71368c31abSDavid du Colombier httpdobj("/debug", hdebug); 72368c31abSDavid du Colombier 73368c31abSDavid du Colombier if(vtproc(listenproc, address) < 0) 74368c31abSDavid du Colombier return -1; 75368c31abSDavid du Colombier return 0; 76368c31abSDavid du Colombier } 77368c31abSDavid du Colombier 78368c31abSDavid du Colombier static int 79368c31abSDavid du Colombier httpdobj(char *name, int (*f)(HConnect*)) 80368c31abSDavid du Colombier { 81368c31abSDavid du Colombier int i; 82368c31abSDavid du Colombier 83368c31abSDavid du Colombier if(name == nil || strlen(name) >= ObjNameSize) 84368c31abSDavid du Colombier return -1; 85368c31abSDavid du Colombier for(i = 0; i < MaxObjs; i++){ 86368c31abSDavid du Colombier if(objs[i].name[0] == '\0'){ 87368c31abSDavid du Colombier strcpy(objs[i].name, name); 88368c31abSDavid du Colombier objs[i].f = f; 89368c31abSDavid du Colombier return 0; 90368c31abSDavid du Colombier } 91368c31abSDavid du Colombier if(strcmp(objs[i].name, name) == 0) 92368c31abSDavid du Colombier return -1; 93368c31abSDavid du Colombier } 94368c31abSDavid du Colombier return -1; 95368c31abSDavid du Colombier } 96368c31abSDavid du Colombier 97368c31abSDavid du Colombier static HConnect* 98368c31abSDavid du Colombier mkconnect(void) 99368c31abSDavid du Colombier { 100368c31abSDavid du Colombier HConnect *c; 101368c31abSDavid du Colombier 102368c31abSDavid du Colombier c = mallocz(sizeof(HConnect), 1); 103368c31abSDavid du Colombier if(c == nil) 104368c31abSDavid du Colombier sysfatal("out of memory"); 105368c31abSDavid du Colombier c->replog = nil; 106368c31abSDavid du Colombier c->hpos = c->header; 107368c31abSDavid du Colombier c->hstop = c->header; 108368c31abSDavid du Colombier return c; 109368c31abSDavid du Colombier } 110368c31abSDavid du Colombier 111368c31abSDavid du Colombier void httpproc(void*); 112368c31abSDavid du Colombier 113368c31abSDavid du Colombier static void 114368c31abSDavid du Colombier listenproc(void *vaddress) 115368c31abSDavid du Colombier { 116368c31abSDavid du Colombier HConnect *c; 117368c31abSDavid du Colombier char *address, ndir[NETPATHLEN], dir[NETPATHLEN]; 118368c31abSDavid du Colombier int ctl, nctl, data; 119368c31abSDavid du Colombier 120368c31abSDavid du Colombier address = vaddress; 121368c31abSDavid du Colombier ctl = announce(address, dir); 122368c31abSDavid du Colombier if(ctl < 0){ 123368c31abSDavid du Colombier fprint(2, "venti: httpd can't announce on %s: %r\n", address); 124368c31abSDavid du Colombier return; 125368c31abSDavid du Colombier } 126368c31abSDavid du Colombier 127368c31abSDavid du Colombier if(0) print("announce ctl %d dir %s\n", ctl, dir); 128368c31abSDavid du Colombier for(;;){ 129368c31abSDavid du Colombier /* 130368c31abSDavid du Colombier * wait for a call (or an error) 131368c31abSDavid du Colombier */ 132368c31abSDavid du Colombier nctl = listen(dir, ndir); 133368c31abSDavid du Colombier if(0) print("httpd listen %d %s...\n", nctl, ndir); 134368c31abSDavid du Colombier if(nctl < 0){ 135368c31abSDavid du Colombier fprint(2, "venti: httpd can't listen on %s: %r\n", address); 136368c31abSDavid du Colombier return; 137368c31abSDavid du Colombier } 138368c31abSDavid du Colombier 139368c31abSDavid du Colombier data = accept(ctl, ndir); 140368c31abSDavid du Colombier if(0) print("httpd accept %d...\n", data); 141368c31abSDavid du Colombier if(data < 0){ 142368c31abSDavid du Colombier fprint(2, "venti: httpd accept: %r\n"); 143368c31abSDavid du Colombier close(nctl); 144368c31abSDavid du Colombier continue; 145368c31abSDavid du Colombier } 146368c31abSDavid du Colombier if(0) print("httpd close nctl %d\n", nctl); 147368c31abSDavid du Colombier close(nctl); 148368c31abSDavid du Colombier c = mkconnect(); 149368c31abSDavid du Colombier hinit(&c->hin, data, Hread); 150368c31abSDavid du Colombier hinit(&c->hout, data, Hwrite); 151368c31abSDavid du Colombier vtproc(httpproc, c); 152368c31abSDavid du Colombier } 153368c31abSDavid du Colombier } 154368c31abSDavid du Colombier 155368c31abSDavid du Colombier void 156368c31abSDavid du Colombier httpproc(void *v) 157368c31abSDavid du Colombier { 158368c31abSDavid du Colombier HConnect *c; 159368c31abSDavid du Colombier int ok, i, n; 160368c31abSDavid du Colombier 161368c31abSDavid du Colombier c = v; 162368c31abSDavid du Colombier 163368c31abSDavid du Colombier for(;;){ 164368c31abSDavid du Colombier /* 165368c31abSDavid du Colombier * No timeout because the signal appears to hit every 166368c31abSDavid du Colombier * proc, not just us. 167368c31abSDavid du Colombier */ 168368c31abSDavid du Colombier if(hparsereq(c, 0) < 0) 169368c31abSDavid du Colombier break; 170368c31abSDavid du Colombier 171368c31abSDavid du Colombier for(i = 0; i < MaxObjs && objs[i].name[0]; i++){ 172368c31abSDavid du Colombier n = strlen(objs[i].name); 173368c31abSDavid du Colombier if((objs[i].name[n-1] == '/' && strncmp(c->req.uri, objs[i].name, n) == 0) 174368c31abSDavid du Colombier || (objs[i].name[n-1] != '/' && strcmp(c->req.uri, objs[i].name) == 0)){ 175368c31abSDavid du Colombier ok = (*objs[i].f)(c); 176368c31abSDavid du Colombier goto found; 177368c31abSDavid du Colombier } 178368c31abSDavid du Colombier } 179368c31abSDavid du Colombier ok = fromwebdir(c); 180368c31abSDavid du Colombier found: 181368c31abSDavid du Colombier hflush(&c->hout); 182368c31abSDavid du Colombier if(c->head.closeit) 183368c31abSDavid du Colombier ok = -1; 184368c31abSDavid du Colombier hreqcleanup(c); 185368c31abSDavid du Colombier 186368c31abSDavid du Colombier if(ok < 0) 187368c31abSDavid du Colombier break; 188368c31abSDavid du Colombier } 189368c31abSDavid du Colombier hreqcleanup(c); 190368c31abSDavid du Colombier close(c->hin.fd); 191368c31abSDavid du Colombier free(c); 192368c31abSDavid du Colombier } 193368c31abSDavid du Colombier 194368c31abSDavid du Colombier char* 195368c31abSDavid du Colombier hargstr(HConnect *c, char *name, char *def) 196368c31abSDavid du Colombier { 197368c31abSDavid du Colombier HSPairs *p; 198368c31abSDavid du Colombier 199368c31abSDavid du Colombier for(p=c->req.searchpairs; p; p=p->next) 200368c31abSDavid du Colombier if(strcmp(p->s, name) == 0) 201368c31abSDavid du Colombier return p->t; 202368c31abSDavid du Colombier return def; 203368c31abSDavid du Colombier } 204368c31abSDavid du Colombier 205368c31abSDavid du Colombier vlong 206368c31abSDavid du Colombier hargint(HConnect *c, char *name, vlong def) 207368c31abSDavid du Colombier { 208368c31abSDavid du Colombier char *a; 209368c31abSDavid du Colombier 210368c31abSDavid du Colombier if((a = hargstr(c, name, nil)) == nil) 211368c31abSDavid du Colombier return def; 212368c31abSDavid du Colombier return atoll(a); 213368c31abSDavid du Colombier } 214368c31abSDavid du Colombier 215368c31abSDavid du Colombier static int 216368c31abSDavid du Colombier percent(ulong v, ulong total) 217368c31abSDavid du Colombier { 218368c31abSDavid du Colombier if(total == 0) 219368c31abSDavid du Colombier total = 1; 220368c31abSDavid du Colombier if(v < 1000*1000) 221368c31abSDavid du Colombier return (v * 100) / total; 222368c31abSDavid du Colombier total /= 100; 223368c31abSDavid du Colombier if(total == 0) 224368c31abSDavid du Colombier total = 1; 225368c31abSDavid du Colombier return v / total; 226368c31abSDavid du Colombier } 227368c31abSDavid du Colombier 228368c31abSDavid du Colombier static int 229368c31abSDavid du Colombier preq(HConnect *c) 230368c31abSDavid du Colombier { 231368c31abSDavid du Colombier if(hparseheaders(c, 0) < 0) 232368c31abSDavid du Colombier return -1; 233368c31abSDavid du Colombier if(strcmp(c->req.meth, "GET") != 0 234368c31abSDavid du Colombier && strcmp(c->req.meth, "HEAD") != 0) 235368c31abSDavid du Colombier return hunallowed(c, "GET, HEAD"); 236368c31abSDavid du Colombier if(c->head.expectother || c->head.expectcont) 237368c31abSDavid du Colombier return hfail(c, HExpectFail, nil); 238368c31abSDavid du Colombier return 0; 239368c31abSDavid du Colombier } 240368c31abSDavid du Colombier 241368c31abSDavid du Colombier int 242368c31abSDavid du Colombier hsettype(HConnect *c, char *type) 243368c31abSDavid du Colombier { 244368c31abSDavid du Colombier Hio *hout; 245368c31abSDavid du Colombier int r; 246368c31abSDavid du Colombier 247368c31abSDavid du Colombier r = preq(c); 248368c31abSDavid du Colombier if(r < 0) 249368c31abSDavid du Colombier return r; 250368c31abSDavid du Colombier 251368c31abSDavid du Colombier hout = &c->hout; 252368c31abSDavid du Colombier if(c->req.vermaj){ 253368c31abSDavid du Colombier hokheaders(c); 254368c31abSDavid du Colombier hprint(hout, "Content-type: %s\r\n", type); 255368c31abSDavid du Colombier if(http11(c)) 256368c31abSDavid du Colombier hprint(hout, "Transfer-Encoding: chunked\r\n"); 257368c31abSDavid du Colombier hprint(hout, "\r\n"); 258368c31abSDavid du Colombier } 259368c31abSDavid du Colombier 260368c31abSDavid du Colombier if(http11(c)) 261368c31abSDavid du Colombier hxferenc(hout, 1); 262368c31abSDavid du Colombier else 263368c31abSDavid du Colombier c->head.closeit = 1; 264368c31abSDavid du Colombier return 0; 265368c31abSDavid du Colombier } 266368c31abSDavid du Colombier 267368c31abSDavid du Colombier int 268368c31abSDavid du Colombier hsethtml(HConnect *c) 269368c31abSDavid du Colombier { 270368c31abSDavid du Colombier return hsettype(c, "text/html; charset=utf-8"); 271368c31abSDavid du Colombier } 272368c31abSDavid du Colombier 273368c31abSDavid du Colombier int 274368c31abSDavid du Colombier hsettext(HConnect *c) 275368c31abSDavid du Colombier { 276368c31abSDavid du Colombier return hsettype(c, "text/plain; charset=utf-8"); 277368c31abSDavid du Colombier } 278368c31abSDavid du Colombier 279368c31abSDavid du Colombier static int 280368c31abSDavid du Colombier herror(HConnect *c) 281368c31abSDavid du Colombier { 282368c31abSDavid du Colombier int n; 283368c31abSDavid du Colombier Hio *hout; 284368c31abSDavid du Colombier 285368c31abSDavid du Colombier hout = &c->hout; 286368c31abSDavid du Colombier n = snprint(c->xferbuf, HBufSize, "<html><head><title>Error</title></head>\n<body><h1>Error</h1>\n<pre>%r</pre>\n</body></html>"); 287368c31abSDavid du Colombier hprint(hout, "%s %s\r\n", hversion, "400 Bad Request"); 288368c31abSDavid du Colombier hprint(hout, "Date: %D\r\n", time(nil)); 289368c31abSDavid du Colombier hprint(hout, "Server: Venti\r\n"); 290368c31abSDavid du Colombier hprint(hout, "Content-Type: text/html\r\n"); 291368c31abSDavid du Colombier hprint(hout, "Content-Length: %d\r\n", n); 292368c31abSDavid du Colombier if(c->head.closeit) 293368c31abSDavid du Colombier hprint(hout, "Connection: close\r\n"); 294368c31abSDavid du Colombier else if(!http11(c)) 295368c31abSDavid du Colombier hprint(hout, "Connection: Keep-Alive\r\n"); 296368c31abSDavid du Colombier hprint(hout, "\r\n"); 297368c31abSDavid du Colombier 298368c31abSDavid du Colombier if(c->req.meth == nil || strcmp(c->req.meth, "HEAD") != 0) 299368c31abSDavid du Colombier hwrite(hout, c->xferbuf, n); 300368c31abSDavid du Colombier 301368c31abSDavid du Colombier return hflush(hout); 302368c31abSDavid du Colombier } 303368c31abSDavid du Colombier 304368c31abSDavid du Colombier int 305368c31abSDavid du Colombier hnotfound(HConnect *c) 306368c31abSDavid du Colombier { 307368c31abSDavid du Colombier int r; 308368c31abSDavid du Colombier 309368c31abSDavid du Colombier r = preq(c); 310368c31abSDavid du Colombier if(r < 0) 311368c31abSDavid du Colombier return r; 312368c31abSDavid du Colombier return hfail(c, HNotFound, c->req.uri); 313368c31abSDavid du Colombier } 314368c31abSDavid du Colombier 315368c31abSDavid du Colombier struct { 316368c31abSDavid du Colombier char *ext; 317368c31abSDavid du Colombier char *type; 318368c31abSDavid du Colombier } exttab[] = { 319368c31abSDavid du Colombier ".html", "text/html", 320368c31abSDavid du Colombier ".txt", "text/plain", 321368c31abSDavid du Colombier ".xml", "text/xml", 322368c31abSDavid du Colombier ".png", "image/png", 323368c31abSDavid du Colombier ".gif", "image/gif", 324368c31abSDavid du Colombier 0 325368c31abSDavid du Colombier }; 326368c31abSDavid du Colombier 327368c31abSDavid du Colombier static int 328368c31abSDavid du Colombier fromwebdir(HConnect *c) 329368c31abSDavid du Colombier { 330368c31abSDavid du Colombier char buf[4096], *p, *ext, *type; 331368c31abSDavid du Colombier int i, fd, n, defaulted; 332368c31abSDavid du Colombier Dir *d; 333368c31abSDavid du Colombier 334368c31abSDavid du Colombier if(webroot == nil || strstr(c->req.uri, "..")) 335368c31abSDavid du Colombier return hnotfound(c); 336368c31abSDavid du Colombier snprint(buf, sizeof buf-20, "%s/%s", webroot, c->req.uri+1); 337368c31abSDavid du Colombier defaulted = 0; 338368c31abSDavid du Colombier reopen: 339368c31abSDavid du Colombier if((fd = open(buf, OREAD)) < 0) 340368c31abSDavid du Colombier return hnotfound(c); 341368c31abSDavid du Colombier d = dirfstat(fd); 342368c31abSDavid du Colombier if(d == nil){ 343368c31abSDavid du Colombier close(fd); 344368c31abSDavid du Colombier return hnotfound(c); 345368c31abSDavid du Colombier } 346368c31abSDavid du Colombier if(d->mode&DMDIR){ 347368c31abSDavid du Colombier if(!defaulted){ 348368c31abSDavid du Colombier defaulted = 1; 349368c31abSDavid du Colombier strcat(buf, "/index.html"); 350368c31abSDavid du Colombier free(d); 351368c31abSDavid du Colombier close(fd); 352368c31abSDavid du Colombier goto reopen; 353368c31abSDavid du Colombier } 354368c31abSDavid du Colombier free(d); 355368c31abSDavid du Colombier return hnotfound(c); 356368c31abSDavid du Colombier } 357368c31abSDavid du Colombier free(d); 358368c31abSDavid du Colombier p = buf+strlen(buf); 359368c31abSDavid du Colombier type = "application/octet-stream"; 360368c31abSDavid du Colombier for(i=0; exttab[i].ext; i++){ 361368c31abSDavid du Colombier ext = exttab[i].ext; 362368c31abSDavid du Colombier if(p-strlen(ext) >= buf && strcmp(p-strlen(ext), ext) == 0){ 363368c31abSDavid du Colombier type = exttab[i].type; 364368c31abSDavid du Colombier break; 365368c31abSDavid du Colombier } 366368c31abSDavid du Colombier } 367368c31abSDavid du Colombier if(hsettype(c, type) < 0){ 368368c31abSDavid du Colombier close(fd); 369368c31abSDavid du Colombier return 0; 370368c31abSDavid du Colombier } 371368c31abSDavid du Colombier while((n = read(fd, buf, sizeof buf)) > 0) 372368c31abSDavid du Colombier if(hwrite(&c->hout, buf, n) < 0) 373368c31abSDavid du Colombier break; 374368c31abSDavid du Colombier close(fd); 375368c31abSDavid du Colombier hflush(&c->hout); 376368c31abSDavid du Colombier return 0; 377368c31abSDavid du Colombier } 378368c31abSDavid du Colombier 379368c31abSDavid du Colombier static struct 380368c31abSDavid du Colombier { 381368c31abSDavid du Colombier char *name; 382368c31abSDavid du Colombier int *p; 383368c31abSDavid du Colombier } namedints[] = 384368c31abSDavid du Colombier { 385368c31abSDavid du Colombier "compress", &compressblocks, 386368c31abSDavid du Colombier "devnull", &writestodevnull, 387368c31abSDavid du Colombier "logging", &ventilogging, 388368c31abSDavid du Colombier "stats", &collectstats, 389368c31abSDavid du Colombier "icachesleeptime", &icachesleeptime, 390368c31abSDavid du Colombier "minicachesleeptime", &minicachesleeptime, 391368c31abSDavid du Colombier "arenasumsleeptime", &arenasumsleeptime, 392368c31abSDavid du Colombier "l0quantum", &l0quantum, 393368c31abSDavid du Colombier "l1quantum", &l1quantum, 394368c31abSDavid du Colombier "manualscheduling", &manualscheduling, 395368c31abSDavid du Colombier "ignorebloom", &ignorebloom, 396368c31abSDavid du Colombier "syncwrites", &syncwrites, 397368c31abSDavid du Colombier "icacheprefetch", &icacheprefetch, 398368c31abSDavid du Colombier 0 399368c31abSDavid du Colombier }; 400368c31abSDavid du Colombier 401368c31abSDavid du Colombier static int 402368c31abSDavid du Colombier xset(HConnect *c) 403368c31abSDavid du Colombier { 404368c31abSDavid du Colombier int i, old; 405368c31abSDavid du Colombier char *name, *value; 406368c31abSDavid du Colombier 407368c31abSDavid du Colombier if(hsettext(c) < 0) 408368c31abSDavid du Colombier return -1; 409368c31abSDavid du Colombier 410368c31abSDavid du Colombier if((name = hargstr(c, "name", nil)) == nil || name[0] == 0){ 411368c31abSDavid du Colombier for(i=0; namedints[i].name; i++) 412368c31abSDavid du Colombier hprint(&c->hout, "%s = %d\n", namedints[i].name, *namedints[i].p); 413368c31abSDavid du Colombier hflush(&c->hout); 414368c31abSDavid du Colombier return 0; 415368c31abSDavid du Colombier } 416368c31abSDavid du Colombier 417368c31abSDavid du Colombier for(i=0; namedints[i].name; i++) 418368c31abSDavid du Colombier if(strcmp(name, namedints[i].name) == 0) 419368c31abSDavid du Colombier break; 420368c31abSDavid du Colombier if(!namedints[i].name){ 421368c31abSDavid du Colombier hprint(&c->hout, "%s not found\n", name); 422368c31abSDavid du Colombier hflush(&c->hout); 423368c31abSDavid du Colombier return 0; 424368c31abSDavid du Colombier } 425368c31abSDavid du Colombier 426368c31abSDavid du Colombier if((value = hargstr(c, "value", nil)) == nil || value[0] == 0){ 427368c31abSDavid du Colombier hprint(&c->hout, "%s = %d\n", namedints[i].name, *namedints[i].p); 428368c31abSDavid du Colombier hflush(&c->hout); 429368c31abSDavid du Colombier return 0; 430368c31abSDavid du Colombier } 431368c31abSDavid du Colombier 432368c31abSDavid du Colombier old = *namedints[i].p; 433368c31abSDavid du Colombier *namedints[i].p = atoll(value); 434368c31abSDavid du Colombier hprint(&c->hout, "%s = %d (was %d)\n", name, *namedints[i].p, old); 435368c31abSDavid du Colombier hflush(&c->hout); 436368c31abSDavid du Colombier return 0; 437368c31abSDavid du Colombier } 438368c31abSDavid du Colombier 439368c31abSDavid du Colombier static int 440368c31abSDavid du Colombier estats(HConnect *c) 441368c31abSDavid du Colombier { 442368c31abSDavid du Colombier Hio *hout; 443368c31abSDavid du Colombier int r; 444368c31abSDavid du Colombier 445368c31abSDavid du Colombier r = hsettext(c); 446368c31abSDavid du Colombier if(r < 0) 447368c31abSDavid du Colombier return r; 448368c31abSDavid du Colombier 449368c31abSDavid du Colombier 450368c31abSDavid du Colombier hout = &c->hout; 451368c31abSDavid du Colombier /* 452368c31abSDavid du Colombier hprint(hout, "lump writes=%,ld\n", stats.lumpwrites); 453368c31abSDavid du Colombier hprint(hout, "lump reads=%,ld\n", stats.lumpreads); 454368c31abSDavid du Colombier hprint(hout, "lump cache read hits=%,ld\n", stats.lumphit); 455368c31abSDavid du Colombier hprint(hout, "lump cache read misses=%,ld\n", stats.lumpmiss); 456368c31abSDavid du Colombier 457368c31abSDavid du Colombier hprint(hout, "clump disk writes=%,ld\n", stats.clumpwrites); 458368c31abSDavid du Colombier hprint(hout, "clump disk bytes written=%,lld\n", stats.clumpbwrites); 459368c31abSDavid du Colombier hprint(hout, "clump disk bytes compressed=%,lld\n", stats.clumpbcomp); 460368c31abSDavid du Colombier hprint(hout, "clump disk reads=%,ld\n", stats.clumpreads); 461368c31abSDavid du Colombier hprint(hout, "clump disk bytes read=%,lld\n", stats.clumpbreads); 462368c31abSDavid du Colombier hprint(hout, "clump disk bytes uncompressed=%,lld\n", stats.clumpbuncomp); 463368c31abSDavid du Colombier 464368c31abSDavid du Colombier hprint(hout, "clump directory disk writes=%,ld\n", stats.ciwrites); 465368c31abSDavid du Colombier hprint(hout, "clump directory disk reads=%,ld\n", stats.cireads); 466368c31abSDavid du Colombier 467368c31abSDavid du Colombier hprint(hout, "index disk writes=%,ld\n", stats.indexwrites); 468368c31abSDavid du Colombier hprint(hout, "index disk reads=%,ld\n", stats.indexreads); 469368c31abSDavid du Colombier hprint(hout, "index disk bloom filter hits=%,ld %d%% falsemisses=%,ld %d%%\n", 470368c31abSDavid du Colombier stats.indexbloomhits, 471368c31abSDavid du Colombier percent(stats.indexbloomhits, stats.indexreads), 472368c31abSDavid du Colombier stats.indexbloomfalsemisses, 473368c31abSDavid du Colombier percent(stats.indexbloomfalsemisses, stats.indexreads)); 474368c31abSDavid du Colombier hprint(hout, "bloom filter bits=%,ld of %,ld %d%%\n", 475368c31abSDavid du Colombier stats.bloomones, stats.bloombits, percent(stats.bloomones, stats.bloombits)); 476368c31abSDavid du Colombier hprint(hout, "index disk reads for modify=%,ld\n", stats.indexwreads); 477368c31abSDavid du Colombier hprint(hout, "index disk reads for allocation=%,ld\n", stats.indexareads); 478368c31abSDavid du Colombier hprint(hout, "index block splits=%,ld\n", stats.indexsplits); 479368c31abSDavid du Colombier 480368c31abSDavid du Colombier hprint(hout, "index cache lookups=%,ld\n", stats.iclookups); 481368c31abSDavid du Colombier hprint(hout, "index cache hits=%,ld %d%%\n", stats.ichits, 482368c31abSDavid du Colombier percent(stats.ichits, stats.iclookups)); 483368c31abSDavid du Colombier hprint(hout, "index cache fills=%,ld %d%%\n", stats.icfills, 484368c31abSDavid du Colombier percent(stats.icfills, stats.iclookups)); 485368c31abSDavid du Colombier hprint(hout, "index cache inserts=%,ld\n", stats.icinserts); 486368c31abSDavid du Colombier 487368c31abSDavid du Colombier hprint(hout, "disk cache hits=%,ld\n", stats.pchit); 488368c31abSDavid du Colombier hprint(hout, "disk cache misses=%,ld\n", stats.pcmiss); 489368c31abSDavid du Colombier hprint(hout, "disk cache reads=%,ld\n", stats.pcreads); 490368c31abSDavid du Colombier hprint(hout, "disk cache bytes read=%,lld\n", stats.pcbreads); 491368c31abSDavid du Colombier 492368c31abSDavid du Colombier hprint(hout, "disk cache writes=%,ld\n", stats.dirtydblocks); 493368c31abSDavid du Colombier hprint(hout, "disk cache writes absorbed=%,ld %d%%\n", stats.absorbedwrites, 494368c31abSDavid du Colombier percent(stats.absorbedwrites, stats.dirtydblocks)); 495368c31abSDavid du Colombier 496368c31abSDavid du Colombier hprint(hout, "disk cache flushes=%,ld\n", stats.dcacheflushes); 497368c31abSDavid du Colombier hprint(hout, "disk cache flush writes=%,ld (%,ld per flush)\n", 498368c31abSDavid du Colombier stats.dcacheflushwrites, 499368c31abSDavid du Colombier stats.dcacheflushwrites/(stats.dcacheflushes ? stats.dcacheflushes : 1)); 500368c31abSDavid du Colombier 501368c31abSDavid du Colombier hprint(hout, "disk writes=%,ld\n", stats.diskwrites); 502368c31abSDavid du Colombier hprint(hout, "disk bytes written=%,lld\n", stats.diskbwrites); 503368c31abSDavid du Colombier hprint(hout, "disk reads=%,ld\n", stats.diskreads); 504368c31abSDavid du Colombier hprint(hout, "disk bytes read=%,lld\n", stats.diskbreads); 505368c31abSDavid du Colombier */ 506368c31abSDavid du Colombier 507368c31abSDavid du Colombier hflush(hout); 508368c31abSDavid du Colombier return 0; 509368c31abSDavid du Colombier } 510368c31abSDavid du Colombier 511368c31abSDavid du Colombier static int 512368c31abSDavid du Colombier sindex(HConnect *c) 513368c31abSDavid du Colombier { 514368c31abSDavid du Colombier Hio *hout; 515368c31abSDavid du Colombier Index *ix; 516368c31abSDavid du Colombier Arena *arena; 517368c31abSDavid du Colombier vlong clumps, cclumps, uncsize, used, size; 518368c31abSDavid du Colombier int i, r, active; 519368c31abSDavid du Colombier 520368c31abSDavid du Colombier r = hsettext(c); 521368c31abSDavid du Colombier if(r < 0) 522368c31abSDavid du Colombier return r; 523368c31abSDavid du Colombier hout = &c->hout; 524368c31abSDavid du Colombier 525368c31abSDavid du Colombier ix = mainindex; 526368c31abSDavid du Colombier 527368c31abSDavid du Colombier hprint(hout, "index=%s\n", ix->name); 528368c31abSDavid du Colombier 529368c31abSDavid du Colombier active = 0; 530368c31abSDavid du Colombier clumps = 0; 531368c31abSDavid du Colombier cclumps = 0; 532368c31abSDavid du Colombier uncsize = 0; 533368c31abSDavid du Colombier used = 0; 534368c31abSDavid du Colombier size = 0; 535368c31abSDavid du Colombier for(i = 0; i < ix->narenas; i++){ 536368c31abSDavid du Colombier arena = ix->arenas[i]; 537368c31abSDavid du Colombier if(arena != nil && arena->memstats.clumps != 0){ 538368c31abSDavid du Colombier active++; 539368c31abSDavid du Colombier clumps += arena->memstats.clumps; 540368c31abSDavid du Colombier cclumps += arena->memstats.cclumps; 541368c31abSDavid du Colombier uncsize += arena->memstats.uncsize; 542368c31abSDavid du Colombier used += arena->memstats.used; 543368c31abSDavid du Colombier } 544368c31abSDavid du Colombier size += arena->size; 545368c31abSDavid du Colombier } 546368c31abSDavid du Colombier hprint(hout, "total arenas=%,d active=%,d\n", ix->narenas, active); 547368c31abSDavid du Colombier hprint(hout, "total space=%,lld used=%,lld\n", size, used + clumps * ClumpInfoSize); 548368c31abSDavid du Colombier hprint(hout, "clumps=%,lld compressed clumps=%,lld data=%,lld compressed data=%,lld\n", 549368c31abSDavid du Colombier clumps, cclumps, uncsize, used - clumps * ClumpSize); 550368c31abSDavid du Colombier hflush(hout); 551368c31abSDavid du Colombier return 0; 552368c31abSDavid du Colombier } 553368c31abSDavid du Colombier 554368c31abSDavid du Colombier static void 555368c31abSDavid du Colombier darena(Hio *hout, Arena *arena) 556368c31abSDavid du Colombier { 557368c31abSDavid du Colombier hprint(hout, "arena='%s' on %s at [%lld,%lld)\n\tversion=%d created=%d modified=%d", 558368c31abSDavid du Colombier arena->name, arena->part->name, arena->base, arena->base + arena->size + 2 * arena->blocksize, 559368c31abSDavid du Colombier arena->version, arena->ctime, arena->wtime); 560368c31abSDavid du Colombier if(arena->memstats.sealed) 561368c31abSDavid du Colombier hprint(hout, " mem=sealed"); 562368c31abSDavid du Colombier if(arena->diskstats.sealed) 563368c31abSDavid du Colombier hprint(hout, " disk=sealed"); 564368c31abSDavid du Colombier hprint(hout, "\n"); 565368c31abSDavid du Colombier if(scorecmp(zeroscore, arena->score) != 0) 566368c31abSDavid du Colombier hprint(hout, "\tscore=%V\n", arena->score); 567368c31abSDavid du Colombier 568*f9e1cf08SDavid du Colombier hprint(hout, "\twritten: clumps=%d compressed clumps=%d data=%,lld compressed data=%,lld storage=%,lld\n", 569368c31abSDavid du Colombier arena->memstats.clumps, arena->memstats.cclumps, arena->memstats.uncsize, 570368c31abSDavid du Colombier arena->memstats.used - arena->memstats.clumps * ClumpSize, 571368c31abSDavid du Colombier arena->memstats.used + arena->memstats.clumps * ClumpInfoSize); 572*f9e1cf08SDavid du Colombier hprint(hout, "\tindexed: clumps=%d compressed clumps=%d data=%,lld compressed data=%,lld storage=%,lld\n", 573368c31abSDavid du Colombier arena->diskstats.clumps, arena->diskstats.cclumps, arena->diskstats.uncsize, 574368c31abSDavid du Colombier arena->diskstats.used - arena->diskstats.clumps * ClumpSize, 575368c31abSDavid du Colombier arena->diskstats.used + arena->diskstats.clumps * ClumpInfoSize); 576368c31abSDavid du Colombier } 577368c31abSDavid du Colombier 578368c31abSDavid du Colombier static int 579368c31abSDavid du Colombier hempty(HConnect *c) 580368c31abSDavid du Colombier { 581368c31abSDavid du Colombier Hio *hout; 582368c31abSDavid du Colombier int r; 583368c31abSDavid du Colombier 584368c31abSDavid du Colombier r = hsettext(c); 585368c31abSDavid du Colombier if(r < 0) 586368c31abSDavid du Colombier return r; 587368c31abSDavid du Colombier hout = &c->hout; 588368c31abSDavid du Colombier 589368c31abSDavid du Colombier emptylumpcache(); 590368c31abSDavid du Colombier emptydcache(); 591368c31abSDavid du Colombier emptyicache(); 592368c31abSDavid du Colombier hprint(hout, "emptied all caches\n"); 593368c31abSDavid du Colombier hflush(hout); 594368c31abSDavid du Colombier return 0; 595368c31abSDavid du Colombier } 596368c31abSDavid du Colombier 597368c31abSDavid du Colombier static int 598368c31abSDavid du Colombier hlcacheempty(HConnect *c) 599368c31abSDavid du Colombier { 600368c31abSDavid du Colombier Hio *hout; 601368c31abSDavid du Colombier int r; 602368c31abSDavid du Colombier 603368c31abSDavid du Colombier r = hsettext(c); 604368c31abSDavid du Colombier if(r < 0) 605368c31abSDavid du Colombier return r; 606368c31abSDavid du Colombier hout = &c->hout; 607368c31abSDavid du Colombier 608368c31abSDavid du Colombier emptylumpcache(); 609368c31abSDavid du Colombier hprint(hout, "emptied lumpcache\n"); 610368c31abSDavid du Colombier hflush(hout); 611368c31abSDavid du Colombier return 0; 612368c31abSDavid du Colombier } 613368c31abSDavid du Colombier 614368c31abSDavid du Colombier static int 615368c31abSDavid du Colombier hicacheempty(HConnect *c) 616368c31abSDavid du Colombier { 617368c31abSDavid du Colombier Hio *hout; 618368c31abSDavid du Colombier int r; 619368c31abSDavid du Colombier 620368c31abSDavid du Colombier r = hsettext(c); 621368c31abSDavid du Colombier if(r < 0) 622368c31abSDavid du Colombier return r; 623368c31abSDavid du Colombier hout = &c->hout; 624368c31abSDavid du Colombier 625368c31abSDavid du Colombier emptyicache(); 626368c31abSDavid du Colombier hprint(hout, "emptied icache\n"); 627368c31abSDavid du Colombier hflush(hout); 628368c31abSDavid du Colombier return 0; 629368c31abSDavid du Colombier } 630368c31abSDavid du Colombier 631368c31abSDavid du Colombier static int 632368c31abSDavid du Colombier hdcacheempty(HConnect *c) 633368c31abSDavid du Colombier { 634368c31abSDavid du Colombier Hio *hout; 635368c31abSDavid du Colombier int r; 636368c31abSDavid du Colombier 637368c31abSDavid du Colombier r = hsettext(c); 638368c31abSDavid du Colombier if(r < 0) 639368c31abSDavid du Colombier return r; 640368c31abSDavid du Colombier hout = &c->hout; 641368c31abSDavid du Colombier 642368c31abSDavid du Colombier emptydcache(); 643368c31abSDavid du Colombier hprint(hout, "emptied dcache\n"); 644368c31abSDavid du Colombier hflush(hout); 645368c31abSDavid du Colombier return 0; 646368c31abSDavid du Colombier } 647368c31abSDavid du Colombier static int 648368c31abSDavid du Colombier hicachekick(HConnect *c) 649368c31abSDavid du Colombier { 650368c31abSDavid du Colombier Hio *hout; 651368c31abSDavid du Colombier int r; 652368c31abSDavid du Colombier 653368c31abSDavid du Colombier r = hsettext(c); 654368c31abSDavid du Colombier if(r < 0) 655368c31abSDavid du Colombier return r; 656368c31abSDavid du Colombier hout = &c->hout; 657368c31abSDavid du Colombier 658368c31abSDavid du Colombier kickicache(); 659368c31abSDavid du Colombier hprint(hout, "kicked icache\n"); 660368c31abSDavid du Colombier hflush(hout); 661368c31abSDavid du Colombier return 0; 662368c31abSDavid du Colombier } 663368c31abSDavid du Colombier 664368c31abSDavid du Colombier static int 665368c31abSDavid du Colombier hdcachekick(HConnect *c) 666368c31abSDavid du Colombier { 667368c31abSDavid du Colombier Hio *hout; 668368c31abSDavid du Colombier int r; 669368c31abSDavid du Colombier 670368c31abSDavid du Colombier r = hsettext(c); 671368c31abSDavid du Colombier if(r < 0) 672368c31abSDavid du Colombier return r; 673368c31abSDavid du Colombier hout = &c->hout; 674368c31abSDavid du Colombier 675368c31abSDavid du Colombier kickdcache(); 676368c31abSDavid du Colombier hprint(hout, "kicked dcache\n"); 677368c31abSDavid du Colombier hflush(hout); 678368c31abSDavid du Colombier return 0; 679368c31abSDavid du Colombier } 680368c31abSDavid du Colombier static int 681368c31abSDavid du Colombier hicacheflush(HConnect *c) 682368c31abSDavid du Colombier { 683368c31abSDavid du Colombier Hio *hout; 684368c31abSDavid du Colombier int r; 685368c31abSDavid du Colombier 686368c31abSDavid du Colombier r = hsettext(c); 687368c31abSDavid du Colombier if(r < 0) 688368c31abSDavid du Colombier return r; 689368c31abSDavid du Colombier hout = &c->hout; 690368c31abSDavid du Colombier 691368c31abSDavid du Colombier flushicache(); 692368c31abSDavid du Colombier hprint(hout, "flushed icache\n"); 693368c31abSDavid du Colombier hflush(hout); 694368c31abSDavid du Colombier return 0; 695368c31abSDavid du Colombier } 696368c31abSDavid du Colombier 697368c31abSDavid du Colombier static int 698368c31abSDavid du Colombier hdcacheflush(HConnect *c) 699368c31abSDavid du Colombier { 700368c31abSDavid du Colombier Hio *hout; 701368c31abSDavid du Colombier int r; 702368c31abSDavid du Colombier 703368c31abSDavid du Colombier r = hsettext(c); 704368c31abSDavid du Colombier if(r < 0) 705368c31abSDavid du Colombier return r; 706368c31abSDavid du Colombier hout = &c->hout; 707368c31abSDavid du Colombier 708368c31abSDavid du Colombier flushdcache(); 709368c31abSDavid du Colombier hprint(hout, "flushed dcache\n"); 710368c31abSDavid du Colombier hflush(hout); 711368c31abSDavid du Colombier return 0; 712368c31abSDavid du Colombier } 713368c31abSDavid du Colombier 714368c31abSDavid du Colombier static int 715368c31abSDavid du Colombier dindex(HConnect *c) 716368c31abSDavid du Colombier { 717368c31abSDavid du Colombier Hio *hout; 718368c31abSDavid du Colombier Index *ix; 719368c31abSDavid du Colombier int i, r; 720368c31abSDavid du Colombier 721368c31abSDavid du Colombier r = hsettext(c); 722368c31abSDavid du Colombier if(r < 0) 723368c31abSDavid du Colombier return r; 724368c31abSDavid du Colombier hout = &c->hout; 725368c31abSDavid du Colombier 726368c31abSDavid du Colombier 727368c31abSDavid du Colombier ix = mainindex; 728368c31abSDavid du Colombier hprint(hout, "index=%s version=%d blocksize=%d tabsize=%d\n", 729368c31abSDavid du Colombier ix->name, ix->version, ix->blocksize, ix->tabsize); 730368c31abSDavid du Colombier hprint(hout, "\tbuckets=%d div=%d\n", ix->buckets, ix->div); 731368c31abSDavid du Colombier for(i = 0; i < ix->nsects; i++) 732368c31abSDavid du Colombier 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); 733368c31abSDavid du Colombier for(i = 0; i < ix->narenas; i++){ 734368c31abSDavid du Colombier if(ix->arenas[i] != nil && ix->arenas[i]->memstats.clumps != 0){ 735368c31abSDavid du Colombier hprint(hout, "arena=%s at index [%lld,%lld)\n\t", ix->amap[i].name, ix->amap[i].start, ix->amap[i].stop); 736368c31abSDavid du Colombier darena(hout, ix->arenas[i]); 737368c31abSDavid du Colombier } 738368c31abSDavid du Colombier } 739368c31abSDavid du Colombier hflush(hout); 740368c31abSDavid du Colombier return 0; 741368c31abSDavid du Colombier } 742368c31abSDavid du Colombier 743368c31abSDavid du Colombier typedef struct Arg Arg; 744368c31abSDavid du Colombier struct Arg 745368c31abSDavid du Colombier { 746368c31abSDavid du Colombier int index; 747368c31abSDavid du Colombier int index2; 748368c31abSDavid du Colombier }; 749368c31abSDavid du Colombier 750368c31abSDavid du Colombier static long 751368c31abSDavid du Colombier rawgraph(Stats *s, Stats *t, void *va) 752368c31abSDavid du Colombier { 753368c31abSDavid du Colombier Arg *a; 754368c31abSDavid du Colombier 755368c31abSDavid du Colombier USED(s); 756368c31abSDavid du Colombier a = va; 757368c31abSDavid du Colombier return t->n[a->index]; 758368c31abSDavid du Colombier } 759368c31abSDavid du Colombier 760368c31abSDavid du Colombier static long 761368c31abSDavid du Colombier diffgraph(Stats *s, Stats *t, void *va) 762368c31abSDavid du Colombier { 763368c31abSDavid du Colombier Arg *a; 764368c31abSDavid du Colombier 765368c31abSDavid du Colombier a = va; 766368c31abSDavid du Colombier return t->n[a->index] - s->n[a->index]; 767368c31abSDavid du Colombier } 768368c31abSDavid du Colombier 769368c31abSDavid du Colombier static long 770368c31abSDavid du Colombier pctgraph(Stats *s, Stats *t, void *va) 771368c31abSDavid du Colombier { 772368c31abSDavid du Colombier Arg *a; 773368c31abSDavid du Colombier 774368c31abSDavid du Colombier USED(s); 775368c31abSDavid du Colombier a = va; 776368c31abSDavid du Colombier return percent(t->n[a->index], t->n[a->index2]); 777368c31abSDavid du Colombier } 778368c31abSDavid du Colombier 779368c31abSDavid du Colombier static long 780368c31abSDavid du Colombier pctdiffgraph(Stats *s, Stats *t, void *va) 781368c31abSDavid du Colombier { 782368c31abSDavid du Colombier Arg *a; 783368c31abSDavid du Colombier 784368c31abSDavid du Colombier a = va; 785368c31abSDavid du Colombier return percent(t->n[a->index]-s->n[a->index], t->n[a->index2]-s->n[a->index2]); 786368c31abSDavid du Colombier } 787368c31abSDavid du Colombier 788368c31abSDavid du Colombier static long 789368c31abSDavid du Colombier xdiv(long a, long b) 790368c31abSDavid du Colombier { 791368c31abSDavid du Colombier if(b == 0) 792368c31abSDavid du Colombier b++; 793368c31abSDavid du Colombier return a/b; 794368c31abSDavid du Colombier } 795368c31abSDavid du Colombier 796368c31abSDavid du Colombier static long 797368c31abSDavid du Colombier divdiffgraph(Stats *s, Stats *t, void *va) 798368c31abSDavid du Colombier { 799368c31abSDavid du Colombier Arg *a; 800368c31abSDavid du Colombier 801368c31abSDavid du Colombier a = va; 802368c31abSDavid du Colombier return xdiv(t->n[a->index] - s->n[a->index], t->n[a->index2] - s->n[a->index2]); 803368c31abSDavid du Colombier } 804368c31abSDavid du Colombier 805368c31abSDavid du Colombier static long 806368c31abSDavid du Colombier netbw(Stats *s) 807368c31abSDavid du Colombier { 808368c31abSDavid du Colombier ulong *n; 809368c31abSDavid du Colombier 810368c31abSDavid du Colombier n = s->n; 811368c31abSDavid du Colombier return n[StatRpcReadBytes]+n[StatRpcWriteBytes]; /* not exactly right */ 812368c31abSDavid du Colombier } 813368c31abSDavid du Colombier 814368c31abSDavid du Colombier static long 815368c31abSDavid du Colombier diskbw(Stats *s) 816368c31abSDavid du Colombier { 817368c31abSDavid du Colombier ulong *n; 818368c31abSDavid du Colombier 819368c31abSDavid du Colombier n = s->n; 820368c31abSDavid du Colombier return n[StatApartReadBytes]+n[StatApartWriteBytes] 821368c31abSDavid du Colombier + n[StatIsectReadBytes]+n[StatIsectWriteBytes] 822368c31abSDavid du Colombier + n[StatSumReadBytes]; 823368c31abSDavid du Colombier } 824368c31abSDavid du Colombier 825368c31abSDavid du Colombier static long 826368c31abSDavid du Colombier iobw(Stats *s) 827368c31abSDavid du Colombier { 828368c31abSDavid du Colombier return netbw(s)+diskbw(s); 829368c31abSDavid du Colombier } 830368c31abSDavid du Colombier 831368c31abSDavid du Colombier static long 832368c31abSDavid du Colombier diskgraph(Stats *s, Stats *t, void *va) 833368c31abSDavid du Colombier { 834368c31abSDavid du Colombier USED(va); 835368c31abSDavid du Colombier return diskbw(t)-diskbw(s); 836368c31abSDavid du Colombier } 837368c31abSDavid du Colombier 838368c31abSDavid du Colombier static long 839368c31abSDavid du Colombier netgraph(Stats *s, Stats *t, void *va) 840368c31abSDavid du Colombier { 841368c31abSDavid du Colombier USED(va); 842368c31abSDavid du Colombier return netbw(t)-netbw(s); 843368c31abSDavid du Colombier } 844368c31abSDavid du Colombier 845368c31abSDavid du Colombier static long 846368c31abSDavid du Colombier iograph(Stats *s, Stats *t, void *va) 847368c31abSDavid du Colombier { 848368c31abSDavid du Colombier USED(va); 849368c31abSDavid du Colombier return iobw(t)-iobw(s); 850368c31abSDavid du Colombier } 851368c31abSDavid du Colombier 852368c31abSDavid du Colombier 853368c31abSDavid du Colombier static char* graphname[] = 854368c31abSDavid du Colombier { 855368c31abSDavid du Colombier "rpctotal", 856368c31abSDavid du Colombier "rpcread", 857368c31abSDavid du Colombier "rpcreadok", 858368c31abSDavid du Colombier "rpcreadfail", 859368c31abSDavid du Colombier "rpcreadbyte", 860368c31abSDavid du Colombier "rpcreadtime", 861368c31abSDavid du Colombier "rpcreadcached", 862368c31abSDavid du Colombier "rpcreadcachedtime", 863368c31abSDavid du Colombier "rpcreaduncached", 864368c31abSDavid du Colombier "rpcreaduncachedtime", 865368c31abSDavid du Colombier "rpcwrite", 866368c31abSDavid du Colombier "rpcwritenew", 867368c31abSDavid du Colombier "rpcwriteold", 868368c31abSDavid du Colombier "rpcwritefail", 869368c31abSDavid du Colombier "rpcwritebyte", 870368c31abSDavid du Colombier "rpcwritetime", 871368c31abSDavid du Colombier "rpcwritenewtime", 872368c31abSDavid du Colombier "rpcwriteoldtime", 873368c31abSDavid du Colombier 874368c31abSDavid du Colombier "lcachehit", 875368c31abSDavid du Colombier "lcachemiss", 876368c31abSDavid du Colombier "lcachelookup", 877368c31abSDavid du Colombier "lcachewrite", 878368c31abSDavid du Colombier "lcachesize", 879368c31abSDavid du Colombier "lcachestall", 880368c31abSDavid du Colombier "lcachelookuptime", 881368c31abSDavid du Colombier 882368c31abSDavid du Colombier "dcachehit", 883368c31abSDavid du Colombier "dcachemiss", 884368c31abSDavid du Colombier "dcachelookup", 885368c31abSDavid du Colombier "dcacheread", 886368c31abSDavid du Colombier "dcachewrite", 887368c31abSDavid du Colombier "dcachedirty", 888368c31abSDavid du Colombier "dcachesize", 889368c31abSDavid du Colombier "dcacheflush", 890368c31abSDavid du Colombier "dcachestall", 891368c31abSDavid du Colombier "dcachelookuptime", 892368c31abSDavid du Colombier 893368c31abSDavid du Colombier "dblockstall", 894368c31abSDavid du Colombier "lumpstall", 895368c31abSDavid du Colombier 896368c31abSDavid du Colombier "icachehit", 897368c31abSDavid du Colombier "icachemiss", 898*f9e1cf08SDavid du Colombier "icacheread", 899368c31abSDavid du Colombier "icachewrite", 900368c31abSDavid du Colombier "icachefill", 901368c31abSDavid du Colombier "icacheprefetch", 902368c31abSDavid du Colombier "icachedirty", 903368c31abSDavid du Colombier "icachesize", 904368c31abSDavid du Colombier "icacheflush", 905368c31abSDavid du Colombier "icachestall", 906368c31abSDavid du Colombier "icachelookuptime", 907*f9e1cf08SDavid du Colombier "icachelookup", 908*f9e1cf08SDavid du Colombier "scachehit", 909*f9e1cf08SDavid du Colombier "scacheprefetch", 910368c31abSDavid du Colombier 911368c31abSDavid du Colombier "bloomhit", 912368c31abSDavid du Colombier "bloommiss", 913368c31abSDavid du Colombier "bloomfalsemiss", 914368c31abSDavid du Colombier "bloomlookup", 915368c31abSDavid du Colombier "bloomones", 916368c31abSDavid du Colombier "bloombits", 917368c31abSDavid du Colombier "bloomlookuptime", 918368c31abSDavid du Colombier 919368c31abSDavid du Colombier "apartread", 920368c31abSDavid du Colombier "apartreadbyte", 921368c31abSDavid du Colombier "apartwrite", 922368c31abSDavid du Colombier "apartwritebyte", 923368c31abSDavid du Colombier 924368c31abSDavid du Colombier "isectread", 925368c31abSDavid du Colombier "isectreadbyte", 926368c31abSDavid du Colombier "isectwrite", 927368c31abSDavid du Colombier "isectwritebyte", 928368c31abSDavid du Colombier 929368c31abSDavid du Colombier "sumread", 930368c31abSDavid du Colombier "sumreadbyte", 931*f9e1cf08SDavid du Colombier 932*f9e1cf08SDavid du Colombier "cigload", 933*f9e1cf08SDavid du Colombier "cigloadtime", 934368c31abSDavid du Colombier }; 935368c31abSDavid du Colombier 936368c31abSDavid du Colombier static int 937368c31abSDavid du Colombier findname(char *s) 938368c31abSDavid du Colombier { 939368c31abSDavid du Colombier int i; 940368c31abSDavid du Colombier 941368c31abSDavid du Colombier for(i=0; i<nelem(graphname); i++) 942368c31abSDavid du Colombier if(strcmp(graphname[i], s) == 0) 943368c31abSDavid du Colombier return i; 944368c31abSDavid du Colombier return -1; 945368c31abSDavid du Colombier } 946368c31abSDavid du Colombier 947368c31abSDavid du Colombier static void 948368c31abSDavid du Colombier dotextbin(Hio *io, Graph *g) 949368c31abSDavid du Colombier { 950368c31abSDavid du Colombier int i, nbin; 951368c31abSDavid du Colombier Statbin *b, bin[2000]; /* 32 kB, but whack is worse */ 952368c31abSDavid du Colombier 953368c31abSDavid du Colombier needstack(8192); /* double check that bin didn't kill us */ 954368c31abSDavid du Colombier nbin = 100; 955368c31abSDavid du Colombier binstats(g->fn, g->arg, g->t0, g->t1, bin, nbin); 956368c31abSDavid du Colombier 957368c31abSDavid du Colombier hprint(io, "stats\n\n"); 958368c31abSDavid du Colombier for(i=0; i<nbin; i++){ 959368c31abSDavid du Colombier b = &bin[i]; 960368c31abSDavid du Colombier hprint(io, "%d: nsamp=%d min=%d max=%d avg=%d\n", 961368c31abSDavid du Colombier i, b->nsamp, b->min, b->max, b->avg); 962368c31abSDavid du Colombier } 963368c31abSDavid du Colombier } 964368c31abSDavid du Colombier 965368c31abSDavid du Colombier static int 966368c31abSDavid du Colombier xgraph(HConnect *c) 967368c31abSDavid du Colombier { 968368c31abSDavid du Colombier char *name; 969368c31abSDavid du Colombier Hio *hout; 970368c31abSDavid du Colombier Memimage *m; 971368c31abSDavid du Colombier int dotext; 972368c31abSDavid du Colombier Graph g; 973368c31abSDavid du Colombier Arg arg; 974368c31abSDavid du Colombier char *graph, *a; 975368c31abSDavid du Colombier 976368c31abSDavid du Colombier name = hargstr(c, "arg", ""); 977368c31abSDavid du Colombier if((arg.index = findname(name)) == -1 && strcmp(name, "*") != 0){ 978368c31abSDavid du Colombier werrstr("unknown name %s", name); 979368c31abSDavid du Colombier goto error; 980368c31abSDavid du Colombier } 981368c31abSDavid du Colombier a = hargstr(c, "arg2", ""); 982368c31abSDavid du Colombier if(a[0] && (arg.index2 = findname(a)) == -1){ 983368c31abSDavid du Colombier werrstr("unknown name %s", a); 984368c31abSDavid du Colombier goto error; 985368c31abSDavid du Colombier } 986368c31abSDavid du Colombier 987368c31abSDavid du Colombier g.arg = &arg; 988368c31abSDavid du Colombier g.t0 = hargint(c, "t0", -120); 989368c31abSDavid du Colombier g.t1 = hargint(c, "t1", 0); 990368c31abSDavid du Colombier g.min = hargint(c, "min", -1); 991368c31abSDavid du Colombier g.max = hargint(c, "max", -1); 992368c31abSDavid du Colombier g.wid = hargint(c, "wid", -1); 993368c31abSDavid du Colombier g.ht = hargint(c, "ht", -1); 994368c31abSDavid du Colombier dotext = hargstr(c, "text", "")[0] != 0; 995368c31abSDavid du Colombier g.fill = hargint(c, "fill", -1); 996368c31abSDavid du Colombier 997368c31abSDavid du Colombier graph = hargstr(c, "graph", "raw"); 998368c31abSDavid du Colombier if(strcmp(graph, "raw") == 0) 999368c31abSDavid du Colombier g.fn = rawgraph; 1000368c31abSDavid du Colombier else if(strcmp(graph, "diskbw") == 0) 1001368c31abSDavid du Colombier g.fn = diskgraph; 1002368c31abSDavid du Colombier else if(strcmp(graph, "iobw") == 0) 1003368c31abSDavid du Colombier g.fn = iograph; 1004368c31abSDavid du Colombier else if(strcmp(graph, "netbw") == 0) 1005368c31abSDavid du Colombier g.fn = netgraph; 1006368c31abSDavid du Colombier else if(strcmp(graph, "diff") == 0) 1007368c31abSDavid du Colombier g.fn = diffgraph; 1008368c31abSDavid du Colombier else if(strcmp(graph, "pct") == 0) 1009368c31abSDavid du Colombier g.fn = pctgraph; 1010368c31abSDavid du Colombier else if(strcmp(graph, "pctdiff") == 0) 1011368c31abSDavid du Colombier g.fn = pctdiffgraph; 1012368c31abSDavid du Colombier else if(strcmp(graph, "divdiff") == 0) 1013368c31abSDavid du Colombier g.fn = divdiffgraph; 1014368c31abSDavid du Colombier else{ 1015368c31abSDavid du Colombier werrstr("unknown graph %s", graph); 1016368c31abSDavid du Colombier goto error; 1017368c31abSDavid du Colombier } 1018368c31abSDavid du Colombier 1019368c31abSDavid du Colombier if(dotext){ 1020368c31abSDavid du Colombier hsettype(c, "text/plain"); 1021368c31abSDavid du Colombier dotextbin(&c->hout, &g); 1022368c31abSDavid du Colombier hflush(&c->hout); 1023368c31abSDavid du Colombier return 0; 1024368c31abSDavid du Colombier } 1025368c31abSDavid du Colombier 1026368c31abSDavid du Colombier m = statgraph(&g); 1027368c31abSDavid du Colombier if(m == nil) 1028368c31abSDavid du Colombier goto error; 1029368c31abSDavid du Colombier 1030368c31abSDavid du Colombier if(hsettype(c, "image/png") < 0) 1031368c31abSDavid du Colombier return -1; 1032368c31abSDavid du Colombier hout = &c->hout; 1033368c31abSDavid du Colombier writepng(hout, m); 1034368c31abSDavid du Colombier qlock(&memdrawlock); 1035368c31abSDavid du Colombier freememimage(m); 1036368c31abSDavid du Colombier qunlock(&memdrawlock); 1037368c31abSDavid du Colombier hflush(hout); 1038368c31abSDavid du Colombier return 0; 1039368c31abSDavid du Colombier 1040368c31abSDavid du Colombier error: 1041368c31abSDavid du Colombier return herror(c); 1042368c31abSDavid du Colombier } 1043368c31abSDavid du Colombier 1044368c31abSDavid du Colombier static int 1045368c31abSDavid du Colombier xloglist(HConnect *c) 1046368c31abSDavid du Colombier { 1047368c31abSDavid du Colombier if(hsettype(c, "text/html") < 0) 1048368c31abSDavid du Colombier return -1; 1049368c31abSDavid du Colombier vtloghlist(&c->hout); 1050368c31abSDavid du Colombier hflush(&c->hout); 1051368c31abSDavid du Colombier return 0; 1052368c31abSDavid du Colombier } 1053368c31abSDavid du Colombier 1054368c31abSDavid du Colombier static int 1055368c31abSDavid du Colombier xlog(HConnect *c) 1056368c31abSDavid du Colombier { 1057368c31abSDavid du Colombier char *name; 1058368c31abSDavid du Colombier VtLog *l; 1059368c31abSDavid du Colombier 1060368c31abSDavid du Colombier name = hargstr(c, "log", ""); 1061368c31abSDavid du Colombier if(!name[0]) 1062368c31abSDavid du Colombier return xloglist(c); 1063368c31abSDavid du Colombier l = vtlogopen(name, 0); 1064368c31abSDavid du Colombier if(l == nil) 1065368c31abSDavid du Colombier return hnotfound(c); 1066368c31abSDavid du Colombier if(hsettype(c, "text/html") < 0){ 1067368c31abSDavid du Colombier vtlogclose(l); 1068368c31abSDavid du Colombier return -1; 1069368c31abSDavid du Colombier } 1070368c31abSDavid du Colombier vtloghdump(&c->hout, l); 1071368c31abSDavid du Colombier vtlogclose(l); 1072368c31abSDavid du Colombier hflush(&c->hout); 1073368c31abSDavid du Colombier return 0; 1074368c31abSDavid du Colombier } 1075368c31abSDavid du Colombier 1076368c31abSDavid du Colombier static int 1077368c31abSDavid du Colombier xindex(HConnect *c) 1078368c31abSDavid du Colombier { 1079368c31abSDavid du Colombier if(hsettype(c, "text/xml") < 0) 1080368c31abSDavid du Colombier return -1; 1081368c31abSDavid du Colombier xmlindex(&c->hout, mainindex, "index", 0); 1082368c31abSDavid du Colombier hflush(&c->hout); 1083368c31abSDavid du Colombier return 0; 1084368c31abSDavid du Colombier } 1085368c31abSDavid du Colombier 1086368c31abSDavid du Colombier void 1087368c31abSDavid du Colombier xmlindent(Hio *hout, int indent) 1088368c31abSDavid du Colombier { 1089368c31abSDavid du Colombier int i; 1090368c31abSDavid du Colombier 1091368c31abSDavid du Colombier for(i = 0; i < indent; i++) 1092368c31abSDavid du Colombier hputc(hout, '\t'); 1093368c31abSDavid du Colombier } 1094368c31abSDavid du Colombier 1095368c31abSDavid du Colombier void 1096368c31abSDavid du Colombier xmlaname(Hio *hout, char *v, char *tag) 1097368c31abSDavid du Colombier { 1098368c31abSDavid du Colombier hprint(hout, " %s=\"%s\"", tag, v); 1099368c31abSDavid du Colombier } 1100368c31abSDavid du Colombier 1101368c31abSDavid du Colombier void 1102368c31abSDavid du Colombier xmlscore(Hio *hout, u8int *v, char *tag) 1103368c31abSDavid du Colombier { 1104368c31abSDavid du Colombier if(scorecmp(zeroscore, v) == 0) 1105368c31abSDavid du Colombier return; 1106368c31abSDavid du Colombier hprint(hout, " %s=\"%V\"", tag, v); 1107368c31abSDavid du Colombier } 1108368c31abSDavid du Colombier 1109368c31abSDavid du Colombier void 1110368c31abSDavid du Colombier xmlsealed(Hio *hout, int v, char *tag) 1111368c31abSDavid du Colombier { 1112368c31abSDavid du Colombier if(!v) 1113368c31abSDavid du Colombier return; 1114368c31abSDavid du Colombier hprint(hout, " %s=\"yes\"", tag); 1115368c31abSDavid du Colombier } 1116368c31abSDavid du Colombier 1117368c31abSDavid du Colombier void 1118368c31abSDavid du Colombier xmlu32int(Hio *hout, u32int v, char *tag) 1119368c31abSDavid du Colombier { 1120368c31abSDavid du Colombier hprint(hout, " %s=\"%ud\"", tag, v); 1121368c31abSDavid du Colombier } 1122368c31abSDavid du Colombier 1123368c31abSDavid du Colombier void 1124368c31abSDavid du Colombier xmlu64int(Hio *hout, u64int v, char *tag) 1125368c31abSDavid du Colombier { 1126368c31abSDavid du Colombier hprint(hout, " %s=\"%llud\"", tag, v); 1127368c31abSDavid du Colombier } 1128368c31abSDavid du Colombier 1129368c31abSDavid du Colombier void 1130368c31abSDavid du Colombier vtloghdump(Hio *h, VtLog *l) 1131368c31abSDavid du Colombier { 1132368c31abSDavid du Colombier int i; 1133368c31abSDavid du Colombier VtLogChunk *c; 1134368c31abSDavid du Colombier char *name; 1135368c31abSDavid du Colombier 1136368c31abSDavid du Colombier name = l ? l->name : "<nil>"; 1137368c31abSDavid du Colombier 1138368c31abSDavid du Colombier hprint(h, "<html><head>\n"); 1139368c31abSDavid du Colombier hprint(h, "<title>Venti Server Log: %s</title>\n", name); 1140368c31abSDavid du Colombier hprint(h, "</head><body>\n"); 1141368c31abSDavid du Colombier hprint(h, "<b>Venti Server Log: %s</b>\n<p>\n", name); 1142368c31abSDavid du Colombier 1143368c31abSDavid du Colombier if(l){ 1144368c31abSDavid du Colombier c = l->w; 1145368c31abSDavid du Colombier for(i=0; i<l->nchunk; i++){ 1146368c31abSDavid du Colombier if(++c == l->chunk+l->nchunk) 1147368c31abSDavid du Colombier c = l->chunk; 1148368c31abSDavid du Colombier hwrite(h, c->p, c->wp-c->p); 1149368c31abSDavid du Colombier } 1150368c31abSDavid du Colombier } 1151368c31abSDavid du Colombier hprint(h, "</body></html>\n"); 1152368c31abSDavid du Colombier } 1153368c31abSDavid du Colombier 1154368c31abSDavid du Colombier static int 1155368c31abSDavid du Colombier strpcmp(const void *va, const void *vb) 1156368c31abSDavid du Colombier { 1157368c31abSDavid du Colombier return strcmp(*(char**)va, *(char**)vb); 1158368c31abSDavid du Colombier } 1159368c31abSDavid du Colombier 1160368c31abSDavid du Colombier void 1161368c31abSDavid du Colombier vtloghlist(Hio *h) 1162368c31abSDavid du Colombier { 1163368c31abSDavid du Colombier char **p; 1164368c31abSDavid du Colombier int i, n; 1165368c31abSDavid du Colombier 1166368c31abSDavid du Colombier hprint(h, "<html><head>\n"); 1167368c31abSDavid du Colombier hprint(h, "<title>Venti Server Logs</title>\n"); 1168368c31abSDavid du Colombier hprint(h, "</head><body>\n"); 1169368c31abSDavid du Colombier hprint(h, "<b>Venti Server Logs</b>\n<p>\n"); 1170368c31abSDavid du Colombier 1171368c31abSDavid du Colombier p = vtlognames(&n); 1172368c31abSDavid du Colombier qsort(p, n, sizeof(p[0]), strpcmp); 1173368c31abSDavid du Colombier for(i=0; i<n; i++) 1174368c31abSDavid du Colombier hprint(h, "<a href=\"/log?log=%s\">%s</a><br>\n", p[i], p[i]); 1175368c31abSDavid du Colombier vtfree(p); 1176368c31abSDavid du Colombier hprint(h, "</body></html>\n"); 1177368c31abSDavid du Colombier } 1178