12 typedef struct Allocs Allocs;
17 u32int stfree; /* free memory at start */
23 int mainstacksize = 256*1024;
26 static void ventiserver(void*);
32 uvlong size, userpgs = 0, userused = 0;
38 bp = Bopen("/dev/swap", OREAD);
40 while ((ln = Brdline(bp, '\n')) != nil) {
41 ln[Blinelen(bp)-1] = '\0';
42 nf = tokenize(ln, fields, nelem(fields));
45 if (strcmp(fields[1], "pagesize") == 0)
46 pgsize = atoi(fields[0]);
47 else if (strcmp(fields[1], "user") == 0) {
48 sl = strchr(fields[0], '/');
51 userpgs = atoll(sl+1);
52 userused = atoll(fields[0]);
56 if (pgsize > 0 && userpgs > 0 && userused > 0)
57 size = (userpgs - userused) * pgsize;
59 fprint(2, "%s: failed to open /dev/swap\n", argv0);
61 /* cap it to keep the size within 32 bits */
62 if (size >= 3840UL * 1024 * 1024){
63 size = 3840UL * 1024 * 1024;
64 fprint(2, "%s: Reduced free memory detected to 3840MiB because we don't support 64-bit addresses yet.\n", argv0);
66 /* FIXME: we use signed 32-bit integers in some places for some fucking reason.
67 Limiting accordingly for now.
69 if (size >= 2047UL * 1024 * 1024){
70 size = 2047UL * 1024 * 1024;
71 fprint(2, "%s: Reduced free memory detected to 2047MiB because we have bugz.\n", argv0);
77 allocminima(Allocs *all) /* enforce minima for sanity */
79 if (all->icmem < 6 * 1024 * 1024)
80 all->icmem = 6 * 1024 * 1024;
81 if (all->mem < 1024 * 1024 || all->mem == Unspecified) /* lumps */
82 all->mem = 1024 * 1024;
83 if (all->bcmem < 2 * 1024 * 1024)
84 all->bcmem = 2 * 1024 * 1024;
87 /* automatic memory allocations sizing per venti(8) guidelines */
89 allocbypcnt(u32int mempcnt, u32int stfree)
96 all.mem = Unspecified;
97 all.bcmem = all.icmem = 0;
98 all.mempcnt = mempcnt;
103 blmsize = stfree - free;
106 avail = ((vlong)stfree * mempcnt) / 100;
107 if (blmsize >= avail || (avail -= blmsize) <= (1 + 2 + 6) * 1024 * 1024)
108 fprint(2, "%s: bloom filter bigger than mem pcnt; "
109 "resorting to minimum values (9MB total)\n", argv0);
111 if (avail >= 2047UL * 1024 * 1024){
112 avail = 2047UL * 1024 * 1024; /* sanity */
113 fprint(2, "%s: restricting memory usage to 2047MiB\n", argv0);
119 all.bcmem = 2 * avail;
125 * we compute default values for allocations,
126 * which can be overridden by (in order):
127 * configuration file parameters,
128 * command-line options other than -m, and -m.
131 sizeallocs(Allocs opt, Config *cfg)
135 /* work out sane defaults */
136 all = allocbypcnt(20, opt.stfree);
138 /* config file parameters override */
139 if (cfg->mem && cfg->mem != Unspecified)
142 all.bcmem = cfg->bcmem;
144 all.icmem = cfg->icmem;
146 /* command-line options override */
147 if (opt.mem && opt.mem != Unspecified)
150 all.bcmem = opt.bcmem;
152 all.icmem = opt.icmem;
154 /* automatic memory sizing? */
156 all = allocbypcnt(opt.mempcnt, opt.stfree);
165 fprint(2, "usage: venti [-Ldrsw] [-a ventiaddr] [-c config] "
166 "[-h httpaddr] [-m %%mem] [-B blockcachesize] [-C cachesize] [-I icachesize] "
168 threadexitsall("usage");
172 threadmain(int argc, char *argv[])
174 char *configfile, *haddr, *vaddr, *webroot;
175 u32int mem, icmem, bcmem, minbcmem, mempcnt, stfree;
180 threadsetname("main");
191 vaddr = EARGF(usage());
194 bcmem = unittoull(EARGF(usage()));
197 configfile = EARGF(usage());
200 mem = unittoull(EARGF(usage()));
203 settrace(EARGF(usage()));
210 haddr = EARGF(usage());
213 mempcnt = atoi(EARGF(usage()));
214 if (mempcnt <= 0 || mempcnt >= 100)
218 icmem = unittoull(EARGF(usage()));
229 case 'w': /* compatibility with old venti */
233 webroot = EARGF(usage());
247 /* sigh - needed to avoid signals when writing to hungup networks */
249 memset(&sa, 0, sizeof sa);
250 sa.sa_handler = SIG_IGN;
251 sigaction(SIGPIPE, &sa, nil);
256 trace(TraceQuiet, "venti started");
257 fprint(2, "%T venti: ");
259 if(configfile == nil)
260 configfile = "venti.conf";
262 /* remember free memory before initventi & loadbloom, for auto-sizing */
264 fprint(2, "conf...");
265 if(initventi(configfile, &config) < 0)
266 sysfatal("can't init server: %r");
270 if(mainindex->bloom && loadbloom(mainindex->bloom) < 0)
271 sysfatal("can't load bloom filter: %r");
274 * size memory allocations; assumes bloom filter is loaded
276 allocs = sizeallocs((Allocs){mem, bcmem, icmem, stfree, mempcnt},
279 bcmem = allocs.bcmem;
280 icmem = allocs.icmem;
281 fprint(2, "%s: mem %,ud bcmem %,ud icmem %,ud...",
282 argv0, mem, bcmem, icmem);
285 * default other configuration-file parameters
288 haddr = config.haddr;
290 vaddr = config.vaddr;
292 vaddr = "tcp!*!venti";
294 webroot = config.webroot;
296 queuewrites = config.queuewrites;
299 fprint(2, "httpd %s...", haddr);
300 if(httpdinit(haddr, webroot) < 0)
301 fprint(2, "warning: can't start http server: %r");
303 fprint(2, "init...");
308 if(0) fprint(2, "initialize %d bytes of lump cache for %d lumps\n",
309 mem, mem / (8 * 1024));
310 initlumpcache(mem, mem / (8 * 1024));
319 * block cache: need a block for every arena and every process
321 minbcmem = maxblocksize *
322 (mainindex->narenas + mainindex->nsects*4 + 16);
325 if(0) fprint(2, "initialize %d bytes of disk block cache\n", bcmem);
329 startbloomproc(mainindex->bloom);
331 fprint(2, "sync...");
332 if(!readonly && syncindex(mainindex) < 0)
333 sysfatal("can't sync server: %r");
335 if(!readonly && queuewrites){
336 fprint(2, "queue...");
337 if(initlumpqueues(mainindex->nsects) < 0){
338 fprint(2, "can't initialize lump queues,"
339 " disabling write queueing: %r");
344 if(initarenasum() < 0)
345 fprint(2, "warning: can't initialize arena summing process: %r");
347 fprint(2, "announce %s...", vaddr);
348 ventisrv = vtlisten(vaddr);
350 sysfatal("can't announce %s: %r", vaddr);
352 fprint(2, "serving.\n");
356 vtproc(ventiserver, nil);
362 vtrerror(VtReq *r, char *error)
364 r->rx.msgtype = VtRerror;
365 r->rx.error = estrdup(error);
378 threadsetname("ventiserver");
379 trace(TraceWork, "start");
380 while((r = vtgetreq(ventisrv)) != nil){
381 trace(TraceWork, "finish");
382 trace(TraceWork, "start request %F", &r->tx);
383 trace(TraceRpc, "<- %F", &r->tx);
384 r->rx.msgtype = r->tx.msgtype+1;
385 addstat(StatRpcTotal, 1);
386 if(0) print("req (arenas[0]=%p sects[0]=%p) %F\n",
387 mainindex->arenas[0], mainindex->sects[0], &r->tx);
388 switch(r->tx.msgtype){
390 vtrerror(r, "unknown request");
394 r->rx.data = readlump(r->tx.score, r->tx.blocktype, r->tx.count, &cached);
396 addstat2(StatRpcRead, 1, StatRpcReadTime, ms);
397 if(r->rx.data == nil){
398 addstat(StatRpcReadFail, 1);
399 rerrstr(err, sizeof err);
402 addstat(StatRpcReadBytes, packetsize(r->rx.data));
403 addstat(StatRpcReadOk, 1);
405 addstat2(StatRpcReadCached, 1, StatRpcReadCachedTime, ms);
407 addstat2(StatRpcReadUncached, 1, StatRpcReadUncachedTime, ms);
412 vtrerror(r, "read only");
417 addstat(StatRpcWriteBytes, packetsize(p));
419 ok = writelump(p, r->rx.score, r->tx.blocktype, 0, ms);
421 addstat2(StatRpcWrite, 1, StatRpcWriteTime, ms);
424 addstat(StatRpcWriteFail, 1);
425 rerrstr(err, sizeof err);
434 trace(TraceRpc, "-> %F", &r->rx);
436 trace(TraceWork, "start");