changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > ventivac / changeset: venti/copy, copies file/hash trees from one venti server to the other.

changeset 70: 5ed3f84d045b
parent 69: 66d0acdf1366
child 71: 73677062595d
author: Mechiel Lukkien <mechiel@ueber.net>
date: Sat, 14 Jul 2007 12:58:55 +0200
files: appl/cmd/venti/copy.b appl/cmd/venti/mkfile man/1/venti
description: venti/copy, copies file/hash trees from one venti server to the other.

does not correctly copy the current rabin fingerprinted hash trees. vacput -r first needs to write different pointerblocktypes.
     1.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2+++ b/appl/cmd/venti/copy.b	Sat Jul 14 12:58:55 2007 +0200
     1.3@@ -0,0 +1,180 @@
     1.4+implement Venticopy;
     1.5+
     1.6+include "sys.m";
     1.7+	sys: Sys;
     1.8+include "draw.m";
     1.9+include "bufio.m";
    1.10+	bufio: Bufio;
    1.11+	Iobuf: import bufio;
    1.12+include "arg.m";
    1.13+include "string.m";
    1.14+include "venti.m";
    1.15+include "vac.m";
    1.16+
    1.17+str: String;
    1.18+venti: Venti;
    1.19+vac: Vac;
    1.20+
    1.21+print, sprint, fprint, fildes: import sys;
    1.22+Score, Session, Roottype, Dirtype, Datatype, Scoresize: import venti;
    1.23+Root, Rootsize, Entry, Entrysize, Entryactive, Entrydir: import vac;
    1.24+
    1.25+Venticopy: module {
    1.26+	init:	fn(nil: ref Draw->Context, args: list of string);
    1.27+};
    1.28+
    1.29+dflag, fflag: int;
    1.30+session: ref Session;
    1.31+srcs, dsts: ref Session;
    1.32+
    1.33+init(nil: ref Draw->Context, args: list of string)
    1.34+{
    1.35+	sys = load Sys Sys->PATH;
    1.36+	bufio = load Bufio Bufio->PATH;
    1.37+	arg := load Arg Arg->PATH;
    1.38+	str = load String String->PATH;
    1.39+	venti = load Venti Venti->PATH;
    1.40+	vac = load Vac Vac->PATH;
    1.41+	if(venti == nil || vac == nil)
    1.42+		error("loading venti,vac");
    1.43+	venti->init();
    1.44+	vac->init();
    1.45+
    1.46+	arg->init(args);
    1.47+	arg->setusage(sprint("%s [-df] srcaddr dstaddr [vac:]score", arg->progname()));
    1.48+	while((c := arg->opt()) != 0)
    1.49+		case c {
    1.50+		'd' =>	dflag++;
    1.51+			vac->dflag++;
    1.52+		'f' =>	fflag++;
    1.53+		* =>	fprint(fildes(2), "bad option: -%c\n", c);
    1.54+			arg->usage();
    1.55+		}
    1.56+	args = arg->argv();
    1.57+	if(len args != 3)
    1.58+		arg->usage();
    1.59+
    1.60+	srcaddr := hd args;
    1.61+	dstaddr := hd tl args;
    1.62+	args = tl tl args;
    1.63+
    1.64+	(tag, scorestr) := str->splitstrr(hd args, ":");
    1.65+	if(tag != nil)
    1.66+		tag = tag[:len tag-1];
    1.67+	t: int;
    1.68+	case tag {
    1.69+	"vac" =>	t = Roottype;
    1.70+	"entry" =>	t = Dirtype;
    1.71+	* =>	fprint(fildes(2), "bad score type\n");
    1.72+		arg->usage();
    1.73+	}
    1.74+
    1.75+	(sok, score) := Score.parse(scorestr);
    1.76+	if(sok != 0)
    1.77+		error("bad score: "+scorestr);
    1.78+	say("have score");
    1.79+
    1.80+	srcs = dial(srcaddr);
    1.81+	dsts = dial(dstaddr);
    1.82+
    1.83+	walk(score, t, 0);
    1.84+	say("have walk");
    1.85+
    1.86+	if(dsts.sync() < 0)
    1.87+		error(sprint("syncing destination: %r"));
    1.88+	say("synced");
    1.89+}
    1.90+
    1.91+walk(s: Score, t, dt: int)
    1.92+{
    1.93+	say(sprint("walk: %s/%d", s.text(), t));
    1.94+
    1.95+	if(fflag && dsts.read(s, t, Venti->Maxlumpsize) != nil) {
    1.96+		say(sprint("skipping %s/%d", s.text(), t));
    1.97+		return;
    1.98+	}
    1.99+
   1.100+	d := srcs.read(s, t, Venti->Maxlumpsize);
   1.101+	if(d == nil)
   1.102+		error(sprint("reading %s/%d: %r", s.text(), t));
   1.103+
   1.104+	case t {
   1.105+	Roottype =>
   1.106+		r := Root.unpack(d);
   1.107+		if(r == nil)
   1.108+			error(sprint("bad root: %r"));
   1.109+		walk(r.score, Dirtype, 0);
   1.110+		if(!isnul(*r.prev))
   1.111+			walk(*r.prev, Roottype, 0);
   1.112+
   1.113+	Dirtype =>
   1.114+		for(o := 0; o+Entrysize <= len d; o += Entrysize) {
   1.115+			e := Entry.unpack(d[o:o+Entrysize]);
   1.116+			if(e == nil)
   1.117+				error(sprint("bad entry: %r"));
   1.118+			if(!(e.flags&Entryactive))
   1.119+				continue;
   1.120+			nt := Datatype;
   1.121+			if(e.flags&Entrydir)
   1.122+				nt = Dirtype;
   1.123+			if(e.depth == 0)
   1.124+				walk(e.score, nt, 0);
   1.125+			else
   1.126+				walk(e.score, Venti->Pointertype0-1+e.depth, nt);
   1.127+		}
   1.128+		
   1.129+	Datatype =>
   1.130+		;
   1.131+
   1.132+	* =>
   1.133+		for(o := 0; o+Scoresize <= len d; o += Scoresize) {
   1.134+			ns := Score(d[o:o+Scoresize]);
   1.135+			if(ns.eq(Score.zero()))
   1.136+				continue;
   1.137+			nt := t-1;
   1.138+			if(t == Venti->Pointertype0)
   1.139+				nt = dt;
   1.140+			walk(ns, nt, dt);
   1.141+		}
   1.142+	}
   1.143+	
   1.144+	(ok, ns) := dsts.write(t, d);
   1.145+	if(ok < 0)
   1.146+		error(sprint("writing %s/%d: %r", ns.text(), t));
   1.147+	if(!ns.eq(s))
   1.148+		error(sprint("destination returned different score: %s versus %s", s.text(), ns.text()));
   1.149+}
   1.150+
   1.151+isnul(s: Score): int
   1.152+{
   1.153+	for(i := 0; i < len s.a; i++)
   1.154+		if(s.a[i] != byte 0)
   1.155+			return 0;
   1.156+	return 1;
   1.157+}
   1.158+
   1.159+dial(addr: string): ref Session
   1.160+{
   1.161+	(cok, conn) := sys->dial(addr, nil);
   1.162+	if(cok < 0)
   1.163+		error(sprint("dialing %s: %r", addr));
   1.164+	say("have connection");
   1.165+
   1.166+	session = Session.new(conn.dfd);
   1.167+	if(session == nil)
   1.168+		error(sprint("handshake: %r"));
   1.169+	say("have handshake");
   1.170+	return session;
   1.171+}
   1.172+
   1.173+error(s: string)
   1.174+{
   1.175+	fprint(fildes(2), "%s\n", s);
   1.176+	raise "fail:"+s;
   1.177+}
   1.178+
   1.179+say(s: string)
   1.180+{
   1.181+	if(dflag)
   1.182+		fprint(fildes(2), "%s\n", s);
   1.183+}
     2.1--- a/appl/cmd/venti/mkfile	Sat Jul 14 11:59:07 2007 +0200
     2.2+++ b/appl/cmd/venti/mkfile	Sat Jul 14 12:58:55 2007 +0200
     2.3@@ -5,6 +5,7 @@
     2.4 	ping.dis\
     2.5 	get.dis\
     2.6 	put.dis\
     2.7+	copy.dis\
     2.8 
     2.9 SYSMODULES=\
    2.10 	arg.m\
     3.1--- a/man/1/venti	Sat Jul 14 11:59:07 2007 +0200
     3.2+++ b/man/1/venti	Sat Jul 14 12:58:55 2007 +0200
     3.3@@ -1,6 +1,6 @@
     3.4 .TH VENTI 1
     3.5 .SH NAME
     3.6-venti/sync, venti/ping, venti/get, venti/put \- venti utilities
     3.7+venti/sync, venti/ping, venti/get, venti/put, venti/copy \- venti utilities
     3.8 .SH SYNOPSIS
     3.9 .B venti/sync
    3.10 [
    3.11@@ -40,6 +40,14 @@
    3.12 .I addr
    3.13 ]
    3.14 .I entry:score
    3.15+.br
    3.16+.B venti/copy
    3.17+[
    3.18+.B -df
    3.19+]
    3.20+.I srcaddr
    3.21+.I dstaddr
    3.22+.I tag:score
    3.23 .SH DESCRIPTION
    3.24 .I Venti/sync 
    3.25 sends a sync messages to a venti server.  When it returns, the venti server has flushed its data to stable storage.
    3.26@@ -51,16 +59,37 @@
    3.27 .PP
    3.28 .I Venti/put
    3.29 reads data from standard input and writes it to venti.  When done, the score of the resulting venti entry is printed.
    3.30+.PP
    3.31 .I Venti/get
    3.32 reads the data from the venti entry referenced by
    3.33 .I score
    3.34 and writes it to standard output.
    3.35 .PP
    3.36+.I Venti/copy
    3.37+copies the file tree referenced by
    3.38+.I tag:score
    3.39+from 
    3.40+.I srcaddr
    3.41+to
    3.42+.IR dstaddr .
    3.43+.I Tag
    3.44+can be either
    3.45+.I vac
    3.46+or
    3.47+.IR entry .
    3.48+.PP
    3.49 The options the programs understand are:
    3.50 .TP
    3.51 .B -d
    3.52 Print debug messages.
    3.53 .TP
    3.54+.B -f
    3.55+Only copy score that
    3.56+.I dstaddr
    3.57+does not yet have.  When a score is present, all scores it references are assumed to be present as well.
    3.58+Only for
    3.59+.IR venti/copy .
    3.60+.TP
    3.61 .BI -a " address"
    3.62 Dial
    3.63 .I address