Пример #1
0
int
loadbloom(Bloom *b)
{
	int i, n;
	uint ones;
	uchar *data;
	u32int *a;
	
	data = vtmallocz(b->size);
	if(readpart(b->part, 0, data, b->size) < 0){
		vtfree(b);
		vtfree(data);
		return -1;
	}
	b->data = data;

	a = (u32int*)b->data;
	n = b->size/4;
	ones = 0;
	for(i=0; i<n; i++)
		ones += countbits(a[i]); 
	addstat(StatBloomOnes, ones);

	if(b->size == MaxBloomSize)	/* 2^32 overflows ulong */
		addstat(StatBloomBits, b->size*8-1);
	else
		addstat(StatBloomBits, b->size*8);
		
	return 0;
}
Пример #2
0
static void
listenproc(void *v)
{
	int ctl;
	char dir[NETPATHLEN];
	VtSrv *srv;
	VtSconn *sc;

	srv = v;
	for(;;){
		ctl = listen(srv->adir, dir);
		if(ctl < 0){
			srv->dead = 1;
			break;
		}
		sc = vtmallocz(sizeof(VtSconn));
		sc->ref = 1;
		sc->ctl = ctl;
		sc->srv = srv;
		strcpy(sc->dir, dir);
		proccreate(connproc, sc, STACK);
	}

	/* hangup */
}
Пример #3
0
Bloom*
readbloom(Part *p)
{
	uchar buf[512];
	Bloom *b;
	
	b = vtmallocz(sizeof *b);
	if(readpart(p, 0, buf, sizeof buf) < 0)
		return nil;
	/*
	 * pass buf as b->data so that bloominit
	 * can parse header.  won't be used for
	 * accessing bits (cleared below).
	 */
	if(bloominit(b, 0, buf) < 0){
		vtfree(b);
		return nil;
	}else{
		/*
		 * default block size is system page size.
		 * the bloom filter is usually very big.
		 * bump the block size up to speed i/o.
		 */
		if(p->blocksize < (1<<20)){
			p->blocksize = 1<<20;
			if(p->blocksize > p->size)
				p->blocksize = p->size;
		}
	}
	b->part = p;
	b->data = nil;
	return b;
}
Пример #4
0
void
threadmain(int argc, char *argv[])
{
	int i, n;
	unsigned char score[VtScoreSize];
	unsigned char *buf;
	VtConn *z;
	char *host;
	VtRoot root;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('V', vtscorefmt);
	quotefmtinstall();

	host = nil;
	ARGBEGIN{
	case 'h':
		host = EARGF(usage());
		break;
	default:
		usage();
		break;
	}ARGEND

	if(argc == 0)
		usage();

	buf = vtmallocz(VtMaxLumpSize);

	z = vtdial(host);
	if(z == nil)
		sysfatal("could not connect to server: %r");

	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");

	for(i=0; i<argc; i++){
		if(vtparsescore(argv[i], nil, score) < 0){
			fprint(2, "cannot parse score '%s': %r\n", argv[i]);
			continue;
		}
		n = vtread(z, score, VtRootType, buf, VtMaxLumpSize);
		if(n < 0){
			fprint(2, "could not read block %V: %r\n", score);
			continue;
		}
		if(n != VtRootSize){
			fprint(2, "block %V is wrong size %d != 300\n", score, n);
			continue;
		}
		if(vtrootunpack(&root, buf) < 0){
			fprint(2, "unpacking block %V: %r\n", score);
			continue;
		}
		print("%V: %q %q %V %d %V\n", score, root.name, root.type, root.score, root.blocksize, root.prev);
	}
	vthangup(z);
	threadexitsall(0);
}
Пример #5
0
Queue*
qalloc(void)
{
	Queue *q;

	q = vtmallocz(sizeof(Queue));
	q->r.l = &q->lk;
	return q;
}
Пример #6
0
void
initicache(u32int mem0)
{
	u32int mem;
	int i, entries, scache;
	
	icache.full.l = &icache.lock;

	mem = mem0;
	entries = mem / (sizeof(IEntry)+sizeof(IEntry*));
	scache = (entries/8) / ArenaCIGSize;
	entries -= entries/8;
	if(scache < 4)
		scache = 4;
	if(scache > 16)
		scache = 16;
	if(entries < 1000)
		entries = 1000;
fprint(2, "icache %,d bytes = %,d entries; %d scache\n", mem0, entries, scache);

	icache.clean.prev = icache.clean.next = &icache.clean;
	icache.dirty.prev = icache.dirty.next = &icache.dirty;
	icache.free.prev = icache.free.next = &icache.free;
	
	icache.hash = mkihash(entries);
	icache.nentries = entries;
	setstat(StatIcacheSize, entries);
	icache.entries = vtmallocz(entries*sizeof icache.entries[0]);
	icache.maxdirty = entries / 2;
	for(i=0; i<entries; i++)
		pushfirst(&icache.free, &icache.entries[i]);

	icache.nsum = scache;
	icache.sum = vtmallocz(scache*sizeof icache.sum[0]);
	icache.sum[0] = vtmallocz(scache*sizeof icache.sum[0][0]);
	icache.nsentries = scache * ArenaCIGSize;
	icache.sentries = vtmallocz(scache*ArenaCIGSize*sizeof icache.sentries[0]);
	icache.shash = mkihash(scache*ArenaCIGSize);
	for(i=0; i<scache; i++){
		icache.sum[i] = icache.sum[0] + i;
		icache.sum[i]->entries = icache.sentries + i*ArenaCIGSize;
	}
}
Пример #7
0
static File *
fileAlloc(Fs *fs)
{
	File *f;

	f = vtmallocz(sizeof(File));
	f->ref = 1;
	f->fs = fs;
	f->boff = NilBlock;
	f->mode = fs->mode;
	return f;
}
Пример #8
0
int
resetbloom(Bloom *b)
{
	uchar *data;
	
	data = vtmallocz(b->size);
	b->data = data;
	if(b->size == MaxBloomSize)	/* 2^32 overflows ulong */
		addstat(StatBloomBits, b->size*8-1);
	else
		addstat(StatBloomBits, b->size*8);
	return 0;
}
Пример #9
0
void
threadmain(int argc, char *argv[])
{
	char *host;
	int dotrunc, n, type;
	uchar *p, score[VtScoreSize];
	VtConn *z;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('V', vtscorefmt);

	host = nil;
	dotrunc = 0;
	type = VtDataType;
	ARGBEGIN{
	case 'z':
		dotrunc = 1;
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 't':
		type = atoi(EARGF(usage()));
		break;
	default:
		usage();
		break;
	}ARGEND

	if(argc != 0)
		usage();

	p = vtmallocz(VtMaxLumpSize+1);
	n = readn(0, p, VtMaxLumpSize+1);
	if(n > VtMaxLumpSize)
		sysfatal("input too big: max block size is %d", VtMaxLumpSize);
	z = vtdial(host);
	if(z == nil)
		sysfatal("could not connect to server: %r");
	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");
	if(dotrunc)
		n = vtzerotruncate(type, p, n);
	if(vtwrite(z, score, type, p, n) < 0)
		sysfatal("vtwrite: %r");
	vthangup(z);
	print("%V\n", score);
	threadexitsall(0);
}
Пример #10
0
Periodic *
periodicAlloc(void (*f)(void*), void *a, int msec)
{
	Periodic *p;

	p = vtmallocz(sizeof(Periodic));
	p->f = f;
	p->a = a;
	p->msec = msec;
	if(p->msec < 10)
		p->msec = 10;

	proccreate(periodicThread, p, STACK);
	return p;
}
Пример #11
0
VtSrv*
vtlisten(char *addr)
{
	VtSrv *s;

	s = vtmallocz(sizeof(VtSrv));
	s->afd = announce(addr, s->adir);
	if(s->afd < 0){
		free(s);
		return nil;
	}
	s->q = _vtqalloc();
	proccreate(listenproc, s, STACK);
	return s;
}
Пример #12
0
static IHash*
mkihash(int size1)
{
	u32int size;
	int bits;
	IHash *ih;
	
	bits = 0;
	size = 1;
	while(size < size1){
		bits++;
		size <<= 1;
	}
	
	ih = vtmallocz(sizeof(IHash)+size*sizeof(ih->table[0]));
	ih->table = (IEntry**)(ih+1);
	ih->bits = bits;
	ih->size = size;
	return ih;
}
Пример #13
0
VtConn*
vtconn(int infd, int outfd)
{
	VtConn *z;
	NetConnInfo *nci;

	z = vtmallocz(sizeof(VtConn));
	z->tagrend.l = &z->lk;
	z->rpcfork.l = &z->lk;
	z->infd = infd;
	z->outfd = outfd;
	z->part = packetalloc();
	nci = getnetconninfo(nil, infd);
	if(nci == nil)
		snprint(z->addr, sizeof z->addr, "/dev/fd/%d", infd);
	else{
		strecpy(z->addr, z->addr+sizeof z->addr, nci->raddr);
		freenetconninfo(nci);
	}
	return z;
}
Пример #14
0
Fid *
newfid(int fid)
{
	Fid *f, *ff;

	ff = 0;
	for(f = fids; f; f = f->next)
		if(f->fid == fid)
			return f;
		else if(!ff && !f->busy)
			ff = f;
	if(ff){
		ff->fid = fid;
		return ff;
	}
	f = vtmallocz(sizeof *f);
	f->fid = fid;
	f->next = fids;
	fids = f;
	return f;
}
Пример #15
0
DirEntryEnum *
deeOpen(File *f)
{
	DirEntryEnum *dee;
	File *p;

	if(!fileIsDir(f)){
		werrstr(ENotDir);
		fileDecRef(f);
		return nil;
	}

	/* flush out meta data */
	if(!fileLock(f))
		return nil;
	for(p=f->down; p; p=p->next)
		fileMetaFlush2(p, nil);
	fileUnlock(f);

	dee = vtmallocz(sizeof(DirEntryEnum));
	dee->file = fileIncRef(f);

	return dee;
}
Пример #16
0
static void
connproc(void *v)
{
	VtSconn *sc;
	VtConn *c;
	Packet *p;
	VtReq *r;
	int fd;
static int first=1;

if(first && chattyventi){
	first=0;
	fmtinstall('F', vtfcallfmt);
}
	r = nil;
	sc = v;
	sc->c = nil;
	if(0) fprint(2, "new call %s on %d\n", sc->dir, sc->ctl);
	fd = accept(sc->ctl, sc->dir);
	close(sc->ctl);
	if(fd < 0){
		fprint(2, "accept %s: %r\n", sc->dir);
		goto out;
	}

	c = vtconn(fd, fd);
	sc->c = c;
	if(vtversion(c) < 0){
		fprint(2, "vtversion %s: %r\n", sc->dir);
		goto out;
	}
	if(vtsrvhello(c) < 0){
		fprint(2, "vtsrvhello %s: %r\n", sc->dir);
		goto out;
	}

	if(0) fprint(2, "new proc %s\n", sc->dir);
	proccreate(vtsendproc, c, STACK);
	qlock(&c->lk);
	while(!c->writeq)
		rsleep(&c->rpcfork);
	qunlock(&c->lk);

	while((p = vtrecv(c)) != nil){
		r = vtmallocz(sizeof(VtReq));
		if(vtfcallunpack(&r->tx, p) < 0){
			vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv bad packet %p: %r<br>\n", c->addr, p);
			fprint(2, "bad packet on %s: %r\n", sc->dir);
			packetfree(p);
			continue;
		}
		vtlog(VtServerLog, "<font size=-1>%T %s:</font> recv packet %p (%F)<br>\n", c->addr, p, &r->tx);
		if(chattyventi)
			fprint(2, "%s <- %F\n", argv0, &r->tx);
		packetfree(p);
		if(r->tx.msgtype == VtTgoodbye)
			break;
		r->rx.tag = r->tx.tag;
		r->sc = sc;
		scincref(sc);
		if(_vtqsend(sc->srv->q, r) < 0){
			scdecref(sc);
			fprint(2, "hungup queue\n");
			break;
		}
		r = nil;
	}

	if(0) fprint(2, "eof on %s\n", sc->dir);

out:
	if(r){
		vtfcallclear(&r->tx);
		vtfree(r);
	}
	if(0) fprint(2, "freed %s\n", sc->dir);
	scdecref(sc);
	return;
}
Пример #17
0
void
main(int argc, char *argv[])
{
	int type, n;
	unsigned char score[VtScoreSize];
	unsigned char *buf;
	char *prefix;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('V', vtscorefmt);

	type = -1;
	ARGBEGIN{
	case 'V':
		chattyventi++;
		break;
	case 'f':
		fast = 1;
		break;
	case 'i':
		if(rewrite)
			usage();
		ignoreerrors = 1;
		break;
	case 'm':
		scoretree = mkavltree(scoretreecmp);
		break;
	case 'r':
		if(ignoreerrors)
			usage();
		rewrite = 1;
		break;
	case 't':
		type = atoi(EARGF(usage()));
		break;
	case 'v':
		verbose = 1;
		break;
	default:
		usage();
		break;
	}ARGEND

	if(argc != 3)
		usage();

	if(vtparsescore(argv[2], &prefix, score) < 0)
		sysfatal("could not parse score: %r");

	buf = vtmallocz(VtMaxLumpSize);

	zsrc = vtdial(argv[0]);
	if(zsrc == nil)
		sysfatal("could not dial src server: %r");
	if(vtconnect(zsrc) < 0)
		sysfatal("vtconnect src: %r");

	zdst = vtdial(argv[1]);
	if(zdst == nil)
		sysfatal("could not dial dst server: %r");
	if(vtconnect(zdst) < 0)
		sysfatal("vtconnect dst: %r");

	if(type != -1){
		n = vtread(zsrc, score, type, buf, VtMaxLumpSize);
		if(n < 0)
			sysfatal("could not read block: %r");
	}else{
		for(type=0; type<VtMaxType; type++){
			n = vtread(zsrc, score, type, buf, VtMaxLumpSize);
			if(n >= 0)
				break;
		}
		if(type == VtMaxType)
			sysfatal("could not find block %V of any type", score);
	}

	walk(score, type, VtDirType);
	if(changes)
		print("%s:%V (%d pointers rewritten)\n", prefix, score, changes);

	if(verbose)
		print("%d skipped, %d written\n", nskip, nwrite);

	if(vtsync(zdst) < 0)
		sysfatal("could not sync dst server: %r");

	exits(0);
}
Пример #18
0
void
threadmain(int argc, char *argv[])
{
	int type, n;
	uchar score[VtScoreSize];
	uchar *buf;
	VtConn *z;
	char *host;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('V', vtscorefmt);

	host = nil;
	type = -1;
	ARGBEGIN{
	case 'h':
		host = EARGF(usage());
		break;
	case 't':
		type = atoi(EARGF(usage()));
		break;
	default:
		usage();
		break;
	}ARGEND

	if(argc != 1)
		usage();

	if(vtparsescore(argv[0], nil, score) < 0)
		sysfatal("could not parse score '%s': %r", argv[0]);

	buf = vtmallocz(VtMaxLumpSize);

	z = vtdial(host);
	if(z == nil)
		sysfatal("could not connect to server: %r");

	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");

	if(type == -1){
		n = -1;
		for(type=0; type<VtMaxType; type++){
			n = vtread(z, score, type, buf, VtMaxLumpSize);
			if(n >= 0){
				fprint(2, "venti/read%s%s %V %d\n", host ? " -h" : "", host ? host : "",
					score, type);
				break;
			}
		}
	}else
		n = vtread(z, score, type, buf, VtMaxLumpSize);

	vthangup(z);
	if(n < 0)
		sysfatal("could not read block: %r");
	if(write(1, buf, n) != n)
		sysfatal("write: %r");
	threadexitsall(0);
}
Пример #19
0
void
threadmain(int argc, char **argv)
{
	char *pref, *mountname, *mountplace;
	uchar score[VtScoreSize], prev[VtScoreSize];
	int i, fd, csize;
	vlong bsize;
	Tm tm;
	VtEntry e;
	VtBlock *b;
	VtCache *c;
	VtRoot root;
	char *tmp, *tmpnam;

	fmtinstall('F', vtfcallfmt);
	fmtinstall('H', encodefmt);
	fmtinstall('T', timefmt);
	fmtinstall('V', vtscorefmt);

	mountname = sysname();
	mountplace = nil;
	ARGBEGIN{
	default:
		usage();
		break;
	case 'D':
		debug++;
		break;
	case 'V':
		chattyventi = 1;
		break;
	case 'f':
		fastwrites = 1;
		break;
	case 'i':
		incremental = 1;
		break;
	case 'm':
		mountname = EARGF(usage());
		break;
	case 'M':
		mountplace = EARGF(usage());
		i = strlen(mountplace);
		if(i > 0 && mountplace[i-1] == '/')
			mountplace[i-1] = 0;
		break;
	case 'n':
		nop = 1;
		break;
	case 's':
		statustime = atoi(EARGF(usage()));
		break;
	case 'v':
		verbose = 1;
		break;
	case 'w':
		nwritethread = atoi(EARGF(usage()));
		break;
	}ARGEND

	if(argc != 1 && argc != 2)
		usage();

	if(statustime)
		print("# %T vbackup %s %s\n", argv[0], argc>=2 ? argv[1] : "");

	/*
	 * open fs
	 */
	if((disk = diskopenfile(argv[0])) == nil)
		sysfatal("diskopen: %r");
	if((disk = diskcache(disk, 32768, 2*MAXQ+16)) == nil)
		sysfatal("diskcache: %r");
	if((fsys = fsysopen(disk)) == nil)
		sysfatal("fsysopen: %r");

	/*
	 * connect to venti
	 */
	if((z = vtdial(nil)) == nil)
		sysfatal("vtdial: %r");
	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");

	/*
	 * set up venti block cache
	 */
	zero = vtmallocz(fsys->blocksize);
	bsize = fsys->blocksize;
	csize = 50;	/* plenty; could probably do with 5 */

	if(verbose)
		fprint(2, "cache %d blocks\n", csize);
	c = vtcachealloc(z, bsize*csize);
	zcache = c;

	/*
	 * parse starting score
	 */
	memset(prev, 0, sizeof prev);
	if(argc == 1){
		vfile = vtfilecreateroot(c, (fsys->blocksize/VtScoreSize)*VtScoreSize,
			fsys->blocksize, VtDataType);
		if(vfile == nil)
			sysfatal("vtfilecreateroot: %r");
		vtfilelock(vfile, VtORDWR);
		if(vtfilewrite(vfile, zero, 1, bsize*fsys->nblock-1) != 1)
			sysfatal("vtfilewrite: %r");
		if(vtfileflush(vfile) < 0)
			sysfatal("vtfileflush: %r");
	}else{
		if(vtparsescore(argv[1], &pref, score) < 0)
			sysfatal("bad score: %r");
		if(pref!=nil && strcmp(pref, fsys->type) != 0)
			sysfatal("score is %s but fsys is %s", pref, fsys->type);
		b = vtcacheglobal(c, score, VtRootType, VtRootSize);
		if(b){
			if(vtrootunpack(&root, b->data) < 0)
				sysfatal("bad root: %r");
			if(strcmp(root.type, fsys->type) != 0)
				sysfatal("root is %s but fsys is %s", root.type, fsys->type);
			memmove(prev, score, VtScoreSize);
			memmove(score, root.score, VtScoreSize);
			vtblockput(b);
		}
		b = vtcacheglobal(c, score, VtDirType, VtEntrySize);
		if(b == nil)
			sysfatal("vtcacheglobal %V: %r", score);
		if(vtentryunpack(&e, b->data, 0) < 0)
			sysfatal("%V: vtentryunpack failed", score);
		if(verbose)
			fprint(2, "entry: size %llud psize %d dsize %d\n",
				e.size, e.psize, e.dsize);
		vtblockput(b);
		if((vfile = vtfileopenroot(c, &e)) == nil)
			sysfatal("vtfileopenroot: %r");
		vtfilelock(vfile, VtORDWR);
		if(e.dsize != bsize)
			sysfatal("file system block sizes don't match %d %lld", e.dsize, bsize);
		if(e.size != fsys->nblock*bsize)
			sysfatal("file system block counts don't match %lld %lld", e.size, fsys->nblock*bsize);
	}

	tmpnam = nil;
	if(incremental){
		if(vtfilegetentry(vfile, &e) < 0)
			sysfatal("vtfilegetentry: %r");
		if((vscores = vtfileopenroot(c, &e)) == nil)
			sysfatal("vtfileopenroot: %r");
		vtfileunlock(vfile);
	}else{
		/*
		 * write scores of blocks into temporary file
		 */
		if((tmp = getenv("TMP")) != nil){
			/* okay, good */
		}else if(access("/var/tmp", 0) >= 0)
			tmp = "/var/tmp";
		else
			tmp = "/tmp";
		tmpnam = smprint("%s/vbackup.XXXXXX", tmp);
		if(tmpnam == nil)
			sysfatal("smprint: %r");
	
		if((fd = opentemp(tmpnam, ORDWR|ORCLOSE)) < 0)
			sysfatal("opentemp %s: %r", tmpnam);
		if(statustime)
			print("# %T reading scores into %s\n", tmpnam);
		if(verbose)
			fprint(2, "read scores into %s...\n", tmpnam);
	
		Binit(&bscores, fd, OWRITE);
		for(i=0; i<fsys->nblock; i++){
			if(vtfileblockscore(vfile, i, score) < 0)
				sysfatal("vtfileblockhash %d: %r", i);
			if(Bwrite(&bscores, score, VtScoreSize) != VtScoreSize)
				sysfatal("Bwrite: %r");
		}
		Bterm(&bscores);
		vtfileunlock(vfile);
	
		/*
		 * prep scores for rereading
		 */
		seek(fd, 0, 0);
		Binit(&bscores, fd, OREAD);
	}

	/*
	 * start the main processes 
	 */
	if(statustime)
		print("# %T starting procs\n");
	qcmp = qalloc();
	qventi = qalloc();

	rlock(&endlk);
	proccreate(fsysproc, nil, STACK);
	rlock(&endlk);
	proccreate(ventiproc, nil, STACK);
	rlock(&endlk);
	proccreate(cmpproc, nil, STACK);
	if(statustime){
		rlock(&endlk);
		proccreate(statusproc, nil, STACK);
	}

	/*
	 * wait for processes to finish
	 */
	wlock(&endlk);
	
	qfree(qcmp);
	qfree(qventi);

	if(statustime)
		print("# %T procs exited: %d of %d %d-byte blocks changed, "
			"%d read, %d written, %d skipped, %d copied\n",
			nchange, fsys->nblock, fsys->blocksize,
			vtcachenread, vtcachenwrite, nskip, vtcachencopy);

	/*
	 * prepare root block
	 */
	if(incremental)
		vtfileclose(vscores);
	vtfilelock(vfile, -1);
	if(vtfileflush(vfile) < 0)
		sysfatal("vtfileflush: %r");
	if(vtfilegetentry(vfile, &e) < 0)
		sysfatal("vtfilegetentry: %r");
	vtfileunlock(vfile);
	vtfileclose(vfile);

	b = vtcacheallocblock(c, VtDirType, VtEntrySize);
	if(b == nil)
		sysfatal("vtcacheallocblock: %r");
	vtentrypack(&e, b->data, 0);
	if(vtblockwrite(b) < 0)
		sysfatal("vtblockwrite: %r");

	memset(&root, 0, sizeof root);
	strecpy(root.name, root.name+sizeof root.name, argv[0]);
	strecpy(root.type, root.type+sizeof root.type, fsys->type);
	memmove(root.score, b->score, VtScoreSize);
	root.blocksize = fsys->blocksize;
	memmove(root.prev, prev, VtScoreSize);
	vtblockput(b);

	b = vtcacheallocblock(c, VtRootType, VtRootSize);
	if(b == nil)
		sysfatal("vtcacheallocblock: %r");
	vtrootpack(&root, b->data);
	if(vtblockwrite(b) < 0)
		sysfatal("vtblockwrite: %r");

	tm = *localtime(time(0));
	tm.year += 1900;
	tm.mon++;
	if(mountplace == nil)
		mountplace = guessmountplace(argv[0]);
	print("mount /%s/%d/%02d%02d%s %s:%V %d/%02d%02d/%02d%02d\n",
		mountname, tm.year, tm.mon, tm.mday, 
		mountplace,
		root.type, b->score,
		tm.year, tm.mon, tm.mday, tm.hour, tm.min);
	print("# %T %s %s:%V\n", argv[0], root.type, b->score);
	if(statustime)
		print("# %T venti sync\n");
	vtblockput(b);
	if(vtsync(z) < 0)
		sysfatal("vtsync: %r");
	if(statustime)
		print("# %T synced\n");
	
	fsysclose(fsys);
	diskclose(disk);
	vtcachefree(zcache);

	// Vtgoodbye hangs on Linux - not sure why.
	// Probably vtfcallrpc doesn't quite get the
	// remote hangup right.  Also probably related
	// to the vtrecvproc problem below.
	// vtgoodbye(z);

	// Leak here, because I can't seem to make
	// the vtrecvproc exit.
	// vtfreeconn(z);

	free(tmpnam);
	z = nil;
	zcache = nil;
	fsys = nil;
	disk = nil;
	threadexitsall(nil);
}
Пример #20
0
void
walk(uint8_t score[VtScoreSize], uint type, int base)
{
	int i, n;
	uint8_t *buf;
	uint8_t nscore[VtScoreSize];
	VtEntry e;
	VtRoot root;

	if(memcmp(score, vtzeroscore, VtScoreSize) == 0 || memcmp(score, zeroscore, VtScoreSize) == 0)
		return;

	if(havevisited(score, type)){
		nskip++;
		return;
	}

	buf = vtmallocz(VtMaxLumpSize);
	if(fast && vtread(zdst, score, type, buf, VtMaxLumpSize) >= 0){
		if(verbose)
			fprint(2, "skip %V\n", score);
		free(buf);
		return;
	}

	n = vtread(zsrc, score, type, buf, VtMaxLumpSize);
	if(n < 0){
		if(rewrite){
			changes++;
			memmove(score, vtzeroscore, VtScoreSize);
		}else if(!ignoreerrors)
			sysfatal("reading block %V (type %d): %r", score, type);
		return;
	}

	switch(type){
	case VtRootType:
		if(vtrootunpack(&root, buf) < 0){
			fprint(2, "warning: could not unpack root in %V %d\n", score, type);
			break;
		}
		walk(root.prev, VtRootType, 0);
		walk(root.score, VtDirType, 0);
		if(rewrite)
			vtrootpack(&root, buf);	/* walk might have changed score */
		break;

	case VtDirType:
		for(i=0; i*VtEntrySize<n; i++){
			if(vtentryunpack(&e, buf, i) < 0){
				fprint(2, "warning: could not unpack entry #%d in %V %d\n", i, score, type);
				continue;
			}
			if(!(e.flags & VtEntryActive))
				continue;
			walk(e.score, e.type, e.type&VtTypeBaseMask);
			/*
			 * Don't repack unless we're rewriting -- some old
			 * vac files have psize==0 and dsize==0, and these
			 * get rewritten by vtentryunpack to have less strange
			 * block sizes.  So vtentryunpack; vtentrypack does not
			 * guarantee to preserve the exact bytes in buf.
			 */
			if(rewrite)
				vtentrypack(&e, buf, i);
		}
		break;

	case VtDataType:
		break;

	default:	/* pointers */
		for(i=0; i<n; i+=VtScoreSize)
			if(memcmp(buf+i, vtzeroscore, VtScoreSize) != 0)
				walk(buf+i, type-1, base);
		break;
	}

	nwrite++;
	if(vtwrite(zdst, nscore, type, buf, n) < 0){
		/* figure out score for better error message */
		/* can't use input argument - might have changed contents */
		n = vtzerotruncate(type, buf, n);
		sha1(buf, n, score, nil);
		sysfatal("writing block %V (type %d): %r", score, type);
	}
	if(!rewrite && memcmp(score, nscore, VtScoreSize) != 0){
		fprint(2, "not rewriting: wrote %V got %V\n", score, nscore);
		abort();
		sysfatal("not rewriting: wrote %V got %V", score, nscore);
	}
	markvisited(score, type);
	free(buf);
}
Пример #21
0
void
threadmain(int argc, char *argv[])
{
	int i, printstats;
	char *host;
	VacFile *f;

	fmtinstall('H', encodefmt);
	fmtinstall('V', vtscorefmt);
	fmtinstall('F', vtfcallfmt);
	fmtinstall('t', mtimefmt);
	fmtinstall('M', dirmodefmt);
	
	host = nil;
	printstats = 0;

	ARGBEGIN{
	case 'T':
		settimes = 1;
		break;
	case 'V':
		chattyventi = 1;
		break;
	case 'c':
		tostdout++;
		break;
	case 'd':
		diff++;
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 's':
		printstats++;
		break;
	case 't':
		table++;
		break;
	case 'v':
		chatty++;
		break;
	default:
		usage();
	}ARGEND

	if(argc < 1)
		usage();

	if(tostdout && diff){
		fprint(2, "cannot use -c with -d\n");
		usage();
	}

	conn = vtdial(host);
	if(conn == nil)
		sysfatal("could not connect to server: %r");

	if(vtconnect(conn) < 0)
		sysfatal("vtconnect: %r");

	fs = vacfsopen(conn, argv[0], VtOREAD, 128);
	if(fs == nil)
		sysfatal("vacfsopen: %r");

	nwant = argc-1;
	want = argv+1;
	found = vtmallocz(nwant*sizeof found[0]);

	if((f = vacfsgetroot(fs)) == nil)
		sysfatal("vacfsgetroot: %r");
	
	unvac(f, nil, nil);
	for(i=0; i<nwant; i++){
		if(want[i] && !found[i]){
			fprint(2, "warning: didn't find %s\n", want[i]);
			errors++;
		}
	}
	if(errors)
		threadexitsall("errors");
	if(printstats)
		fprint(2, "%lld bytes read, %lld bytes skipped\n",
			stats.data, stats.skipdata);
	threadexitsall(0);
}
Пример #22
0
void
threadmain(int argc, char *argv[])
{
	int n;
	uchar score[VtScoreSize];
	uchar *buf;
	char *host, *type;
	vlong off;
	VtEntry e;
	VtRoot root;
	VtCache *c;
	VtConn *z;
	VtFile *f;

	quotefmtinstall();
	fmtinstall('F', vtfcallfmt);
	fmtinstall('V', vtscorefmt);

	host = nil;
	ARGBEGIN{
	case 'V':
		chattyventi++;
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 'v':
		chatty++;
		break;
	default:
		usage();
		break;
	}ARGEND

	if(argc != 1)
		usage();

	type = nil;
	if(vtparsescore(argv[0], &type, score) < 0)
		sysfatal("could not parse score '%s': %r", argv[0]);
	if(type == nil || strcmp(type, "file") != 0)
		sysfatal("bad score - not file:...");

	buf = vtmallocz(VtMaxLumpSize);

	z = vtdial(host);
	if(z == nil)
		sysfatal("could not connect to server: %r");

	if(vtconnect(z) < 0)
		sysfatal("vtconnect: %r");

	// root block ...
	n = vtread(z, score, VtRootType, buf, VtMaxLumpSize);
	if(n < 0)
		sysfatal("could not read root %V: %r", score);
	if(n != VtRootSize)
		sysfatal("root block %V is wrong size %d != %d", score, n, VtRootSize);
	if(vtrootunpack(&root, buf) < 0)
		sysfatal("unpacking root block %V: %r", score);
	if(strcmp(root.type, "file") != 0)
		sysfatal("bad root type %q (not 'file')", root.type);
	if(chatty)
		fprint(2, "%V: %q %q %V %d %V\n",
			score, root.name, root.type,
			root.score, root.blocksize, root.prev);

	// ... points at entry block
	n = vtread(z, root.score, VtDirType, buf, VtMaxLumpSize);
	if(n < 0)
		sysfatal("could not read entry %V: %r", root.score);
	if(n != VtEntrySize)
		sysfatal("dir block %V is wrong size %d != %d", root.score, n, VtEntrySize);
	if(vtentryunpack(&e, buf, 0) < 0)
		sysfatal("unpacking dir block %V: %r", root.score);
	if((e.type&VtTypeBaseMask) != VtDataType)
		sysfatal("not a single file");

	// open and read file
	c = vtcachealloc(z, root.blocksize*32);
	if(c == nil)
		sysfatal("vtcachealloc: %r");
	f = vtfileopenroot(c, &e);
	if(f == nil)
		sysfatal("vtfileopenroot: %r");
	off = 0;
	vtfilelock(f, VtOREAD);
	while((n = vtfileread(f, buf, VtMaxLumpSize, off)) > 0){
		write(1, buf, n);
		off += n;
	}
	threadexitsall(0);
}
Пример #23
0
Packet*
_vtrpc(VtConn *z, Packet *p, VtFcall *tx)
{
	int i;
	uchar tag, buf[2], *top;
	Rwait *r, *rr;

	/* must malloc because stack could be private */
	r = vtmallocz(sizeof(Rwait));

	qlock(&z->lk);
	r->r.l = &z->lk;
	tag = gettag(z, r);
	if(tx){
		/* vtfcallrpc can't print packet because it doesn't have tag */
		tx->tag = tag;
		if(chattyventi)
			fprint(2, "%s -> %F\n", argv0, tx);
	}

	/* slam tag into packet */
	top = packetpeek(p, buf, 0, 2);
	if(top == nil){
		packetfree(p);
		return nil;
	}
	if(top == buf){
		werrstr("first two bytes must be in same packet fragment");
		packetfree(p);
		vtfree(r);
		return nil;
	}
	top[1] = tag;
	qunlock(&z->lk);
	if(vtsend(z, p) < 0){
		vtfree(r);
		return nil;
	}

	qlock(&z->lk);
	/* wait for the muxer to give us our packet */
	r->sleeping = 1;
	z->nsleep++;
	while(z->muxer && !r->done)
		rsleep(&r->r);
	z->nsleep--;
	r->sleeping = 0;

	/* if not done, there's no muxer: start muxing */
	if(!r->done){
		if(z->muxer)
			abort();
		z->muxer = 1;
		while(!r->done){
			qunlock(&z->lk);
			if((p = vtrecv(z)) == nil){
				werrstr("unexpected eof on venti connection");
				z->muxer = 0;
				vtfree(r);
				return nil;
			}
			qlock(&z->lk);
			muxrpc(z, p);
		}
		z->muxer = 0;
		/* if there is anyone else sleeping, wake first unfinished to mux */
		if(z->nsleep)
		for(i=0; i<256; i++){
			rr = z->wait[i];
			if(rr && rr->sleeping && !rr->done){
				rwakeup(&rr->r);
				break;
			}
		}
	}

	p = r->p;
	puttag(z, r, tag);
	vtfree(r);
	qunlock(&z->lk);
	return p;
}
Пример #24
0
/*
 * Archive the file named name, which has stat info d,
 * into the vac directory fp (p = parent).  
 *
 * If we're doing a vac -d against another archive, the
 * equivalent directory to fp in that archive is diffp.
 */
