changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > ventivac / changeset: fix tracking qids. previous attempt was wrong because the usecount-keeping was wrong. the assumptions when the navigator walk was called was wrong. this code is probably a bit too much intertwined with styxservers though.

changeset 110: 9d2a54eb24ce
parent 109: c4ccc5d9f9fe
child 111: 8fd6132b12be
author: Mechiel Lukkien <mechiel@ueber.net>
date: Fri, 17 Aug 2007 16:39:52 +0200
files: appl/cmd/vacfs.b
description: fix tracking qids. previous attempt was wrong because the usecount-keeping was wrong. the assumptions when the navigator walk was called was wrong. this code is probably a bit too much intertwined with styxservers though.
     1.1--- a/appl/cmd/vacfs.b	Thu Aug 16 14:55:38 2007 +0200
     1.2+++ b/appl/cmd/vacfs.b	Fri Aug 17 16:39:52 2007 +0200
     1.3@@ -38,7 +38,6 @@
     1.4 	qid:	int;
     1.5 	de: 	ref Direntry;
     1.6 	size:	big;
     1.7-	nused:	int;	# fids using Elem
     1.8 	pick {
     1.9 	File =>	vf: 	ref Vacfile;
    1.10 	Dir =>	vd:	ref Vacdir;
    1.11@@ -57,15 +56,20 @@
    1.12 	cqids:	list of (big, int);
    1.13 };
    1.14 
    1.15+# path that has been walked to
    1.16+Path: adt {
    1.17+	path, nused:	int;
    1.18+	elems:	list of ref Elem;
    1.19+};
    1.20+
    1.21 Qfakeroot:	con 0;
    1.22 
    1.23-Mapsize:	con 512;
    1.24-fileelems := array[Mapsize] of list of ref Elem.File;
    1.25-direlems := array[Mapsize] of list of ref Elem.Dir;
    1.26-qidmaps:= array[Mapsize] of list of ref Qidmap;
    1.27 lastqid := 0;
    1.28-qidscores: list of (string, int);
    1.29+qidmaps := array[512] of list of ref Qidmap;
    1.30+scoreelems: list of (string, ref Elem.Dir);
    1.31+rootelem: ref Elem;
    1.32 
    1.33+curelems: list of ref Elem;
    1.34 
    1.35 init(nil: ref Draw->Context, args: list of string)
    1.36 {
    1.37@@ -116,31 +120,27 @@
    1.38 		error(sprint("handshake: %r"));
    1.39 	say("have handshake");
    1.40 
    1.41-	rqid: int;
    1.42-	red: ref Elem;
    1.43 	if(args == nil) {
    1.44 		de := Direntry.new();
    1.45 		de.uid = de.gid = de.mid = "vacfs";
    1.46 		de.ctime = de.atime = de.mtime = daytime->now();
    1.47 		de.mode = Vac->Modedir|8r555;
    1.48 		de.emode = Sys->DMDIR|8r555;
    1.49-		rqid = Qfakeroot;
    1.50-		red = Elem.mkdir(rqid, de, big 0, nil, rqid);
    1.51+		rootelem = Elem.mkdir(Qfakeroot, de, big 0, nil, Qfakeroot);
    1.52 	} else {
    1.53 		(vd, de, err) := vac->vdroot(session, *score);
    1.54 		if(err != nil)
    1.55 			error(err);
    1.56-		rqid = ++lastqid;
    1.57-		red = Elem.mkdir(rqid, de, big 0, vd, rqid);
    1.58+		qid := ++lastqid;
    1.59+		rootelem = Elem.mkdir(qid, de, big 0, vd, qid);
    1.60 	}
    1.61-	elemput(red);
    1.62 
    1.63 	navchan := chan of ref Navop;
    1.64 	nav := Navigator.new(navchan);
    1.65 	spawn navigator(navchan);
    1.66 
    1.67 	msgc: chan of ref Tmsg;
    1.68-	(msgc, srv) = Styxserver.new(sys->fildes(0), nav, big rqid);
    1.69+	(msgc, srv) = Styxserver.new(sys->fildes(0), nav, big rootelem.qid);
    1.70 
    1.71 serve:
    1.72 	while((mm := <-msgc) != nil)
    1.73@@ -149,52 +149,82 @@
    1.74 			fprint(fildes(2), "styx read: %s\n", m.error);
    1.75 			break serve;
    1.76 
    1.77+		Attach =>
    1.78+			f := srv.attach(m);
    1.79+			if(f != nil) {
    1.80+				p := getpath(int f.path);
    1.81+				if(p == nil)
    1.82+					putpath(p = ref Path(int f.path, 0, rootelem::nil));
    1.83+				p.nused++;
    1.84+			}
    1.85+
    1.86 		Read =>
    1.87 			if(dflag) say(sprint("have read, offset=%ubd count=%d", m.offset, m.count));
    1.88-			(c, err) := srv.canread(m);
    1.89-			if(c == nil){
    1.90+			(f, err) := srv.canread(m);
    1.91+			if(f == nil){
    1.92 				srv.reply(ref Rmsg.Error(m.tag, err));
    1.93 				continue;
    1.94 			}
    1.95-			if(c.qtype & Sys->QTDIR){
    1.96+			if(f.qtype & Sys->QTDIR){
    1.97 				srv.default(m);
    1.98 				continue;
    1.99 			}
   1.100 
   1.101-			ef := getfile(int c.path);
   1.102+			p := getpath(int f.path);
   1.103+			file: ref Elem.File;
   1.104+			pick e := hd p.elems {
   1.105+			File =>	file = e;
   1.106+			Dir =>	srv.reply(ref Rmsg.Error(m.tag, "internal error"));
   1.107+				continue;
   1.108+			}
   1.109 			n := m.count;
   1.110 			a := array[n] of byte;
   1.111-			have := ef.vf.pread(a, n, m.offset);
   1.112+			have := file.vf.pread(a, n, m.offset);
   1.113 			if(have < 0) {
   1.114 				srv.reply(ref Rmsg.Error(m.tag, sprint("%r")));
   1.115 				continue;
   1.116 			}
   1.117 			srv.reply(ref Rmsg.Read(m.tag, a[:have]));
   1.118 
   1.119+		Walk =>
   1.120+			f := srv.getfid(m.fid);
   1.121+			if(f == nil) {
   1.122+				srv.reply(ref Rmsg.Error(m.tag, styxservers->Ebadfid));
   1.123+				continue;
   1.124+			}
   1.125+			p := getpath(int f.path);
   1.126+			curelems = p.elems;
   1.127+			nf := srv.walk(m);
   1.128+			if(nf != nil) {
   1.129+				if(nf.fid == f.fid) {
   1.130+					if(--p.nused <= 0)
   1.131+						delpath(p);
   1.132+				}
   1.133+				putpath(p = ref Path(int nf.path, 0, curelems));
   1.134+				p.nused++;
   1.135+			}
   1.136+			curelems = nil;
   1.137+
   1.138 		Open =>
   1.139-			(c, mode, f, err) := canopen(m);
   1.140-			if(c == nil){
   1.141+			(f, mode, d, err) := canopen(m);
   1.142+			if(f == nil){
   1.143 				srv.reply(ref Rmsg.Error(m.tag, err));
   1.144 				continue;
   1.145 			}
   1.146-			c.open(mode, f.qid);
   1.147-			srv.reply(ref Rmsg.Open(m.tag, f.qid, srv.iounit()));
   1.148+			f.open(mode, d.qid);
   1.149+			srv.reply(ref Rmsg.Open(m.tag, d.qid, srv.iounit()));
   1.150 
   1.151-		Clunk =>
   1.152+		Clunk or Remove =>
   1.153 			f := srv.getfid(m.fid);
   1.154-			if(0 && f != nil) {
   1.155-				pick e := elemget(int f.path) {
   1.156-				Dir =>
   1.157-					if(e.pqid != Qfakeroot && --e.nused <= 0)
   1.158-						elemdel(e);
   1.159-					say(sprint("clunk dir qid=%d nused=%d", e.qid, e.nused));
   1.160-				File =>
   1.161-					if(--e.nused <= 0)
   1.162-						elemdel(e);
   1.163-					say(sprint("clunk file qid=%d nused=%d", e.qid, e.nused));
   1.164-				}
   1.165+			if(f != nil) {
   1.166+				p := getpath(int f.path);
   1.167+				if(--p.nused <= 0)
   1.168+					delpath(p);
   1.169 			}
   1.170-			srv.default(m);
   1.171+			if(tagof m == tagof Tmsg.Remove)
   1.172+				srv.reply(ref Rmsg.Error(m.tag, styxservers->Eperm));
   1.173+			else
   1.174+				srv.default(m);
   1.175 
   1.176 		* =>
   1.177 			srv.default(m);
   1.178@@ -230,19 +260,27 @@
   1.179 	while((navop := <-c) != nil)
   1.180 		pick n := navop {
   1.181 		Stat =>
   1.182-			n.reply <-= (elemget(int n.path).stat(), nil);
   1.183+			e := rootelem;
   1.184+			if(int n.path != rootelem.qid) {
   1.185+				p := getpath(int n.path);
   1.186+				if(p != nil) {
   1.187+					e = hd p.elems;
   1.188+				} else if(curelems != nil && (hd curelems).qid == int n.path) {
   1.189+					e = hd curelems;
   1.190+				} else {
   1.191+					n.reply <-= (nil, "internal error");
   1.192+					continue;
   1.193+				}
   1.194+			}
   1.195+			n.reply <-= (e.stat(), nil);
   1.196 
   1.197 		Walk =>
   1.198-			ed := getdir(int n.path);
   1.199-			(ne, err) := walk(ed, n.name);
   1.200+			(e, err) := walk(int n.path, n.name);
   1.201 			if(err != nil) {
   1.202 				n.reply <-= (nil, err);
   1.203 				continue;
   1.204 			}
   1.205-			ed.nused--;
   1.206-			ne.nused++;
   1.207-			if(dflag) say(sprint("walk from (qid=%d nused=%d) to (qid=%d nused=%d)", ed.qid, ed.nused, ne.qid, ne.nused));
   1.208-			n.reply <-= (ne.stat(), nil);
   1.209+			n.reply <-= (e.stat(), nil);
   1.210 
   1.211 		Readdir =>
   1.212 			if(dflag) say(sprint("have readdir path=%bd offset=%d count=%d", n.path, n.offset, n.count));
   1.213@@ -250,42 +288,88 @@
   1.214 				n.reply <-= (nil, nil);
   1.215 				continue;
   1.216 			}
   1.217-			ed := getdir(int n.path);
   1.218+
   1.219+			p := getpath(int n.path);
   1.220+			e: ref Elem.Dir;
   1.221+			pick ee := hd p.elems {
   1.222+			Dir =>	e = ee;
   1.223+			File =>	n.reply <-= (nil, "internal error");
   1.224+				continue;
   1.225+			}
   1.226 			if(n.offset == 0) {
   1.227-				ed.vd.rewind();
   1.228-				ed.prev = (-1, nil);
   1.229+				e.vd.rewind();
   1.230+				e.prev = (-1, nil);
   1.231 			}
   1.232 
   1.233 			# prev is needed because styxservers can request the previously returned Dir
   1.234-			(loffset, d) := ed.prev;
   1.235+			(loffset, d) := e.prev;
   1.236 			if(n.offset == loffset+1) {
   1.237-				(ok, de) := ed.vd.readdir();
   1.238+				(ok, de) := e.vd.readdir();
   1.239 				if(ok < 0) {
   1.240 					say(sprint("readdir error: %r"));
   1.241 					n.reply <-= (nil, sprint("reading directory: %r"));
   1.242 					continue;
   1.243 				}
   1.244 				if(de != nil) {
   1.245-					cqid := qidget(ed.qid, de.qid);
   1.246+					cqid := qidget(e.qid, de.qid);
   1.247 					if(cqid < 0)
   1.248-						cqid = qidput(ed.qid, de.qid);
   1.249-					ne := elemget(cqid);
   1.250-					if(ne == nil)
   1.251-						ne = Elem.new(cqid, ed.vd, de, ed.qid);
   1.252-					if(dflag) say(sprint("readdir, qidget(%d, %bd) = %d", ed.qid, de.qid, ne.qid));
   1.253-					ed.prev = (n.offset, ne.stat());
   1.254+						cqid = qidput(e.qid, de.qid);
   1.255+					ne := Elem.new(cqid, e.vd, de, e.qid);
   1.256+					e.prev = (n.offset, ne.stat());
   1.257 				} else {
   1.258-					ed.prev = (n.offset, nil);
   1.259+					e.prev = (n.offset, nil);
   1.260 				}
   1.261 			} else if(n.offset != loffset)
   1.262 				error("internal error");
   1.263-			(nil, d) = ed.prev;
   1.264+			(nil, d) = e.prev;
   1.265 			if(d != nil)
   1.266 				n.reply <-= (d, nil);
   1.267 			n.reply <-= (nil, nil);
   1.268 		}
   1.269 }
   1.270 
   1.271+walk(path: int, name: string): (ref Elem, string)
   1.272+{
   1.273+	if(name == "..") {
   1.274+		if(len curelems > 1)
   1.275+			curelems = tl curelems;
   1.276+		return (hd curelems, nil);
   1.277+	}
   1.278+
   1.279+	if(path == Qfakeroot) {
   1.280+		e := scoreget(name);
   1.281+		if(e == nil) {
   1.282+			(ok, score) := Score.parse(name);
   1.283+			if(ok != 0)
   1.284+				return (nil, "bad score");
   1.285+
   1.286+			(vd, de, err) := vac->vdroot(session, score);
   1.287+			if(err != nil)
   1.288+				return (nil, err);
   1.289+
   1.290+			e = Elem.mkdir(++lastqid, de, big 0, vd, rootelem.qid);
   1.291+			scoreput(name, e);
   1.292+		}
   1.293+		curelems = e::curelems;
   1.294+		return (hd curelems, nil);
   1.295+	}
   1.296+
   1.297+	pick e := hd curelems {
   1.298+	File =>
   1.299+		return (nil, styxservers->Enotdir);
   1.300+	Dir =>
   1.301+		de := e.vd.walk(name);
   1.302+		if(de == nil)
   1.303+			return (nil, sprint("%r"));
   1.304+		cqid := qidget(e.qid, de.qid);
   1.305+		if(cqid < 0)
   1.306+			cqid = qidput(e.qid, de.qid);
   1.307+		ne := Elem.new(cqid, e.vd, de, e.qid);
   1.308+		curelems = ne::curelems;
   1.309+		return (ne, nil);
   1.310+	}
   1.311+}
   1.312+
   1.313 qidget(qid: int, vqid: big): int
   1.314 {
   1.315 	for(l := qidmaps[qid % len qidmaps]; l != nil; l = tl l) {
   1.316@@ -316,25 +400,24 @@
   1.317 	return lastqid;
   1.318 }
   1.319 
   1.320-scoreget(score: string): ref Elem
   1.321+scoreget(score: string): ref Elem.Dir
   1.322 {
   1.323-	for(l := qidscores; l != nil; l = tl l) {
   1.324-		(s, n) := hd l;
   1.325+	for(l := scoreelems; l != nil; l = tl l) {
   1.326+		(s, e) := hd l;
   1.327 		if(s == score)
   1.328-			return elemget(n);
   1.329+			return e;
   1.330 	}
   1.331 	return nil;
   1.332 }
   1.333 
   1.334-scoreput(score: string): int
   1.335+scoreput(score: string, e: ref Elem.Dir)
   1.336 {
   1.337-	qidscores = (score, ++lastqid)::qidscores;
   1.338-	return lastqid;
   1.339+	scoreelems = (score, e)::scoreelems;
   1.340 }
   1.341 
   1.342 Elem.mkdir(qid: int, de: ref Direntry, size: big, vd: ref Vacdir, pqid: int): ref Elem.Dir
   1.343 {
   1.344-	return ref Elem.Dir(qid, de, size, 0, vd, pqid, (-1, nil));
   1.345+	return ref Elem.Dir(qid, de, size, vd, pqid, (-1, nil));
   1.346 }
   1.347 
   1.348 Elem.new(nqid: int, vd: ref Vacdir, de: ref Direntry, pqid: int): ref Elem
   1.349@@ -344,7 +427,7 @@
   1.350 		return nil;
   1.351 	if(de.mode & Vac->Modedir)
   1.352 		return Elem.mkdir(nqid, de, e.size, Vacdir.new(session, e, me), pqid);
   1.353-	return ref Elem.File(nqid, de, e.size, 0, Vacfile.new(session, e));
   1.354+	return ref Elem.File(nqid, de, e.size, Vacfile.new(session, e));
   1.355 }
   1.356 
   1.357 Elem.stat(e: self ref Elem): ref Sys->Dir
   1.358@@ -355,91 +438,34 @@
   1.359 	return d;
   1.360 }
   1.361 
   1.362-walk(ed: ref Elem.Dir, name: string): (ref Elem, string)
   1.363-{
   1.364-	if(name == "..")
   1.365-		return (elemget(ed.pqid), nil);
   1.366 
   1.367-	if(ed.qid == Qfakeroot) {
   1.368-		ne := scoreget(name);
   1.369-		if(ne == nil) {
   1.370-			(ok, score) := Score.parse(name);
   1.371-			if(ok != 0)
   1.372-				return (nil, "bad score");
   1.373-
   1.374-			(vd, de, err) := vac->vdroot(session, score);
   1.375-			if(err != nil)
   1.376-				return (nil, err);
   1.377+qidpaths := array[512] of list of ref Path;
   1.378+nqidpaths := 0;
   1.379 
   1.380-			nqid := scoreput(name);
   1.381-			ne = Elem.mkdir(nqid, de, big 0, vd, ed.qid);
   1.382-			elemput(ne);
   1.383-		}
   1.384-		return (ne, nil);
   1.385-	}
   1.386-
   1.387-	de := ed.vd.walk(name);
   1.388-	if(de == nil)
   1.389-		return (nil, sprint("%r"));
   1.390-	ne: ref Elem;
   1.391-	cqid := qidget(ed.qid, de.qid);
   1.392-	if(cqid < 0)
   1.393-		cqid = qidput(ed.qid, de.qid);
   1.394-	else
   1.395-		ne = elemget(cqid);
   1.396-	if(ne == nil) {
   1.397-		ne = Elem.new(cqid, ed.vd, de, ed.qid);
   1.398-		elemput(ne);
   1.399-	}
   1.400-	return (ne, nil);
   1.401+delpath(p: ref Path)
   1.402+{
   1.403+	i := p.path % len qidpaths;
   1.404+	r: list of ref Path;
   1.405+	for(l := qidpaths[i]; l != nil; l = tl l)
   1.406+		if(hd l != p)
   1.407+			r = hd l::r;
   1.408+		else
   1.409+			nqidpaths--;
   1.410+	qidpaths[i] = r;
   1.411 }
   1.412 
   1.413-elemget(qid: int): ref Elem
   1.414+putpath(p: ref Path)
   1.415 {
   1.416-	e := getdir(qid);
   1.417-	if(e != nil)
   1.418-		return e;
   1.419-	return getfile(qid);
   1.420-}
   1.421-
   1.422-elemput(e: ref Elem)
   1.423-{
   1.424-	pick ee := e {
   1.425-	File =>	fileelems[e.qid % len fileelems] = ee::fileelems[e.qid % len fileelems];
   1.426-	Dir =>	direlems[e.qid % len direlems] = ee::direlems[e.qid % len direlems];
   1.427-	}
   1.428+	i := p.path % len qidpaths;
   1.429+	qidpaths[i] = p::qidpaths[i];
   1.430+	nqidpaths++;
   1.431 }
   1.432 
   1.433-remove[T](l: list of T, e: T): list of T
   1.434-{
   1.435-	r: list of T;
   1.436-	for(; l != nil; l = tl l)
   1.437-		if(hd l != e)
   1.438-			r = hd l::r;
   1.439-	return r;
   1.440-}
   1.441-
   1.442-elemdel(e: ref Elem)
   1.443+getpath(path: int): ref Path
   1.444 {
   1.445-	i := e.qid % Mapsize;
   1.446-	pick ee := e {
   1.447-	File =>	fileelems[i] = remove(fileelems[i], ee);
   1.448-	Dir =>	direlems[i] = remove(direlems[i], ee);
   1.449-	}
   1.450-}
   1.451-
   1.452-getfile(qid: int): ref Elem.File
   1.453-{
   1.454-	for(l := fileelems[qid % len fileelems]; l != nil; l = tl l)
   1.455-		if((hd l).qid == qid)
   1.456-			return hd l;
   1.457-	return nil;
   1.458-}
   1.459-
   1.460-getdir(qid: int): ref Elem.Dir
   1.461-{
   1.462-	for(l := direlems[qid % len direlems]; l != nil; l = tl l)
   1.463-		if((hd l).qid == qid)
   1.464+	i := path % len qidpaths;
   1.465+	for(l := qidpaths[i]; l != nil; l = tl l)
   1.466+		if((hd l).path == path)
   1.467 			return hd l;
   1.468 	return nil;
   1.469 }