1368c31abSDavid du Colombier #include "stdinc.h"
2368c31abSDavid du Colombier #include "dat.h"
3368c31abSDavid du Colombier #include "fns.h"
4368c31abSDavid du Colombier #include "whack.h"
5368c31abSDavid du Colombier
6368c31abSDavid du Colombier static int disksummary(HConnect*);
7368c31abSDavid du Colombier static int diskarenapart(HConnect*, char*, Part*);
8368c31abSDavid du Colombier static int diskbloom(HConnect*, char*, Part*);
9368c31abSDavid du Colombier static int diskisect(HConnect*, char*, Part*);
10368c31abSDavid du Colombier
11368c31abSDavid du Colombier int
hdisk(HConnect * c)12368c31abSDavid du Colombier hdisk(HConnect *c)
13368c31abSDavid du Colombier {
14368c31abSDavid du Colombier char *disk, *type;
15368c31abSDavid du Colombier Part *p;
16368c31abSDavid du Colombier int ret;
17368c31abSDavid du Colombier
18368c31abSDavid du Colombier if(hsethtml(c) < 0)
19368c31abSDavid du Colombier return -1;
20368c31abSDavid du Colombier
21368c31abSDavid du Colombier disk = hargstr(c, "disk", "");
22368c31abSDavid du Colombier if(!disk[0])
23368c31abSDavid du Colombier return disksummary(c);
24368c31abSDavid du Colombier if((p = initpart(disk, OREAD)) == nil){
25368c31abSDavid du Colombier hprint(&c->hout, "open %s: %r", disk);
26368c31abSDavid du Colombier return 0;
27368c31abSDavid du Colombier }
28368c31abSDavid du Colombier
29368c31abSDavid du Colombier type = hargstr(c, "type", "");
30368c31abSDavid du Colombier switch(type[0]){
31368c31abSDavid du Colombier case 'a':
32368c31abSDavid du Colombier ret = diskarenapart(c, disk, p);
33368c31abSDavid du Colombier break;
34368c31abSDavid du Colombier case 'b':
35368c31abSDavid du Colombier ret = diskbloom(c, disk, p);
36368c31abSDavid du Colombier break;
37368c31abSDavid du Colombier case 'i':
38368c31abSDavid du Colombier ret = diskisect(c, disk, p);
39368c31abSDavid du Colombier break;
40368c31abSDavid du Colombier default:
41368c31abSDavid du Colombier hprint(&c->hout, "unknown disk type %s", type);
42368c31abSDavid du Colombier return 0;
43368c31abSDavid du Colombier }
44368c31abSDavid du Colombier freepart(p);
45368c31abSDavid du Colombier return ret;
46368c31abSDavid du Colombier }
47368c31abSDavid du Colombier
48368c31abSDavid du Colombier static int
disksummary(HConnect * c)49368c31abSDavid du Colombier disksummary(HConnect *c)
50368c31abSDavid du Colombier {
51368c31abSDavid du Colombier int i;
52368c31abSDavid du Colombier Index *ix;
53368c31abSDavid du Colombier Part *p;
54368c31abSDavid du Colombier
55368c31abSDavid du Colombier hprint(&c->hout, "<h1>venti disks</h1>\n");
56368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
57368c31abSDavid du Colombier ix = mainindex;
58368c31abSDavid du Colombier p = nil;
59368c31abSDavid du Colombier for(i=0; i<ix->narenas; i++){
60368c31abSDavid du Colombier if(ix->arenas[i]->part == p)
61368c31abSDavid du Colombier continue;
62368c31abSDavid du Colombier p = ix->arenas[i]->part;
63368c31abSDavid du Colombier hprint(&c->hout, "<a href=\"/disk?disk=%s&type=a\">%s</a> %s\n", p->name, p->name, ix->arenas[i]->name);
64368c31abSDavid du Colombier }
65368c31abSDavid du Colombier hprint(&c->hout, "\n");
66368c31abSDavid du Colombier p = nil;
67368c31abSDavid du Colombier for(i=0; i<ix->nsects; i++){
68368c31abSDavid du Colombier if(ix->sects[i]->part == p)
69368c31abSDavid du Colombier continue;
70368c31abSDavid du Colombier p = ix->sects[i]->part;
71368c31abSDavid du Colombier hprint(&c->hout, "<a href=\"/disk?disk=%s&type=i\">%s</a> %s\n", p->name, p->name, ix->sects[i]->name);
72368c31abSDavid du Colombier }
73368c31abSDavid du Colombier hprint(&c->hout, "\n");
74368c31abSDavid du Colombier if(ix->bloom){
75368c31abSDavid du Colombier p = ix->bloom->part;
76368c31abSDavid du Colombier hprint(&c->hout, "<a href=\"/disk?disk=%s&type=b\">%s</a> %s\n", p->name, p->name, "bloom filter");
77368c31abSDavid du Colombier }
78368c31abSDavid du Colombier return 0;
79368c31abSDavid du Colombier }
80368c31abSDavid du Colombier
81368c31abSDavid du Colombier static char*
readap(Part * p,ArenaPart * ap)82368c31abSDavid du Colombier readap(Part *p, ArenaPart *ap)
83368c31abSDavid du Colombier {
84368c31abSDavid du Colombier uchar *blk;
85368c31abSDavid du Colombier char *table;
86368c31abSDavid du Colombier
87368c31abSDavid du Colombier blk = vtmalloc(8192);
88368c31abSDavid du Colombier if(readpart(p, PartBlank, blk, 8192) != 8192)
89368c31abSDavid du Colombier return nil;
90368c31abSDavid du Colombier if(unpackarenapart(ap, blk) < 0){
91368c31abSDavid du Colombier werrstr("corrupt arena part header: %r");
92368c31abSDavid du Colombier return nil;
93368c31abSDavid du Colombier }
94368c31abSDavid du Colombier vtfree(blk);
95368c31abSDavid du Colombier ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1);
96368c31abSDavid du Colombier ap->tabsize = ap->arenabase - ap->tabbase;
97368c31abSDavid du Colombier table = vtmalloc(ap->tabsize+1);
98368c31abSDavid du Colombier if(readpart(p, ap->tabbase, (uchar*)table, ap->tabsize) != ap->tabsize){
99368c31abSDavid du Colombier werrstr("reading arena part directory: %r");
100368c31abSDavid du Colombier return nil;
101368c31abSDavid du Colombier }
102368c31abSDavid du Colombier table[ap->tabsize] = 0;
103368c31abSDavid du Colombier return table;
104368c31abSDavid du Colombier }
105368c31abSDavid du Colombier
106368c31abSDavid du Colombier static int
xfindarena(char * table,char * name,vlong * start,vlong * end)107368c31abSDavid du Colombier xfindarena(char *table, char *name, vlong *start, vlong *end)
108368c31abSDavid du Colombier {
109368c31abSDavid du Colombier int i, nline;
110368c31abSDavid du Colombier char *p, *q, *f[4], line[256];
111368c31abSDavid du Colombier
112368c31abSDavid du Colombier nline = atoi(table);
113368c31abSDavid du Colombier p = strchr(table, '\n');
114368c31abSDavid du Colombier if(p)
115368c31abSDavid du Colombier p++;
116368c31abSDavid du Colombier for(i=0; i<nline; i++){
117368c31abSDavid du Colombier if(p == nil)
118368c31abSDavid du Colombier break;
119368c31abSDavid du Colombier q = strchr(p, '\n');
120368c31abSDavid du Colombier if(q)
121368c31abSDavid du Colombier *q++ = 0;
122368c31abSDavid du Colombier if(strlen(p) >= sizeof line){
123368c31abSDavid du Colombier p = q;
124368c31abSDavid du Colombier continue;
125368c31abSDavid du Colombier }
126368c31abSDavid du Colombier strcpy(line, p);
127368c31abSDavid du Colombier memset(f, 0, sizeof f);
128368c31abSDavid du Colombier if(tokenize(line, f, nelem(f)) < 3){
129368c31abSDavid du Colombier p = q;
130368c31abSDavid du Colombier continue;
131368c31abSDavid du Colombier }
132368c31abSDavid du Colombier if(strcmp(f[0], name) == 0){
133368c31abSDavid du Colombier *start = strtoull(f[1], 0, 0);
134368c31abSDavid du Colombier *end = strtoull(f[2], 0, 0);
135368c31abSDavid du Colombier return 0;
136368c31abSDavid du Colombier }
137368c31abSDavid du Colombier p = q;
138368c31abSDavid du Colombier }
139368c31abSDavid du Colombier return -1;
140368c31abSDavid du Colombier }
141368c31abSDavid du Colombier
142368c31abSDavid du Colombier static void
diskarenatable(HConnect * c,char * disk,char * table)143368c31abSDavid du Colombier diskarenatable(HConnect *c, char *disk, char *table)
144368c31abSDavid du Colombier {
145368c31abSDavid du Colombier char *p, *q;
146368c31abSDavid du Colombier int i, nline;
147368c31abSDavid du Colombier char *f[4], line[256], base[256];
148368c31abSDavid du Colombier
149368c31abSDavid du Colombier hprint(&c->hout, "<h2>table</h2>\n");
150368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
151368c31abSDavid du Colombier nline = atoi(table);
152368c31abSDavid du Colombier snprint(base, sizeof base, "/disk?disk=%s&type=a", disk);
153368c31abSDavid du Colombier p = strchr(table, '\n');
154368c31abSDavid du Colombier if(p)
155368c31abSDavid du Colombier p++;
156368c31abSDavid du Colombier for(i=0; i<nline; i++){
157368c31abSDavid du Colombier if(p == nil){
158368c31abSDavid du Colombier hprint(&c->hout, "<b><i>unexpected end of table</i></b>\n");
159368c31abSDavid du Colombier break;
160368c31abSDavid du Colombier }
161368c31abSDavid du Colombier q = strchr(p, '\n');
162368c31abSDavid du Colombier if(q)
163368c31abSDavid du Colombier *q++ = 0;
164368c31abSDavid du Colombier if(strlen(p) >= sizeof line){
165368c31abSDavid du Colombier hprint(&c->hout, "%s\n", p);
166368c31abSDavid du Colombier p = q;
167368c31abSDavid du Colombier continue;
168368c31abSDavid du Colombier }
169368c31abSDavid du Colombier strcpy(line, p);
170368c31abSDavid du Colombier memset(f, 0, sizeof f);
171368c31abSDavid du Colombier if(tokenize(line, f, 3) < 3){
172368c31abSDavid du Colombier hprint(&c->hout, "%s\n", p);
173368c31abSDavid du Colombier p = q;
174368c31abSDavid du Colombier continue;
175368c31abSDavid du Colombier }
176368c31abSDavid du Colombier p = q;
177368c31abSDavid du Colombier hprint(&c->hout, "<a href=\"%s&arena=%s\">%s</a> %s %s\n",
178368c31abSDavid du Colombier base, f[0], f[0], f[1], f[2]);
179368c31abSDavid du Colombier }
180368c31abSDavid du Colombier hprint(&c->hout, "</pre>\n");
181368c31abSDavid du Colombier }
182368c31abSDavid du Colombier
183368c31abSDavid du Colombier static char*
fmttime(char * buf,ulong time)184368c31abSDavid du Colombier fmttime(char *buf, ulong time)
185368c31abSDavid du Colombier {
186368c31abSDavid du Colombier strcpy(buf, ctime(time));
187368c31abSDavid du Colombier buf[28] = 0;
188368c31abSDavid du Colombier return buf;
189368c31abSDavid du Colombier }
190368c31abSDavid du Colombier
191368c31abSDavid du Colombier
192368c31abSDavid du Colombier static int diskarenaclump(HConnect*, Arena*, vlong, char*);
193368c31abSDavid du Colombier static int diskarenatoc(HConnect*, Arena*);
194368c31abSDavid du Colombier
195368c31abSDavid du Colombier static int
diskarenapart(HConnect * c,char * disk,Part * p)196368c31abSDavid du Colombier diskarenapart(HConnect *c, char *disk, Part *p)
197368c31abSDavid du Colombier {
198368c31abSDavid du Colombier char *arenaname;
199368c31abSDavid du Colombier ArenaPart ap;
200368c31abSDavid du Colombier ArenaHead head;
201368c31abSDavid du Colombier Arena arena;
202368c31abSDavid du Colombier char *table;
203368c31abSDavid du Colombier char *score;
204368c31abSDavid du Colombier char *clump;
205368c31abSDavid du Colombier uchar *blk;
206368c31abSDavid du Colombier vlong start, end, off;
207368c31abSDavid du Colombier char tbuf[60];
208368c31abSDavid du Colombier
209368c31abSDavid du Colombier hprint(&c->hout, "<h1>arena partition %s</h1>\n", disk);
210368c31abSDavid du Colombier
211368c31abSDavid du Colombier if((table = readap(p, &ap)) == nil){
212368c31abSDavid du Colombier hprint(&c->hout, "%r\n");
213368c31abSDavid du Colombier goto out;
214368c31abSDavid du Colombier }
215368c31abSDavid du Colombier
216368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
217368c31abSDavid du Colombier hprint(&c->hout, "version=%d blocksize=%d base=%d\n",
218368c31abSDavid du Colombier ap.version, ap.blocksize, ap.arenabase);
219368c31abSDavid du Colombier hprint(&c->hout, "</pre>\n");
220368c31abSDavid du Colombier
221368c31abSDavid du Colombier arenaname = hargstr(c, "arena", "");
222368c31abSDavid du Colombier if(arenaname[0] == 0){
223368c31abSDavid du Colombier diskarenatable(c, disk, table);
224368c31abSDavid du Colombier goto out;
225368c31abSDavid du Colombier }
226368c31abSDavid du Colombier
227368c31abSDavid du Colombier if(xfindarena(table, arenaname, &start, &end) < 0){
228368c31abSDavid du Colombier hprint(&c->hout, "no such arena %s\n", arenaname);
229368c31abSDavid du Colombier goto out;
230368c31abSDavid du Colombier }
231368c31abSDavid du Colombier
232368c31abSDavid du Colombier hprint(&c->hout, "<h2>arena %s</h2>\n", arenaname);
233368c31abSDavid du Colombier hprint(&c->hout, "<pre>start=%#llx end=%#llx<pre>\n", start, end);
234368c31abSDavid du Colombier if(end < start || end - start < HeadSize){
235368c31abSDavid du Colombier hprint(&c->hout, "bad size %#llx\n", end - start);
236368c31abSDavid du Colombier goto out;
237368c31abSDavid du Colombier }
238368c31abSDavid du Colombier
239368c31abSDavid du Colombier // read arena header, tail
240368c31abSDavid du Colombier blk = vtmalloc(HeadSize);
241368c31abSDavid du Colombier if(readpart(p, start, blk, HeadSize) != HeadSize){
242368c31abSDavid du Colombier hprint(&c->hout, "reading header: %r\n");
243368c31abSDavid du Colombier vtfree(blk);
244368c31abSDavid du Colombier goto out;
245368c31abSDavid du Colombier }
246368c31abSDavid du Colombier if(unpackarenahead(&head, blk) < 0){
247368c31abSDavid du Colombier hprint(&c->hout, "corrupt arena header: %r\n");
248368c31abSDavid du Colombier // hhex(blk, HeadSize);
249368c31abSDavid du Colombier vtfree(blk);
250368c31abSDavid du Colombier goto out;
251368c31abSDavid du Colombier }
252368c31abSDavid du Colombier vtfree(blk);
253368c31abSDavid du Colombier
254368c31abSDavid du Colombier hprint(&c->hout, "head:\n<pre>\n");
255368c31abSDavid du Colombier hprint(&c->hout, "version=%d name=%s blocksize=%d size=%#llx clumpmagic=%#ux\n",
256368c31abSDavid du Colombier head.version, head.name, head.blocksize, head.size,
257368c31abSDavid du Colombier head.clumpmagic);
258368c31abSDavid du Colombier hprint(&c->hout, "</pre><br><br>\n");
259368c31abSDavid du Colombier
260368c31abSDavid du Colombier if(head.blocksize > MaxIoSize || head.blocksize >= end - start){
261368c31abSDavid du Colombier hprint(&c->hout, "corrupt block size %d\n", head.blocksize);
262368c31abSDavid du Colombier goto out;
263368c31abSDavid du Colombier }
264368c31abSDavid du Colombier
265368c31abSDavid du Colombier blk = vtmalloc(head.blocksize);
266368c31abSDavid du Colombier if(readpart(p, end - head.blocksize, blk, head.blocksize) < 0){
267368c31abSDavid du Colombier hprint(&c->hout, "reading tail: %r\n");
268368c31abSDavid du Colombier vtfree(blk);
269368c31abSDavid du Colombier goto out;
270368c31abSDavid du Colombier }
271368c31abSDavid du Colombier memset(&arena, 0, sizeof arena);
272368c31abSDavid du Colombier arena.part = p;
273368c31abSDavid du Colombier arena.blocksize = head.blocksize;
274368c31abSDavid du Colombier arena.clumpmax = head.blocksize / ClumpInfoSize;
275368c31abSDavid du Colombier arena.base = start + head.blocksize;
276368c31abSDavid du Colombier arena.size = end - start - 2 * head.blocksize;
277368c31abSDavid du Colombier if(unpackarena(&arena, blk) < 0){
278368c31abSDavid du Colombier vtfree(blk);
279368c31abSDavid du Colombier goto out;
280368c31abSDavid du Colombier }
281368c31abSDavid du Colombier scorecp(arena.score, blk+head.blocksize - VtScoreSize);
282368c31abSDavid du Colombier
283368c31abSDavid du Colombier vtfree(blk);
284368c31abSDavid du Colombier
285368c31abSDavid du Colombier hprint(&c->hout, "tail:\n<pre>\n");
286368c31abSDavid du Colombier hprint(&c->hout, "version=%d name=%s\n", arena.version, arena.name);
287368c31abSDavid du Colombier hprint(&c->hout, "ctime=%d %s\n", arena.ctime, fmttime(tbuf, arena.ctime));
288368c31abSDavid du Colombier hprint(&c->hout, "wtime=%d %s\n", arena.wtime, fmttime(tbuf, arena.wtime));
289368c31abSDavid du Colombier hprint(&c->hout, "clumpmagic=%#ux\n", arena.clumpmagic);
290368c31abSDavid du Colombier hprint(&c->hout, "score %V\n", arena.score);
291368c31abSDavid du Colombier hprint(&c->hout, "diskstats:\n");
292368c31abSDavid du Colombier hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n",
293368c31abSDavid du Colombier arena.diskstats.clumps, arena.diskstats.cclumps,
294368c31abSDavid du Colombier arena.diskstats.used, arena.diskstats.uncsize,
295368c31abSDavid du Colombier arena.diskstats.sealed);
296368c31abSDavid du Colombier hprint(&c->hout, "memstats:\n");
297368c31abSDavid du Colombier hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n",
298368c31abSDavid du Colombier arena.memstats.clumps, arena.memstats.cclumps,
299368c31abSDavid du Colombier arena.memstats.used, arena.memstats.uncsize,
300368c31abSDavid du Colombier arena.memstats.sealed);
301368c31abSDavid du Colombier if(arena.clumpmax == 0){
302368c31abSDavid du Colombier hprint(&c->hout, "bad clumpmax\n");
303368c31abSDavid du Colombier goto out;
304368c31abSDavid du Colombier }
305368c31abSDavid du Colombier
306368c31abSDavid du Colombier score = hargstr(c, "score", "");
307368c31abSDavid du Colombier clump = hargstr(c, "clump", "");
308368c31abSDavid du Colombier
309368c31abSDavid du Colombier if(clump[0]){
310368c31abSDavid du Colombier off = strtoull(clump, 0, 0);
311368c31abSDavid du Colombier diskarenaclump(c, &arena, off, score[0] ? score : nil);
312368c31abSDavid du Colombier }else if(score[0]){
313368c31abSDavid du Colombier diskarenaclump(c, &arena, -1, score);
314368c31abSDavid du Colombier }else{
315368c31abSDavid du Colombier diskarenatoc(c, &arena);
316368c31abSDavid du Colombier }
317368c31abSDavid du Colombier
318368c31abSDavid du Colombier out:
319368c31abSDavid du Colombier free(table);
320368c31abSDavid du Colombier return 0;
321368c31abSDavid du Colombier }
322368c31abSDavid du Colombier
323368c31abSDavid du Colombier static vlong
findintoc(HConnect * c,Arena * arena,uchar * score)324368c31abSDavid du Colombier findintoc(HConnect *c, Arena *arena, uchar *score)
325368c31abSDavid du Colombier {
326368c31abSDavid du Colombier uchar *blk;
327368c31abSDavid du Colombier int i;
328368c31abSDavid du Colombier vlong off;
329368c31abSDavid du Colombier vlong coff;
330368c31abSDavid du Colombier ClumpInfo ci;
331368c31abSDavid du Colombier
332368c31abSDavid du Colombier blk = vtmalloc(arena->blocksize);
333368c31abSDavid du Colombier off = arena->base + arena->size;
334368c31abSDavid du Colombier coff = 0;
335368c31abSDavid du Colombier for(i=0; i<arena->memstats.clumps; i++){
336368c31abSDavid du Colombier if(i%arena->clumpmax == 0){
337368c31abSDavid du Colombier off -= arena->blocksize;
338368c31abSDavid du Colombier if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){
339368c31abSDavid du Colombier if(c)
340368c31abSDavid du Colombier hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n",
341368c31abSDavid du Colombier off);
342368c31abSDavid du Colombier break;
343368c31abSDavid du Colombier }
344368c31abSDavid du Colombier }
345368c31abSDavid du Colombier unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize);
346368c31abSDavid du Colombier if(scorecmp(ci.score, score) == 0){
347368c31abSDavid du Colombier vtfree(blk);
348368c31abSDavid du Colombier return coff;
349368c31abSDavid du Colombier }
350368c31abSDavid du Colombier coff += ClumpSize + ci.size;
351368c31abSDavid du Colombier }
352368c31abSDavid du Colombier vtfree(blk);
353368c31abSDavid du Colombier return -1;
354368c31abSDavid du Colombier }
355368c31abSDavid du Colombier
356368c31abSDavid du Colombier
357368c31abSDavid du Colombier static int
diskarenatoc(HConnect * c,Arena * arena)358368c31abSDavid du Colombier diskarenatoc(HConnect *c, Arena *arena)
359368c31abSDavid du Colombier {
360368c31abSDavid du Colombier uchar *blk;
361368c31abSDavid du Colombier int i;
362368c31abSDavid du Colombier vlong off;
363368c31abSDavid du Colombier vlong coff;
364368c31abSDavid du Colombier ClumpInfo ci;
365368c31abSDavid du Colombier char base[512];
366368c31abSDavid du Colombier int cib;
367368c31abSDavid du Colombier
368368c31abSDavid du Colombier snprint(base, sizeof base, "/disk?disk=%s&type=a&arena=%s",
369368c31abSDavid du Colombier arena->part->name, arena->name);
370368c31abSDavid du Colombier
371368c31abSDavid du Colombier blk = vtmalloc(arena->blocksize);
372368c31abSDavid du Colombier off = arena->base + arena->size;
373368c31abSDavid du Colombier hprint(&c->hout, "<h2>table of contents</h2>\n");
374368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
375368c31abSDavid du Colombier hprint(&c->hout, "%5s %6s %7s %s\n", "type", "size", "uncsize", "score");
376368c31abSDavid du Colombier coff = 0;
377368c31abSDavid du Colombier cib = hargint(c, "cib", 0);
378368c31abSDavid du Colombier
379368c31abSDavid du Colombier for(i=0; i<arena->memstats.clumps; i++){
380368c31abSDavid du Colombier if(i%arena->clumpmax == 0){
381368c31abSDavid du Colombier off -= arena->blocksize;
382368c31abSDavid du Colombier if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){
383368c31abSDavid du Colombier hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n",
384368c31abSDavid du Colombier off);
385368c31abSDavid du Colombier i += arena->clumpmax-1;
386368c31abSDavid du Colombier coff = -1;
387368c31abSDavid du Colombier continue;
388368c31abSDavid du Colombier }
389368c31abSDavid du Colombier }
390368c31abSDavid du Colombier unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize);
391368c31abSDavid du Colombier if(i/arena->clumpmax == cib || i%arena->clumpmax == 0){
392368c31abSDavid du Colombier hprint(&c->hout, "%5d %6d %7d %V",
393368c31abSDavid du Colombier ci.type, ci.size, ci.uncsize, ci.score);
394368c31abSDavid du Colombier if(coff >= 0)
395368c31abSDavid du Colombier hprint(&c->hout, " at <a href=\"%s&clump=%#llx&score=%V\">%#llx</a>",
396368c31abSDavid du Colombier base, coff, ci.score, coff);
397368c31abSDavid du Colombier if(i/arena->clumpmax != cib)
398368c31abSDavid du Colombier hprint(&c->hout, " <font size=-1><a href=\"%s&cib=%d\">more</a></font>", base, i/arena->clumpmax);
399368c31abSDavid du Colombier hprint(&c->hout, "\n");
400368c31abSDavid du Colombier }
401368c31abSDavid du Colombier if(coff >= 0)
402368c31abSDavid du Colombier coff += ClumpSize + ci.size;
403368c31abSDavid du Colombier }
404368c31abSDavid du Colombier hprint(&c->hout, "</pre>\n");
405368c31abSDavid du Colombier return 0;
406368c31abSDavid du Colombier }
407368c31abSDavid du Colombier
408368c31abSDavid du Colombier #define U32GET(p) ((u32int)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
409368c31abSDavid du Colombier static int
diskarenaclump(HConnect * c,Arena * arena,vlong off,char * scorestr)410368c31abSDavid du Colombier diskarenaclump(HConnect *c, Arena *arena, vlong off, char *scorestr)
411368c31abSDavid du Colombier {
412368c31abSDavid du Colombier uchar *blk, *blk2;
413368c31abSDavid du Colombier Clump cl;
414368c31abSDavid du Colombier char err[ERRMAX];
415368c31abSDavid du Colombier uchar xscore[VtScoreSize], score[VtScoreSize];
416368c31abSDavid du Colombier Unwhack uw;
417368c31abSDavid du Colombier int n;
418368c31abSDavid du Colombier
419368c31abSDavid du Colombier if(scorestr){
420368c31abSDavid du Colombier if(vtparsescore(scorestr, nil, score) < 0){
421368c31abSDavid du Colombier hprint(&c->hout, "bad score %s: %r\n", scorestr);
422368c31abSDavid du Colombier return -1;
423368c31abSDavid du Colombier }
424368c31abSDavid du Colombier if(off < 0){
425368c31abSDavid du Colombier off = findintoc(c, arena, score);
426368c31abSDavid du Colombier if(off < 0){
427368c31abSDavid du Colombier hprint(&c->hout, "score %V not found in arena %s\n", score, arena->name);
428368c31abSDavid du Colombier return -1;
429368c31abSDavid du Colombier }
430368c31abSDavid du Colombier hprint(&c->hout, "score %V at %#llx\n", score, off);
431368c31abSDavid du Colombier }
432368c31abSDavid du Colombier }else
433368c31abSDavid du Colombier memset(score, 0, sizeof score);
434368c31abSDavid du Colombier
435368c31abSDavid du Colombier if(off < 0){
436368c31abSDavid du Colombier hprint(&c->hout, "bad offset %#llx\n", off);
437368c31abSDavid du Colombier return -1;
438368c31abSDavid du Colombier }
439368c31abSDavid du Colombier
440368c31abSDavid du Colombier off += arena->base;
441368c31abSDavid du Colombier
442368c31abSDavid du Colombier blk = vtmalloc(ClumpSize + VtMaxLumpSize);
443368c31abSDavid du Colombier if(readpart(arena->part, off, blk, ClumpSize + VtMaxLumpSize) != ClumpSize + VtMaxLumpSize){
444368c31abSDavid du Colombier hprint(&c->hout, "reading at %#llx: %r\n", off);
445368c31abSDavid du Colombier vtfree(blk);
446368c31abSDavid du Colombier return -1;
447368c31abSDavid du Colombier }
448368c31abSDavid du Colombier
449368c31abSDavid du Colombier if(unpackclump(&cl, blk, arena->clumpmagic) < 0){
450368c31abSDavid du Colombier hprint(&c->hout, "unpackclump: %r\n<br>");
451368c31abSDavid du Colombier rerrstr(err, sizeof err);
452368c31abSDavid du Colombier if(strstr(err, "magic")){
453368c31abSDavid du Colombier hprint(&c->hout, "trying again with magic=%#ux<br>\n", U32GET(blk));
454368c31abSDavid du Colombier if(unpackclump(&cl, blk, U32GET(blk)) < 0){
455368c31abSDavid du Colombier hprint(&c->hout, "unpackclump: %r\n<br>\n");
456368c31abSDavid du Colombier goto error;
457368c31abSDavid du Colombier }
458368c31abSDavid du Colombier }else
459368c31abSDavid du Colombier goto error;
460368c31abSDavid du Colombier }
461368c31abSDavid du Colombier
462368c31abSDavid du Colombier hprint(&c->hout, "<pre>type=%d size=%d uncsize=%d score=%V\n", cl.info.type, cl.info.size, cl.info.uncsize, cl.info.score);
463368c31abSDavid du Colombier hprint(&c->hout, "encoding=%d creator=%d time=%d %s</pre>\n", cl.encoding, cl.creator, cl.time, fmttime(err, cl.time));
464368c31abSDavid du Colombier
465368c31abSDavid du Colombier if(cl.info.type == VtCorruptType)
466368c31abSDavid du Colombier hprint(&c->hout, "clump is marked corrupt<br>\n");
467368c31abSDavid du Colombier
468368c31abSDavid du Colombier if(cl.info.size >= VtMaxLumpSize){
469368c31abSDavid du Colombier hprint(&c->hout, "clump too big\n");
470368c31abSDavid du Colombier goto error;
471368c31abSDavid du Colombier }
472368c31abSDavid du Colombier
473368c31abSDavid du Colombier switch(cl.encoding){
474368c31abSDavid du Colombier case ClumpECompress:
475368c31abSDavid du Colombier blk2 = vtmalloc(VtMaxLumpSize);
476368c31abSDavid du Colombier unwhackinit(&uw);
477368c31abSDavid du Colombier n = unwhack(&uw, blk2, cl.info.uncsize, blk+ClumpSize, cl.info.size);
478368c31abSDavid du Colombier if(n < 0){
479368c31abSDavid du Colombier hprint(&c->hout, "decompression failed\n");
480368c31abSDavid du Colombier vtfree(blk2);
481368c31abSDavid du Colombier goto error;
482368c31abSDavid du Colombier }
483368c31abSDavid du Colombier if(n != cl.info.uncsize){
484368c31abSDavid du Colombier hprint(&c->hout, "got wrong amount: %d wanted %d\n", n, cl.info.uncsize);
485368c31abSDavid du Colombier // hhex(blk2, n);
486368c31abSDavid du Colombier vtfree(blk2);
487368c31abSDavid du Colombier goto error;
488368c31abSDavid du Colombier }
489368c31abSDavid du Colombier scoremem(xscore, blk2, cl.info.uncsize);
490368c31abSDavid du Colombier vtfree(blk2);
491368c31abSDavid du Colombier break;
492368c31abSDavid du Colombier case ClumpENone:
493368c31abSDavid du Colombier scoremem(xscore, blk+ClumpSize, cl.info.size);
494368c31abSDavid du Colombier break;
495368c31abSDavid du Colombier }
496368c31abSDavid du Colombier
497368c31abSDavid du Colombier hprint(&c->hout, "score=%V<br>\n", xscore);
498368c31abSDavid du Colombier if(scorestr && scorecmp(score, xscore) != 0)
499368c31abSDavid du Colombier hprint(&c->hout, "score does NOT match expected %V\n", score);
500368c31abSDavid du Colombier
501368c31abSDavid du Colombier vtfree(blk);
502368c31abSDavid du Colombier return 0;
503368c31abSDavid du Colombier
504368c31abSDavid du Colombier error:
505368c31abSDavid du Colombier // hhex(blk, ClumpSize + VtMaxLumpSize);
506368c31abSDavid du Colombier vtfree(blk);
507368c31abSDavid du Colombier return -1;
508368c31abSDavid du Colombier }
509368c31abSDavid du Colombier
510368c31abSDavid du Colombier static int
diskbloom(HConnect * c,char * disk,Part * p)511368c31abSDavid du Colombier diskbloom(HConnect *c, char *disk, Part *p)
512368c31abSDavid du Colombier {
513368c31abSDavid du Colombier USED(c);
514368c31abSDavid du Colombier USED(disk);
515368c31abSDavid du Colombier USED(p);
516368c31abSDavid du Colombier return 0;
517368c31abSDavid du Colombier }
518368c31abSDavid du Colombier
519368c31abSDavid du Colombier static int
diskisect(HConnect * c,char * disk,Part * p)520368c31abSDavid du Colombier diskisect(HConnect *c, char *disk, Part *p)
521368c31abSDavid du Colombier {
522368c31abSDavid du Colombier USED(c);
523368c31abSDavid du Colombier USED(disk);
524368c31abSDavid du Colombier USED(p);
525368c31abSDavid du Colombier return 0;
526368c31abSDavid du Colombier }
527368c31abSDavid du Colombier
528368c31abSDavid du Colombier static void
debugamap(HConnect * c)529368c31abSDavid du Colombier debugamap(HConnect *c)
530368c31abSDavid du Colombier {
531368c31abSDavid du Colombier int i;
532368c31abSDavid du Colombier AMap *amap;
533368c31abSDavid du Colombier
534368c31abSDavid du Colombier hprint(&c->hout, "<h2>arena map</h2>\n");
535368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
536368c31abSDavid du Colombier
537368c31abSDavid du Colombier amap = mainindex->amap;
538368c31abSDavid du Colombier for(i=0; i<mainindex->narenas; i++)
539368c31abSDavid du Colombier hprint(&c->hout, "%s %#llx %#llx\n",
540368c31abSDavid du Colombier amap[i].name, amap[i].start, amap[i].stop);
541368c31abSDavid du Colombier }
542368c31abSDavid du Colombier
543368c31abSDavid du Colombier static void
debugread(HConnect * c,u8int * score)544368c31abSDavid du Colombier debugread(HConnect *c, u8int *score)
545368c31abSDavid du Colombier {
546368c31abSDavid du Colombier int type;
547368c31abSDavid du Colombier Lump *u;
548368c31abSDavid du Colombier IAddr ia;
549368c31abSDavid du Colombier IEntry ie;
550*f9e1cf08SDavid du Colombier int i;
551368c31abSDavid du Colombier Arena *arena;
552368c31abSDavid du Colombier u64int aa;
553368c31abSDavid du Colombier ZBlock *zb;
554368c31abSDavid du Colombier Clump cl;
555368c31abSDavid du Colombier vlong off;
556368c31abSDavid du Colombier u8int sc[VtScoreSize];
557368c31abSDavid du Colombier
558368c31abSDavid du Colombier if(scorecmp(score, zeroscore) == 0){
559368c31abSDavid du Colombier hprint(&c->hout, "zero score\n");
560368c31abSDavid du Colombier return;
561368c31abSDavid du Colombier }
562368c31abSDavid du Colombier
563368c31abSDavid du Colombier hprint(&c->hout, "<h2>index search %V</h2><pre>\n", score);
564*f9e1cf08SDavid du Colombier if(icachelookup(score, -1, &ia) < 0)
565368c31abSDavid du Colombier hprint(&c->hout, " icache: not found\n");
566368c31abSDavid du Colombier else
567368c31abSDavid du Colombier hprint(&c->hout, " icache: addr=%#llx size=%d type=%d blocks=%d\n",
568368c31abSDavid du Colombier ia.addr, ia.size, ia.type, ia.blocks);
569368c31abSDavid du Colombier
570368c31abSDavid du Colombier if(loadientry(mainindex, score, -1, &ie) < 0)
571368c31abSDavid du Colombier hprint(&c->hout, " idisk: not found\n");
572368c31abSDavid du Colombier else
573368c31abSDavid du Colombier hprint(&c->hout, " idisk: addr=%#llx size=%d type=%d blocks=%d\n",
574368c31abSDavid du Colombier ie.ia.addr, ie.ia.size, ie.ia.type, ie.ia.blocks);
575368c31abSDavid du Colombier
576368c31abSDavid du Colombier hprint(&c->hout, "</pre><h2>lookup %V</h2>\n", score);
577368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
578368c31abSDavid du Colombier
579368c31abSDavid du Colombier for(type=0; type < VtMaxType; type++){
580368c31abSDavid du Colombier hprint(&c->hout, "%V type %d:", score, type);
581368c31abSDavid du Colombier u = lookuplump(score, type);
582368c31abSDavid du Colombier if(u->data != nil)
583368c31abSDavid du Colombier hprint(&c->hout, " +cache");
584368c31abSDavid du Colombier else
585368c31abSDavid du Colombier hprint(&c->hout, " -cache");
586368c31abSDavid du Colombier putlump(u);
587368c31abSDavid du Colombier
588*f9e1cf08SDavid du Colombier if(lookupscore(score, type, &ia) < 0){
589368c31abSDavid du Colombier hprint(&c->hout, " -lookup\n");
590368c31abSDavid du Colombier continue;
591368c31abSDavid du Colombier }
592*f9e1cf08SDavid du Colombier hprint(&c->hout, "\n lookupscore: addr=%#llx size=%d blocks=%d\n",
593*f9e1cf08SDavid du Colombier ia.addr, ia.size, ia.blocks);
594368c31abSDavid du Colombier
595368c31abSDavid du Colombier arena = amapitoa(mainindex, ia.addr, &aa);
596368c31abSDavid du Colombier if(arena == nil){
597368c31abSDavid du Colombier hprint(&c->hout, " amapitoa failed: %r\n");
598368c31abSDavid du Colombier continue;
599368c31abSDavid du Colombier }
600368c31abSDavid du Colombier
601368c31abSDavid du Colombier hprint(&c->hout, " amapitoa: aa=%#llx arena="
602368c31abSDavid du Colombier "<a href=\"/disk?disk=%s&type=a&arena=%s&score=%V\">%s</a>\n",
603368c31abSDavid du Colombier aa, arena->part->name, arena->name, score, arena->name);
604368c31abSDavid du Colombier zb = loadclump(arena, aa, ia.blocks, &cl, sc, 1);
605368c31abSDavid du Colombier if(zb == nil){
606368c31abSDavid du Colombier hprint(&c->hout, " loadclump failed: %r\n");
607368c31abSDavid du Colombier continue;
608368c31abSDavid du Colombier }
609368c31abSDavid du Colombier
610368c31abSDavid du Colombier hprint(&c->hout, " loadclump: uncsize=%d type=%d score=%V\n",
611368c31abSDavid du Colombier cl.info.uncsize, cl.info.type, sc);
612368c31abSDavid du Colombier if(ia.size != cl.info.uncsize || ia.type != cl.info.type || scorecmp(score, sc) != 0){
613368c31abSDavid du Colombier hprint(&c->hout, " clump info mismatch\n");
614368c31abSDavid du Colombier continue;
615368c31abSDavid du Colombier }
616368c31abSDavid du Colombier }
617368c31abSDavid du Colombier
618368c31abSDavid du Colombier if(hargstr(c, "brute", "")[0] == 'y'){
619368c31abSDavid du Colombier hprint(&c->hout, "</pre>\n");
620368c31abSDavid du Colombier hprint(&c->hout, "<h2>brute force arena search %V</h2>\n", score);
621368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
622368c31abSDavid du Colombier
623368c31abSDavid du Colombier for(i=0; i<mainindex->narenas; i++){
624368c31abSDavid du Colombier arena = mainindex->arenas[i];
625368c31abSDavid du Colombier hprint(&c->hout, "%s...\n", arena->name);
626368c31abSDavid du Colombier hflush(&c->hout);
627368c31abSDavid du Colombier off = findintoc(nil, arena, score);
628368c31abSDavid du Colombier if(off >= 0)
629368c31abSDavid du Colombier hprint(&c->hout, "%s %#llx (%#llx)\n", arena->name, off, mainindex->amap[i].start + off);
630368c31abSDavid du Colombier }
631368c31abSDavid du Colombier }
632368c31abSDavid du Colombier
633368c31abSDavid du Colombier hprint(&c->hout, "</pre>\n");
634368c31abSDavid du Colombier }
635368c31abSDavid du Colombier
636368c31abSDavid du Colombier static void
debugmem(HConnect * c)637368c31abSDavid du Colombier debugmem(HConnect *c)
638368c31abSDavid du Colombier {
639368c31abSDavid du Colombier Index *ix;
640368c31abSDavid du Colombier
641368c31abSDavid du Colombier ix = mainindex;
642368c31abSDavid du Colombier hprint(&c->hout, "<h2>memory</h2>\n");
643368c31abSDavid du Colombier
644368c31abSDavid du Colombier hprint(&c->hout, "<pre>\n");
645368c31abSDavid du Colombier hprint(&c->hout, "ix=%p\n", ix);
646368c31abSDavid du Colombier hprint(&c->hout, "\tarenas=%p\n", ix->arenas);
647368c31abSDavid du Colombier if(ix->narenas > 0)
648368c31abSDavid du Colombier hprint(&c->hout, "\tarenas[...] = %p...%p\n", ix->arenas[0], ix->arenas[ix->narenas-1]);
649368c31abSDavid du Colombier hprint(&c->hout, "\tsmap=%p\n", ix->smap);
650368c31abSDavid du Colombier hprint(&c->hout, "\tamap=%p\n", ix->amap);
651368c31abSDavid du Colombier hprint(&c->hout, "\tbloom=%p\n", ix->bloom);
652368c31abSDavid du Colombier hprint(&c->hout, "\tbloom->data=%p\n", ix->bloom ? ix->bloom->data : nil);
653368c31abSDavid du Colombier hprint(&c->hout, "\tisects=%p\n", ix->sects);
654368c31abSDavid du Colombier if(ix->nsects > 0)
655368c31abSDavid du Colombier hprint(&c->hout, "\tsects[...] = %p...%p\n", ix->sects[0], ix->sects[ix->nsects-1]);
656368c31abSDavid du Colombier }
657368c31abSDavid du Colombier
658368c31abSDavid du Colombier int
hdebug(HConnect * c)659368c31abSDavid du Colombier hdebug(HConnect *c)
660368c31abSDavid du Colombier {
661368c31abSDavid du Colombier char *scorestr, *op;
662368c31abSDavid du Colombier u8int score[VtScoreSize];
663368c31abSDavid du Colombier
664368c31abSDavid du Colombier if(hsethtml(c) < 0)
665368c31abSDavid du Colombier return -1;
666368c31abSDavid du Colombier hprint(&c->hout, "<h1>venti debug</h1>\n");
667368c31abSDavid du Colombier
668368c31abSDavid du Colombier op = hargstr(c, "op", "");
669368c31abSDavid du Colombier if(!op[0]){
670368c31abSDavid du Colombier hprint(&c->hout, "no op\n");
671368c31abSDavid du Colombier return 0;
672368c31abSDavid du Colombier }
673368c31abSDavid du Colombier
674368c31abSDavid du Colombier if(strcmp(op, "amap") == 0){
675368c31abSDavid du Colombier debugamap(c);
676368c31abSDavid du Colombier return 0;
677368c31abSDavid du Colombier }
678368c31abSDavid du Colombier
679368c31abSDavid du Colombier if(strcmp(op, "mem") == 0){
680368c31abSDavid du Colombier debugmem(c);
681368c31abSDavid du Colombier return 0;
682368c31abSDavid du Colombier }
683368c31abSDavid du Colombier
684368c31abSDavid du Colombier if(strcmp(op, "read") == 0){
685368c31abSDavid du Colombier scorestr = hargstr(c, "score", "");
686368c31abSDavid du Colombier if(vtparsescore(scorestr, nil, score) < 0){
687368c31abSDavid du Colombier hprint(&c->hout, "bad score %s: %r\n", scorestr);
688368c31abSDavid du Colombier return 0;
689368c31abSDavid du Colombier }
690368c31abSDavid du Colombier debugread(c, score);
691368c31abSDavid du Colombier return 0;
692368c31abSDavid du Colombier }
693368c31abSDavid du Colombier
694368c31abSDavid du Colombier hprint(&c->hout, "unknown op %s", op);
695368c31abSDavid du Colombier return 0;
696368c31abSDavid du Colombier }
697