hdisk.c 16 KB

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