1.1--- a/appl/cmd/vacget.b Fri Jul 13 16:34:26 2007 +0200
1.2+++ b/appl/cmd/vacget.b Fri Jul 13 16:48:29 2007 +0200
1.3@@ -42,7 +42,7 @@
1.4 vac->init();
1.5
1.6 arg->init(args);
1.7- arg->setusage(sprint("%s [-dtv] [-a addr] [tag:]score", arg->progname()));
1.8+ arg->setusage(sprint("%s [-dptv] [-a addr] [tag:]score", arg->progname()));
1.9 while((c := arg->opt()) != 0)
1.10 case c {
1.11 'a' => addr = arg->earg();
2.1--- a/appl/cmd/vacput.b Fri Jul 13 16:34:26 2007 +0200
2.2+++ b/appl/cmd/vacput.b Fri Jul 13 16:48:29 2007 +0200
2.3@@ -62,7 +62,7 @@
2.4 blockmax = 32*1024;
2.5
2.6 arg->init(args);
2.7- arg->setusage(sprint("%s [-drtv] [-a addr] [-b blocksize] [-n name] path ...", arg->progname()));
2.8+ arg->setusage(sprint("%s [-drv] [-a addr] [-b blocksize] [-n name] path ...", arg->progname()));
2.9 while((c := arg->opt()) != 0)
2.10 case c {
2.11 'a' => addr = arg->earg();
3.1--- a/appl/cmd/vcache.b Fri Jul 13 16:34:26 2007 +0200
3.2+++ b/appl/cmd/vcache.b Fri Jul 13 16:48:29 2007 +0200
3.3@@ -33,7 +33,11 @@
3.4 init: fn(nil: ref Draw->Context, args: list of string);
3.5 };
3.6
3.7+Eperm: con "permission denied";
3.8+
3.9 laddr := "net!*!venti";
3.10+statsdir := "/chan/";
3.11+statsfile := "vcachestats";
3.12 dflag := nflag := vflag := wflag := 0;
3.13
3.14 maxcachesize := 0;
3.15@@ -79,13 +83,18 @@
3.16 venti->init();
3.17
3.18 arg->init(args);
3.19- arg->setusage(arg->progname()+" [-dnvw] [-a laddr] [-s size] remoteaddr [proxyaddr]");
3.20+ arg->setusage(arg->progname()+" [-dnvw] [-a laddr] [-s size] [-S statsfile] remoteaddr [proxyaddr]");
3.21 while((c := arg->opt()) != 0)
3.22 case c {
3.23 'a' => laddr = arg->earg();
3.24 'd' => dflag++;
3.25 'n' => nflag++;
3.26 's' => maxcachesize = int arg->earg();
3.27+ 'S' => (statsdir, statsfile) = str->splitstrr(arg->earg(), "/");
3.28+ if(statsfile == nil) {
3.29+ fprint(fildes(2), "bad statsfile\n");
3.30+ arg->usage();
3.31+ }
3.32 'v' => vflag++;
3.33 'w' => wflag = 1;
3.34 * => fprint(fildes(2), "bad option: -%c\n", c);
3.35@@ -404,6 +413,7 @@
3.36 rscore := Score(sha1(msg.data));
3.37 return rscore.eq(*op.s);
3.38 Rwrite =>
3.39+verbose(sprint("opokay, msg.score=%s op.s nil==%d", msg.score.text(), op.s==nil));
3.40 return msg.score.eq(*op.s);
3.41 };
3.42 return 1;
3.43@@ -434,9 +444,12 @@
3.44 bogusreqc := chan of (ref Vmsg, int);
3.45 reqc := requestc;
3.46
3.47- tickch := chan of int;
3.48- if(dflag)
3.49- spawn tick(tickch);
3.50+ fio := sys->file2chan(statsdir, statsfile);
3.51+ if(fio == nil) {
3.52+ fprint(fildes(2), "file2chan: %r; not serving statistics\n");
3.53+ fio = ref sys->FileIO(chan of (int, int, int, sys->Rread), chan of (int, array of byte, int, sys->Rwrite));
3.54+ } else
3.55+ if(dflag) debug(sprint("file2chan: serving %s%s", statsdir, statsfile));
3.56
3.57 debug("central: beginning loop");
3.58 initheap := heapused();
3.59@@ -453,6 +466,33 @@
3.60 if(dflag) debug(sprint("central: ALT rclaim=%d pclaim=%d rfree=%d pfree=%d",
3.61 remote.claimed, proxy.claimed, remote.tidsfree(), proxy.tidsfree()));
3.62 alt {
3.63+ (offset, nil, nil, rc) := <- fio.read =>
3.64+ if(rc == nil)
3.65+ continue;
3.66+
3.67+ buf := array of byte sprint(
3.68+ "%14d clients\n%14d proxy connection\n%14d proxy transitops\n%14d remote connection\n%14d remote transitops\n"+
3.69+ "%14d maxcachesize\n%14d cacheheads\n%14d cacheused\n"+
3.70+ "%14d cachemiss\n%14d cachehit\n%14d cacherequest\n"+
3.71+ "%14d proxymiss\n%14d proxyhit\n%14d proxyrequest\n"+
3.72+ "%14d remotereads\n%14d remotewrites\n"+
3.73+ "%14d heapused\n",
3.74+ len clients, proxy.fd != nil, 256-proxy.tidsfree(), remote.fd != nil, 256-remote.tidsfree(),
3.75+ maxcachesize, len cacheheads, cacheused,
3.76+ cachemiss, cachereq-cachemiss, cachereq,
3.77+ proxymiss, proxyreq-proxymiss, proxyreq,
3.78+ remotereads, remotewrites, heapused()-initheap);
3.79+
3.80+ if(offset > len buf)
3.81+ offset = len buf;
3.82+ rc <-= (buf[offset:], nil);
3.83+
3.84+ (nil, nil, nil, wc) := <- fio.write =>
3.85+ if(wc == nil)
3.86+ continue;
3.87+ if(dflag) debug("main: file2chan write");
3.88+ wc <-= (0, Eperm);
3.89+
3.90 (rpid, wpid, respc) := <- registerc =>
3.91 verbose("central: new client");
3.92 clientput(rpid, wpid, respc);
3.93@@ -642,7 +682,7 @@
3.94 cacheput(*op.s, op.dtype, r.data);
3.95 isread = 1;
3.96 if(proxyaddr != nil && needconn(proxy, nil) >= 0) {
3.97- ptid := proxy.opput(ref Op(0, nil, 0, nil, Nothing, nil, 0, 0));
3.98+ ptid := proxy.opput(ref Op(0, nil, 0, nil, Nothing, op.s, 0, 0));
3.99 proxy.writec <-= ref Vmsg.Twrite(1, ptid, op.dtype, r.data);
3.100 if(dflag) debug("central: wrote data from remote to proxy");
3.101 }
3.102@@ -661,12 +701,6 @@
3.103 <- remote.errorc =>
3.104 verbose("central: remote writer error");
3.105 remote.close(proxy);
3.106-
3.107- <- tickch =>
3.108- debug(sprint("cachemiss=%d cachehit=%d cacherequest=%d", cachemiss, cachereq-cachemiss, cachereq));
3.109- debug(sprint("proxymiss=%d proxyhit=%d proxyrequest=%d", proxymiss, proxyreq-proxymiss, proxyreq));
3.110- debug(sprint("remotereads=%d remotewrites=%d", remotereads, remotewrites));
3.111- debug(sprint("heapused=%d", heapused()-initheap));
3.112 }
3.113 }
3.114 }
4.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2+++ b/appl/cmd/venti/get.b Fri Jul 13 16:48:29 2007 +0200
4.3@@ -0,0 +1,124 @@
4.4+implement Ventiget;
4.5+
4.6+include "sys.m";
4.7+ sys: Sys;
4.8+include "draw.m";
4.9+include "bufio.m";
4.10+ bufio: Bufio;
4.11+ Iobuf: import bufio;
4.12+include "arg.m";
4.13+include "string.m";
4.14+include "venti.m";
4.15+include "vac.m";
4.16+
4.17+str: String;
4.18+venti: Venti;
4.19+vac: Vac;
4.20+
4.21+print, sprint, fprint, fildes: import sys;
4.22+Score, Session: import venti;
4.23+Dirtype, Datatype: import venti;
4.24+Entry, Entrysize, Vacfile: import vac;
4.25+
4.26+Ventiget: module {
4.27+ init: fn(nil: ref Draw->Context, args: list of string);
4.28+};
4.29+
4.30+addr := "net!$venti!venti";
4.31+dflag := 0;
4.32+session: ref Session;
4.33+
4.34+init(nil: ref Draw->Context, args: list of string)
4.35+{
4.36+ sys = load Sys Sys->PATH;
4.37+ bufio = load Bufio Bufio->PATH;
4.38+ arg := load Arg Arg->PATH;
4.39+ str = load String String->PATH;
4.40+ venti = load Venti Venti->PATH;
4.41+ vac = load Vac Vac->PATH;
4.42+ if(venti == nil || vac == nil)
4.43+ error("loading venti,vac");
4.44+ venti->init();
4.45+ vac->init();
4.46+
4.47+ arg->init(args);
4.48+ arg->setusage(sprint("%s [-d] [-a addr] [entry:]score", arg->progname()));
4.49+ while((c := arg->opt()) != 0)
4.50+ case c {
4.51+ 'a' => addr = arg->earg();
4.52+ 'd' => dflag++;
4.53+ vac->dflag++;
4.54+ * => fprint(fildes(2), "bad option: -%c\n", c);
4.55+ arg->usage();
4.56+ }
4.57+ args = arg->argv();
4.58+ if(len args != 1)
4.59+ arg->usage();
4.60+
4.61+ (tag, scorestr) := str->splitstrr(hd args, ":");
4.62+ if(tag != nil)
4.63+ tag = tag[:len tag-1];
4.64+ if(tag == nil)
4.65+ tag = "entry";
4.66+ if(tag != "entry")
4.67+ error("bad score type: "+tag);
4.68+
4.69+ (sok, score) := Score.parse(scorestr);
4.70+ if(sok != 0)
4.71+ error("bad score: "+scorestr);
4.72+ say("have score");
4.73+
4.74+ (cok, conn) := sys->dial(addr, nil);
4.75+ if(cok < 0)
4.76+ error(sprint("dialing %s: %r", addr));
4.77+ say("have connection");
4.78+
4.79+ fd := conn.dfd;
4.80+ session = Session.new(fd);
4.81+ if(session == nil)
4.82+ error(sprint("handshake: %r"));
4.83+ say("have handshake");
4.84+
4.85+ d := session.read(score, Dirtype, Entrysize);
4.86+ if(d == nil)
4.87+ error(sprint("reading entry: %r"));
4.88+ e := Entry.unpack(d);
4.89+ if(e == nil)
4.90+ error(sprint("unpacking entry: %r"));
4.91+ say("have entry");
4.92+
4.93+ bio := bufio->fopen(fildes(1), bufio->OWRITE);
4.94+ if(bio == nil)
4.95+ error(sprint("bufio fopen: %r"));
4.96+
4.97+ say("reading");
4.98+ buf := array[sys->ATOMICIO] of byte;
4.99+ vf := Vacfile.new(session, e);
4.100+ for(;;) {
4.101+ rn := vf.read(buf, len buf);
4.102+ if(rn == 0)
4.103+ break;
4.104+ if(rn < 0)
4.105+ error(sprint("reading: %r"));
4.106+ wn := bio.write(buf, rn);
4.107+ if(wn != rn)
4.108+ error(sprint("writing: %r"));
4.109+ }
4.110+ bok := bio.flush();
4.111+ bio.close();
4.112+ if(bok == bufio->ERROR || bok == bufio->EOF)
4.113+ error(sprint("bufio close: %r"));
4.114+ say("done");
4.115+}
4.116+
4.117+error(s: string)
4.118+{
4.119+ fprint(fildes(2), "%s\n", s);
4.120+ raise "fail:"+s;
4.121+}
4.122+
4.123+say(s: string)
4.124+{
4.125+ if(dflag)
4.126+ fprint(fildes(2), "%s\n", s);
4.127+}
5.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2+++ b/appl/cmd/venti/mkfile Fri Jul 13 16:48:29 2007 +0200
5.3@@ -0,0 +1,25 @@
5.4+<../../../mkconfig
5.5+
5.6+TARG=\
5.7+ sync.dis\
5.8+ ping.dis\
5.9+ get.dis\
5.10+ put.dis\
5.11+
5.12+SYSMODULES=\
5.13+ arg.m\
5.14+ bufio.m\
5.15+ daytime.m\
5.16+ draw.m\
5.17+ keyring.m\
5.18+ string.m\
5.19+ styx.m\
5.20+ styxservers.m\
5.21+ sys.m\
5.22+ vac.m\
5.23+ venti.m\
5.24+
5.25+DISBIN=$ROOT/dis/venti
5.26+
5.27+<$ROOT/mkfiles/mkdis
5.28+<$ROOT/mkfiles/mksubdirs
6.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2+++ b/appl/cmd/venti/ping.b Fri Jul 13 16:48:29 2007 +0200
6.3@@ -0,0 +1,81 @@
6.4+implement Ventiping;
6.5+
6.6+include "sys.m";
6.7+include "draw.m";
6.8+include "arg.m";
6.9+include "venti.m";
6.10+
6.11+sys: Sys;
6.12+venti: Venti;
6.13+
6.14+print, sprint, fprint, fildes: import sys;
6.15+Score, Session, Vmsg: import venti;
6.16+
6.17+Ventiping: module {
6.18+ init: fn(nil: ref Draw->Context, args: list of string);
6.19+};
6.20+
6.21+addr := "net!$venti!venti";
6.22+dflag := 0;
6.23+n := 3;
6.24+
6.25+init(nil: ref Draw->Context, args: list of string)
6.26+{
6.27+ sys = load Sys Sys->PATH;
6.28+ arg := load Arg Arg->PATH;
6.29+ venti = load Venti Venti->PATH;
6.30+ venti->init();
6.31+
6.32+ arg->init(args);
6.33+ arg->setusage(arg->progname() + " [-d] [-n count] [-a addr]");
6.34+ while((c := arg->opt()) != 0)
6.35+ case c {
6.36+ 'a' => addr = arg->earg();
6.37+ 'd' => dflag++;
6.38+ 'n' => n = int arg->earg();
6.39+ * => fprint(fildes(2), "bad option: -%c", c);
6.40+ arg->usage();
6.41+ }
6.42+ args = arg->argv();
6.43+ if(len args != 0)
6.44+ arg->usage();
6.45+
6.46+ say("dialing");
6.47+ (cok, conn) := sys->dial(addr, nil);
6.48+ if(cok < 0)
6.49+ fail(sprint("dialing %s: %r", addr));
6.50+ fd := conn.dfd;
6.51+ say("have connection");
6.52+
6.53+ session := Session.new(fd);
6.54+ if(session == nil)
6.55+ fail(sprint("handshake: %r"));
6.56+ say("have handshake");
6.57+
6.58+ tm := ref Vmsg.Tping(1, 0);
6.59+ i := 0;
6.60+ for(;;) {
6.61+ t0 := sys->millisec();
6.62+ (rm, err) := session.rpc(tm);
6.63+ if(rm == nil)
6.64+ fail("ping: "+err);
6.65+ t1 := sys->millisec();
6.66+ print("%d ms\n", t1-t0);
6.67+ i++;
6.68+ if(i == n)
6.69+ break;
6.70+ sys->sleep(1*1000);
6.71+ }
6.72+}
6.73+
6.74+fail(s: string)
6.75+{
6.76+ fprint(fildes(2), "%s\n", s);
6.77+ raise "fail:"+s;
6.78+}
6.79+
6.80+say(s: string)
6.81+{
6.82+ if(dflag)
6.83+ fprint(fildes(2), "%s\n", s);
6.84+}
7.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2+++ b/appl/cmd/venti/put.b Fri Jul 13 16:48:29 2007 +0200
7.3@@ -0,0 +1,118 @@
7.4+implement Ventiput;
7.5+
7.6+include "sys.m";
7.7+ sys: Sys;
7.8+include "draw.m";
7.9+include "bufio.m";
7.10+ bufio: Bufio;
7.11+ Iobuf: import bufio;
7.12+include "arg.m";
7.13+include "venti.m";
7.14+include "vac.m";
7.15+
7.16+venti: Venti;
7.17+vac: Vac;
7.18+
7.19+print, sprint, fprint, fildes: import sys;
7.20+Score, Session: import venti;
7.21+Dirtype, Datatype: import venti;
7.22+Entry, File: import vac;
7.23+
7.24+Ventiput: module {
7.25+ init: fn(nil: ref Draw->Context, args: list of string);
7.26+};
7.27+
7.28+addr := "net!$venti!venti";
7.29+dflag := 0;
7.30+blocksize := vac->Dsize;
7.31+session: ref Session;
7.32+
7.33+init(nil: ref Draw->Context, args: list of string)
7.34+{
7.35+ sys = load Sys Sys->PATH;
7.36+ bufio = load Bufio Bufio->PATH;
7.37+ arg := load Arg Arg->PATH;
7.38+ venti = load Venti Venti->PATH;
7.39+ vac = load Vac Vac->PATH;
7.40+ if(venti == nil || vac == nil)
7.41+ error("loading venti,vac");
7.42+ venti->init();
7.43+ vac->init();
7.44+
7.45+ arg->init(args);
7.46+ arg->setusage(sprint("%s [-d] [-a addr] [-b blocksize]", arg->progname()));
7.47+ while((c := arg->opt()) != 0)
7.48+ case c {
7.49+ 'a' => addr = arg->earg();
7.50+ 'b' => blocksize = int arg->earg();
7.51+ 'd' => dflag++;
7.52+ vac->dflag++;
7.53+ * => fprint(fildes(2), "bad option: -%c", c);
7.54+ arg->usage();
7.55+ }
7.56+ args = arg->argv();
7.57+ if(len args != 0)
7.58+ arg->usage();
7.59+
7.60+ (cok, conn) := sys->dial(addr, nil);
7.61+ if(cok < 0)
7.62+ error(sprint("dialing %s: %r", addr));
7.63+ say("have connection");
7.64+
7.65+ session = Session.new(conn.dfd);
7.66+ if(session == nil)
7.67+ error(sprint("handshake: %r"));
7.68+ say("have handshake");
7.69+
7.70+ bio := bufio->fopen(fildes(0), bufio->OREAD);
7.71+ if(bio == nil)
7.72+ error(sprint("bufio open: %r"));
7.73+
7.74+ say("writing");
7.75+ f := File.new(session, Datatype, blocksize, 0);
7.76+ for(;;) {
7.77+ buf := array[blocksize] of byte;
7.78+ n := 0;
7.79+ while(n < len buf) {
7.80+ want := len buf - n;
7.81+ have := bio.read(buf[n:], want);
7.82+ if(have == 0)
7.83+ break;
7.84+ if(have < 0)
7.85+ error(sprint("reading: %r"));
7.86+ n += have;
7.87+ }
7.88+ if(dflag) say(sprint("have buf, length %d", n));
7.89+
7.90+ if(f.write(buf[:n]) < 0)
7.91+ error(sprint("writing: %r"));
7.92+ if(n != len buf)
7.93+ break;
7.94+ }
7.95+ bio.close();
7.96+ e := f.finish();
7.97+ if(e == nil)
7.98+ error(sprint("flushing: %r"));
7.99+ d := e.pack();
7.100+
7.101+ (rok, rscore) := session.write(Dirtype, d);
7.102+ if(rok < 0)
7.103+ error(sprint("writing root score: %r"));
7.104+ say("entry written, "+rscore.text());
7.105+ print("entry:%s\n", rscore.text());
7.106+
7.107+ if(session.sync() < 0)
7.108+ error(sprint("syncing server: %r"));
7.109+}
7.110+
7.111+error(s: string)
7.112+{
7.113+ fprint(fildes(2), "%s\n", s);
7.114+ raise "fail:"+s;
7.115+}
7.116+
7.117+say(s: string)
7.118+{
7.119+ if(dflag)
7.120+ fprint(fildes(2), "%s\n", s);
7.121+}
8.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2+++ b/appl/cmd/venti/sync.b Fri Jul 13 16:48:29 2007 +0200
8.3@@ -0,0 +1,68 @@
8.4+implement Ventisync;
8.5+
8.6+include "sys.m";
8.7+include "draw.m";
8.8+include "arg.m";
8.9+include "venti.m";
8.10+
8.11+sys: Sys;
8.12+venti: Venti;
8.13+
8.14+print, sprint, fprint, fildes: import sys;
8.15+Score, Session: import venti;
8.16+
8.17+Ventisync: module {
8.18+ init: fn(nil: ref Draw->Context, args: list of string);
8.19+};
8.20+
8.21+addr := "net!$venti!venti";
8.22+dflag := 0;
8.23+
8.24+init(nil: ref Draw->Context, args: list of string)
8.25+{
8.26+ sys = load Sys Sys->PATH;
8.27+ arg := load Arg Arg->PATH;
8.28+ venti = load Venti Venti->PATH;
8.29+ venti->init();
8.30+
8.31+ arg->init(args);
8.32+ arg->setusage(arg->progname() + " [-d] [-a addr]");
8.33+ while((c := arg->opt()) != 0)
8.34+ case c {
8.35+ 'a' => addr = arg->earg();
8.36+ 'd' => dflag++;
8.37+ * => fprint(fildes(2), "bad option: -%c", c);
8.38+ arg->usage();
8.39+ }
8.40+ args = arg->argv();
8.41+ if(len args != 0)
8.42+ arg->usage();
8.43+
8.44+ say("dialing");
8.45+ (cok, conn) := sys->dial(addr, nil);
8.46+ if(cok < 0)
8.47+ fail(sprint("dialing %s: %r", addr));
8.48+ fd := conn.dfd;
8.49+ say("have connection");
8.50+
8.51+ session := Session.new(fd);
8.52+ if(session == nil)
8.53+ fail(sprint("handshake: %r"));
8.54+ say("have handshake");
8.55+
8.56+ if(session.sync() < 0)
8.57+ fail(sprint("sync: %r"));
8.58+ say("synced");
8.59+}
8.60+
8.61+fail(s: string)
8.62+{
8.63+ fprint(fildes(2), "%s\n", s);
8.64+ raise "fail:"+s;
8.65+}
8.66+
8.67+say(s: string)
8.68+{
8.69+ if(dflag)
8.70+ fprint(fildes(2), "%s\n", s);
8.71+}
9.1--- a/appl/cmd/ventisrv.b Fri Jul 13 16:34:26 2007 +0200
9.2+++ b/appl/cmd/ventisrv.b Fri Jul 13 16:48:29 2007 +0200
9.3@@ -4,13 +4,12 @@
9.4 # - queue index writes?
9.5 # - starting up is slow. reading index file is fast. packing/unpacking is necessary. inserting non-sorted at startup, and then sorting is faster, but involves unpacking the "blocks" in memory, sorting, and packing again. premature optimisation.
9.6 # - sync when client disconnects? sync periodically?
9.7-# - write only large buffers, e.g. 128k to disk?
9.8 # - only compress data and dir blocks? not pointer blocks (they have random scores). should make sure the index file and data file remain in sync.
9.9
9.10 # does not have:
9.11 # - using raw disks for storage
9.12 # - tools for analysing problems and fixing bad index/data file state
9.13-# - authentication, or disallowing writes
9.14+# - authentication
9.15
9.16 implement Ventisrv;
9.17
9.18@@ -153,9 +152,11 @@
9.19 finish: fn(f: self ref Flate): (array of byte, string);
9.20 };
9.21
9.22+Eperm: con "permission denied";
9.23
9.24 Indexscoresize: con 8;
9.25-Ihdrsize: con Indexscoresize+1+6;
9.26+Icomprmask: con big 1<<(6*8-1);
9.27+Ihdrsize: con Indexscoresize+1+6; # scoresize+typesize+addrsize
9.28 Iverify: con 128; # check the half scores of the last n entries in the index file against the data file
9.29 Ichunksize: con ((128*1024)/Ihdrsize)*Ihdrsize; # chunk in bytes of index entries to read at a time
9.30 Nqueuechunks: con 32; # queue n Ichunksize blocks when reading index at startup
9.31@@ -182,6 +183,8 @@
9.32 listenaddr: con "net!*!venti";
9.33 indexfile := "index";
9.34 datafile := "data";
9.35+statsdir := "/chan/";
9.36+statsfile := "ventisrvstats";
9.37 debug, Cflag, cflag, qflag, verbose: int;
9.38 raddrs, waddrs: list of string;
9.39
9.40@@ -200,6 +203,7 @@
9.41 storec: chan of ref Store;
9.42 writererrorc: chan of string;
9.43 sem: ref Semaphore;
9.44+statsem: ref Semaphore;
9.45
9.46 writequeue: ref Queue;
9.47 flatequeue: ref Fifo;
9.48@@ -207,9 +211,7 @@
9.49 initheap, configheap: big;
9.50 nreads, nwrites, nwritesdup, nsyncs, npings: int;
9.51 nblocks, nflateblocks: int;
9.52-lookupclashes: int;
9.53-
9.54-flatesequence := 1;
9.55+lookupcollisions: int;
9.56
9.57
9.58 init(nil: ref Draw->Context, args: list of string)
9.59@@ -229,7 +231,7 @@
9.60 venti->init();
9.61
9.62 arg->init(args);
9.63- arg->setusage(arg->progname()+ " [-Dcqv] [-i index] [-d data] [-r addr] [-w addr] maxdatasize meanblocksize");
9.64+ arg->setusage(arg->progname()+ " [-DcCqv] [-i index] [-d data] [-s statsfile] [-r addr] [-w addr] maxdatasize meanblocksize");
9.65 while((c := arg->opt()) != 0)
9.66 case c {
9.67 'D' => debug++;
9.68@@ -241,6 +243,11 @@
9.69 'q' => qflag++;
9.70 verbose++;
9.71 'v' => verbose++;
9.72+ 's' => (statsdir, statsfile) = str->splitstrr(arg->earg(), "/");
9.73+ if(statsfile == nil) {
9.74+ fprint(fildes(2), "bad stats file");
9.75+ arg->usage();
9.76+ }
9.77 'r' => raddrs = arg->earg()::raddrs;
9.78 'w' => waddrs = arg->earg()::waddrs;
9.79 * =>
9.80@@ -290,6 +297,7 @@
9.81 storec = chan[32] of ref Store;
9.82 writererrorc = chan of string;
9.83 sem = Semaphore.new();
9.84+ statsem = Semaphore.new();
9.85
9.86 writequeue = ref Queue(array[2] of ref Block, 0);
9.87 flatequeue = ref Fifo(array[64] of ref Block, 0, 0, Semaphore.new());
9.88@@ -389,6 +397,14 @@
9.89 io = big 0;
9.90 if(indexsize > big 0) {
9.91 if(debug) say(sprint("config: verifying last entries in index file at offset=%bd", io));
9.92+ ih := getihdr(io);
9.93+ while(ih.compressed) {
9.94+ io += big Ihdrsize;
9.95+ nih := getihdr(io);
9.96+ if(nih.offset != ih.offset)
9.97+ break;
9.98+ ih = nih;
9.99+ }
9.100 while(io < indexsize)
9.101 (doffset, io) = indexverify(io);
9.102 }
9.103@@ -398,7 +414,7 @@
9.104 while(doffset < datasize) {
9.105 (dhdrs, compr, noffset, err) := offsetread(doffset);
9.106 if(err != nil)
9.107- fail("syncing index from data: "+err);
9.108+ fail(sprint("syncing index from data at offset=%bd: %s", doffset, err));
9.109 for(i := 0; i < len dhdrs; i++) {
9.110 dhdr := dhdrs[i];
9.111 err = indexstore(ref Ihdr(dhdr.score.a[:Indexscoresize], dhdr.dtype, doffset, compr));
9.112@@ -445,8 +461,8 @@
9.113 {
9.114 if(halfcmp(ih.halfscore, dh.score.a, ih.dtype, dh.dtype) == 0)
9.115 return;
9.116- fail(sprint("partial score or type index file does not match block in data file at offset=%bd, index: score=%s type=%d, data: score=%s type=%d",
9.117- ih.offset, scorestr(ih.halfscore), ih.dtype, dh.score.text(), dh.dtype));
9.118+ fail(sprint("partial score or type index file does not match block in data file at offset=%bd, index: score=%s type=%d compressed=%d, data: score=%s type=%d",
9.119+ ih.offset, scorestr(ih.halfscore), ih.dtype, ih.compressed, dh.score.text(), dh.dtype));
9.120 }
9.121
9.122 getihdr(o: big): ref Ihdr
9.123@@ -661,8 +677,10 @@
9.124 if(debug) say("reader: have hit, already in datafile");
9.125 sem.obtain();
9.126 writequeue.remove(w.b);
9.127+ sem.release();
9.128+ statsem.obtain();
9.129 nwritesdup++;
9.130- sem.release();
9.131+ statsem.release();
9.132 } else {
9.133 if(debug) say("reader: no hit, need to write block");
9.134 if(debug) say("reader: data not yet present for write");
9.135@@ -875,9 +893,13 @@
9.136 {
9.137 writeerror: string;
9.138
9.139- tickch := chan of int;
9.140- if(debug)
9.141- spawn ticker(tickch);
9.142+ fio := sys->file2chan(statsdir, statsfile);
9.143+ if(fio == nil) {
9.144+ say(sprint("file2chan: %r; not serving statistics"));
9.145+ fio = ref sys->FileIO(chan of (int, int, int, sys->Rread), chan of (int, array of byte, int, sys->Rwrite));
9.146+ } else
9.147+ if(debug) say(sprint("file2chan: serving %s%s", statsdir, statsfile));
9.148+
9.149 spawn writer();
9.150
9.151 configheap = heapused();
9.152@@ -885,6 +907,41 @@
9.153 say(sprint("heap used after startup=%bd", configheap-initheap));
9.154
9.155 for(;;) alt {
9.156+ (offset, nil, nil, rc) := <- fio.read =>
9.157+ if(rc == nil)
9.158+ continue;
9.159+
9.160+ statsem.obtain();
9.161+ lnblocks := nblocks;
9.162+ lnflateblocks := nflateblocks;
9.163+ ldatasize := datasize;
9.164+ lnwritesdup := nwritesdup;
9.165+ statsem.release();
9.166+
9.167+ h := heapused();
9.168+ mean := 0;
9.169+ if(lnblocks > 0)
9.170+ mean = int (ldatasize/big lnblocks);
9.171+ buf := array of byte sprint(
9.172+ "%14d reads\n%14d writes\n%14d syncs\n%14d pings\n"+
9.173+ "%14d dupwrites\n%14d lookupcollisions\n%14d blocks\n%14d flateblocks\n%14d meanblocksize\n"+
9.174+ "%14d readerprocs\n%14d busyreaderprocs\n%14d readerwrites\n"+
9.175+ "%14bd totalheap\n%14bd newheap\n%14bd datasize\n%s\n",
9.176+ nreads, nwrites, nsyncs, npings,
9.177+ lnwritesdup, lookupcollisions, lnblocks, lnflateblocks, mean,
9.178+ nreaders, nbusyreaders, nreaderwrites,
9.179+ h, h-configheap, ldatasize, writeerror);
9.180+
9.181+ if(offset > len buf)
9.182+ offset = len buf;
9.183+ rc <-= (buf[offset:], nil);
9.184+
9.185+ (nil, nil, nil, wc) := <- fio.write =>
9.186+ if(wc == nil)
9.187+ continue;
9.188+ if(debug) say("main: file2chan write");
9.189+ wc <-= (0, Eperm);
9.190+
9.191 (iswrite, rmsg, c) := <-lookupdonec =>
9.192 lookupdone(iswrite, rmsg, c);
9.193
9.194@@ -1000,16 +1057,6 @@
9.195 * =>
9.196 if(debug) say(sprint("main: bad tmsg, tag=%d", tagof vmsg));
9.197 }
9.198-
9.199- <-tickch =>
9.200- h := heapused();
9.201- say(sprint("total heap used=%bd, new heap since startup=%bd", h, h-configheap));
9.202- say(sprint("nreads=%d nwrites=%d nwritesdup=%d nsyncs=%d npings=%d",
9.203- nreads, nwrites, nwritesdup, nsyncs, npings));
9.204- mean := 0;
9.205- if(nblocks > 0)
9.206- mean = int (datasize/big nblocks);
9.207- say(sprint("nblocks=%d nflateblocks=%d meanblocksize=%d lookupclashes=%d", nblocks, nflateblocks, mean, lookupclashes));
9.208 }
9.209 }
9.210
9.211@@ -1139,10 +1186,13 @@
9.212 n = sys->pwrite(datafd, d, len d, datasize+big len fhbuf);
9.213 if(n != len d)
9.214 return (datasize, sprint("writing flateblock data: %r"));
9.215+
9.216 offset := datasize;
9.217+ statsem.obtain();
9.218 datasize += big (len fhbuf+len d);
9.219 nblocks += len blocks;
9.220 nflateblocks += len blocks;
9.221+ statsem.release();
9.222 if(debug) say(sprint("datastoreflate: stored at offset=%bd datasize=%bd len blocks=%d comprsize=%d", offset, datasize, len blocks, len d));
9.223 return (offset, nil);
9.224 }
9.225@@ -1166,8 +1216,10 @@
9.226 return (datasize, sprint("writing data: %r"));
9.227
9.228 offset := datasize;
9.229+ statsem.obtain();
9.230 datasize += big (len dhbuf+len d);
9.231 nblocks++;
9.232+ statsem.release();
9.233 if(debug) say(sprint("datastore: stored at offset=%bd datasize=%bd blocksize=%d", offset, datasize, dh.size));
9.234 return (offset, nil);
9.235 }
9.236@@ -1412,7 +1464,10 @@
9.237 v |= big c.d[o++] << (b-8);
9.238 if(b > 0)
9.239 v |= big c.d[o] >> (8-b);
9.240- return (int ((v&comprmask)>>(addrbits-1)), v&~comprmask);
9.241+ iscompr := Cflag && int ((v&comprmask)>>(addrbits-1));
9.242+ if(iscompr)
9.243+ v &= ~comprmask;
9.244+ return (iscompr, v);
9.245 }
9.246
9.247 Chain.lookup(c: self ref Chain, d: array of byte, l: list of (int, big)): list of (int, big)
9.248@@ -1571,7 +1626,7 @@
9.249 for(c := heads[head(score.a)]; c != nil; c = c.next)
9.250 addrs = c.lookup(d, addrs);
9.251 if(len addrs > 1)
9.252- lookupclashes += len addrs-1;
9.253+ lookupcollisions += len addrs-1;
9.254 return addrs;
9.255 }
9.256
9.257@@ -1642,9 +1697,9 @@
9.258 o += 1;
9.259 offset := get48(d, o);
9.260 compressed := 0;
9.261- if(int ((offset&comprmask)>>(addrbits-1)))
9.262+ if((offset&Icomprmask) == Icomprmask)
9.263 compressed = 1;
9.264- offset &= ~comprmask;
9.265+ offset &= ~Icomprmask;
9.266 o += 6;
9.267 if(o != Ihdrsize)
9.268 fail("bad iheader.unpack");
9.269@@ -1660,7 +1715,7 @@
9.270 o += 1;
9.271 offset := ih.offset;
9.272 if(ih.compressed)
9.273- offset |= comprmask;
9.274+ offset |= Icomprmask;
9.275 put48(d, o, offset);
9.276 o += 6;
9.277 if(o != Ihdrsize)
9.278@@ -1671,7 +1726,7 @@
9.279 {
9.280 o := 0;
9.281 if(get32(d, o) != Dhdrmagic)
9.282- return (nil, "bad magic");
9.283+ return (nil, "bad dhdr magic");
9.284 o += 4;
9.285 score := d[o:o+Scoresize];
9.286 o += Scoresize;
9.287@@ -1708,7 +1763,7 @@
9.288 {
9.289 o := 0;
9.290 if(get32(d, o) != Fhdrmagic)
9.291- return (nil, nil, "bad magic");
9.292+ return (nil, nil, "bad fhdr magic");
9.293 o += 4;
9.294 nb := int d[o++];
9.295 hsize := nb*Fbhdrsize;
10.1--- a/man/1/vacget Fri Jul 13 16:34:26 2007 +0200
10.2+++ b/man/1/vacget Fri Jul 13 16:48:29 2007 +0200
10.3@@ -67,6 +67,9 @@
10.4 .br
10.5 .B /appl/cmd/vacput.b
10.6 .SH SEE ALSO
10.7+.IR venti (1),
10.8+.IR vacget (1),
10.9+.IR vacput (1),
10.10 .IR vcache (1),
10.11 .IR venti (2),
10.12 .IR vacfs (4),
11.1--- a/man/1/vcache Fri Jul 13 16:34:26 2007 +0200
11.2+++ b/man/1/vcache Fri Jul 13 16:48:29 2007 +0200
11.3@@ -11,17 +11,20 @@
11.4 ] [
11.5 .B -s
11.6 .I size
11.7+] [
11.8+.B -S
11.9+.I statsfile
11.10 ]
11.11 .I remoteaddr
11.12 [
11.13 .I proxyaddr
11.14 ]
11.15 .SH DESCRIPTION
11.16-Vcache is a cache for venti blocks. It acts as a venti server and serves requests using its in-memory cache, optionally a proxy server, and finally an authorative venti server. Only read requests are cached, and only if they returned data. Cache blocks are replaced using a clock replacement algorithm. If not handled by the cache, read requests go to the proxy server, falling back to the authorative server if the data is absent at the proxy or no proxy server is used. Read data returned by the authorative server are written to the proxy server. If
11.17+Vcache is a cache for venti blocks. It acts as a venti server and serves requests using its in-memory cache, optionally a proxy server, and finally an authoritative venti server. Only read requests are cached, and only if they returned data. Cache blocks are replaced using a clock replacement algorithm. If not handled by the cache, read requests go to the proxy server, falling back to the authoritative server if the data is absent at the proxy or no proxy server is used. Read data returned by the authoritative server are written to the proxy server. If
11.18 .B -w
11.19-has been specified, the proxy server is used as write through cache: all write and sync requests from clients go to both the proxy and the authorative server, keeping them in sync. Requests only succeed if both servers return success, this allows reads of previously written data to succeed, even when the authorative server is down.
11.20+has been specified, the proxy server is used as write through cache: all write and sync requests from clients go to both the proxy and the authoritative server, keeping them in sync. Requests only succeed if both servers return success, this allows reads of previously written data to succeed, even when the authoritative server is down.
11.21 .PP
11.22-Typically, the proxy server is running locally and the authorative server is remote, possibly on a high latency link. At startup, no connections to the venti server are initiated. All clients share a single connection to the proxy server and authorative server. The servers are dialed when needed only, no connections are made before the first client connects. Once connected, the proxy connection is always kept. The connection to the authorative server is closed when the last client disconnects. When connections to the proxy or authorative server fail, all clients with pending requests are disconnected.
11.23+Typically, the proxy server is running locally and the authoritative server is remote, possibly on a high latency link. At startup, no connections to the venti server are initiated. All clients share a single connection to the proxy server and authoritative server. The servers are dialed when needed only, no connections are made before the first client connects. Once connected, the proxy connection is always kept. The connection to the authoritative server is closed when the last client disconnects. When connections to the proxy or authoritative server fail, all clients with pending requests are disconnected.
11.24 .TP
11.25 .BI -a " address"
11.26 Listen on
11.27@@ -31,8 +34,13 @@
11.28 .BI -s " size"
11.29 Size of the in-memory cache in bytes. The overhead of the score and data structures is included in the size. Default is 0 bytes.
11.30 .TP
11.31+.BI -S " statsfile"
11.32+File to serve statistics on. Default is
11.33+.IR /chan/vcachestats .
11.34+Each line starts with a space-padded 14 byte number followed by a space and a textual description.
11.35+.TP
11.36 .B -n
11.37-Do not check the results of the proxy and authorative server. By default, vcache verifies the returned data and scores.
11.38+Do not check the results of the proxy and authoritative server. By default, vcache verifies the returned data and scores.
11.39 .TP
11.40 .B -w
11.41 Use the proxy server as write-through cache.
11.42@@ -45,6 +53,7 @@
11.43 .SH SOURCE
11.44 .B /appl/cmd/vcache.b
11.45 .SH SEE ALSO
11.46+.IR venti (1),
11.47 .IR vacget (1),
11.48 .IR vacput (1),
11.49 .IR venti (2),
11.50@@ -53,4 +62,4 @@
11.51 .SH BUGS
11.52 The in-memory cache needs a better replacement policy, with more efficient implementation.
11.53 .br
11.54-When a connection to a proxy or authorative server breaks, all clients with pending requests are closed down, open requests are not responded to. Sending venti error responses for all open requests might be nicer.
11.55+When a connection to a proxy or authoritative server breaks, all clients with pending requests are closed down, open requests are not responded to. Sending venti error responses for all open requests might be nicer.
12.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2+++ b/man/1/venti Fri Jul 13 16:48:29 2007 +0200
12.3@@ -0,0 +1,93 @@
12.4+.TH VENTI 1
12.5+.SH NAME
12.6+venti/sync, venti/ping, venti/get, venti/put \- venti utilities
12.7+.SH SYNOPSIS
12.8+.B venti/sync
12.9+[
12.10+.B -d
12.11+] [
12.12+.B -a
12.13+.I addr
12.14+]
12.15+.br
12.16+.B venti/ping
12.17+[
12.18+.B -d
12.19+] [
12.20+.B -a
12.21+.I addr
12.22+] [
12.23+.B -n
12.24+.I count
12.25+]
12.26+.br
12.27+.B venti/put
12.28+[
12.29+.B -d
12.30+] [
12.31+.B -a
12.32+.I addr
12.33+] [
12.34+.B -b
12.35+.I blocksize
12.36+]
12.37+.br
12.38+.B venti/get
12.39+[
12.40+.B -d
12.41+] [
12.42+.B -a
12.43+.I addr
12.44+]
12.45+.I entry:score
12.46+.SH DESCRIPTION
12.47+.I Venti/sync
12.48+sends a sync messages to a venti server. When it returns, the venti server has flushed its data to stable storage.
12.49+.PP
12.50+.I Venti/ping
12.51+pings a venti server. Option
12.52+.B -n
12.53+sets the number of ping messages to send. The round trip time for each message is printed.
12.54+.PP
12.55+.I Venti/put
12.56+reads data from standard input and writes it to venti. When done, the score of the resulting venti entry is printed.
12.57+.I Venti/get
12.58+reads the data from the venti entry referenced by
12.59+.I score
12.60+and writes it to standard output.
12.61+.PP
12.62+The options the programs understand are:
12.63+.TP
12.64+.B -d
12.65+Print debug messages.
12.66+.TP
12.67+.BI -a " address"
12.68+Dial
12.69+.I address
12.70+instead of the default venti server.
12.71+.TP
12.72+.BI -b " blocksize"
12.73+Use blocks with
12.74+.I blocksize
12.75+bytes instead of the default 8192 byte blocks. Only for
12.76+.IR venti/put .
12.77+.TP
12.78+.BI -n " count"
12.79+Send
12.80+.I count
12.81+pings to the venti server. The default is three. When set to zero,
12.82+.I venti/ping
12.83+pings until interrupted.
12.84+.SH SOURCE
12.85+.B /appl/cmd/venti/sync.b
12.86+.br
12.87+.B /appl/cmd/venti/ping.b
12.88+.br
12.89+.B /appl/cmd/venti/get.b
12.90+.br
12.91+.B /appl/cmd/venti/put.b
12.92+.SH SEE ALSO
12.93+.IR vcache (1),
12.94+.IR venti (2),
12.95+.IR vacfs (4),
12.96+.IR ventisrv (8)
13.1--- a/man/4/vacfs Fri Jul 13 16:34:26 2007 +0200
13.2+++ b/man/4/vacfs Fri Jul 13 16:48:29 2007 +0200
13.3@@ -36,6 +36,7 @@
13.4 .SH SOURCE
13.5 .B /appl/cmd/vacfs.b
13.6 .SH SEE ALSO
13.7+.IR venti (1),
13.8 .IR vacget (1),
13.9 .IR vacput (1),
13.10 .IR vcache (1),
14.1--- a/man/8/ventisrv Fri Jul 13 16:34:26 2007 +0200
14.2+++ b/man/8/ventisrv Fri Jul 13 16:48:29 2007 +0200
14.3@@ -12,6 +12,9 @@
14.4 .B -d
14.5 .I data
14.6 ] [
14.7+.B -s
14.8+.I statsfile
14.9+] [
14.10 .B -r
14.11 .I addr
14.12 ] [
14.13@@ -63,8 +66,13 @@
14.14 File to use as data file. Default is
14.15 .IR data .
14.16 .TP
14.17+.BI -s " statsfile"
14.18+File to serve statistics on. Default is
14.19+.IR /chan/ventisrvstats .
14.20+Each line starts with a space-padded 14 byte number followed by a space and a textual description. The last line is empty unless a write error has occurred, in which it contains the error message.
14.21+.TP
14.22 .B -D
14.23-Print (lots of) debug messages. Prints multiple lines per venti transaction and periodically prints statistics about memory and block usage.
14.24+Print (lots of) debug messages. Prints multiple lines per venti transaction.
14.25 .TP
14.26 .B -v
14.27 Be more verbose, especially at startup and when errors occur.
14.28@@ -86,6 +94,7 @@
14.29 .SH SOURCE
14.30 .B /appl/cmd/ventisrv.b
14.31 .SH SEE ALSO
14.32+.IR venti (1),
14.33 .IR vacget (1),
14.34 .IR vacput (1),
14.35 .IR vcache (1),