hdisk.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "stdinc.h"
  10. #include "dat.h"
  11. #include "fns.h"
  12. #include "whack.h"
  13. static int disksummary(HConnect*);
  14. static int diskarenapart(HConnect*, char*, Part*);
  15. static int diskbloom(HConnect*, char*, Part*);
  16. static int diskisect(HConnect*, char*, Part*);
  17. int
  18. hdisk(HConnect *c)
  19. {
  20. char *disk, *type;
  21. Part *p;
  22. int ret;
  23. if(hsethtml(c) < 0)
  24. return -1;
  25. disk = hargstr(c, "disk", "");
  26. if(!disk[0])
  27. return disksummary(c);
  28. if((p = initpart(disk, OREAD)) == nil){
  29. hprint(&c->hout, "open %s: %r", disk);
  30. return 0;
  31. }
  32. type = hargstr(c, "type", "");
  33. switch(type[0]){
  34. case 'a':
  35. ret = diskarenapart(c, disk, p);
  36. break;
  37. case 'b':
  38. ret = diskbloom(c, disk, p);
  39. break;
  40. case 'i':
  41. ret = diskisect(c, disk, p);
  42. break;
  43. default:
  44. hprint(&c->hout, "unknown disk type %s", type);
  45. return 0;
  46. }
  47. freepart(p);
  48. return ret;
  49. }
  50. static int
  51. disksummary(HConnect *c)
  52. {
  53. int i;
  54. Index *ix;
  55. Part *p;
  56. hprint(&c->hout, "<h1>venti disks</h1>\n");
  57. hprint(&c->hout, "<pre>\n");
  58. ix = mainindex;
  59. p = nil;
  60. for(i=0; i<ix->narenas; i++){
  61. if(ix->arenas[i]->part == p)
  62. continue;
  63. p = ix->arenas[i]->part;
  64. hprint(&c->hout, "<a href=\"/disk?disk=%s&type=a\">%s</a> %s\n", p->name, p->name, ix->arenas[i]->name);
  65. }
  66. hprint(&c->hout, "\n");
  67. p = nil;
  68. for(i=0; i<ix->nsects; i++){
  69. if(ix->sects[i]->part == p)
  70. continue;
  71. p = ix->sects[i]->part;
  72. hprint(&c->hout, "<a href=\"/disk?disk=%s&type=i\">%s</a> %s\n", p->name, p->name, ix->sects[i]->name);
  73. }
  74. hprint(&c->hout, "\n");
  75. if(ix->bloom){
  76. p = ix->bloom->part;
  77. hprint(&c->hout, "<a href=\"/disk?disk=%s&type=b\">%s</a> %s\n", p->name, p->name, "bloom filter");
  78. }
  79. return 0;
  80. }
  81. static char*
  82. readap(Part *p, ArenaPart *ap)
  83. {
  84. uint8_t *blk;
  85. char *table;
  86. blk = vtmalloc(8192);
  87. if(readpart(p, PartBlank, blk, 8192) != 8192)
  88. return nil;
  89. if(unpackarenapart(ap, blk) < 0){
  90. werrstr("corrupt arena part header: %r");
  91. return nil;
  92. }
  93. vtfree(blk);
  94. ap->tabbase = (PartBlank+HeadSize+ap->blocksize-1)&~(ap->blocksize-1);
  95. ap->tabsize = ap->arenabase - ap->tabbase;
  96. table = vtmalloc(ap->tabsize+1);
  97. if(readpart(p, ap->tabbase, (uint8_t*)table, ap->tabsize) != ap->tabsize){
  98. werrstr("reading arena part directory: %r");
  99. return nil;
  100. }
  101. table[ap->tabsize] = 0;
  102. return table;
  103. }
  104. static int
  105. xfindarena(char *table, char *name, int64_t *start, int64_t *end)
  106. {
  107. int i, nline;
  108. char *p, *q, *f[4], line[256];
  109. nline = atoi(table);
  110. p = strchr(table, '\n');
  111. if(p)
  112. p++;
  113. for(i=0; i<nline; i++){
  114. if(p == nil)
  115. break;
  116. q = strchr(p, '\n');
  117. if(q)
  118. *q++ = 0;
  119. if(strlen(p) >= sizeof line){
  120. p = q;
  121. continue;
  122. }
  123. strcpy(line, p);
  124. memset(f, 0, sizeof f);
  125. if(tokenize(line, f, nelem(f)) < 3){
  126. p = q;
  127. continue;
  128. }
  129. if(strcmp(f[0], name) == 0){
  130. *start = strtoull(f[1], 0, 0);
  131. *end = strtoull(f[2], 0, 0);
  132. return 0;
  133. }
  134. p = q;
  135. }
  136. return -1;
  137. }
  138. static void
  139. diskarenatable(HConnect *c, char *disk, char *table)
  140. {
  141. char *p, *q;
  142. int i, nline;
  143. char *f[4], line[256], base[256];
  144. hprint(&c->hout, "<h2>table</h2>\n");
  145. hprint(&c->hout, "<pre>\n");
  146. nline = atoi(table);
  147. snprint(base, sizeof base, "/disk?disk=%s&type=a", disk);
  148. p = strchr(table, '\n');
  149. if(p)
  150. p++;
  151. for(i=0; i<nline; i++){
  152. if(p == nil){
  153. hprint(&c->hout, "<b><i>unexpected end of table</i></b>\n");
  154. break;
  155. }
  156. q = strchr(p, '\n');
  157. if(q)
  158. *q++ = 0;
  159. if(strlen(p) >= sizeof line){
  160. hprint(&c->hout, "%s\n", p);
  161. p = q;
  162. continue;
  163. }
  164. strcpy(line, p);
  165. memset(f, 0, sizeof f);
  166. if(tokenize(line, f, 3) < 3){
  167. hprint(&c->hout, "%s\n", p);
  168. p = q;
  169. continue;
  170. }
  171. p = q;
  172. hprint(&c->hout, "<a href=\"%s&arena=%s\">%s</a> %s %s\n",
  173. base, f[0], f[0], f[1], f[2]);
  174. }
  175. hprint(&c->hout, "</pre>\n");
  176. }
  177. static char*
  178. fmttime(char *buf, uint32_t time)
  179. {
  180. strcpy(buf, ctime(time));
  181. buf[28] = 0;
  182. return buf;
  183. }
  184. static int diskarenaclump(HConnect*, Arena*, int64_t, char*);
  185. static int diskarenatoc(HConnect*, Arena*);
  186. static int
  187. diskarenapart(HConnect *c, char *disk, Part *p)
  188. {
  189. char *arenaname;
  190. ArenaPart ap;
  191. ArenaHead head;
  192. Arena arena;
  193. char *table;
  194. char *score;
  195. char *clump;
  196. uint8_t *blk;
  197. int64_t start, end, off;
  198. char tbuf[60];
  199. hprint(&c->hout, "<h1>arena partition %s</h1>\n", disk);
  200. if((table = readap(p, &ap)) == nil){
  201. hprint(&c->hout, "%r\n");
  202. goto out;
  203. }
  204. hprint(&c->hout, "<pre>\n");
  205. hprint(&c->hout, "version=%d blocksize=%d base=%d\n",
  206. ap.version, ap.blocksize, ap.arenabase);
  207. hprint(&c->hout, "</pre>\n");
  208. arenaname = hargstr(c, "arena", "");
  209. if(arenaname[0] == 0){
  210. diskarenatable(c, disk, table);
  211. goto out;
  212. }
  213. if(xfindarena(table, arenaname, &start, &end) < 0){
  214. hprint(&c->hout, "no such arena %s\n", arenaname);
  215. goto out;
  216. }
  217. hprint(&c->hout, "<h2>arena %s</h2>\n", arenaname);
  218. hprint(&c->hout, "<pre>start=%#llx end=%#llx<pre>\n", start, end);
  219. if(end < start || end - start < HeadSize){
  220. hprint(&c->hout, "bad size %#llx\n", end - start);
  221. goto out;
  222. }
  223. // read arena header, tail
  224. blk = vtmalloc(HeadSize);
  225. if(readpart(p, start, blk, HeadSize) != HeadSize){
  226. hprint(&c->hout, "reading header: %r\n");
  227. vtfree(blk);
  228. goto out;
  229. }
  230. if(unpackarenahead(&head, blk) < 0){
  231. hprint(&c->hout, "corrupt arena header: %r\n");
  232. // hhex(blk, HeadSize);
  233. vtfree(blk);
  234. goto out;
  235. }
  236. vtfree(blk);
  237. hprint(&c->hout, "head:\n<pre>\n");
  238. hprint(&c->hout, "version=%d name=%s blocksize=%d size=%#llx clumpmagic=%#x\n",
  239. head.version, head.name, head.blocksize, head.size,
  240. head.clumpmagic);
  241. hprint(&c->hout, "</pre><br><br>\n");
  242. if(head.blocksize > MaxIoSize || head.blocksize >= end - start){
  243. hprint(&c->hout, "corrupt block size %d\n", head.blocksize);
  244. goto out;
  245. }
  246. blk = vtmalloc(head.blocksize);
  247. if(readpart(p, end - head.blocksize, blk, head.blocksize) < 0){
  248. hprint(&c->hout, "reading tail: %r\n");
  249. vtfree(blk);
  250. goto out;
  251. }
  252. memset(&arena, 0, sizeof arena);
  253. arena.part = p;
  254. arena.blocksize = head.blocksize;
  255. arena.clumpmax = head.blocksize / ClumpInfoSize;
  256. arena.base = start + head.blocksize;
  257. arena.size = end - start - 2 * head.blocksize;
  258. if(unpackarena(&arena, blk) < 0){
  259. vtfree(blk);
  260. goto out;
  261. }
  262. scorecp(arena.score, blk+head.blocksize - VtScoreSize);
  263. vtfree(blk);
  264. hprint(&c->hout, "tail:\n<pre>\n");
  265. hprint(&c->hout, "version=%d name=%s\n", arena.version, arena.name);
  266. hprint(&c->hout, "ctime=%d %s\n", arena.ctime, fmttime(tbuf, arena.ctime));
  267. hprint(&c->hout, "wtime=%d %s\n", arena.wtime, fmttime(tbuf, arena.wtime));
  268. hprint(&c->hout, "clumpmagic=%#x\n", arena.clumpmagic);
  269. hprint(&c->hout, "score %V\n", arena.score);
  270. hprint(&c->hout, "diskstats:\n");
  271. hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n",
  272. arena.diskstats.clumps, arena.diskstats.cclumps,
  273. arena.diskstats.used, arena.diskstats.uncsize,
  274. arena.diskstats.sealed);
  275. hprint(&c->hout, "memstats:\n");
  276. hprint(&c->hout, "\tclumps=%,d cclumps=%,d used=%,lld uncsize=%,lld sealed=%d\n",
  277. arena.memstats.clumps, arena.memstats.cclumps,
  278. arena.memstats.used, arena.memstats.uncsize,
  279. arena.memstats.sealed);
  280. if(arena.clumpmax == 0){
  281. hprint(&c->hout, "bad clumpmax\n");
  282. goto out;
  283. }
  284. score = hargstr(c, "score", "");
  285. clump = hargstr(c, "clump", "");
  286. if(clump[0]){
  287. off = strtoull(clump, 0, 0);
  288. diskarenaclump(c, &arena, off, score[0] ? score : nil);
  289. }else if(score[0]){
  290. diskarenaclump(c, &arena, -1, score);
  291. }else{
  292. diskarenatoc(c, &arena);
  293. }
  294. out:
  295. free(table);
  296. return 0;
  297. }
  298. static int64_t
  299. findintoc(HConnect *c, Arena *arena, uint8_t *score)
  300. {
  301. uint8_t *blk;
  302. int i;
  303. int64_t off;
  304. int64_t coff;
  305. ClumpInfo ci;
  306. blk = vtmalloc(arena->blocksize);
  307. off = arena->base + arena->size;
  308. coff = 0;
  309. for(i=0; i<arena->memstats.clumps; i++){
  310. if(i%arena->clumpmax == 0){
  311. off -= arena->blocksize;
  312. if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){
  313. if(c)
  314. hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n",
  315. off);
  316. break;
  317. }
  318. }
  319. unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize);
  320. if(scorecmp(ci.score, score) == 0){
  321. vtfree(blk);
  322. return coff;
  323. }
  324. coff += ClumpSize + ci.size;
  325. }
  326. vtfree(blk);
  327. return -1;
  328. }
  329. static int
  330. diskarenatoc(HConnect *c, Arena *arena)
  331. {
  332. uint8_t *blk;
  333. int i;
  334. int64_t off;
  335. int64_t coff;
  336. ClumpInfo ci;
  337. char base[512];
  338. int cib;
  339. snprint(base, sizeof base, "/disk?disk=%s&type=a&arena=%s",
  340. arena->part->name, arena->name);
  341. blk = vtmalloc(arena->blocksize);
  342. off = arena->base + arena->size;
  343. hprint(&c->hout, "<h2>table of contents</h2>\n");
  344. hprint(&c->hout, "<pre>\n");
  345. hprint(&c->hout, "%5s %6s %7s %s\n", "type", "size", "uncsize", "score");
  346. coff = 0;
  347. cib = hargint(c, "cib", 0);
  348. for(i=0; i<arena->memstats.clumps; i++){
  349. if(i%arena->clumpmax == 0){
  350. off -= arena->blocksize;
  351. if(readpart(arena->part, off, blk, arena->blocksize) != arena->blocksize){
  352. hprint(&c->hout, "<i>clump info directory at %#llx: %r</i>\n<br>\n",
  353. off);
  354. i += arena->clumpmax-1;
  355. coff = -1;
  356. continue;
  357. }
  358. }
  359. unpackclumpinfo(&ci, blk+(i%arena->clumpmax)*ClumpInfoSize);
  360. if(i/arena->clumpmax == cib || i%arena->clumpmax == 0){
  361. hprint(&c->hout, "%5d %6d %7d %V",
  362. ci.type, ci.size, ci.uncsize, ci.score);
  363. if(coff >= 0)
  364. hprint(&c->hout, " at <a href=\"%s&clump=%#llx&score=%V\">%#llx</a>",
  365. base, coff, ci.score, coff);
  366. if(i/arena->clumpmax != cib)
  367. hprint(&c->hout, " <font size=-1><a href=\"%s&cib=%d\">more</a></font>", base, i/arena->clumpmax);
  368. hprint(&c->hout, "\n");
  369. }
  370. if(coff >= 0)
  371. coff += ClumpSize + ci.size;
  372. }
  373. hprint(&c->hout, "</pre>\n");
  374. return 0;
  375. }
  376. #define U32GET(p) ((uint32_t)(((p)[0]<<24)|((p)[1]<<16)|((p)[2]<<8)|(p)[3]))
  377. static int
  378. diskarenaclump(HConnect *c, Arena *arena, int64_t off, char *scorestr)
  379. {
  380. uint8_t *blk, *blk2;
  381. Clump cl;
  382. char err[ERRMAX];
  383. uint8_t xscore[VtScoreSize], score[VtScoreSize];
  384. Unwhack uw;
  385. int n;
  386. if(scorestr){
  387. if(vtparsescore(scorestr, nil, score) < 0){
  388. hprint(&c->hout, "bad score %s: %r\n", scorestr);
  389. return -1;
  390. }
  391. if(off < 0){
  392. off = findintoc(c, arena, score);
  393. if(off < 0){
  394. hprint(&c->hout, "score %V not found in arena %s\n", score, arena->name);
  395. return -1;
  396. }
  397. hprint(&c->hout, "score %V at %#llx\n", score, off);
  398. }
  399. }else
  400. memset(score, 0, sizeof score);
  401. if(off < 0){
  402. hprint(&c->hout, "bad offset %#llx\n", off);
  403. return -1;
  404. }
  405. off += arena->base;
  406. blk = vtmalloc(ClumpSize + VtMaxLumpSize);
  407. if(readpart(arena->part, off, blk, ClumpSize + VtMaxLumpSize) != ClumpSize + VtMaxLumpSize){
  408. hprint(&c->hout, "reading at %#llx: %r\n", off);
  409. vtfree(blk);
  410. return -1;
  411. }
  412. if(unpackclump(&cl, blk, arena->clumpmagic) < 0){
  413. hprint(&c->hout, "unpackclump: %r\n<br>");
  414. rerrstr(err, sizeof err);
  415. if(strstr(err, "magic")){
  416. hprint(&c->hout, "trying again with magic=%#x<br>\n", U32GET(blk));
  417. if(unpackclump(&cl, blk, U32GET(blk)) < 0){
  418. hprint(&c->hout, "unpackclump: %r\n<br>\n");
  419. goto error;
  420. }
  421. }else
  422. goto error;
  423. }
  424. 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);
  425. hprint(&c->hout, "encoding=%d creator=%d time=%d %s</pre>\n", cl.encoding, cl.creator, cl.time, fmttime(err, cl.time));
  426. if(cl.info.type == VtCorruptType)
  427. hprint(&c->hout, "clump is marked corrupt<br>\n");
  428. if(cl.info.size >= VtMaxLumpSize){
  429. hprint(&c->hout, "clump too big\n");
  430. goto error;
  431. }
  432. switch(cl.encoding){
  433. case ClumpECompress:
  434. blk2 = vtmalloc(VtMaxLumpSize);
  435. unwhackinit(&uw);
  436. n = unwhack(&uw, blk2, cl.info.uncsize, blk+ClumpSize, cl.info.size);
  437. if(n < 0){
  438. hprint(&c->hout, "decompression failed\n");
  439. vtfree(blk2);
  440. goto error;
  441. }
  442. if(n != cl.info.uncsize){
  443. hprint(&c->hout, "got wrong amount: %d wanted %d\n", n, cl.info.uncsize);
  444. // hhex(blk2, n);
  445. vtfree(blk2);
  446. goto error;
  447. }
  448. scoremem(xscore, blk2, cl.info.uncsize);
  449. vtfree(blk2);
  450. break;
  451. case ClumpENone:
  452. scoremem(xscore, blk+ClumpSize, cl.info.size);
  453. break;
  454. }
  455. hprint(&c->hout, "score=%V<br>\n", xscore);
  456. if(scorestr && scorecmp(score, xscore) != 0)
  457. hprint(&c->hout, "score does NOT match expected %V\n", score);
  458. vtfree(blk);
  459. return 0;
  460. error:
  461. // hhex(blk, ClumpSize + VtMaxLumpSize);
  462. vtfree(blk);
  463. return -1;
  464. }
  465. static int
  466. diskbloom(HConnect *c, char *disk, Part *p)
  467. {
  468. USED(c);
  469. USED(disk);
  470. USED(p);
  471. return 0;
  472. }
  473. static int
  474. diskisect(HConnect *c, char *disk, Part *p)
  475. {
  476. USED(c);
  477. USED(disk);
  478. USED(p);
  479. return 0;
  480. }
  481. static void
  482. debugamap(HConnect *c)
  483. {
  484. int i;
  485. AMap *amap;
  486. hprint(&c->hout, "<h2>arena map</h2>\n");
  487. hprint(&c->hout, "<pre>\n");
  488. amap = mainindex->amap;
  489. for(i=0; i<mainindex->narenas; i++)
  490. hprint(&c->hout, "%s %#llx %#llx\n",
  491. amap[i].name, amap[i].start, amap[i].stop);
  492. }
  493. static void
  494. debugread(HConnect *c, uint8_t *score)
  495. {
  496. int type;
  497. Lump *u;
  498. IAddr ia;
  499. IEntry ie;
  500. int i;
  501. Arena *arena;
  502. uint64_t aa;
  503. ZBlock *zb;
  504. Clump cl;
  505. int64_t off;
  506. uint8_t sc[VtScoreSize];
  507. if(scorecmp(score, zeroscore) == 0){
  508. hprint(&c->hout, "zero score\n");
  509. return;
  510. }
  511. hprint(&c->hout, "<h2>index search %V</h2><pre>\n", score);
  512. if(icachelookup(score, -1, &ia) < 0)
  513. hprint(&c->hout, " icache: not found\n");
  514. else
  515. hprint(&c->hout, " icache: addr=%#llx size=%d type=%d blocks=%d\n",
  516. ia.addr, ia.size, ia.type, ia.blocks);
  517. if(loadientry(mainindex, score, -1, &ie) < 0)
  518. hprint(&c->hout, " idisk: not found\n");
  519. else
  520. hprint(&c->hout, " idisk: addr=%#llx size=%d type=%d blocks=%d\n",
  521. ie.ia.addr, ie.ia.size, ie.ia.type, ie.ia.blocks);
  522. hprint(&c->hout, "</pre><h2>lookup %V</h2>\n", score);
  523. hprint(&c->hout, "<pre>\n");
  524. for(type=0; type < VtMaxType; type++){
  525. hprint(&c->hout, "%V type %d:", score, type);
  526. u = lookuplump(score, type);
  527. if(u->data != nil)
  528. hprint(&c->hout, " +cache");
  529. else
  530. hprint(&c->hout, " -cache");
  531. putlump(u);
  532. if(lookupscore(score, type, &ia) < 0){
  533. hprint(&c->hout, " -lookup\n");
  534. continue;
  535. }
  536. hprint(&c->hout, "\n lookupscore: addr=%#llx size=%d blocks=%d\n",
  537. ia.addr, ia.size, ia.blocks);
  538. arena = amapitoa(mainindex, ia.addr, &aa);
  539. if(arena == nil){
  540. hprint(&c->hout, " amapitoa failed: %r\n");
  541. continue;
  542. }
  543. hprint(&c->hout, " amapitoa: aa=%#llx arena="
  544. "<a href=\"/disk?disk=%s&type=a&arena=%s&score=%V\">%s</a>\n",
  545. aa, arena->part->name, arena->name, score, arena->name);
  546. zb = loadclump(arena, aa, ia.blocks, &cl, sc, 1);
  547. if(zb == nil){
  548. hprint(&c->hout, " loadclump failed: %r\n");
  549. continue;
  550. }
  551. hprint(&c->hout, " loadclump: uncsize=%d type=%d score=%V\n",
  552. cl.info.uncsize, cl.info.type, sc);
  553. if(ia.size != cl.info.uncsize || ia.type != cl.info.type || scorecmp(score, sc) != 0){
  554. hprint(&c->hout, " clump info mismatch\n");
  555. continue;
  556. }
  557. }
  558. if(hargstr(c, "brute", "")[0] == 'y'){
  559. hprint(&c->hout, "</pre>\n");
  560. hprint(&c->hout, "<h2>brute force arena search %V</h2>\n", score);
  561. hprint(&c->hout, "<pre>\n");
  562. for(i=0; i<mainindex->narenas; i++){
  563. arena = mainindex->arenas[i];
  564. hprint(&c->hout, "%s...\n", arena->name);
  565. hflush(&c->hout);
  566. off = findintoc(nil, arena, score);
  567. if(off >= 0)
  568. hprint(&c->hout, "%s %#llx (%#llx)\n", arena->name, off, mainindex->amap[i].start + off);
  569. }
  570. }
  571. hprint(&c->hout, "</pre>\n");
  572. }
  573. static void
  574. debugmem(HConnect *c)
  575. {
  576. Index *ix;
  577. ix = mainindex;
  578. hprint(&c->hout, "<h2>memory</h2>\n");
  579. hprint(&c->hout, "<pre>\n");
  580. hprint(&c->hout, "ix=%p\n", ix);
  581. hprint(&c->hout, "\tarenas=%p\n", ix->arenas);
  582. if(ix->narenas > 0)
  583. hprint(&c->hout, "\tarenas[...] = %p...%p\n", ix->arenas[0], ix->arenas[ix->narenas-1]);
  584. hprint(&c->hout, "\tsmap=%p\n", ix->smap);
  585. hprint(&c->hout, "\tamap=%p\n", ix->amap);
  586. hprint(&c->hout, "\tbloom=%p\n", ix->bloom);
  587. hprint(&c->hout, "\tbloom->data=%p\n", ix->bloom ? ix->bloom->data : nil);
  588. hprint(&c->hout, "\tisects=%p\n", ix->sects);
  589. if(ix->nsects > 0)
  590. hprint(&c->hout, "\tsects[...] = %p...%p\n", ix->sects[0], ix->sects[ix->nsects-1]);
  591. }
  592. int
  593. hdebug(HConnect *c)
  594. {
  595. char *scorestr, *op;
  596. uint8_t score[VtScoreSize];
  597. if(hsethtml(c) < 0)
  598. return -1;
  599. hprint(&c->hout, "<h1>venti debug</h1>\n");
  600. op = hargstr(c, "op", "");
  601. if(!op[0]){
  602. hprint(&c->hout, "no op\n");
  603. return 0;
  604. }
  605. if(strcmp(op, "amap") == 0){
  606. debugamap(c);
  607. return 0;
  608. }
  609. if(strcmp(op, "mem") == 0){
  610. debugmem(c);
  611. return 0;
  612. }
  613. if(strcmp(op, "read") == 0){
  614. scorestr = hargstr(c, "score", "");
  615. if(vtparsescore(scorestr, nil, score) < 0){
  616. hprint(&c->hout, "bad score %s: %r\n", scorestr);
  617. return 0;
  618. }
  619. debugread(c, score);
  620. return 0;
  621. }
  622. hprint(&c->hout, "unknown op %s", op);
  623. return 0;
  624. }