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); }
void threadmain(int argc, char *argv[]) { char *host; int dotrunc, n, type; uchar *p, score[VtScoreSize]; VtConn *z; fmtinstall('F', vtfcallfmt); fmtinstall('V', vtscorefmt); host = nil; dotrunc = 0; type = VtDataType; ARGBEGIN{ case 'z': dotrunc = 1; break; case 'h': host = EARGF(usage()); break; case 't': type = atoi(EARGF(usage())); break; default: usage(); break; }ARGEND if(argc != 0) usage(); p = vtmallocz(VtMaxLumpSize+1); n = readn(0, p, VtMaxLumpSize+1); if(n > VtMaxLumpSize) sysfatal("input too big: max block size is %d", VtMaxLumpSize); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); if(dotrunc) n = vtzerotruncate(type, p, n); if(vtwrite(z, score, type, p, n) < 0) sysfatal("vtwrite: %r"); vthangup(z); print("%V\n", score); threadexitsall(0); }
void wr(char *buf, char *buf2) { uint8_t score[VtScoreSize], score2[VtScoreSize]; DigestState ds; USED(buf2); memset(&ds, 0, sizeof ds); if(doublecheck) sha1((uint8_t*)buf, blocksize, score, &ds); if(vtwrite(z, score2, VtDataType, (uint8_t*)buf, blocksize) < 0) sysfatal("vtwrite %V at %,lld: %r", score, cur); if(doublecheck && memcmp(score, score2, VtScoreSize) != 0) sysfatal("score mismatch! %V %V", score, score2); }
void threadmain(int argc, char *argv[]) { uchar score[VtScoreSize]; uchar buf[VtRootSize]; VtConn *z; VtRoot root; ARGBEGIN{ case 'h': host = EARGF(usage()); break; default: usage(); break; }ARGEND if(argc != 5) usage(); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); strecpy(root.name, root.name+sizeof root.name, argv[0]); strecpy(root.type, root.type+sizeof root.type, argv[1]); if(vtparsescore(argv[2], nil, root.score) < 0) sysfatal("bad score '%s'", argv[2]); root.blocksize = atoi(argv[3]); if(vtparsescore(argv[4], nil, root.prev) < 0) sysfatal("bad score '%s'", argv[4]); vtrootpack(&root, buf); z = vtdial(host); if(z == nil) sysfatal("could not connect to server: %r"); if(vtconnect(z) < 0) sysfatal("vtconnect: %r"); if(vtwrite(z, score, VtRootType, buf, VtRootSize) < 0) sysfatal("vtwrite: %r"); if(vtsync(z) < 0) sysfatal("vtsync: %r"); vthangup(z); print("%V\n", score); threadexitsall(0); }
int myvtwrite(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n) { WriteReq wr; if(nwritethread == 0){ n = vtwrite(z, score, type, buf, n); if(n < 0) sysfatal("vtwrite: %r"); return n; } wr.p = packetalloc(); packetappend(wr.p, buf, n); packetsha1(wr.p, score); memmove(wr.score, score, VtScoreSize); wr.type = type; nsend++; send(writechan, &wr); return 0; }
void walk(uint8_t score[VtScoreSize], uint type, int base) { int i, n; uint8_t *buf; uint8_t nscore[VtScoreSize]; VtEntry e; VtRoot root; if(memcmp(score, vtzeroscore, VtScoreSize) == 0 || memcmp(score, zeroscore, VtScoreSize) == 0) return; if(havevisited(score, type)){ nskip++; return; } buf = vtmallocz(VtMaxLumpSize); if(fast && vtread(zdst, score, type, buf, VtMaxLumpSize) >= 0){ if(verbose) fprint(2, "skip %V\n", score); free(buf); return; } n = vtread(zsrc, score, type, buf, VtMaxLumpSize); if(n < 0){ if(rewrite){ changes++; memmove(score, vtzeroscore, VtScoreSize); }else if(!ignoreerrors) sysfatal("reading block %V (type %d): %r", score, type); return; } switch(type){ case VtRootType: if(vtrootunpack(&root, buf) < 0){ fprint(2, "warning: could not unpack root in %V %d\n", score, type); break; } walk(root.prev, VtRootType, 0); walk(root.score, VtDirType, 0); if(rewrite) vtrootpack(&root, buf); /* walk might have changed score */ break; case VtDirType: for(i=0; i*VtEntrySize<n; i++){ if(vtentryunpack(&e, buf, i) < 0){ fprint(2, "warning: could not unpack entry #%d in %V %d\n", i, score, type); continue; } if(!(e.flags & VtEntryActive)) continue; walk(e.score, e.type, e.type&VtTypeBaseMask); /* * Don't repack unless we're rewriting -- some old * vac files have psize==0 and dsize==0, and these * get rewritten by vtentryunpack to have less strange * block sizes. So vtentryunpack; vtentrypack does not * guarantee to preserve the exact bytes in buf. */ if(rewrite) vtentrypack(&e, buf, i); } break; case VtDataType: break; default: /* pointers */ for(i=0; i<n; i+=VtScoreSize) if(memcmp(buf+i, vtzeroscore, VtScoreSize) != 0) walk(buf+i, type-1, base); break; } nwrite++; if(vtwrite(zdst, nscore, type, buf, n) < 0){ /* figure out score for better error message */ /* can't use input argument - might have changed contents */ n = vtzerotruncate(type, buf, n); sha1(buf, n, score, nil); sysfatal("writing block %V (type %d): %r", score, type); } if(!rewrite && memcmp(score, nscore, VtScoreSize) != 0){ fprint(2, "not rewriting: wrote %V got %V\n", score, nscore); abort(); sysfatal("not rewriting: wrote %V got %V", score, nscore); } markvisited(score, type); free(buf); }