123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- #include "stdinc.h"
- #include "dat.h"
- #include "fns.h"
- QLock godot;
- char *host;
- int readonly = 1; /* for part.c */
- int mainstacksize = 256*1024;
- Channel *c;
- VtConn *z;
- int fast; /* and a bit unsafe; only for benchmarking */
- int haveaoffset;
- int maxwrites = -1;
- int verbose;
- typedef struct ZClump ZClump;
- struct ZClump
- {
- ZBlock *lump;
- Clump cl;
- u64int aa;
- };
- void
- usage(void)
- {
- fprint(2, "usage: wrarena [-h host] arenafile [offset]\n");
- threadexitsall("usage");
- }
- void
- vtsendthread(void *v)
- {
- ZClump zcl;
- USED(v);
- while(recv(c, &zcl) == 1){
- if(zcl.lump == nil)
- break;
- if(vtwrite(z, zcl.cl.info.score, zcl.cl.info.type, zcl.lump->data, zcl.cl.info.uncsize) < 0)
- sysfatal("failed writing clump %llud: %r", zcl.aa);
- if(verbose)
- print("%V\n", zcl.cl.info.score);
- freezblock(zcl.lump);
- }
- /*
- * All the send threads try to exit right when
- * threadmain is calling threadexitsall.
- * Either libthread or the Linux NPTL pthreads library
- * can't handle this condition (I suspect NPTL but have
- * not confirmed this) and we get a seg fault in exit.
- * I spent a day tracking this down with no success,
- * so we're going to work around it instead by just
- * sitting here and waiting for the threadexitsall to
- * take effect.
- */
- qlock(&godot);
- }
- static void
- rdarena(Arena *arena, u64int offset)
- {
- int i;
- u64int a, aa, e;
- uchar score[VtScoreSize];
- Clump cl;
- ClumpInfo ci;
- ZBlock *lump;
- ZClump zcl;
- fprint(2, "wrarena: copying %s to venti\n", arena->name);
- printarena(2, arena);
- a = arena->base;
- e = arena->base + arena->size;
- if(offset != ~(u64int)0) {
- if(offset >= e - a)
- sysfatal("bad offset %#llx >= %#llx", offset, e - a);
- aa = offset;
- } else
- aa = 0;
- i = 0;
- for(a = 0; maxwrites != 0 && i < arena->memstats.clumps;
- a += ClumpSize + ci.size){
- if(readclumpinfo(arena, i++, &ci) < 0)
- break;
- if(a < aa || ci.type == VtCorruptType){
- if(ci.type == VtCorruptType)
- fprint(2, "%s: corrupt clump read at %#llx: +%d\n",
- argv0, a, ClumpSize+ci.size);
- continue;
- }
- lump = loadclump(arena, a, 0, &cl, score, 0);
- if(lump == nil) {
- fprint(2, "clump %#llx failed to read: %r\n", a);
- continue;
- }
- if(!fast && cl.info.type != VtCorruptType) {
- scoremem(score, lump->data, cl.info.uncsize);
- if(scorecmp(cl.info.score, score) != 0) {
- fprint(2, "clump %#llx has mismatched score\n",
- a);
- break;
- }
- if(vttypevalid(cl.info.type) < 0) {
- fprint(2, "clump %#llx has bad type %d\n",
- a, cl.info.type);
- break;
- }
- }
- if(z && cl.info.type != VtCorruptType){
- zcl.cl = cl;
- zcl.lump = lump;
- zcl.aa = a;
- send(c, &zcl);
- }else
- freezblock(lump);
- if(maxwrites > 0)
- --maxwrites;
- }
- if(a > aa)
- aa = a;
- if(haveaoffset)
- print("end offset %#llx\n", aa);
- }
- void
- threadmain(int argc, char *argv[])
- {
- int i;
- char *file;
- Arena *arena;
- u64int offset, aoffset;
- Part *part;
- uchar buf[8192];
- ArenaHead head;
- ZClump zerocl;
- ventifmtinstall();
- qlock(&godot);
- aoffset = 0;
- ARGBEGIN{
- case 'f':
- fast = 1;
- ventidoublechecksha1 = 0;
- break;
- case 'h':
- host = EARGF(usage());
- break;
- case 'o':
- haveaoffset = 1;
- aoffset = strtoull(EARGF(usage()), 0, 0);
- break;
- case 'M':
- maxwrites = atoi(EARGF(usage()));
- break;
- case 'v':
- verbose = 1;
- break;
- default:
- usage();
- break;
- }ARGEND
- offset = ~(u64int)0;
- switch(argc) {
- default:
- usage();
- case 2:
- offset = strtoull(argv[1], 0, 0);
- /* fall through */
- case 1:
- file = argv[0];
- }
- fmtinstall('V', vtscorefmt);
- statsinit();
- part = initpart(file, OREAD);
- if(part == nil)
- sysfatal("can't open file %s: %r", file);
- if(readpart(part, aoffset, buf, sizeof buf) < 0)
- sysfatal("can't read file %s: %r", file);
- if(unpackarenahead(&head, buf) < 0)
- sysfatal("corrupted arena header: %r");
- if(aoffset+head.size > part->size)
- sysfatal("arena is truncated: want %llud bytes have %llud",
- head.size, part->size);
- partblocksize(part, head.blocksize);
- initdcache(8 * MaxDiskBlock);
- arena = initarena(part, aoffset, head.size, head.blocksize);
- if(arena == nil)
- sysfatal("initarena: %r");
- z = nil;
- if(host==nil || strcmp(host, "/dev/null") != 0){
- z = vtdial(host);
- if(z == nil)
- sysfatal("could not connect to server: %r");
- if(vtconnect(z) < 0)
- sysfatal("vtconnect: %r");
- }
-
- c = chancreate(sizeof(ZClump), 0);
- for(i=0; i<12; i++)
- vtproc(vtsendthread, nil);
- rdarena(arena, offset);
- if(vtsync(z) < 0)
- sysfatal("executing sync: %r");
- memset(&zerocl, 0, sizeof zerocl);
- for(i=0; i<12; i++)
- send(c, &zerocl);
- if(z){
- vthangup(z);
- }
- threadexitsall(0);
- }
|