wrarena.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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", 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, "%s: corrupt clump read at %#llx: +%d\n",
  82. argv0, 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. ventifmtinstall();
  130. qlock(&godot);
  131. aoffset = 0;
  132. ARGBEGIN{
  133. case 'f':
  134. fast = 1;
  135. ventidoublechecksha1 = 0;
  136. break;
  137. case 'h':
  138. host = EARGF(usage());
  139. break;
  140. case 'o':
  141. haveaoffset = 1;
  142. aoffset = strtoull(EARGF(usage()), 0, 0);
  143. break;
  144. case 'M':
  145. maxwrites = atoi(EARGF(usage()));
  146. break;
  147. case 'v':
  148. verbose = 1;
  149. break;
  150. default:
  151. usage();
  152. break;
  153. }ARGEND
  154. offset = ~(u64int)0;
  155. switch(argc) {
  156. default:
  157. usage();
  158. case 2:
  159. offset = strtoull(argv[1], 0, 0);
  160. /* fall through */
  161. case 1:
  162. file = argv[0];
  163. }
  164. fmtinstall('V', vtscorefmt);
  165. statsinit();
  166. part = initpart(file, OREAD);
  167. if(part == nil)
  168. sysfatal("can't open file %s: %r", file);
  169. if(readpart(part, aoffset, buf, sizeof buf) < 0)
  170. sysfatal("can't read file %s: %r", file);
  171. if(unpackarenahead(&head, buf) < 0)
  172. sysfatal("corrupted arena header: %r");
  173. if(aoffset+head.size > part->size)
  174. sysfatal("arena is truncated: want %llud bytes have %llud",
  175. head.size, part->size);
  176. partblocksize(part, head.blocksize);
  177. initdcache(8 * MaxDiskBlock);
  178. arena = initarena(part, aoffset, head.size, head.blocksize);
  179. if(arena == nil)
  180. sysfatal("initarena: %r");
  181. z = nil;
  182. if(host==nil || strcmp(host, "/dev/null") != 0){
  183. z = vtdial(host);
  184. if(z == nil)
  185. sysfatal("could not connect to server: %r");
  186. if(vtconnect(z) < 0)
  187. sysfatal("vtconnect: %r");
  188. }
  189. c = chancreate(sizeof(ZClump), 0);
  190. for(i=0; i<12; i++)
  191. vtproc(vtsendthread, nil);
  192. rdarena(arena, offset);
  193. if(vtsync(z) < 0)
  194. sysfatal("executing sync: %r");
  195. memset(&zerocl, 0, sizeof zerocl);
  196. for(i=0; i<12; i++)
  197. send(c, &zerocl);
  198. if(z){
  199. vthangup(z);
  200. }
  201. threadexitsall(0);
  202. }