|  | #ifdef PLAN9PORT | 
|  | #include <u.h> | 
|  | #include <signal.h> | 
|  | #endif | 
|  | #include "stdinc.h" | 
|  | #include "dat.h" | 
|  | #include "fns.h" | 
|  |  | 
|  | #include "whack.h" | 
|  |  | 
|  | int debug; | 
|  | int nofork; | 
|  | int mainstacksize = 256*1024; | 
|  | VtSrv *ventisrv; | 
|  |  | 
|  | static void	ventiserver(void*); | 
|  |  | 
|  | void | 
|  | usage(void) | 
|  | { | 
|  | fprint(2, "usage: venti [-Ldrs] [-a address] [-B blockcachesize] [-c config] " | 
|  | "[-C lumpcachesize] [-h httpaddress] [-I indexcachesize] [-W webroot]\n"); | 
|  | threadexitsall("usage"); | 
|  | } | 
|  |  | 
|  | void | 
|  | threadmain(int argc, char *argv[]) | 
|  | { | 
|  | char *configfile, *haddr, *vaddr, *webroot; | 
|  | u32int mem, icmem, bcmem, minbcmem; | 
|  | Config config; | 
|  |  | 
|  | traceinit(); | 
|  | threadsetname("main"); | 
|  | vaddr = nil; | 
|  | haddr = nil; | 
|  | configfile = nil; | 
|  | webroot = nil; | 
|  | mem = 0; | 
|  | icmem = 0; | 
|  | bcmem = 0; | 
|  | ARGBEGIN{ | 
|  | case 'a': | 
|  | vaddr = EARGF(usage()); | 
|  | break; | 
|  | case 'B': | 
|  | bcmem = unittoull(EARGF(usage())); | 
|  | break; | 
|  | case 'c': | 
|  | configfile = EARGF(usage()); | 
|  | break; | 
|  | case 'C': | 
|  | mem = unittoull(EARGF(usage())); | 
|  | break; | 
|  | case 'D': | 
|  | settrace(EARGF(usage())); | 
|  | break; | 
|  | case 'd': | 
|  | debug = 1; | 
|  | nofork = 1; | 
|  | break; | 
|  | case 'h': | 
|  | haddr = EARGF(usage()); | 
|  | break; | 
|  | case 'I': | 
|  | icmem = unittoull(EARGF(usage())); | 
|  | break; | 
|  | case 'L': | 
|  | ventilogging = 1; | 
|  | break; | 
|  | case 'r': | 
|  | readonly = 1; | 
|  | break; | 
|  | case 's': | 
|  | nofork = 1; | 
|  | break; | 
|  | case 'w':			/* compatibility with old venti */ | 
|  | queuewrites = 1; | 
|  | break; | 
|  | case 'W': | 
|  | webroot = EARGF(usage()); | 
|  | break; | 
|  | default: | 
|  | usage(); | 
|  | }ARGEND | 
|  |  | 
|  | if(argc) | 
|  | usage(); | 
|  |  | 
|  | if(!nofork) | 
|  | rfork(RFNOTEG); | 
|  |  | 
|  | #ifdef PLAN9PORT | 
|  | { | 
|  | /* sigh - needed to avoid signals when writing to hungup networks */ | 
|  | struct sigaction sa; | 
|  | memset(&sa, 0, sizeof sa); | 
|  | sa.sa_handler = SIG_IGN; | 
|  | sigaction(SIGPIPE, &sa, nil); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | ventifmtinstall(); | 
|  | trace(TraceQuiet, "venti started"); | 
|  | fprint(2, "%T venti: "); | 
|  |  | 
|  | if(configfile == nil) | 
|  | configfile = "venti.conf"; | 
|  |  | 
|  | fprint(2, "conf..."); | 
|  | if(initventi(configfile, &config) < 0) | 
|  | sysfatal("can't init server: %r"); | 
|  | /* | 
|  | * load bloom filter | 
|  | */ | 
|  | if(mainindex->bloom && loadbloom(mainindex->bloom) < 0) | 
|  | sysfatal("can't load bloom filter: %r"); | 
|  |  | 
|  | if(mem == 0) | 
|  | mem = config.mem; | 
|  | if(bcmem == 0) | 
|  | bcmem = config.bcmem; | 
|  | if(icmem == 0) | 
|  | icmem = config.icmem; | 
|  | if(haddr == nil) | 
|  | haddr = config.haddr; | 
|  | if(vaddr == nil) | 
|  | vaddr = config.vaddr; | 
|  | if(vaddr == nil) | 
|  | vaddr = "tcp!*!venti"; | 
|  | if(webroot == nil) | 
|  | webroot = config.webroot; | 
|  | if(queuewrites == 0) | 
|  | queuewrites = config.queuewrites; | 
|  |  | 
|  | if(haddr){ | 
|  | fprint(2, "httpd %s...", haddr); | 
|  | if(httpdinit(haddr, webroot) < 0) | 
|  | fprint(2, "warning: can't start http server: %r"); | 
|  | } | 
|  | fprint(2, "init..."); | 
|  |  | 
|  | if(mem == 0xffffffffUL) | 
|  | mem = 1 * 1024 * 1024; | 
|  |  | 
|  | /* | 
|  | * lump cache | 
|  | */ | 
|  | if(0) fprint(2, "initialize %d bytes of lump cache for %d lumps\n", | 
|  | mem, mem / (8 * 1024)); | 
|  | initlumpcache(mem, mem / (8 * 1024)); | 
|  |  | 
|  | /* | 
|  | * index cache | 
|  | */ | 
|  | initicache(icmem); | 
|  | initicachewrite(); | 
|  |  | 
|  | /* | 
|  | * block cache: need a block for every arena and every process | 
|  | */ | 
|  | minbcmem = maxblocksize * | 
|  | (mainindex->narenas + mainindex->nsects*4 + 16); | 
|  | if(bcmem < minbcmem) | 
|  | bcmem = minbcmem; | 
|  | if(0) fprint(2, "initialize %d bytes of disk block cache\n", bcmem); | 
|  | initdcache(bcmem); | 
|  |  | 
|  | if(mainindex->bloom) | 
|  | startbloomproc(mainindex->bloom); | 
|  |  | 
|  | fprint(2, "sync..."); | 
|  | if(!readonly && syncindex(mainindex) < 0) | 
|  | sysfatal("can't sync server: %r"); | 
|  |  | 
|  | if(!readonly && queuewrites){ | 
|  | fprint(2, "queue..."); | 
|  | if(initlumpqueues(mainindex->nsects) < 0){ | 
|  | fprint(2, "can't initialize lump queues," | 
|  | " disabling write queueing: %r"); | 
|  | queuewrites = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | if(initarenasum() < 0) | 
|  | fprint(2, "warning: can't initialize arena summing process: %r"); | 
|  |  | 
|  | fprint(2, "announce %s...", vaddr); | 
|  | ventisrv = vtlisten(vaddr); | 
|  | if(ventisrv == nil) | 
|  | sysfatal("can't announce %s: %r", vaddr); | 
|  |  | 
|  | fprint(2, "serving.\n"); | 
|  | if(nofork) | 
|  | ventiserver(nil); | 
|  | else | 
|  | vtproc(ventiserver, nil); | 
|  |  | 
|  | threadexits(nil); | 
|  | } | 
|  |  | 
|  | static void | 
|  | vtrerror(VtReq *r, char *error) | 
|  | { | 
|  | r->rx.msgtype = VtRerror; | 
|  | r->rx.error = estrdup(error); | 
|  | } | 
|  |  | 
|  | static void | 
|  | ventiserver(void *v) | 
|  | { | 
|  | Packet *p; | 
|  | VtReq *r; | 
|  | char err[ERRMAX]; | 
|  | uint ms; | 
|  | int cached, ok; | 
|  |  | 
|  | USED(v); | 
|  | threadsetname("ventiserver"); | 
|  | trace(TraceWork, "start"); | 
|  | while((r = vtgetreq(ventisrv)) != nil){ | 
|  | trace(TraceWork, "finish"); | 
|  | trace(TraceWork, "start request %F", &r->tx); | 
|  | trace(TraceRpc, "<- %F", &r->tx); | 
|  | r->rx.msgtype = r->tx.msgtype+1; | 
|  | addstat(StatRpcTotal, 1); | 
|  | if(0) print("req (arenas[0]=%p sects[0]=%p) %F\n", | 
|  | mainindex->arenas[0], mainindex->sects[0], &r->tx); | 
|  | switch(r->tx.msgtype){ | 
|  | default: | 
|  | vtrerror(r, "unknown request"); | 
|  | break; | 
|  | case VtTread: | 
|  | ms = msec(); | 
|  | r->rx.data = readlump(r->tx.score, r->tx.blocktype, r->tx.count, &cached); | 
|  | ms = msec() - ms; | 
|  | addstat2(StatRpcRead, 1, StatRpcReadTime, ms); | 
|  | if(r->rx.data == nil){ | 
|  | addstat(StatRpcReadFail, 1); | 
|  | rerrstr(err, sizeof err); | 
|  | vtrerror(r, err); | 
|  | }else{ | 
|  | addstat(StatRpcReadBytes, packetsize(r->rx.data)); | 
|  | addstat(StatRpcReadOk, 1); | 
|  | if(cached) | 
|  | addstat2(StatRpcReadCached, 1, StatRpcReadCachedTime, ms); | 
|  | else | 
|  | addstat2(StatRpcReadUncached, 1, StatRpcReadUncachedTime, ms); | 
|  | } | 
|  | break; | 
|  | case VtTwrite: | 
|  | if(readonly){ | 
|  | vtrerror(r, "read only"); | 
|  | break; | 
|  | } | 
|  | p = r->tx.data; | 
|  | r->tx.data = nil; | 
|  | addstat(StatRpcWriteBytes, packetsize(p)); | 
|  | ms = msec(); | 
|  | ok = writelump(p, r->rx.score, r->tx.blocktype, 0, ms); | 
|  | ms = msec() - ms; | 
|  | addstat2(StatRpcWrite, 1, StatRpcWriteTime, ms); | 
|  |  | 
|  | if(ok < 0){ | 
|  | addstat(StatRpcWriteFail, 1); | 
|  | rerrstr(err, sizeof err); | 
|  | vtrerror(r, err); | 
|  | } | 
|  | break; | 
|  | case VtTsync: | 
|  | flushqueue(); | 
|  | flushdcache(); | 
|  | break; | 
|  | } | 
|  | trace(TraceRpc, "-> %F", &r->rx); | 
|  | vtrespond(r); | 
|  | trace(TraceWork, "start"); | 
|  | } | 
|  | flushdcache(); | 
|  | flushicache(); | 
|  | threadexitsall(0); | 
|  | } |