shithub: gefs

ref: 7d85dc87bcb5ab2cc6c032bf0ae4eef3bdf14c21
dir: /test/freplay.c/

View raw version
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>

char*	mountpt	= "/n/replay";
char*	logfile;
char*	replayfile;
char*	membuf;
vlong	membufsz;
vlong	replaycount = -1;
int	logfd;

void
log1(int fd, void *buf, vlong off, vlong sz)
{
	char *p, hdr[12];

	p = hdr;
	PBIT64(p, off);	p += 8;
	PBIT32(p, sz);
	if(write(fd, hdr, sizeof(hdr)) == -1)
		sysfatal("write header: %r");
	if(write(fd, buf, sz) == -1)
		sysfatal("write data: %r\n");
}

int
replay1(int fd)
{
	uchar *p, hdr[12];
	vlong o;
	int n, r;

	r = readn(fd, hdr, 12);
	if(r == 0)
		return 0;
	if(r != 12)
		sysfatal("failed to read operation header: %r");

	p = hdr;
	o = GBIT64(p);	p += 8;
	n = GBIT32(p);
	if(o + n > membufsz)
		sysfatal("operation exceeds buffer size");
	if(readn(fd, membuf + o, n) != n)
		sysfatal("read op: %r");
	return 1;
}

void
fsread(Req *r)
{
	readbuf(r, membuf, membufsz);
	respond(r, nil);
}

void
fswrite(Req *r)
{
	if(r->ifcall.offset + r->ifcall.count >= membufsz)
		respond(r, "operation exceeds file size");
	log1(logfd, r->ifcall.data, r->ifcall.offset, r->ifcall.count);
	memcpy(membuf + r->ifcall.offset, r->ifcall.data, r->ifcall.count);
	r->ofcall.count = r->ifcall.count;
	respond(r, nil);
}

void
usage(void)
{
	fprint(2, "usage: %s -l log [-r replay] [-c count] file\n", argv0);
	exits("usage");
}	

static Srv fs = {
	.read = fsread,
	.write = fswrite,
};
void
main(int argc, char *argv[])
{
	int fd, replayfd;
	vlong n, off;
	char *uid;
	File *f;
	Dir *d;
	int i;
	
	ARGBEGIN{
	case 'd':
		chatty9p++;
		break;
	case 'l':
		logfile = EARGF(usage());
		break;
	case 'r':
		replayfile = EARGF(usage());
		break;
	case 'c':
		replaycount = atoi(EARGF(usage()));
		break;
	case 'm':
		mountpt = EARGF(usage());
		break;
	default:
		usage();
	}ARGEND;
	
	if(argc != 1 || logfile == nil)
		usage();
	
	if((fd = open(argv[0], OREAD)) == -1)
		sysfatal("open %s: %r", argv[0]);
	if((d = dirfstat(fd)) == nil)
		sysfatal("failed to stat file: %r");
	if((membuf = mallocz(d->length, 1)) == nil)
		sysfatal("failed to allocate buffer: %r");
	for(off = 0; off < d->length; off += n)
		if((n = read(fd, membuf+off, d->length - off)) <= 0)
			sysfatal("read %s: short read", argv[0]);
	membufsz = d->length;
	free(d);
	if(replayfile != nil){
		if((replayfd = open(replayfile, OREAD)) == -1)
			sysfatal("failed to open replay file: %r");
		for(i = 0; i < replaycount || replaycount == -1; i++)
			if(replay1(replayfd) == 0)
				break;
		close(replayfd);
	}

	if((logfd = create(logfile, OWRITE, 0666)) == -1)
		sysfatal("failed to open log file: %r");
	uid = getuser();
	fs.tree = alloctree(uid, uid, DMDIR|0555, nil);
	f = createfile(fs.tree->root, "data", uid, 0666, nil);
	f->length = membufsz;
	postmountsrv(&fs, nil, mountpt, 0);
	exits(nil);
}