| #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); |
| } |