ref: f5e421deff7f2278fd3a937241dc64aaf25a8a32
dir: /test/freplay.c/
#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);
}