7 typedef struct HttpObj HttpObj;
17 char name[ObjNameSize];
21 static HttpObj objs[MaxObjs];
23 static void listenproc(void*);
24 static int estats(HConnect *c);
25 static int dindex(HConnect *c);
26 static int xindex(HConnect *c);
27 static int sindex(HConnect *c);
28 static int notfound(HConnect *c);
29 static int httpdobj(char *name, int (*f)(HConnect*));
32 httpdinit(char *address)
34 fmtinstall('D', hdatefmt);
35 fmtinstall('H', httpfmt);
36 fmtinstall('U', hurlfmt);
39 address = "tcp!*!http";
41 httpdobj("/stats", estats);
42 httpdobj("/index", dindex);
43 httpdobj("/storage", sindex);
44 httpdobj("/xindex", xindex);
46 if(vtproc(listenproc, address) < 0)
52 httpdobj(char *name, int (*f)(HConnect*))
56 if(name == nil || strlen(name) >= ObjNameSize)
58 for(i = 0; i < MaxObjs; i++){
59 if(objs[i].name[0] == '\0'){
60 strcpy(objs[i].name, name);
64 if(strcmp(objs[i].name, name) == 0)
75 c = mallocz(sizeof(HConnect), 1);
77 sysfatal("out of memory");
87 listenproc(void *vaddress)
90 char *address, ndir[NETPATHLEN], dir[NETPATHLEN];
93 //sleep(1000); /* let strace find us */
96 ctl = announce(address, dir);
98 fprint(2, "venti: httpd can't announce on %s: %r\n", address);
102 print("announce ctl %d dir %s\n", ctl, dir);
105 * wait for a call (or an error)
107 nctl = listen(dir, ndir);
108 print("httpd listen %d %s...\n", nctl, ndir);
110 fprint(2, "venti: httpd can't listen on %s: %r\n", address);
114 data = accept(ctl, ndir);
115 print("httpd accept %d...\n", data);
117 fprint(2, "venti: httpd accept: %r\n");
121 print("httpd close nctl %d\n", nctl);
124 hinit(&c->hin, data, Hread);
125 hinit(&c->hout, data, Hwrite);
136 //sleep(1000); /* let strace find us */
139 for(t = 15*60*1000; ; t = 15*1000){
140 if(hparsereq(c, t) < 0)
144 for(i = 0; i < MaxObjs && objs[i].name[0]; i++){
145 if(strcmp(c->req.uri, objs[i].name) == 0){
146 ok = (*objs[i].f)(c);
165 percent(long v, long total)
170 return (v * 100) / total;
180 if(hparseheaders(c, 15*60*1000) < 0)
182 fprint(2, "hparseheaders failed\n");
185 if(strcmp(c->req.meth, "GET") != 0
186 && strcmp(c->req.meth, "HEAD") != 0)
187 return hunallowed(c, "GET, HEAD");
188 if(c->head.expectother || c->head.expectcont)
189 return hfail(c, HExpectFail, nil);
194 preqtext(HConnect *c)
206 hprint(hout, "Content-type: text/plain\r\n");
208 hprint(hout, "Transfer-Encoding: chunked\r\n");
209 hprint(hout, "\r\n");
220 notfound(HConnect *c)
227 return hfail(c, HNotFound, c->req.uri);
242 hprint(hout, "lump writes=%,ld\n", stats.lumpwrites);
243 hprint(hout, "lump reads=%,ld\n", stats.lumpreads);
244 hprint(hout, "lump cache read hits=%,ld\n", stats.lumphit);
245 hprint(hout, "lump cache read misses=%,ld\n", stats.lumpmiss);
247 hprint(hout, "clump disk writes=%,ld\n", stats.clumpwrites);
248 hprint(hout, "clump disk bytes written=%,lld\n", stats.clumpbwrites);
249 hprint(hout, "clump disk bytes compressed=%,lld\n", stats.clumpbcomp);
250 hprint(hout, "clump disk reads=%,ld\n", stats.clumpreads);
251 hprint(hout, "clump disk bytes read=%,lld\n", stats.clumpbreads);
252 hprint(hout, "clump disk bytes uncompressed=%,lld\n", stats.clumpbuncomp);
254 hprint(hout, "clump directory disk writes=%,ld\n", stats.ciwrites);
255 hprint(hout, "clump directory disk reads=%,ld\n", stats.cireads);
257 hprint(hout, "index disk writes=%,ld\n", stats.indexwrites);
258 hprint(hout, "index disk reads=%,ld\n", stats.indexreads);
259 hprint(hout, "index disk reads for modify=%,ld\n", stats.indexwreads);
260 hprint(hout, "index disk reads for allocation=%,ld\n", stats.indexareads);
261 hprint(hout, "index block splits=%,ld\n", stats.indexsplits);
263 hprint(hout, "index cache lookups=%,ld\n", stats.iclookups);
264 hprint(hout, "index cache hits=%,ld %d%%\n", stats.ichits,
265 percent(stats.ichits, stats.iclookups));
266 hprint(hout, "index cache fills=%,ld %d%%\n", stats.icfills,
267 percent(stats.icfills, stats.iclookups));
268 hprint(hout, "index cache inserts=%,ld\n", stats.icinserts);
270 hprint(hout, "disk cache hits=%,ld\n", stats.pchit);
271 hprint(hout, "disk cache misses=%,ld\n", stats.pcmiss);
272 hprint(hout, "disk cache reads=%,ld\n", stats.pcreads);
273 hprint(hout, "disk cache bytes read=%,lld\n", stats.pcbreads);
275 hprint(hout, "disk cache writes=%,ld\n", stats.dirtydblocks);
276 hprint(hout, "disk cache writes absorbed=%,ld %d%%\n", stats.absorbedwrites,
277 percent(stats.absorbedwrites, stats.dirtydblocks));
279 hprint(hout, "disk cache flushes=%,ld\n", stats.dcacheflushes);
280 hprint(hout, "disk cache flush writes=%,ld (%,ld per flush)\n",
281 stats.dcacheflushwrites,
282 stats.dcacheflushwrites/(stats.dcacheflushes ? stats.dcacheflushes : 1));
284 hprint(hout, "disk writes=%,ld\n", stats.diskwrites);
285 hprint(hout, "disk bytes written=%,lld\n", stats.diskbwrites);
286 hprint(hout, "disk reads=%,ld\n", stats.diskreads);
287 hprint(hout, "disk bytes read=%,lld\n", stats.diskbreads);
299 vlong clumps, cclumps, uncsize, used, size;
309 hprint(hout, "index=%s\n", ix->name);
317 for(i = 0; i < ix->narenas; i++){
318 arena = ix->arenas[i];
319 if(arena != nil && arena->clumps != 0){
321 clumps += arena->clumps;
322 cclumps += arena->cclumps;
323 uncsize += arena->uncsize;
328 hprint(hout, "total arenas=%d active=%d\n", ix->narenas, active);
329 hprint(hout, "total space=%lld used=%lld\n", size, used + clumps * ClumpInfoSize);
330 hprint(hout, "clumps=%lld compressed clumps=%lld data=%lld compressed data=%lld\n",
331 clumps, cclumps, uncsize, used - clumps * ClumpSize);
337 darena(Hio *hout, Arena *arena)
339 hprint(hout, "arena='%s' on %s at [%lld,%lld)\n\tversion=%d created=%d modified=%d",
340 arena->name, arena->part->name, arena->base, arena->base + arena->size + 2 * arena->blocksize,
341 arena->version, arena->ctime, arena->wtime);
343 hprint(hout, " sealed\n");
346 if(scorecmp(zeroscore, arena->score) != 0)
347 hprint(hout, "\tscore=%V\n", arena->score);
349 hprint(hout, "\tclumps=%d compressed clumps=%d data=%lld compressed data=%lld disk storage=%lld\n",
350 arena->clumps, arena->cclumps, arena->uncsize,
351 arena->used - arena->clumps * ClumpSize,
352 arena->used + arena->clumps * ClumpInfoSize);
369 hprint(hout, "index=%s version=%d blocksize=%d tabsize=%d\n",
370 ix->name, ix->version, ix->blocksize, ix->tabsize);
371 hprint(hout, "\tbuckets=%d div=%d\n", ix->buckets, ix->div);
372 for(i = 0; i < ix->nsects; i++)
373 hprint(hout, "\tsect=%s for buckets [%lld,%lld) buckmax=%d\n", ix->smap[i].name, ix->smap[i].start, ix->smap[i].stop, ix->sects[i]->buckmax);
374 for(i = 0; i < ix->narenas; i++){
375 if(ix->arenas[i] != nil && ix->arenas[i]->clumps != 0){
376 hprint(hout, "arena=%s at index [%lld,%lld)\n\t", ix->amap[i].name, ix->amap[i].start, ix->amap[i].stop);
377 darena(hout, ix->arenas[i]);
397 hprint(hout, "Content-type: text/xml\r\n");
399 hprint(hout, "Transfer-Encoding: chunked\r\n");
400 hprint(hout, "\r\n");
407 xmlindex(hout, mainindex, "index", 0);
413 xmlindent(Hio *hout, int indent)
417 for(i = 0; i < indent; i++)
422 xmlaname(Hio *hout, char *v, char *tag)
424 hprint(hout, " %s=\"%s\"", tag, v);
428 xmlscore(Hio *hout, u8int *v, char *tag)
430 if(scorecmp(zeroscore, v) == 0)
432 hprint(hout, " %s=\"%V\"", tag, v);
436 xmlsealed(Hio *hout, int v, char *tag)
440 hprint(hout, " %s=\"yes\"", tag);
444 xmlu32int(Hio *hout, u32int v, char *tag)
446 hprint(hout, " %s=\"%ud\"", tag, v);
450 xmlu64int(Hio *hout, u64int v, char *tag)
452 hprint(hout, " %s=\"%llud\"", tag, v);