xref: /plan9/sys/src/cmd/venti/srv/venti.c (revision 36066be07288900642605e3e4f42ceece4e473a9)
1368c31abSDavid du Colombier #ifdef PLAN9PORT
2368c31abSDavid du Colombier #include <u.h>
3368c31abSDavid du Colombier #include <signal.h>
4368c31abSDavid du Colombier #endif
5368c31abSDavid du Colombier #include "stdinc.h"
6b8a11165SDavid du Colombier #include <bio.h>
7368c31abSDavid du Colombier #include "dat.h"
8368c31abSDavid du Colombier #include "fns.h"
9368c31abSDavid du Colombier 
10368c31abSDavid du Colombier #include "whack.h"
11368c31abSDavid du Colombier 
127fd2696aSDavid du Colombier typedef struct Allocs Allocs;
137fd2696aSDavid du Colombier struct Allocs {
147fd2696aSDavid du Colombier 	u32int	mem;
157fd2696aSDavid du Colombier 	u32int	bcmem;
167fd2696aSDavid du Colombier 	u32int	icmem;
177fd2696aSDavid du Colombier 	u32int	stfree;				/* free memory at start */
187fd2696aSDavid du Colombier 	uint	mempcnt;
197fd2696aSDavid du Colombier };
207fd2696aSDavid du Colombier 
21368c31abSDavid du Colombier int debug;
22368c31abSDavid du Colombier int nofork;
23368c31abSDavid du Colombier int mainstacksize = 256*1024;
24368c31abSDavid du Colombier VtSrv *ventisrv;
25368c31abSDavid du Colombier 
26368c31abSDavid du Colombier static void	ventiserver(void*);
27368c31abSDavid du Colombier 
28b8a11165SDavid du Colombier static ulong
freemem(void)29b8a11165SDavid du Colombier freemem(void)
30b8a11165SDavid du Colombier {
31b8a11165SDavid du Colombier 	int nf, pgsize = 0;
32b8a11165SDavid du Colombier 	uvlong size, userpgs = 0, userused = 0;
33b8a11165SDavid du Colombier 	char *ln, *sl;
34b8a11165SDavid du Colombier 	char *fields[2];
35b8a11165SDavid du Colombier 	Biobuf *bp;
36b8a11165SDavid du Colombier 
37b8a11165SDavid du Colombier 	size = 64*1024*1024;
38b8a11165SDavid du Colombier 	bp = Bopen("#c/swap", OREAD);
39b8a11165SDavid du Colombier 	if (bp != nil) {
40b8a11165SDavid du Colombier 		while ((ln = Brdline(bp, '\n')) != nil) {
41b8a11165SDavid du Colombier 			ln[Blinelen(bp)-1] = '\0';
42b8a11165SDavid du Colombier 			nf = tokenize(ln, fields, nelem(fields));
43b8a11165SDavid du Colombier 			if (nf != 2)
44b8a11165SDavid du Colombier 				continue;
45b8a11165SDavid du Colombier 			if (strcmp(fields[1], "pagesize") == 0)
46b8a11165SDavid du Colombier 				pgsize = atoi(fields[0]);
47b8a11165SDavid du Colombier 			else if (strcmp(fields[1], "user") == 0) {
48b8a11165SDavid du Colombier 				sl = strchr(fields[0], '/');
49b8a11165SDavid du Colombier 				if (sl == nil)
50b8a11165SDavid du Colombier 					continue;
51b8a11165SDavid du Colombier 				userpgs = atoll(sl+1);
52b8a11165SDavid du Colombier 				userused = atoll(fields[0]);
53b8a11165SDavid du Colombier 			}
54b8a11165SDavid du Colombier 		}
55b8a11165SDavid du Colombier 		Bterm(bp);
56*36066be0SDavid du Colombier 		if (pgsize > 0 && userpgs > 0 && userused > 0)
57b8a11165SDavid du Colombier 			size = (userpgs - userused) * pgsize;
58b8a11165SDavid du Colombier 	}
59b8a11165SDavid du Colombier 	/* cap it to keep the size within 32 bits */
60b8a11165SDavid du Colombier 	if (size >= 3840UL * 1024 * 1024)
61b8a11165SDavid du Colombier 		size = 3840UL * 1024 * 1024;
62b8a11165SDavid du Colombier 	return size;
63b8a11165SDavid du Colombier }
64b8a11165SDavid du Colombier 
657fd2696aSDavid du Colombier static void
allocminima(Allocs * all)667fd2696aSDavid du Colombier allocminima(Allocs *all)			/* enforce minima for sanity */
677fd2696aSDavid du Colombier {
687fd2696aSDavid du Colombier 	if (all->icmem < 6 * 1024 * 1024)
697fd2696aSDavid du Colombier 		all->icmem = 6 * 1024 * 1024;
70c18ab83fSDavid du Colombier 	if (all->mem < 1024 * 1024 || all->mem == Unspecified)  /* lumps */
717fd2696aSDavid du Colombier 		all->mem = 1024 * 1024;
727fd2696aSDavid du Colombier 	if (all->bcmem < 2 * 1024 * 1024)
737fd2696aSDavid du Colombier 		all->bcmem = 2 * 1024 * 1024;
747fd2696aSDavid du Colombier }
757fd2696aSDavid du Colombier 
767fd2696aSDavid du Colombier /* automatic memory allocations sizing per venti(8) guidelines */
777fd2696aSDavid du Colombier static Allocs
allocbypcnt(u32int mempcnt,u32int stfree)787fd2696aSDavid du Colombier allocbypcnt(u32int mempcnt, u32int stfree)
797fd2696aSDavid du Colombier {
807fd2696aSDavid du Colombier 	u32int avail;
817fd2696aSDavid du Colombier 	vlong blmsize;
827fd2696aSDavid du Colombier 	Allocs all;
837fd2696aSDavid du Colombier 	static u32int free;
847fd2696aSDavid du Colombier 
85c18ab83fSDavid du Colombier 	all.mem = Unspecified;
86c18ab83fSDavid du Colombier 	all.bcmem = all.icmem = 0;
877fd2696aSDavid du Colombier 	all.mempcnt = mempcnt;
887fd2696aSDavid du Colombier 	all.stfree = stfree;
897fd2696aSDavid du Colombier 
907fd2696aSDavid du Colombier 	if (free == 0)
917fd2696aSDavid du Colombier 		free = freemem();
927fd2696aSDavid du Colombier 	blmsize = stfree - free;
937fd2696aSDavid du Colombier 	if (blmsize <= 0)
947fd2696aSDavid du Colombier 		blmsize = 0;
95*36066be0SDavid du Colombier 	avail = ((vlong)stfree * mempcnt) / 100;
96*36066be0SDavid du Colombier 	if (blmsize >= avail || (avail -= blmsize) <= (1 + 2 + 6) * 1024 * 1024)
977fd2696aSDavid du Colombier 		fprint(2, "%s: bloom filter bigger than mem pcnt; "
987fd2696aSDavid du Colombier 			"resorting to minimum values (9MB total)\n", argv0);
997fd2696aSDavid du Colombier 	else {
1007fd2696aSDavid du Colombier 		if (avail >= 3840UL * 1024 * 1024)
1017fd2696aSDavid du Colombier 			avail = 3840UL * 1024 * 1024;	/* sanity */
1027fd2696aSDavid du Colombier 		avail /= 2;
1037fd2696aSDavid du Colombier 		all.icmem = avail;
1047fd2696aSDavid du Colombier 		avail /= 3;
1057fd2696aSDavid du Colombier 		all.mem = avail;
1067fd2696aSDavid du Colombier 		all.bcmem = 2 * avail;
1077fd2696aSDavid du Colombier 	}
1087fd2696aSDavid du Colombier 	return all;
1097fd2696aSDavid du Colombier }
1107fd2696aSDavid du Colombier 
1117fd2696aSDavid du Colombier /*
1127fd2696aSDavid du Colombier  * we compute default values for allocations,
1137fd2696aSDavid du Colombier  * which can be overridden by (in order):
1147fd2696aSDavid du Colombier  *	configuration file parameters,
1157fd2696aSDavid du Colombier  *	command-line options other than -m, and -m.
1167fd2696aSDavid du Colombier  */
1177fd2696aSDavid du Colombier static Allocs
sizeallocs(Allocs opt,Config * cfg)1187fd2696aSDavid du Colombier sizeallocs(Allocs opt, Config *cfg)
1197fd2696aSDavid du Colombier {
1207fd2696aSDavid du Colombier 	Allocs all;
1217fd2696aSDavid du Colombier 
1227fd2696aSDavid du Colombier 	/* work out sane defaults */
1237fd2696aSDavid du Colombier 	all = allocbypcnt(20, opt.stfree);
1247fd2696aSDavid du Colombier 
1257fd2696aSDavid du Colombier 	/* config file parameters override */
126c18ab83fSDavid du Colombier 	if (cfg->mem && cfg->mem != Unspecified)
1277fd2696aSDavid du Colombier 		all.mem = cfg->mem;
1287fd2696aSDavid du Colombier 	if (cfg->bcmem)
1297fd2696aSDavid du Colombier 		all.bcmem = cfg->bcmem;
1307fd2696aSDavid du Colombier 	if (cfg->icmem)
1317fd2696aSDavid du Colombier 		all.icmem = cfg->icmem;
1327fd2696aSDavid du Colombier 
1337fd2696aSDavid du Colombier 	/* command-line options override */
134c18ab83fSDavid du Colombier 	if (opt.mem && opt.mem != Unspecified)
1357fd2696aSDavid du Colombier 		all.mem = opt.mem;
1367fd2696aSDavid du Colombier 	if (opt.bcmem)
1377fd2696aSDavid du Colombier 		all.bcmem = opt.bcmem;
1387fd2696aSDavid du Colombier 	if (opt.icmem)
1397fd2696aSDavid du Colombier 		all.icmem = opt.icmem;
1407fd2696aSDavid du Colombier 
1417fd2696aSDavid du Colombier 	/* automatic memory sizing? */
1427fd2696aSDavid du Colombier 	if(opt.mempcnt > 0)
1437fd2696aSDavid du Colombier 		all = allocbypcnt(opt.mempcnt, opt.stfree);
1447fd2696aSDavid du Colombier 
1457fd2696aSDavid du Colombier 	allocminima(&all);
1467fd2696aSDavid du Colombier 	return all;
1477fd2696aSDavid du Colombier }
1487fd2696aSDavid du Colombier 
149368c31abSDavid du Colombier void
usage(void)150368c31abSDavid du Colombier usage(void)
151368c31abSDavid du Colombier {
152368c31abSDavid du Colombier 	fprint(2, "usage: venti [-Ldrsw] [-a ventiaddr] [-c config] "
1537fd2696aSDavid du Colombier "[-h httpaddr] [-m %%mem] [-B blockcachesize] [-C cachesize] [-I icachesize] "
154b8a11165SDavid du Colombier "[-W webroot]\n");
155368c31abSDavid du Colombier 	threadexitsall("usage");
156368c31abSDavid du Colombier }
157b8a11165SDavid du Colombier 
158368c31abSDavid du Colombier void
threadmain(int argc,char * argv[])159368c31abSDavid du Colombier threadmain(int argc, char *argv[])
160368c31abSDavid du Colombier {
161368c31abSDavid du Colombier 	char *configfile, *haddr, *vaddr, *webroot;
1627fd2696aSDavid du Colombier 	u32int mem, icmem, bcmem, minbcmem, mempcnt, stfree;
1637fd2696aSDavid du Colombier 	Allocs allocs;
164368c31abSDavid du Colombier 	Config config;
165368c31abSDavid du Colombier 
166368c31abSDavid du Colombier 	traceinit();
167368c31abSDavid du Colombier 	threadsetname("main");
168b8a11165SDavid du Colombier 	mempcnt = 0;
169368c31abSDavid du Colombier 	vaddr = nil;
170368c31abSDavid du Colombier 	haddr = nil;
171368c31abSDavid du Colombier 	configfile = nil;
172368c31abSDavid du Colombier 	webroot = nil;
173c18ab83fSDavid du Colombier 	mem = Unspecified;
174368c31abSDavid du Colombier 	icmem = 0;
175368c31abSDavid du Colombier 	bcmem = 0;
176368c31abSDavid du Colombier 	ARGBEGIN{
177368c31abSDavid du Colombier 	case 'a':
178368c31abSDavid du Colombier 		vaddr = EARGF(usage());
179368c31abSDavid du Colombier 		break;
180368c31abSDavid du Colombier 	case 'B':
181368c31abSDavid du Colombier 		bcmem = unittoull(EARGF(usage()));
182368c31abSDavid du Colombier 		break;
183368c31abSDavid du Colombier 	case 'c':
184368c31abSDavid du Colombier 		configfile = EARGF(usage());
185368c31abSDavid du Colombier 		break;
186368c31abSDavid du Colombier 	case 'C':
187368c31abSDavid du Colombier 		mem = unittoull(EARGF(usage()));
188368c31abSDavid du Colombier 		break;
189368c31abSDavid du Colombier 	case 'D':
190368c31abSDavid du Colombier 		settrace(EARGF(usage()));
191368c31abSDavid du Colombier 		break;
192368c31abSDavid du Colombier 	case 'd':
193368c31abSDavid du Colombier 		debug = 1;
194368c31abSDavid du Colombier 		nofork = 1;
195368c31abSDavid du Colombier 		break;
196368c31abSDavid du Colombier 	case 'h':
197368c31abSDavid du Colombier 		haddr = EARGF(usage());
198368c31abSDavid du Colombier 		break;
199b8a11165SDavid du Colombier 	case 'm':
200b8a11165SDavid du Colombier 		mempcnt = atoi(EARGF(usage()));
201b8a11165SDavid du Colombier 		if (mempcnt <= 0 || mempcnt >= 100)
202b8a11165SDavid du Colombier 			usage();
203b8a11165SDavid du Colombier 		break;
204368c31abSDavid du Colombier 	case 'I':
205368c31abSDavid du Colombier 		icmem = unittoull(EARGF(usage()));
206368c31abSDavid du Colombier 		break;
207368c31abSDavid du Colombier 	case 'L':
208368c31abSDavid du Colombier 		ventilogging = 1;
209368c31abSDavid du Colombier 		break;
210368c31abSDavid du Colombier 	case 'r':
211368c31abSDavid du Colombier 		readonly = 1;
212368c31abSDavid du Colombier 		break;
213368c31abSDavid du Colombier 	case 's':
214368c31abSDavid du Colombier 		nofork = 1;
215368c31abSDavid du Colombier 		break;
216368c31abSDavid du Colombier 	case 'w':			/* compatibility with old venti */
217368c31abSDavid du Colombier 		queuewrites = 1;
218368c31abSDavid du Colombier 		break;
219368c31abSDavid du Colombier 	case 'W':
220368c31abSDavid du Colombier 		webroot = EARGF(usage());
221368c31abSDavid du Colombier 		break;
222368c31abSDavid du Colombier 	default:
223368c31abSDavid du Colombier 		usage();
224368c31abSDavid du Colombier 	}ARGEND
225368c31abSDavid du Colombier 
226368c31abSDavid du Colombier 	if(argc)
227368c31abSDavid du Colombier 		usage();
228368c31abSDavid du Colombier 
229368c31abSDavid du Colombier 	if(!nofork)
230368c31abSDavid du Colombier 		rfork(RFNOTEG);
231368c31abSDavid du Colombier 
232368c31abSDavid du Colombier #ifdef PLAN9PORT
233368c31abSDavid du Colombier 	{
234368c31abSDavid du Colombier 		/* sigh - needed to avoid signals when writing to hungup networks */
235368c31abSDavid du Colombier 		struct sigaction sa;
236368c31abSDavid du Colombier 		memset(&sa, 0, sizeof sa);
237368c31abSDavid du Colombier 		sa.sa_handler = SIG_IGN;
238368c31abSDavid du Colombier 		sigaction(SIGPIPE, &sa, nil);
239368c31abSDavid du Colombier 	}
240368c31abSDavid du Colombier #endif
241368c31abSDavid du Colombier 
242368c31abSDavid du Colombier 	ventifmtinstall();
243368c31abSDavid du Colombier 	trace(TraceQuiet, "venti started");
244368c31abSDavid du Colombier 	fprint(2, "%T venti: ");
245368c31abSDavid du Colombier 
246368c31abSDavid du Colombier 	if(configfile == nil)
247368c31abSDavid du Colombier 		configfile = "venti.conf";
248368c31abSDavid du Colombier 
249c18ab83fSDavid du Colombier 	/* remember free memory before initventi & loadbloom, for auto-sizing */
250c18ab83fSDavid du Colombier 	stfree = freemem();
251368c31abSDavid du Colombier 	fprint(2, "conf...");
252368c31abSDavid du Colombier 	if(initventi(configfile, &config) < 0)
253368c31abSDavid du Colombier 		sysfatal("can't init server: %r");
2547fd2696aSDavid du Colombier 	/*
2557fd2696aSDavid du Colombier 	 * load bloom filter
2567fd2696aSDavid du Colombier 	 */
257368c31abSDavid du Colombier 	if(mainindex->bloom && loadbloom(mainindex->bloom) < 0)
258368c31abSDavid du Colombier 		sysfatal("can't load bloom filter: %r");
259368c31abSDavid du Colombier 
2607fd2696aSDavid du Colombier 	/*
2617fd2696aSDavid du Colombier 	 * size memory allocations; assumes bloom filter is loaded
2627fd2696aSDavid du Colombier 	 */
2637fd2696aSDavid du Colombier 	allocs = sizeallocs((Allocs){mem, bcmem, icmem, stfree, mempcnt},
2647fd2696aSDavid du Colombier 		&config);
2657fd2696aSDavid du Colombier 	mem = allocs.mem;
2667fd2696aSDavid du Colombier 	bcmem = allocs.bcmem;
2677fd2696aSDavid du Colombier 	icmem = allocs.icmem;
2687fd2696aSDavid du Colombier 	fprint(2, "%s: mem %,ud bcmem %,ud icmem %,ud...",
2697fd2696aSDavid du Colombier 		argv0, mem, bcmem, icmem);
270b8a11165SDavid du Colombier 
2717fd2696aSDavid du Colombier 	/*
2727fd2696aSDavid du Colombier 	 * default other configuration-file parameters
2737fd2696aSDavid du Colombier 	 */
274368c31abSDavid du Colombier 	if(haddr == nil)
275368c31abSDavid du Colombier 		haddr = config.haddr;
276368c31abSDavid du Colombier 	if(vaddr == nil)
277368c31abSDavid du Colombier 		vaddr = config.vaddr;
278368c31abSDavid du Colombier 	if(vaddr == nil)
279368c31abSDavid du Colombier 		vaddr = "tcp!*!venti";
280368c31abSDavid du Colombier 	if(webroot == nil)
281368c31abSDavid du Colombier 		webroot = config.webroot;
282368c31abSDavid du Colombier 	if(queuewrites == 0)
283368c31abSDavid du Colombier 		queuewrites = config.queuewrites;
2847fd2696aSDavid du Colombier 
285368c31abSDavid du Colombier 	if(haddr){
286368c31abSDavid du Colombier 		fprint(2, "httpd %s...", haddr);
287368c31abSDavid du Colombier 		if(httpdinit(haddr, webroot) < 0)
288368c31abSDavid du Colombier 			fprint(2, "warning: can't start http server: %r");
289368c31abSDavid du Colombier 	}
290368c31abSDavid du Colombier 	fprint(2, "init...");
291368c31abSDavid du Colombier 
2927fd2696aSDavid du Colombier 	/*
2937fd2696aSDavid du Colombier 	 * lump cache
2947fd2696aSDavid du Colombier 	 */
295368c31abSDavid du Colombier 	if(0) fprint(2, "initialize %d bytes of lump cache for %d lumps\n",
296368c31abSDavid du Colombier 		mem, mem / (8 * 1024));
297368c31abSDavid du Colombier 	initlumpcache(mem, mem / (8 * 1024));
298368c31abSDavid du Colombier 
2997fd2696aSDavid du Colombier 	/*
3007fd2696aSDavid du Colombier 	 * index cache
3017fd2696aSDavid du Colombier 	 */
302f9e1cf08SDavid du Colombier 	initicache(icmem);
303368c31abSDavid du Colombier 	initicachewrite();
304368c31abSDavid du Colombier 
305368c31abSDavid du Colombier 	/*
3067fd2696aSDavid du Colombier 	 * block cache: need a block for every arena and every process
307368c31abSDavid du Colombier 	 */
308368c31abSDavid du Colombier 	minbcmem = maxblocksize *
309368c31abSDavid du Colombier 		(mainindex->narenas + mainindex->nsects*4 + 16);
310368c31abSDavid du Colombier 	if(bcmem < minbcmem)
311368c31abSDavid du Colombier 		bcmem = minbcmem;
312368c31abSDavid du Colombier 	if(0) fprint(2, "initialize %d bytes of disk block cache\n", bcmem);
313368c31abSDavid du Colombier 	initdcache(bcmem);
314368c31abSDavid du Colombier 
315368c31abSDavid du Colombier 	if(mainindex->bloom)
316368c31abSDavid du Colombier 		startbloomproc(mainindex->bloom);
317368c31abSDavid du Colombier 
318368c31abSDavid du Colombier 	fprint(2, "sync...");
319f9e1cf08SDavid du Colombier 	if(!readonly && syncindex(mainindex) < 0)
320368c31abSDavid du Colombier 		sysfatal("can't sync server: %r");
321368c31abSDavid du Colombier 
322368c31abSDavid du Colombier 	if(!readonly && queuewrites){
323368c31abSDavid du Colombier 		fprint(2, "queue...");
324368c31abSDavid du Colombier 		if(initlumpqueues(mainindex->nsects) < 0){
325368c31abSDavid du Colombier 			fprint(2, "can't initialize lump queues,"
326368c31abSDavid du Colombier 				" disabling write queueing: %r");
327368c31abSDavid du Colombier 			queuewrites = 0;
328368c31abSDavid du Colombier 		}
329368c31abSDavid du Colombier 	}
330368c31abSDavid du Colombier 
331f9e1cf08SDavid du Colombier 	if(initarenasum() < 0)
332f9e1cf08SDavid du Colombier 		fprint(2, "warning: can't initialize arena summing process: %r");
333f9e1cf08SDavid du Colombier 
334368c31abSDavid du Colombier 	fprint(2, "announce %s...", vaddr);
335368c31abSDavid du Colombier 	ventisrv = vtlisten(vaddr);
336368c31abSDavid du Colombier 	if(ventisrv == nil)
337368c31abSDavid du Colombier 		sysfatal("can't announce %s: %r", vaddr);
338368c31abSDavid du Colombier 
339368c31abSDavid du Colombier 	fprint(2, "serving.\n");
340368c31abSDavid du Colombier 	if(nofork)
341368c31abSDavid du Colombier 		ventiserver(nil);
342368c31abSDavid du Colombier 	else
343368c31abSDavid du Colombier 		vtproc(ventiserver, nil);
34423566e0cSDavid du Colombier 
34523566e0cSDavid du Colombier 	threadexits(nil);
346368c31abSDavid du Colombier }
347368c31abSDavid du Colombier 
348368c31abSDavid du Colombier static void
vtrerror(VtReq * r,char * error)349368c31abSDavid du Colombier vtrerror(VtReq *r, char *error)
350368c31abSDavid du Colombier {
351368c31abSDavid du Colombier 	r->rx.msgtype = VtRerror;
352368c31abSDavid du Colombier 	r->rx.error = estrdup(error);
353368c31abSDavid du Colombier }
354368c31abSDavid du Colombier 
355368c31abSDavid du Colombier static void
ventiserver(void * v)356368c31abSDavid du Colombier ventiserver(void *v)
357368c31abSDavid du Colombier {
358368c31abSDavid du Colombier 	Packet *p;
359368c31abSDavid du Colombier 	VtReq *r;
360368c31abSDavid du Colombier 	char err[ERRMAX];
361368c31abSDavid du Colombier 	uint ms;
362368c31abSDavid du Colombier 	int cached, ok;
363368c31abSDavid du Colombier 
364368c31abSDavid du Colombier 	USED(v);
365368c31abSDavid du Colombier 	threadsetname("ventiserver");
366368c31abSDavid du Colombier 	trace(TraceWork, "start");
367368c31abSDavid du Colombier 	while((r = vtgetreq(ventisrv)) != nil){
368368c31abSDavid du Colombier 		trace(TraceWork, "finish");
369368c31abSDavid du Colombier 		trace(TraceWork, "start request %F", &r->tx);
370368c31abSDavid du Colombier 		trace(TraceRpc, "<- %F", &r->tx);
371368c31abSDavid du Colombier 		r->rx.msgtype = r->tx.msgtype+1;
372368c31abSDavid du Colombier 		addstat(StatRpcTotal, 1);
373368c31abSDavid du Colombier 		if(0) print("req (arenas[0]=%p sects[0]=%p) %F\n",
374368c31abSDavid du Colombier 			mainindex->arenas[0], mainindex->sects[0], &r->tx);
375368c31abSDavid du Colombier 		switch(r->tx.msgtype){
376368c31abSDavid du Colombier 		default:
377368c31abSDavid du Colombier 			vtrerror(r, "unknown request");
378368c31abSDavid du Colombier 			break;
379368c31abSDavid du Colombier 		case VtTread:
380368c31abSDavid du Colombier 			ms = msec();
381368c31abSDavid du Colombier 			r->rx.data = readlump(r->tx.score, r->tx.blocktype, r->tx.count, &cached);
382368c31abSDavid du Colombier 			ms = msec() - ms;
383368c31abSDavid du Colombier 			addstat2(StatRpcRead, 1, StatRpcReadTime, ms);
384368c31abSDavid du Colombier 			if(r->rx.data == nil){
385368c31abSDavid du Colombier 				addstat(StatRpcReadFail, 1);
386368c31abSDavid du Colombier 				rerrstr(err, sizeof err);
387368c31abSDavid du Colombier 				vtrerror(r, err);
388368c31abSDavid du Colombier 			}else{
389368c31abSDavid du Colombier 				addstat(StatRpcReadBytes, packetsize(r->rx.data));
390368c31abSDavid du Colombier 				addstat(StatRpcReadOk, 1);
391368c31abSDavid du Colombier 				if(cached)
392368c31abSDavid du Colombier 					addstat2(StatRpcReadCached, 1, StatRpcReadCachedTime, ms);
393368c31abSDavid du Colombier 				else
394368c31abSDavid du Colombier 					addstat2(StatRpcReadUncached, 1, StatRpcReadUncachedTime, ms);
395368c31abSDavid du Colombier 			}
396368c31abSDavid du Colombier 			break;
397368c31abSDavid du Colombier 		case VtTwrite:
398368c31abSDavid du Colombier 			if(readonly){
399368c31abSDavid du Colombier 				vtrerror(r, "read only");
400368c31abSDavid du Colombier 				break;
401368c31abSDavid du Colombier 			}
402368c31abSDavid du Colombier 			p = r->tx.data;
403368c31abSDavid du Colombier 			r->tx.data = nil;
404368c31abSDavid du Colombier 			addstat(StatRpcWriteBytes, packetsize(p));
405368c31abSDavid du Colombier 			ms = msec();
406368c31abSDavid du Colombier 			ok = writelump(p, r->rx.score, r->tx.blocktype, 0, ms);
407368c31abSDavid du Colombier 			ms = msec() - ms;
408368c31abSDavid du Colombier 			addstat2(StatRpcWrite, 1, StatRpcWriteTime, ms);
409368c31abSDavid du Colombier 
410368c31abSDavid du Colombier 			if(ok < 0){
411368c31abSDavid du Colombier 				addstat(StatRpcWriteFail, 1);
412368c31abSDavid du Colombier 				rerrstr(err, sizeof err);
413368c31abSDavid du Colombier 				vtrerror(r, err);
414368c31abSDavid du Colombier 			}
415368c31abSDavid du Colombier 			break;
416368c31abSDavid du Colombier 		case VtTsync:
417368c31abSDavid du Colombier 			flushqueue();
418368c31abSDavid du Colombier 			flushdcache();
419368c31abSDavid du Colombier 			break;
420368c31abSDavid du Colombier 		}
421368c31abSDavid du Colombier 		trace(TraceRpc, "-> %F", &r->rx);
422368c31abSDavid du Colombier 		vtrespond(r);
423368c31abSDavid du Colombier 		trace(TraceWork, "start");
424368c31abSDavid du Colombier 	}
425368c31abSDavid du Colombier 	flushdcache();
426368c31abSDavid du Colombier 	flushicache();
427368c31abSDavid du Colombier 	threadexitsall(0);
428368c31abSDavid du Colombier }
429