aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/srv/wrarena.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/venti/srv/wrarena.c')
-rw-r--r--src/cmd/venti/srv/wrarena.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/src/cmd/venti/srv/wrarena.c b/src/cmd/venti/srv/wrarena.c
new file mode 100644
index 00000000..4b8358ca
--- /dev/null
+++ b/src/cmd/venti/srv/wrarena.c
@@ -0,0 +1,217 @@
+#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;
+
+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);
+ 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)
+{
+ u64int a, aa, e;
+ u32int magic;
+ Clump cl;
+ uchar score[VtScoreSize];
+ 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 %llud >= %llud\n",
+ offset, e-a);
+ aa = offset;
+ } else
+ aa = 0;
+
+ if(maxwrites != 0)
+ for(; aa < e; aa += ClumpSize+cl.info.size) {
+ magic = clumpmagic(arena, aa);
+ if(magic == ClumpFreeMagic)
+ break;
+ if(magic != arena->clumpmagic) {
+ // fprint(2, "illegal clump magic number %#8.8ux offset %llud\n",
+ // magic, aa);
+ break;
+ }
+ lump = loadclump(arena, aa, 0, &cl, score, 0);
+ if(lump == nil) {
+ fprint(2, "clump %llud failed to read: %r\n", aa);
+ break;
+ }
+ if(!fast && cl.info.type != VtCorruptType) {
+ scoremem(score, lump->data, cl.info.uncsize);
+ if(scorecmp(cl.info.score, score) != 0) {
+ fprint(2, "clump %llud has mismatched score\n", aa);
+ break;
+ }
+ if(vttypevalid(cl.info.type) < 0) {
+ fprint(2, "clump %llud has bad type %d\n", aa, cl.info.type);
+ break;
+ }
+ }
+ if(z && cl.info.type != VtCorruptType){
+ zcl.cl = cl;
+ zcl.lump = lump;
+ zcl.aa = aa;
+ send(c, &zcl);
+ }else
+ freezblock(lump);
+ if(maxwrites>0 && --maxwrites == 0)
+ break;
+ }
+ if(haveaoffset)
+ print("end offset %llud\n", aa);
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ int i;
+ char *file;
+ Arena *arena;
+ u64int offset, aoffset;
+ Part *part;
+ Dir *d;
+ uchar buf[8192];
+ ArenaHead head;
+ ZClump zerocl;
+
+ 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;
+ 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();
+
+ if((d = dirstat(file)) == nil)
+ sysfatal("can't stat file %s: %r", file);
+
+ 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 > d->length)
+ sysfatal("arena is truncated: want %llud bytes have %llud\n",
+ head.size, d->length);
+
+ partblocksize(part, head.blocksize);
+ initdcache(8 * MaxDiskBlock);
+
+ arena = initarena(part, aoffset, head.size, head.blocksize);
+ if(arena == nil)
+ sysfatal("initarena: %r");
+
+ if(host && 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");
+ }else
+ z = nil;
+
+ 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);
+}