192f5376fSDavid du Colombier /* pump - copy through circular buffer */
292f5376fSDavid du Colombier #include <u.h>
392f5376fSDavid du Colombier #include <libc.h>
492f5376fSDavid du Colombier
592f5376fSDavid du Colombier uchar* buf;
6649197e1SDavid du Colombier
7649197e1SDavid du Colombier Lock arithlock; /* protect 64-bit accesses: unlikely to be atomic */
8649197e1SDavid du Colombier uvlong nin;
9649197e1SDavid du Colombier uvlong nout;
10649197e1SDavid du Colombier
1192f5376fSDavid du Colombier ulong kilo;
1292f5376fSDavid du Colombier ulong max;
1392f5376fSDavid du Colombier long ssize;
14649197e1SDavid du Colombier vlong tsize;
1592f5376fSDavid du Colombier int dsize;
1692f5376fSDavid du Colombier int done;
1792f5376fSDavid du Colombier int ibsize;
1892f5376fSDavid du Colombier int obsize;
1992f5376fSDavid du Colombier int verb;
20*b45eff48SDavid du Colombier vlong off;
2192f5376fSDavid du Colombier
2292f5376fSDavid du Colombier void doinput(int);
2392f5376fSDavid du Colombier void dooutput(int);
2492f5376fSDavid du Colombier
2592f5376fSDavid du Colombier static void
usage(void)2692f5376fSDavid du Colombier usage(void)
2792f5376fSDavid du Colombier {
28*b45eff48SDavid du Colombier fprint(2, "usage: pump [-b iando] [-d sleeptime] [-f ofile] "
29*b45eff48SDavid du Colombier "[-i ireadsize]\n\t[-k KB-buffer] [-o owritesize] "
30*b45eff48SDavid du Colombier "[-s start-KB] [-S seek-offset]\n\t[-t mins] [files]\n");
3192f5376fSDavid du Colombier exits("usage");
3292f5376fSDavid du Colombier }
3392f5376fSDavid du Colombier
3492f5376fSDavid du Colombier void
main(int argc,char * argv[])3592f5376fSDavid du Colombier main(int argc, char *argv[])
3692f5376fSDavid du Colombier {
3792f5376fSDavid du Colombier int i, f, fo;
3892f5376fSDavid du Colombier char *file;
3992f5376fSDavid du Colombier
4092f5376fSDavid du Colombier kilo = 5000;
4192f5376fSDavid du Colombier obsize = ibsize = 8*1024;
4292f5376fSDavid du Colombier dsize = 0;
4392f5376fSDavid du Colombier fo = 1;
44*b45eff48SDavid du Colombier off = 0;
4592f5376fSDavid du Colombier
4692f5376fSDavid du Colombier ARGBEGIN {
4792f5376fSDavid du Colombier default:
4892f5376fSDavid du Colombier usage();
4992f5376fSDavid du Colombier case 'b':
5092f5376fSDavid du Colombier obsize = ibsize = atoi(EARGF(usage()));
5192f5376fSDavid du Colombier break;
5292f5376fSDavid du Colombier case 'd':
5392f5376fSDavid du Colombier dsize = atoi(EARGF(usage()));
5492f5376fSDavid du Colombier break;
5592f5376fSDavid du Colombier case 'f':
5692f5376fSDavid du Colombier file = EARGF(usage());
5792f5376fSDavid du Colombier fo = create(file, 1, 0666);
5892f5376fSDavid du Colombier if(fo < 0)
5992f5376fSDavid du Colombier sysfatal("can't create %s: %r", file);
6092f5376fSDavid du Colombier break;
6192f5376fSDavid du Colombier case 'i':
6292f5376fSDavid du Colombier ibsize = atoi(EARGF(usage()));
6392f5376fSDavid du Colombier break;
6492f5376fSDavid du Colombier case 'k':
6592f5376fSDavid du Colombier kilo = atoi(EARGF(usage()));
6692f5376fSDavid du Colombier break;
6792f5376fSDavid du Colombier case 'o':
6892f5376fSDavid du Colombier obsize = atoi(EARGF(usage()));
6992f5376fSDavid du Colombier break;
7092f5376fSDavid du Colombier case 's':
7192f5376fSDavid du Colombier ssize = atoi(EARGF(usage()));
7292f5376fSDavid du Colombier if(ssize <= 0)
7392f5376fSDavid du Colombier ssize = 800;
7492f5376fSDavid du Colombier ssize <<= 10;
7592f5376fSDavid du Colombier break;
76*b45eff48SDavid du Colombier case 'S':
77*b45eff48SDavid du Colombier off = atoll(EARGF(usage()));
78*b45eff48SDavid du Colombier if(off < 0)
79*b45eff48SDavid du Colombier sysfatal("seek offset %lld must be non-negative", off);
80*b45eff48SDavid du Colombier break;
8192f5376fSDavid du Colombier case 't':
82649197e1SDavid du Colombier tsize = atoll(EARGF(usage()));
8392f5376fSDavid du Colombier tsize *= 10584000; /* minutes */
8492f5376fSDavid du Colombier break;
8592f5376fSDavid du Colombier } ARGEND
8692f5376fSDavid du Colombier kilo <<= 10;
8792f5376fSDavid du Colombier
8892f5376fSDavid du Colombier buf = malloc(kilo);
8992f5376fSDavid du Colombier if(buf == nil)
9092f5376fSDavid du Colombier sysfatal("no memory: %r");
9192f5376fSDavid du Colombier nin = 0;
9292f5376fSDavid du Colombier nout = 0;
9392f5376fSDavid du Colombier done = 0;
9492f5376fSDavid du Colombier max = 0;
9592f5376fSDavid du Colombier
9692f5376fSDavid du Colombier switch(rfork(RFPROC|RFNOWAIT|RFNAMEG|RFMEM)) {
9792f5376fSDavid du Colombier default:
9892f5376fSDavid du Colombier dooutput(fo);
9992f5376fSDavid du Colombier break;
10092f5376fSDavid du Colombier case 0:
10192f5376fSDavid du Colombier for(i=0; i<argc; i++) {
10292f5376fSDavid du Colombier f = open(argv[i], OREAD);
10392f5376fSDavid du Colombier if(f < 0) {
10492f5376fSDavid du Colombier fprint(2, "%s: can't open %s: %r\n",
10592f5376fSDavid du Colombier argv0, argv[i]);
10692f5376fSDavid du Colombier break;
10792f5376fSDavid du Colombier }
10892f5376fSDavid du Colombier doinput(f);
10992f5376fSDavid du Colombier close(f);
11092f5376fSDavid du Colombier }
11192f5376fSDavid du Colombier if(argc == 0)
11292f5376fSDavid du Colombier doinput(0);
11392f5376fSDavid du Colombier break;
11492f5376fSDavid du Colombier case -1:
11592f5376fSDavid du Colombier fprint(2, "%s: fork failed: %r\n", argv0);
11692f5376fSDavid du Colombier break;
11792f5376fSDavid du Colombier }
11892f5376fSDavid du Colombier done = 1;
11992f5376fSDavid du Colombier exits(0);
12092f5376fSDavid du Colombier }
12192f5376fSDavid du Colombier
122649197e1SDavid du Colombier /* call with arithlock held */
123649197e1SDavid du Colombier static int
sleepunlocked(long ms)124649197e1SDavid du Colombier sleepunlocked(long ms)
125649197e1SDavid du Colombier {
126649197e1SDavid du Colombier int r;
127649197e1SDavid du Colombier
128649197e1SDavid du Colombier unlock(&arithlock);
129649197e1SDavid du Colombier r = sleep(ms);
130649197e1SDavid du Colombier lock(&arithlock);
131649197e1SDavid du Colombier return r;
132649197e1SDavid du Colombier }
133649197e1SDavid du Colombier
13492f5376fSDavid du Colombier void
dooutput(int f)13592f5376fSDavid du Colombier dooutput(int f)
13692f5376fSDavid du Colombier {
13792f5376fSDavid du Colombier long n, l, c;
13892f5376fSDavid du Colombier
139*b45eff48SDavid du Colombier seek(f, off, 0);
140649197e1SDavid du Colombier lock(&arithlock);
14192f5376fSDavid du Colombier for (;;) {
14292f5376fSDavid du Colombier n = nin - nout;
14392f5376fSDavid du Colombier if(n == 0) {
14492f5376fSDavid du Colombier if(done)
14592f5376fSDavid du Colombier break;
146649197e1SDavid du Colombier sleepunlocked(dsize);
14792f5376fSDavid du Colombier continue;
14892f5376fSDavid du Colombier }
14992f5376fSDavid du Colombier if(verb && n > max) {
15092f5376fSDavid du Colombier fprint(2, "n = %ld\n", n);
15192f5376fSDavid du Colombier max = n;
15292f5376fSDavid du Colombier }
15392f5376fSDavid du Colombier l = nout % kilo;
154649197e1SDavid du Colombier unlock(&arithlock);
155649197e1SDavid du Colombier
15692f5376fSDavid du Colombier if(kilo-l < n)
15792f5376fSDavid du Colombier n = kilo-l;
15892f5376fSDavid du Colombier if(n > obsize)
15992f5376fSDavid du Colombier n = obsize;
16092f5376fSDavid du Colombier c = write(f, buf+l, n);
161649197e1SDavid du Colombier
162649197e1SDavid du Colombier lock(&arithlock);
16392f5376fSDavid du Colombier if(c != n) {
1644d2c0504SDavid du Colombier fprint(2, "%s: write error at offset %,lld: %r\n",
1654d2c0504SDavid du Colombier argv0, seek(f, 0, 1));
16692f5376fSDavid du Colombier break;
16792f5376fSDavid du Colombier }
16892f5376fSDavid du Colombier nout += c;
16992f5376fSDavid du Colombier if(tsize && nout > tsize) {
17092f5376fSDavid du Colombier fprint(2, "%s: time limit exceeded\n", argv0);
17192f5376fSDavid du Colombier break;
17292f5376fSDavid du Colombier }
17392f5376fSDavid du Colombier }
174649197e1SDavid du Colombier unlock(&arithlock);
17592f5376fSDavid du Colombier }
17692f5376fSDavid du Colombier
17792f5376fSDavid du Colombier void
doinput(int f)17892f5376fSDavid du Colombier doinput(int f)
17992f5376fSDavid du Colombier {
18092f5376fSDavid du Colombier long n, l, c, xnin;
18192f5376fSDavid du Colombier
182*b45eff48SDavid du Colombier seek(f, off, 0);
183649197e1SDavid du Colombier lock(&arithlock);
18492f5376fSDavid du Colombier if(ssize > 0) {
18592f5376fSDavid du Colombier for (xnin = 0; xnin < ssize && !done; xnin += c) {
18692f5376fSDavid du Colombier n = kilo - (xnin - nout);
18792f5376fSDavid du Colombier if(n == 0)
18892f5376fSDavid du Colombier break;
189649197e1SDavid du Colombier unlock(&arithlock);
190649197e1SDavid du Colombier
19192f5376fSDavid du Colombier l = xnin % kilo;
19292f5376fSDavid du Colombier if(kilo-l < n)
19392f5376fSDavid du Colombier n = kilo-l;
19492f5376fSDavid du Colombier if(n > ibsize)
19592f5376fSDavid du Colombier n = ibsize;
19692f5376fSDavid du Colombier c = read(f, buf+l, n);
197649197e1SDavid du Colombier
198649197e1SDavid du Colombier lock(&arithlock);
19992f5376fSDavid du Colombier if(c <= 0) {
20092f5376fSDavid du Colombier if(c < 0)
20192f5376fSDavid du Colombier fprint(2, "%s: read error: %r\n", argv0);
20292f5376fSDavid du Colombier break;
20392f5376fSDavid du Colombier }
20492f5376fSDavid du Colombier }
20592f5376fSDavid du Colombier nin = xnin;
20692f5376fSDavid du Colombier }
20792f5376fSDavid du Colombier while(!done) {
20892f5376fSDavid du Colombier n = kilo - (nin - nout);
20992f5376fSDavid du Colombier if(n == 0) {
210649197e1SDavid du Colombier sleepunlocked(0);
21192f5376fSDavid du Colombier continue;
21292f5376fSDavid du Colombier }
21392f5376fSDavid du Colombier l = nin % kilo;
214649197e1SDavid du Colombier unlock(&arithlock);
215649197e1SDavid du Colombier
21692f5376fSDavid du Colombier if(kilo-l < n)
21792f5376fSDavid du Colombier n = kilo-l;
21892f5376fSDavid du Colombier if(n > ibsize)
21992f5376fSDavid du Colombier n = ibsize;
22092f5376fSDavid du Colombier c = read(f, buf+l, n);
221649197e1SDavid du Colombier
222649197e1SDavid du Colombier lock(&arithlock);
22392f5376fSDavid du Colombier if(c <= 0) {
22492f5376fSDavid du Colombier if(c < 0)
22592f5376fSDavid du Colombier fprint(2, "%s: read error: %r\n", argv0);
22692f5376fSDavid du Colombier break;
22792f5376fSDavid du Colombier }
22892f5376fSDavid du Colombier nin += c;
22992f5376fSDavid du Colombier }
230649197e1SDavid du Colombier unlock(&arithlock);
23192f5376fSDavid du Colombier }
232