1177 lines · 22.3 KB · C
RawDownload
#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); inthttpdinit(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 inthttpdobj(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 voidlistenproc(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);	}} voidhttpproc(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;} vlonghargint(HConnect *c, char *name, vlong def){	char *a;		if((a = hargstr(c, name, nil)) == nil)		return def;	return atoll(a);} static intpercent(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 intpreq(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;} inthsettype(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;} inthsethtml(HConnect *c){	return hsettype(c, "text/html; charset=utf-8");} inthsettext(HConnect *c){	return hsettype(c, "text/plain; charset=utf-8");} static intherror(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);}	inthnotfound(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 intfromwebdir(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 intxset(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 intestats(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));

Lines 1–500 of 1177.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t