wrarena.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. QLock godot;
  5. char *host;
  6. int readonly = 1; /* for part.c */
  7. int mainstacksize = 256*1024;
  8. Channel *c;
  9. VtConn *z;
  10. int fast; /* and a bit unsafe; only for benchmarking */
  11. int haveaoffset;
  12. int maxwrites = -1;
  13. int verbose;
  14. typedef struct ZClump ZClump;
  15. struct ZClump
  16. {
  17. ZBlock *lump;
  18. Clump cl;
  19. u64int aa;
  20. };
  21. void
  22. usage(void)
  23. {
  24. fprint(2, "usage: wrarena [-h host] arenafile [offset]\n");
  25. threadexitsall("usage");
  26. }
  27. void
  28. vtsendthread(void *v)
  29. {
  30. ZClump zcl;
  31. USED(v);
  32. while(recv(c, &zcl) == 1){
  33. if(zcl.lump == nil)
  34. break;
  35. if(vtwrite(z, zcl.cl.info.score, zcl.cl.info.type, zcl.lump->data, zcl.cl.info.uncsize) < 0)
  36. sysfatal("failed writing clump %llud: %r", zcl.aa);
  37. if(verbose)
  38. print("%V\n", zcl.cl.info.score);
  39. freezblock(zcl.lump);
  40. }
  41. /*
  42. * All the send threads try to exit right when
  43. * threadmain is calling threadexitsall.
  44. * Either libthread or the Linux NPTL pthreads library
  45. * can't handle this condition (I suspect NPTL but have
  46. * not confirmed this) and we get a seg fault in exit.
  47. * I spent a day tracking this down with no success,
  48. * so we're going to work around it instead by just
  49. * sitting here and waiting for the threadexitsall to
  50. * take effect.
  51. */
  52. qlock(&godot);
  53. }
  54. static void
  55. rdarena(Arena *arena, u64int offset)
  56. {
  57. int i;
  58. u64int a, aa, e;
  59. uchar score[VtScoreSize];
  60. Clump cl;
  61. ClumpInfo ci;
  62. ZBlock *lump;
  63. ZClump zcl;
  64. fprint(2, "wrarena: copying %s to venti\n", arena->name);
  65. printarena(2, arena);
  66. a = arena->base;
  67. e = arena->base + arena->size;
  68. if(offset != ~(u64int)0) {
  69. if(offset >= e - a)
  70. sysfatal("bad offset %#llx >= %#llx\n", offset, e - a);
  71. aa = offset;
  72. } else
  73. aa = 0;
  74. i = 0;
  75. for(a = 0; maxwrites != 0 && i < arena->memstats.clumps;
  76. a += ClumpSize + ci.size){
  77. if(readclumpinfo(arena, i++, &ci) < 0)
  78. break;
  79. if(a < aa || ci.type == VtCorruptType){
  80. if(ci.type == VtCorruptType)
  81. fprint(2, "corrupt at %#llx: +%d\n",
  82. a, ClumpSize+ci.size);
  83. continue;
  84. }
  85. lump = loadclump(arena, a, 0, &cl, score, 0);
  86. if(lump == nil) {
  87. fprint(2, "clump %#llx failed to read: %r\n", a);
  88. continue;
  89. }
  90. if(!fast && cl.info.type != VtCorruptType) {
  91. scoremem(score, lump->data, cl.info.uncsize);
  92. if(scorecmp(cl.info.score, score) != 0) {
  93. fprint(2, "clump %#llx has mismatched score\n",
  94. a);
  95. break;
  96. }
  97. if(vttypevalid(cl.info.type) < 0) {
  98. fprint(2, "clump %#llx has bad type %d\n",
  99. a, cl.info.type);
  100. break;
  101. }
  102. }
  103. if(z && cl.info.type != VtCorruptType){
  104. zcl.cl = cl;
  105. zcl.lump = lump;
  106. zcl.aa = a;
  107. send(c, &zcl);
  108. }else
  109. freezblock(lump);
  110. if(maxwrites > 0)
  111. --maxwrites;
  112. }
  113. if(a > aa)
  114. aa = a;
  115. if(haveaoffset)
  116. print("end offset %#llx\n", aa);
  117. }
  118. void
  119. threadmain(int argc, char *argv[])
  120. {
  121. int i;
  122. char *file;
  123. Arena *arena;
  124. u64int offset, aoffset;
  125. Part *part;
  126. uchar buf[8192];
  127. ArenaHead head;
  128. ZClump zerocl;
  129. qlock(&godot);
  130. aoffset = 0;
  131. ARGBEGIN{
  132. case 'f':
  133. fast = 1;
  134. ventidoublechecksha1 = 0;
  135. break;
  136. case 'h':
  137. host = EARGF(usage());
  138. break;
  139. case 'o':
  140. haveaoffset = 1;
  141. aoffset = strtoull(EARGF(usage()), 0, 0);
  142. break;
  143. case 'M':
  144. maxwrites = atoi(EARGF(usage()));
  145. break;
  146. case 'v':
  147. verbose = 1;
  148. break;
  149. default:
  150. usage();
  151. break;
  152. }ARGEND
  153. offset = ~(u64int)0;
  154. switch(argc) {
  155. default:
  156. usage();
  157. case 2:
  158. offset = strtoull(argv[1], 0, 0);
  159. /* fall through */
  160. case 1:
  161. file = argv[0];
  162. }
  163. fmtinstall('V', vtscorefmt);
  164. statsinit();
  165. part = initpart(file, OREAD);
  166. if(part == nil)
  167. sysfatal("can't open file %s: %r", file);
  168. if(readpart(part, aoffset, buf, sizeof buf) < 0)
  169. sysfatal("can't read file %s: %r", file);
  170. if(unpackarenahead(&head, buf) < 0)
  171. sysfatal("corrupted arena header: %r");
  172. if(aoffset+head.size > part->size)
  173. sysfatal("arena is truncated: want %llud bytes have %llud\n",
  174. head.size, part->size);
  175. partblocksize(part, head.blocksize);
  176. initdcache(8 * MaxDiskBlock);
  177. arena = initarena(part, aoffset, head.size, head.blocksize);
  178. if(arena == nil)
  179. sysfatal("initarena: %r");
  180. z = nil;
  181. if(host==nil || strcmp(host, "/dev/null") != 0){
  182. z = vtdial(host);
  183. if(z == nil)
  184. sysfatal("could not connect to server: %r");
  185. if(vtconnect(z) < 0)
  186. sysfatal("vtconnect: %r");
  187. }
  188. c = chancreate(sizeof(ZClump), 0);
  189. for(i=0; i<12; i++)
  190. vtproc(vtsendthread, nil);
  191. rdarena(arena, offset);
  192. if(vtsync(z) < 0)
  193. sysfatal("executing sync: %r");
  194. memset(&zerocl, 0, sizeof zerocl);
  195. for(i=0; i<12; i++)
  196. send(c, &zerocl);
  197. if(z){
  198. vthangup(z);
  199. }
  200. threadexitsall(0);
  201. }