void
vac(VacFile *fp, VacFile *diffp, char *name, Dir *d)
{
	char *elem, *s;
	static char *buf;
	int fd, i, n, bsize;
	vlong off;
	Dir *dk;	// kids
	VacDir vd, vddiff;
	VacFile *f, *fdiff;
	VtEntry e;

	if(!includefile(name)){
		warn("excluding %s%s", name, (d->mode&DMDIR) ? "/" : "");
		return;
	}

	if(d->mode&DMDIR)
		stats.ndir++;
	else
		stats.nfile++;

	if(merge && vacmerge(fp, name) >= 0)
		return;
	
	if(verbose)
		fprint(2, "%s%s\n", name, (d->mode&DMDIR) ? "/" : "");

#ifdef PLAN9PORT
	if(d->mode&Special)
		fd = -1;
	else
#endif
	if((fd = open(name, OREAD)) < 0){
		warn("open %s: %r", name);
		return;
	}

	elem = strrchr(name, '/');
	if(elem)
		elem++;
	else
		elem = name;

	plan9tovacdir(&vd, d);
	if((f = vacfilecreate(fp, elem, vd.mode)) == nil){
		warn("vacfilecreate %s: %r", name);
		return;
	}
	if(diffp)
		fdiff = vacfilewalk(diffp, elem);
	else
		fdiff = nil;

	if(vacfilesetdir(f, &vd) < 0)
		warn("vacfilesetdir %s: %r", name);

	bsize = fs->bsize;
	if(buf == nil)
		buf = vtmallocz(bsize);

#ifdef PLAN9PORT
	if(d->mode&(DMSOCKET|DMNAMEDPIPE)){
		/* don't write anything */
	}
	else if(d->mode&DMSYMLINK){
		n = readlink(name, buf, sizeof buf);
		if(n > 0 && vacfilewrite(f, buf, n, 0) < 0){
			warn("venti write %s: %r", name);
			goto Out;
		}
		stats.data += n;
	}else if(d->mode&DMDEVICE){
		snprint(buf, sizeof buf, "%c %d %d",
			(char)((d->qid.path >> 16) & 0xFF),
			(int)(d->qid.path & 0xFF),
			(int)((d->qid.path >> 8) & 0xFF));
		if(vacfilewrite(f, buf, strlen(buf), 0) < 0){
			warn("venti write %s: %r", name);
			goto Out;
		}
		stats.data += strlen(buf);
	}else
Пример #25
0
static VtFile *
vtfilealloc(VtCache *c, VtBlock *b, VtFile *p, u32int offset, int mode)
{
	int epb;
	u32int size;
	VtEntry e;
	VtFile *r;

	assert(p==nil || ISLOCKED(p));

	if(p == nil){
		assert(offset == 0);
		epb = 1;
	}else
		epb = p->dsize / VtEntrySize;

	if(b->type != VtDirType){
		werrstr("bad block type %#uo", b->type);
		return nil;
	}

	/*
	 * a non-active entry is the only thing that
	 * can legitimately happen here. all the others
	 * get prints.
	 */
	if(vtentryunpack(&e, b->data, offset % epb) < 0){
		fprint(2, "vtentryunpack failed: %r (%.*H)\n", VtEntrySize, b->data+VtEntrySize*(offset%epb));
		return nil;
	}
	if(!(e.flags & VtEntryActive)){
		werrstr("entry not active");
		return nil;
	}

	if(DEPTH(e.type) < sizetodepth(e.size, e.psize, e.dsize)){
		fprint(2, "depth %ud size %llud psize %ud dsize %ud\n",
			DEPTH(e.type), e.size, e.psize, e.dsize);
		werrstr("bad depth");
		return nil;
	}

	size = vtcacheblocksize(c);
	if(e.dsize > size || e.psize > size){
		werrstr("block sizes %ud, %ud bigger than cache block size %ud",
			e.psize, e.dsize, size);
		return nil;
	}

	r = vtmallocz(sizeof(VtFile));
	r->c = c;
	r->mode = mode;
	r->dsize = e.dsize;
	r->psize = e.psize;
	r->gen = e.gen;
	r->dir = (e.type & VtTypeBaseMask) == VtDirType;
	r->ref = 1;
	r->parent = p;
	if(p){
		qlock(&p->lk);
		assert(mode == VtOREAD || p->mode == VtORDWR);
		p->ref++;
		qunlock(&p->lk);
	}else{
		assert(b->addr != NilBlock);
		r->local = 1;
	}
	memmove(r->score, b->score, VtScoreSize);
	r->offset = offset;
	r->epb = epb;

	return r;
}