changelog shortlog tags branches changeset files revisions annotate raw help

Mercurial > hg > ventivac / appl/cmd/venti/copy.b

changeset 122: 84abb5444a76
parent: c6c061169cb7
child: 7f377ffc9ad3
author: Mechiel Lukkien <mechiel@ueber.net>
date: Fri, 17 Aug 2007 22:28:53 +0200
permissions: -rw-r--r--
description: remove dflag from vac library interface. doesn't belong there anymore.
1 implement Venticopy;
2 
3 include "sys.m";
4  sys: Sys;
5 include "draw.m";
6 include "bufio.m";
7  bufio: Bufio;
8  Iobuf: import bufio;
9 include "arg.m";
10 include "string.m";
11 include "venti.m";
12 include "vac.m";
13 
14 str: String;
15 venti: Venti;
16 vac: Vac;
17 
18 print, sprint, fprint, fildes: import sys;
19 Pointertype0, Pointertype6, Score, Session, Roottype, Dirtype, Datatype, Scoresize: import venti;
20 Pointervarmask, Root, Rootsize, Entry, Entrysize, Entryactive, Entrydir: import vac;
21 
22 Venticopy: module {
23  init: fn(nil: ref Draw->Context, args: list of string);
24 };
25 
26 dflag, fflag: int;
27 session: ref Session;
28 srcs, dsts: ref Session;
29 
30 init(nil: ref Draw->Context, args: list of string)
31 {
32  sys = load Sys Sys->PATH;
33  bufio = load Bufio Bufio->PATH;
34  arg := load Arg Arg->PATH;
35  str = load String String->PATH;
36  venti = load Venti Venti->PATH;
37  vac = load Vac Vac->PATH;
38 
39  venti->init();
40  vac->init();
41 
42  arg->init(args);
43  arg->setusage(sprint("%s [-df] srcaddr dstaddr [vac:]score", arg->progname()));
44  while((c := arg->opt()) != 0)
45  case c {
46  'd' => dflag++;
47  'f' => fflag++;
48  * => arg->usage();
49  }
50  args = arg->argv();
51  if(len args != 3)
52  arg->usage();
53 
54  srcaddr := hd args;
55  dstaddr := hd tl args;
56  args = tl tl args;
57 
58  (tag, scorestr) := str->splitstrr(hd args, ":");
59  if(tag != nil)
60  tag = tag[:len tag-1];
61  t: int;
62  case tag {
63  "vac" => t = Roottype;
64  "entry" => t = Dirtype;
65  * => fprint(fildes(2), "bad score type\n");
66  arg->usage();
67  }
68 
69  (sok, score) := Score.parse(scorestr);
70  if(sok != 0)
71  error("bad score: "+scorestr);
72  say("have score");
73 
74  srcs = dial(srcaddr);
75  dsts = dial(dstaddr);
76 
77  walk(score, t, 0);
78  say("have walk");
79 
80  if(dsts.sync() < 0)
81  error(sprint("syncing destination: %r"));
82  say("synced");
83 }
84 
85 walk(s: Score, t, dt: int)
86 {
87  say(sprint("walk: %s/%d", s.text(), t));
88 
89  if(fflag && dsts.read(s, t, Venti->Maxlumpsize) != nil) {
90  say(sprint("skipping %s/%d", s.text(), t));
91  return;
92  }
93 
94  d := srcs.read(s, t, Venti->Maxlumpsize);
95  if(d == nil)
96  error(sprint("reading %s/%d: %r", s.text(), t));
97 
98  case t {
99  Roottype =>
100  r := Root.unpack(d);
101  if(r == nil)
102  error(sprint("bad root: %r"));
103  walk(r.score, Dirtype, 0);
104  if(!isnul(*r.prev))
105  walk(*r.prev, Roottype, 0);
106 
107  Dirtype =>
108  for(o := 0; o+Entrysize <= len d; o += Entrysize) {
109  e := Entry.unpack(d[o:o+Entrysize]);
110  if(e == nil)
111  error(sprint("bad entry: %r"));
112  if(!(e.flags&Entryactive))
113  continue;
114  tvar := 0;
115  if(e.flags & Vac->Entryvarblocks)
116  tvar = Pointervarmask;
117  nt := Datatype;
118  if(e.flags&Entrydir)
119  nt = Dirtype;
120  if(e.depth == 0)
121  walk(e.score, nt, 0);
122  else
123  walk(e.score, tvar|Pointertype0-1+e.depth, nt);
124  }
125 
126  Pointertype0 to Pointertype6 =>
127  nt := t-1;
128  for(o := 0; o+Scoresize <= len d; o += Scoresize) {
129  ns := Score(d[o:o+Scoresize]);
130  if(ns.eq(Score.zero()))
131  continue;
132  if(t == Pointertype0)
133  nt = dt;
134  walk(ns, nt, dt);
135  }
136 
137  Pointertype0+Pointervarmask to Pointertype6+Pointervarmask =>
138  nt := t-1;
139  for(o := 0; o+Scoresize+8 <= len d; o += Scoresize+8) {
140  ns := Score(d[o:o+Scoresize]);
141  if(ns.eq(Score.zero()))
142  continue;
143  if(t == Pointertype0|Pointervarmask)
144  nt = dt;
145  walk(ns, nt, dt);
146  }
147 
148  Datatype =>
149  ;
150 
151  * =>
152  error(sprint("unknown block type, %s/%d", s.text(), t));
153  }
154 
155  (ok, ns) := dsts.write(t, d);
156  if(ok < 0)
157  error(sprint("writing %s/%d: %r", ns.text(), t));
158  if(!ns.eq(s))
159  error(sprint("destination returned different score: %s versus %s", s.text(), ns.text()));
160 }
161 
162 isnul(s: Score): int
163 {
164  for(i := 0; i < len s.a; i++)
165  if(s.a[i] != byte 0)
166  return 0;
167  return 1;
168 }
169 
170 dial(addr: string): ref Session
171 {
172  (cok, conn) := sys->dial(addr, nil);
173  if(cok < 0)
174  error(sprint("dialing %s: %r", addr));
175  say("have connection");
176 
177  session = Session.new(conn.dfd);
178  if(session == nil)
179  error(sprint("handshake: %r"));
180  say("have handshake");
181  return session;
182 }
183 
184 error(s: string)
185 {
186  fprint(fildes(2), "%s\n", s);
187  raise "fail:"+s;
188 }
189 
190 say(s: string)
191 {
192  if(dflag)
193  fprint(fildes(2), "%s\n", s);
194 }