4d22579f0628231e2459ed82eff903d1bd81a5d5
[archipelago] / xseg / peers / user / xseg-tool.c
1 #define _GNU_SOURCE
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdint.h>
6 #include <ctype.h>
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11
12 #include <xtypes/xhash.h>
13 #include <xtypes/xobj.h>
14 #include <xseg/xseg.h>
15 #include <xseg/protocol.h>
16 int help(void)
17 {
18         printf("xseg <spec> [[[<src_port>]:[<dst_port>]] [<command> <arg>*] ]*\n"
19                 "spec:\n"
20                 "    <type:name:nr_ports:nr_requests:request_size:extra_size:page_shift>\n"
21                 "global commands:\n"
22                 "    reportall\n"
23                 "    create\n"
24                 "    destroy\n"
25                 "    bind <portno>\n"
26                 "    signal <portno>\n"
27                 "    bridge <portno1> <portno2> <logfile> {full|summary|stats}\n"
28                 "port commands:\n"
29                 "    report\n"
30                 "    alloc_requests (to source) <nr>\n"
31                 "    free_requests (from source) <nr>\n"
32                 "    put_requests (all from dest)\n"
33                 "    put_replies (all from dest)\n"
34                 "    wait        <nr_replies>\n"
35                 "    complete    <nr_requests>\n"
36                 "    fail        <nr_requests>\n"
37                 "    rndwrite    <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
38                 "    rndread     <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
39                 "    submit_reqs <nr_loops> <concurrent_reqs>\n"
40                 "    info        <target>\n"
41                 "    read        <target> <offset> <size>\n"
42                 "    write       <target> <offset> < data\n"
43                 "    truncate    <target> <size>\n"
44                 "    delete      <target>\n"
45                 "    acquire     <target>\n"
46                 "    release     <target>\n"
47                 "    copy        <src>  <dst>\n"
48                 "    clone       <src>  <dst>\n"
49         );
50         return 1;
51 }
52
53
54 enum req_action {
55         REPORT = 1,
56         FAIL = 2,
57         COMPLETE = 3
58 };
59
60 char *namebuf;
61 char *chunk;
62 struct xseg_config cfg;
63 struct xseg *xseg;
64 uint32_t srcport, dstport;
65 uint64_t reqs;
66 #define mkname mkname_heavy
67 /* heavy distributes duplicates much more widely than light
68  * ./xseg-tool random 100000 | cut -d' ' -f2- | sort | uniq -d -c |wc -l
69  */
70
71 xport sport = NoPort;
72 static void init_local_signal() 
73 {
74         if (xseg && sport != srcport){
75                 xseg_init_local_signal(xseg, srcport);
76                 sport = srcport;
77         }
78 }
79
80 void mkname_heavy(char *name, uint32_t namelen, uint32_t seed)
81 {
82         int i;
83         char c;
84         for (i = 0; i < namelen; i += 1) {
85                 c = seed + (seed >> 8) + (seed >> 16) + (seed >> 24);
86                 c = '0' + ((c + (c >> 4)) & 0xf);
87                 if (c > '9')
88                         c += 'a'-'0'-10;
89                 name[i] = c;
90                 seed *= ((seed % 137911) | 1) * 137911;
91         }
92 }
93
94 void mkname_light(char *name, uint32_t namelen, uint32_t seed)
95 {
96         int i;
97         char c;
98         for (i = 0; i < namelen; i += 1) {
99                 c = seed;
100                 name[i] = 'A' + (c & 0xf);
101                 seed += 1;
102         }
103 }
104
105 uint64_t pick(uint64_t size)
106 {
107         return (uint64_t)((double)(RAND_MAX) / random());
108 }
109
110 void mkchunk(   char *chunk, uint32_t datalen,
111                 char *target, uint32_t targetlen, uint64_t offset)
112 {
113         long i, r, bufsize = targetlen + 16;
114         char buf[bufsize];
115         r = datalen % bufsize;
116         snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
117
118         for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
119                 memcpy(chunk + i, buf, bufsize);
120
121         memcpy(chunk + datalen - r, buf, r);
122 }
123
124 int chkchunk(   char *chunk, uint32_t datalen,
125                 char *target, uint32_t targetlen, uint64_t offset)
126 {
127         long i, r;
128         int bufsize = targetlen + 16;
129         char buf[bufsize];
130         r = datalen % targetlen;
131         snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
132
133         for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
134                 if (memcmp(chunk + i, buf, bufsize)) {
135                         /*printf("mismatch: '%*s'* vs '%*s'\n",
136                                 bufsize, buf, datalen, chunk);
137                         */
138                         return 0;
139                 }
140
141         if (memcmp(chunk + datalen - r, buf, r))
142                 return 0;
143
144         return 1;
145 }
146
147
148 #define ALLOC_MIN 4096
149 #define ALLOC_MAX 1048576
150
151 void inputbuf(FILE *fp, char **retbuf, uint64_t *retsize)
152 {
153         static uint64_t alloc_size;
154         static char *buf;
155         uint64_t size = 0;
156         char *p;
157         size_t r;
158
159         if (alloc_size < ALLOC_MIN)
160                 alloc_size = ALLOC_MIN;
161
162         if (alloc_size > ALLOC_MAX)
163                 alloc_size = ALLOC_MAX;
164
165         p = realloc(buf, alloc_size);
166         if (!p) {
167                 if (buf)
168                         free(buf);
169                 buf = NULL;
170                 goto out;
171         }
172
173         buf = p;
174
175         while (!feof(fp)) {
176                 r = fread(buf + size, 1, alloc_size - size, fp);
177                 if (!r)
178                         break;
179                 size += r;
180                 if (size >= alloc_size) {
181                         p = realloc(buf, alloc_size * 2);
182                         if (!p) {
183                                 if (buf)
184                                         free(buf);
185                                 buf = NULL;
186                                 size = 0;
187                                 goto out;
188                         }
189                         buf = p;
190                         alloc_size *= 2;
191                 }
192         }
193
194 out:
195         *retbuf = buf;
196         *retsize = size;
197 }
198
199 void report_request(struct xseg_request *req)
200 {
201         char target[64], data[64];
202         char *req_target, *req_data;
203         unsigned int end = (req->targetlen> 63) ? 63 : req->targetlen;
204         req_target = xseg_get_target(xseg, req);
205         req_data = xseg_get_data(xseg, req);
206
207         strncpy(target, req_target, end);
208         target[end] = 0;
209         strncpy(data, req_data, 63);
210         data[63] = 0;
211         fprintf(stderr,
212                 "Request %lx: target[%u](xptr: %llu): %s, data[%llu](xptr: %llu): %s \n\t"
213                 "offset: %llu, size: %llu, serviced; %llu, op: %u, state: %u, flags: %u \n\t"
214                 "src: %u, src_transit: %u, dst: %u, dst_transit: %u\n",
215                 (unsigned long) req, req->targetlen, (unsigned long long)req->target,
216                 xseg_get_target(xseg, req),
217                 (unsigned long long) req->datalen, (unsigned long long) req->data,
218                 xseg_get_data(xseg, req),
219                 (unsigned long long) req->offset, (unsigned long long) req->size,
220                 (unsigned long long) req->serviced, req->op, req->state, req->flags,
221                 (unsigned int) req->src_portno, (unsigned int) req->src_transit_portno,
222                 (unsigned int) req->dst_portno, (unsigned int) req->dst_transit_portno);
223
224
225 }
226
227 int cmd_info(char *target)
228 {
229         uint32_t targetlen = strlen(target);
230         size_t size = sizeof(uint64_t);
231         int r;
232         xport p;
233         struct xseg_request *req;
234         char *req_target;
235
236         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
237         if (!req) {
238                 fprintf(stderr, "No request!\n");
239                 return -1;
240         }
241
242         r = xseg_prep_request(xseg, req, targetlen, size);
243         if (r < 0) {
244                 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
245                         (unsigned long) targetlen, (unsigned long) size);
246                 xseg_put_request(xseg, req, srcport);
247                 return -1;
248         }
249
250         req_target = xseg_get_target(xseg, req);
251         strncpy(req_target, target, targetlen);
252         req->offset = 0;
253         req->size = size;
254         req->op = X_INFO;
255
256         p = xseg_submit(xseg, req, srcport, X_ALLOC);
257         if (p == NoPort)
258                 return -1;
259
260         xseg_signal(xseg, p);
261
262         return 0;
263 }
264
265 int cmd_read(char *target, uint64_t offset, uint64_t size)
266 {
267         uint32_t targetlen = strlen(target);
268         int r;
269         xport p;
270         char *req_target;
271         struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
272         if (!req) {
273                 fprintf(stderr, "No request\n");
274                 return -1;
275         }
276
277         r = xseg_prep_request(xseg, req, targetlen, size);
278         if (r < 0) {
279                 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
280                         (unsigned long)targetlen, (unsigned long long)size);
281                 xseg_put_request(xseg, req, srcport);
282                 return -1;
283         }
284
285         req_target = xseg_get_target(xseg, req);
286         strncpy(req_target, target, targetlen);
287         req->offset = offset;
288         req->size = size;
289         req->op = X_READ;
290         report_request(req);
291         p = xseg_submit(xseg, req, srcport, X_ALLOC);
292         if (p == NoPort)
293                 return -1;
294
295         xseg_signal(xseg, p);
296         return 0;
297 }
298
299 int cmd_write(char *target, uint64_t offset)
300 {
301         char *buf = NULL;
302         int r;
303         xport p;
304         uint64_t size = 0;
305         char *req_target, *req_data;
306         uint32_t targetlen = strlen(target);
307         struct xseg_request *req;
308
309         inputbuf(stdin, &buf, &size);
310         if (!size) {
311                 fprintf(stderr, "No input\n");
312                 return -1;
313         }
314
315         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
316         if (!req) {
317                 fprintf(stderr, "No request\n");
318                 return -1;
319         }
320
321         r = xseg_prep_request(xseg, req, targetlen, size);
322         if (r < 0) {
323                 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
324                         (unsigned long)targetlen, (unsigned long long)size);
325                 xseg_put_request(xseg, req, srcport);
326                 return -1;
327         }
328
329         req_target = xseg_get_target(xseg, req);
330         strncpy(req_target, target, targetlen);
331         
332         req_data = xseg_get_data(xseg, req);
333         memcpy(req_data, buf, size);
334         req->offset = offset;
335         req->size = size;
336         req->op = X_WRITE;
337
338         p = xseg_submit(xseg, req, srcport, X_ALLOC);
339         if (p == NoPort) {
340                 fprintf(stderr, "Cannot submit\n");
341                 return -1;
342         }
343         xseg_signal(xseg, p);
344
345         return 0;
346 }
347
348 int cmd_truncate(char *target, uint64_t offset)
349 {
350         return 0;
351 }
352
353 int cmd_delete(char *target)
354 {
355         uint32_t targetlen = strlen(target);
356         int r;
357         struct xseg_request *req;
358         init_local_signal();
359         xseg_bind_port(xseg, srcport, NULL);
360
361         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
362         if (!req) {
363                 fprintf(stderr, "No request!\n");
364                 return -1;
365         }
366
367         r = xseg_prep_request(xseg, req, targetlen, 0);
368         if (r < 0) {
369                 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
370                         (unsigned long) targetlen, (unsigned long) req->bufferlen - targetlen);
371                 xseg_put_request(xseg, req, srcport);
372                 return -1;
373         }
374
375         char *reqtarget = xseg_get_target(xseg, req);
376         strncpy(reqtarget, target, targetlen);
377         req->op = X_DELETE;
378
379         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
380         if (p == NoPort){
381                 fprintf(stderr, "Couldn't submit request\n");
382                 xseg_put_request(xseg, req, srcport);
383                 return -1;
384         }
385
386         xseg_signal(xseg, p);
387
388         return 0;
389 }
390
391 int cmd_acquire(char *target)
392 {
393         return 0;
394 }
395
396 int cmd_release(char *target)
397 {
398         return 0;
399 }
400
401 int cmd_copy(char *src, char *dst)
402 {
403         return 0;
404 }
405
406 int cmd_clone(char *src, char *dst)
407 {
408
409         uint32_t targetlen = strlen(dst);
410         uint32_t parentlen = strlen(src);
411         struct xseg_request *req;
412         struct xseg_request_clone *xclone;
413         xseg_bind_port(xseg, srcport, NULL);
414         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
415         if (!req) {
416                 fprintf(stderr, "No request\n");
417                 return -1;
418         }
419
420         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
421         if (r < 0) {
422                 fprintf(stderr, "Cannot prepare request!\n");
423                 xseg_put_request(xseg, req, srcport);
424                 return -1;
425         }
426
427         char *target = xseg_get_target(xseg, req);
428         char *data = xseg_get_data(xseg, req);
429
430         strncpy(target, dst, targetlen);
431         xclone = (struct xseg_request_clone *) data;
432         strncpy(xclone->target, src, parentlen);
433         xclone->targetlen = parentlen;
434         xclone->size = -1;
435         req->offset = 0;
436         req->size = sizeof(struct xseg_request_clone);
437         req->op = X_CLONE;
438
439         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
440         if (p == NoPort){
441                 fprintf(stderr, "Cannot submit request\n");
442                 return -1;
443         }
444         xseg_signal(xseg, p);
445
446         return 0;
447 }
448
449 void log_req(int logfd, uint32_t portno2, uint32_t portno1, int op, int method,
450                 struct xseg_request *req)
451 {
452         FILE *logfp;
453         char target[64], data[64];
454         char *req_target, *req_data;
455         /* null terminate name in case of req->target is less than 63 characters,
456          * and next character after name (aka first byte of next buffer) is not
457          * null
458          */
459         unsigned int end = (req->targetlen > 63) ? 63 : req->targetlen;
460         
461         req_target = xseg_get_target(xseg, req);
462         req_data = xseg_get_data(xseg, req);
463
464         logfp = fdopen(logfd, "a");
465         if (!logfp)
466                 return;
467
468         switch(method) {
469         case 0:
470                 strncpy(target, req_target, end);
471                 target[end] = 0;
472                 strncpy(data, req_data, 63);
473                 data[63] = 0;
474
475                 fprintf(logfp,
476                         "src port: %u, dst port: %u,  op:%u offset: %llu size: %lu, reqstate: %u\n"
477                         "target[%u]: '%s', data[%llu]:\n%s------------------\n\n",
478                         (unsigned int)portno1,
479                         (unsigned int)portno2,
480                         (unsigned int)req->op,
481                         (unsigned long long)req->offset,
482                         (unsigned long)req->size,
483                         (unsigned int)req->state,
484                         (unsigned int)req->targetlen, target,
485                         (unsigned long long)req->datalen, data);
486                 break;
487         case 1:
488                 fprintf(logfp,
489                         "src port: %u, dst port: %u, op: %u\n",
490                         (unsigned int)portno1,
491                         (unsigned int)portno2,
492                         (unsigned int)req->op);
493                 break;
494         case 2:
495                 fprintf(logfp, "src port: %u, dst port: %u, reqs: %llu\n",
496                         (unsigned int)portno1,
497                         (unsigned int)portno2,
498                         (unsigned long long)++reqs);
499         }
500
501         fclose(logfp);
502         return;
503 }
504
505 #define LOG_ACCEPT  0
506 #define LOG_RECEIVE 1
507
508 int cmd_bridge(uint32_t portno1, uint32_t portno2, char *logfile, char *how)
509 {
510         struct xseg_request *req;
511         int logfd, method;
512         if (!strcmp(logfile, "-"))
513                 logfd = 1;
514         else {
515                 logfd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0600);
516                 if (logfd < 0) {
517                         perror(logfile);
518                         return -1;
519                 }
520         }
521
522         if (!strcmp(how, "full"))
523                 method = 0;
524         else if (!strcmp(how, "summary"))
525                 method = 1;
526         else
527                 method = 2;
528
529         for (;;) {
530                 int reloop = 0, active;
531                 xseg_prepare_wait(xseg, portno1);
532                 xseg_prepare_wait(xseg, portno2);
533                 req = NULL;
534
535                 for (;;) {
536                         active = 0;
537
538                         //FIXME
539                         req = xseg_accept(xseg, portno1, 0);
540                         if (req) {
541                                 xseg_submit(xseg, req, portno2, X_ALLOC);
542                                 log_req(logfd, portno1, portno2, LOG_ACCEPT, method, req);
543                                 active += 1;
544                         }
545
546                         req = xseg_accept(xseg, portno2, 0);
547                         if (req) {
548                                 xseg_submit(xseg, req, portno1, X_ALLOC);
549                                 log_req(logfd, portno2, portno1, LOG_ACCEPT, method, req);
550                                 active += 1;
551                         }
552
553                         req = xseg_receive(xseg, portno1, 0);
554                         if (req) {
555                                 xseg_respond(xseg, req, portno2, X_ALLOC);
556                                 log_req(logfd, portno1, portno2, LOG_RECEIVE, method, req);
557                                 active += 1;
558                         }
559
560                         req = xseg_receive(xseg, portno2, 0);
561                         if (req) {
562                                 xseg_respond(xseg, req, portno1, X_ALLOC);
563                                 log_req(logfd, portno2, portno1, LOG_RECEIVE, method, req);
564                                 active += 1;
565                         }
566
567                         if (active == 0) {
568                                 if (reloop)
569                                         break;
570                                 /* wait on multiple queues? */
571                                 xseg_wait_signal(xseg, 100000);
572                                 break;
573                         } else {
574                                 xseg_cancel_wait(xseg, portno1);        
575                                 xseg_cancel_wait(xseg, portno2);        
576                                 reloop = 1;
577                         }
578                 }
579         }
580
581         close(logfd);
582
583         return 0;
584 }
585
586 int cmd_rndwrite(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
587 {
588         if (loops < 0)
589                 return help();
590
591         if (targetlen >= chunksize) {
592                 fprintf(stderr, "targetlen >= chunksize\n");
593                 return -1;
594         }
595
596         char *p = realloc(namebuf, targetlen+1);
597         if (!p) {
598                 fprintf(stderr, "Cannot allocate memory\n");
599                 return -1;
600         }
601         namebuf = p;
602
603         p = realloc(chunk, chunksize);
604         if (!p) {
605                 fprintf(stderr, "Cannot allocate memory\n");
606                 return -1;
607         }
608         chunk = p;
609         memset(chunk, 0, chunksize);
610
611         srandom(seed);
612
613         struct xseg_request *submitted = NULL, *received;
614         long nr_submitted = 0, nr_received = 0, nr_failed = 0;
615         int reported = 0, r;
616         uint64_t offset;
617         xport port;
618         char *req_data, *req_target;
619         seed = random();
620         init_local_signal();
621
622         for (;;) {
623                 xseg_prepare_wait(xseg, srcport);
624                 if (nr_submitted < loops &&
625                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
626                         xseg_cancel_wait(xseg, srcport);
627                         r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
628                         if (r < 0) {
629                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
630                                         targetlen, chunksize);
631                                 xseg_put_request(xseg, submitted, srcport);
632                                 return -1;
633                         }
634                         
635                         req_target = xseg_get_target(xseg, submitted);
636                         req_data = xseg_get_data(xseg, submitted);
637
638                         reported = 0;
639                         mkname(namebuf, targetlen, seed);
640                         namebuf[targetlen] = 0;
641                         //printf("%ld: %s\n", nr_submitted, namebuf);
642                         strncpy(req_target, namebuf, targetlen);
643                         offset = 0;// pick(size);
644                         mkchunk(req_data, chunksize, namebuf, targetlen, offset);
645
646                         submitted->offset = offset;
647                         submitted->size = chunksize;
648                         submitted->op = X_WRITE;
649                         submitted->flags |= XF_NOSYNC;
650
651                         port =  xseg_submit(xseg, submitted, srcport, X_ALLOC);
652                         if (port == NoPort) {
653                                 xseg_put_request(xseg, submitted, srcport);
654                         } else {
655                                 seed = random();
656                                 nr_submitted += 1;
657                                 xseg_signal(xseg, port);
658                         }
659                 }
660
661                 received = xseg_receive(xseg, srcport, 0);
662                 if (received) {
663                         xseg_cancel_wait(xseg, srcport);
664                         nr_received += 1;
665                         if (!(received->state & XS_SERVED)) {
666                                 nr_failed += 1;
667                                 report_request(received);
668                         }
669                         if (xseg_put_request(xseg, received, srcport))
670                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
671                 }
672
673                 if (!submitted && !received)
674                         xseg_wait_signal(xseg, 1000000);
675
676                         if (nr_submitted % 1000 == 0 && !reported) {
677                                 reported = 1;
678                                 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
679                                         nr_submitted, nr_received, nr_failed);
680                         }
681
682                         if (nr_received >= loops)
683                                 break;
684         }
685
686         fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
687                 nr_submitted, nr_received, nr_failed);
688         return 0;
689 }
690
691 int cmd_rnddelete(long loops, int32_t seed, uint32_t targetlen)
692 {
693         if (loops < 0)
694                 return help();
695         char *p = realloc(namebuf, targetlen+1);
696         if (!p) {
697                 fprintf(stderr, "Cannot allocate memory\n");
698                 return -1;
699         }
700         namebuf = p;
701
702         srandom(seed);
703
704         struct xseg_request *submitted = NULL, *received;
705         long nr_submitted = 0, nr_received = 0, nr_failed = 0;
706         int reported = 0, r;
707         xport port;
708         char *req_target;
709         seed = random();
710         init_local_signal();
711
712         for (;;) {
713                 xseg_prepare_wait(xseg, srcport);
714                 if (nr_submitted < loops &&
715                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
716                         xseg_cancel_wait(xseg, srcport);
717                         r = xseg_prep_request(xseg, submitted, targetlen, 0);
718                         if (r < 0) {
719                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
720                                         targetlen, 0);
721                                 xseg_put_request(xseg, submitted, srcport);
722                                 return -1;
723                         }
724                         
725                         req_target = xseg_get_target(xseg, submitted);
726
727                         reported = 0;
728                         mkname(namebuf, targetlen, seed);
729                         namebuf[targetlen] = 0;
730                         //printf("%ld: %s\n", nr_submitted, namebuf);
731                         strncpy(req_target, namebuf, targetlen);
732                         submitted->offset = 0;
733                         submitted->size = 0;
734                         submitted->op = X_DELETE;
735                         submitted->flags = 0;
736
737                         port =  xseg_submit(xseg, submitted, srcport, X_ALLOC);
738                         if (port == NoPort) {
739                                 xseg_put_request(xseg, submitted, srcport);
740                         } else {
741                                 seed = random();
742                                 nr_submitted += 1;
743                                 xseg_signal(xseg, port);
744                         }
745                 }
746
747                 received = xseg_receive(xseg, srcport, 0);
748                 if (received) {
749                         xseg_cancel_wait(xseg, srcport);
750                         nr_received += 1;
751                         if (!(received->state & XS_SERVED)) {
752                                 nr_failed += 1;
753                                 report_request(received);
754                         }
755                         if (xseg_put_request(xseg, received, srcport))
756                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
757                 }
758
759                 if (!submitted && !received)
760                         xseg_wait_signal(xseg, 1000000);
761
762                         if (nr_submitted % 1000 == 0 && !reported) {
763                                 reported = 1;
764                                 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
765                                         nr_submitted, nr_received, nr_failed);
766                         }
767
768                         if (nr_received >= loops)
769                                 break;
770         }
771
772         fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
773                 nr_submitted, nr_received, nr_failed);
774         return 0;
775 }
776 /* note:
777  * prepare/wait rhythm,
778  * files are converted to independent chunk access patterns,
779 */
780
781 int cmd_rndread(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
782 {
783         if (loops < 0)
784                 return help();
785
786         if (targetlen >= chunksize) {
787                 fprintf(stderr, "targetlen >= chunksize\n");
788                 return -1;
789         }
790
791         char *p = realloc(namebuf, targetlen+1);
792         if (!p) {
793                 fprintf(stderr, "Cannot allocate memory\n");
794                 return -1;
795         }
796         namebuf = p;
797
798         p = realloc(chunk, chunksize);
799         if (!p) {
800                 fprintf(stderr, "Cannot allocate memory\n");
801                 return -1;
802         }
803         chunk = p;
804         memset(chunk, 0, chunksize);
805
806         srandom(seed);
807
808         struct xseg_request *submitted = NULL, *received;
809         long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0;
810         int reported = 0, r;
811         uint64_t offset;
812         xport port;
813         char *req_data, *req_target;
814         init_local_signal();
815
816         seed = random();
817         for (;;) {
818                 submitted = NULL;
819                 xseg_prepare_wait(xseg, srcport);
820                 if (nr_submitted < loops &&
821                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
822                         xseg_cancel_wait(xseg, srcport);
823                         r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
824                         if (r < 0) {
825                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
826                                         targetlen, chunksize);
827                                 xseg_put_request(xseg, submitted, srcport);
828                                 return -1;
829                         }
830
831                         req_target = xseg_get_target(xseg, submitted);
832                         reported = 0;
833                         mkname(namebuf, targetlen, seed);
834                         namebuf[targetlen] = 0;
835                         //printf("%ld: %s\n", nr_submitted, namebuf);
836                         offset = 0;//pick(size);
837
838                         strncpy(req_target, namebuf, targetlen);
839                         submitted->offset = offset;
840                         submitted->size = chunksize;
841                         submitted->op = X_READ;
842                         port = xseg_submit(xseg, submitted, srcport, X_ALLOC);
843                         if (port == NoPort) {
844                                 xseg_put_request(xseg, submitted, srcport);
845                         } else {
846                                 seed = random();
847                                 nr_submitted += 1;
848                                 xseg_signal(xseg, port);
849                         }
850                 }
851
852                 received = xseg_receive(xseg, srcport, 0);
853                 if (received) {
854                         xseg_cancel_wait(xseg, srcport);
855                         nr_received += 1;
856                         req_target = xseg_get_target(xseg, received);
857                         req_data = xseg_get_data(xseg, received);
858                         if (!(received->state & XS_SERVED)) {
859                                 nr_failed += 1;
860                                 report_request(received);
861                         } else if (!chkchunk(req_data, received->datalen,
862                                         req_target, received->targetlen, received->offset)) {
863         //                      report_request(received);
864                                 nr_mismatch += 1;
865                         }
866
867                         if (xseg_put_request(xseg, received, srcport))
868                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
869                 }
870
871                 if (!submitted && !received)
872                         xseg_wait_signal(xseg, 1000000);
873
874                 if (nr_submitted % 1000 == 0 && !reported) {
875                         reported = 1;
876                         fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
877                         nr_submitted, nr_received, nr_failed, nr_mismatch);
878                 }
879
880                 if (nr_received >= loops)
881                         break;
882         }
883
884         fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
885                 nr_submitted, nr_received, nr_failed, nr_mismatch);
886         return 0;
887 }
888
889 int cmd_submit_reqs(long loops, long concurrent_reqs, int op)
890 {
891         if (loops < 0)
892                 return help();
893
894         struct xseg_request *submitted = NULL, *received;
895         long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0, nr_flying = 0;
896         int reported = 0, r;
897         uint64_t offset;
898         uint32_t targetlen = 10, chunksize = 4096;
899         struct timeval tv1, tv2;
900         xport p;
901         char *req_data, *req_target;
902
903         xseg_bind_port(xseg, srcport, NULL);
904
905         gettimeofday(&tv1, NULL);
906         for (;;) {
907                 submitted = NULL;
908                 xseg_prepare_wait(xseg, srcport);
909                 if (nr_submitted < loops &&  nr_flying < concurrent_reqs &&
910                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
911                         xseg_cancel_wait(xseg, srcport);
912                         r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
913                         if (r < 0) {
914                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
915                                         targetlen, chunksize);
916                                 xseg_put_request(xseg, submitted, srcport);
917                                 return -1;
918                         }
919                         
920                         //FIXME
921                         ++nr_flying;
922                         nr_submitted += 1;
923                         reported = 0;
924                         offset = 0;//pick(size);
925
926                         submitted->offset = offset;
927                         submitted->size = chunksize;
928                         req_target = xseg_get_target(xseg, submitted);
929                         req_data = xseg_get_data(xseg, submitted);
930
931                         if (op == 0)
932                                 submitted->op = X_INFO;
933                         else if (op == 1)
934                                 submitted->op = X_READ;
935                         else if (op == 2) {
936                                 submitted->op = X_WRITE;
937                                 mkchunk(req_data, submitted->datalen, req_target, submitted->targetlen, submitted->offset);
938                         }
939
940                         p = xseg_submit(xseg, submitted, srcport, X_ALLOC);
941                         if ( p != NoPort){
942                                 if (xseg_signal(xseg, p) < 0)
943                                         perror("Cannot signal peer");
944                         }
945                 }
946                 received = xseg_receive(xseg, srcport, 0);
947                 if (received) {
948                         xseg_cancel_wait(xseg, srcport);
949                         --nr_flying;
950                         if (nr_received == 0)
951                                 fprintf(stderr, "latency (time for the first req to complete): %llu usecs\n",
952                                         (unsigned long long)received->elapsed);
953                         nr_received += 1;
954                         if (!(received->state & XS_SERVED)) {
955                                 nr_failed += 1;
956                                 //report_request(received);
957                         }
958
959                         if (xseg_put_request(xseg, received, srcport))
960                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
961                 }
962
963                 if (!submitted && !received)
964                         xseg_wait_signal(xseg, 10000000L);
965
966                 if (nr_received >= loops)
967                         break;
968         }
969         gettimeofday(&tv2, NULL);
970
971         fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
972                 nr_submitted, nr_received, nr_failed, nr_mismatch);
973         long t = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
974         fprintf(stderr, "elpased time: %lf secs, throughput: %lf reqs/sec\n", (double) t / 1000000.0, (double) nr_submitted / (t / 1000000.0));
975
976         return 0;
977 }
978
979 int cmd_report(uint32_t portno)
980 {
981         struct xseg_port *port = xseg_get_port(xseg, portno);
982         if (!port) {
983                 printf("port %u is not assigned\n", portno);
984                 return 0;
985         }
986         struct xq *fq, *rq, *pq;
987         fq = xseg_get_queue(xseg, port, free_queue);
988         rq = xseg_get_queue(xseg, port, request_queue);
989         pq = xseg_get_queue(xseg, port, reply_queue);
990         fprintf(stderr, "port %u:\n"
991                 "   requests: %llu/%llu  src gw: %u  dst gw: %u\n"
992                 "       free_queue [%p] count : %llu\n"
993                 "    request_queue [%p] count : %llu\n"
994                 "      reply_queue [%p] count : %llu\n",
995                 portno, (unsigned long long)port->alloc_reqs, 
996                 (unsigned long long)port->max_alloc_reqs,
997                 xseg->src_gw[portno],
998                 xseg->dst_gw[portno],
999                 (void *)fq, (unsigned long long)xq_count(fq),
1000                 (void *)rq, (unsigned long long)xq_count(rq),
1001                 (void *)pq, (unsigned long long)xq_count(pq));
1002         return 0;
1003 }
1004
1005 int cmd_join(void)
1006 {
1007         if (xseg)
1008                 return 0;
1009
1010         xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
1011         if (!xseg) {
1012                 fprintf(stderr, "cannot join segment!\n");
1013                 return -1;
1014         }
1015         return 0;
1016 }
1017 static void print_hanlder(char *name, struct xobject_h *obj_h)
1018 {
1019         fprintf(stderr, "%20s: free: %4llu, allocated: %4llu, allocated space: %7llu (object size: %llu)\n",
1020                         name,
1021                         (unsigned long long) obj_h->nr_free,
1022                         (unsigned long long) obj_h->nr_allocated,
1023                         (unsigned long long) obj_h->allocated_space,
1024                         (unsigned long long) obj_h->obj_size);
1025 }
1026
1027 int cmd_reportall(void)
1028 {
1029         uint32_t t;
1030
1031         if (cmd_join())
1032                 return -1;
1033
1034
1035         fprintf(stderr, "Heap usage: %llu / %llu\n",
1036                         (unsigned long long)xseg->heap->cur,
1037                         (unsigned long long)xseg->config.heap_size);
1038         fprintf(stderr, "Handlers: \n");
1039         print_hanlder("Requests handler", xseg->request_h);
1040         print_hanlder("Ports handler", xseg->port_h);
1041         print_hanlder("Objects handler", xseg->object_handlers);
1042         fprintf(stderr, "\n");
1043
1044         for (t = 0; t < xseg->config.nr_ports; t++)
1045                 cmd_report(t);
1046
1047         return 0;
1048 }
1049
1050
1051 int finish_req(struct xseg_request *req, enum req_action action)
1052 {
1053         if (action == COMPLETE){
1054                 req->state &= ~XS_FAILED;
1055                 req->state |= XS_SERVED;
1056         } else {
1057                 req->state |= XS_FAILED;
1058                 req->state &= ~XS_SERVED;
1059         }
1060         xport p = xseg_respond(xseg, req, srcport, X_ALLOC);
1061         xseg_signal(xseg, p);
1062 }
1063
1064
1065 int cmd_requests(xport portno, enum req_action action )
1066 {
1067         if (cmd_join())
1068                 return -1;
1069
1070         struct xobject_h *obj_h = xseg->request_h;
1071         void *container = XPTR(&obj_h->container);
1072         xhash_t *allocated = XPTR_TAKE(obj_h->allocated, container);
1073         xhash_iter_t it;
1074         xhash_iter_init(allocated, &it);
1075         xhashidx key, val;
1076         int i;
1077         xlock_acquire(&obj_h->lock, 1);
1078         while (xhash_iterate(allocated, &it, &key, &val)){
1079                 void *mem = XPTR_TAKE(val, container);
1080                 struct xseg_request *req = mem, *t;
1081                 for (i = 0; i < xheap_get_chunk_size(mem)/obj_h->obj_size; i++) {
1082                         t = req + i;
1083                         if (t->src_portno == portno){
1084                                 if (action == REPORT)
1085                                         report_request(t);
1086                                 else if (action == FAIL)
1087                                         finish_req(t, action);
1088                                 else if (action == COMPLETE)
1089                                         finish_req(t, COMPLETE);
1090                         }
1091                 }
1092         }
1093         xlock_release(&obj_h->lock);
1094
1095         fprintf(stderr, "\n");
1096         return 0;
1097 }
1098
1099 int cmd_create(void)
1100 {
1101         int r = xseg_create(&cfg);
1102         if (r) {
1103                 fprintf(stderr, "cannot create segment!\n");
1104                 return -1;
1105         }
1106
1107         fprintf(stderr, "Segment initialized.\n");
1108         return 0;
1109 }
1110
1111 int cmd_destroy(void)
1112 {
1113         if (!xseg && cmd_join())
1114                 return -1;
1115         xseg_leave(xseg);
1116         xseg_destroy(xseg);
1117         xseg = NULL;
1118         fprintf(stderr, "Segment destroyed.\n");
1119         return 0;
1120 }
1121
1122 int cmd_alloc_requests(unsigned long nr)
1123 {
1124         return xseg_alloc_requests(xseg, srcport, nr);
1125 }
1126
1127 int cmd_free_requests(unsigned long nr)
1128 {
1129         return xseg_free_requests(xseg, srcport, nr);
1130 }
1131
1132 int cmd_put_requests(void)
1133 {
1134         struct xseg_request *req;
1135
1136         for (;;) {
1137                 req = xseg_accept(xseg, dstport, 0);
1138                 if (!req)
1139                         break;
1140                 if (xseg_put_request(xseg, req, srcport))
1141                         fprintf(stderr, "Cannot put request at port %u\n", req->src_portno);
1142         }
1143
1144         return 0;
1145 }
1146
1147 int cmd_finish(unsigned long nr, int fail)
1148 {
1149         struct xseg_request *req;
1150         char *buf = malloc(sizeof(char) * 8128);
1151         char *req_target, *req_data;
1152         xseg_bind_port(xseg, srcport, NULL);
1153         xport p;
1154
1155         for (; nr--;) {
1156                 xseg_prepare_wait(xseg, srcport);
1157                 req = xseg_accept(xseg, srcport, 0);
1158                 if (req) {
1159                         req_target = xseg_get_target(xseg, req);
1160                         req_data = xseg_get_data(xseg, req);
1161                         xseg_cancel_wait(xseg, srcport);
1162                         if (fail == 1)
1163                                 req->state &= ~XS_SERVED;
1164                         else {
1165                                 if (req->op == X_READ)
1166                                         mkchunk(req_data, req->datalen, req_target, req->targetlen, req->offset);
1167                                 else if (req->op == X_WRITE) 
1168                                         memcpy(buf, req_data, (sizeof(*buf) > req->datalen) ? req->datalen : sizeof(*buf));
1169                                 else if (req->op == X_INFO)
1170                                         *((uint64_t *) req->data) = 4294967296;
1171                                 
1172                                 req->state |= XS_SERVED;
1173                                 req->serviced = req->size;
1174                         }
1175
1176                         p = xseg_respond(xseg, req, srcport, X_ALLOC);
1177                         xseg_signal(xseg, p);
1178                         continue;
1179                 }
1180                 ++nr;
1181                 xseg_wait_signal(xseg, 10000000L);
1182         }
1183
1184         free(buf);
1185
1186         return 0;
1187 }
1188
1189 void handle_reply(struct xseg_request *req)
1190 {
1191         char *req_data = xseg_get_data(xseg, req);
1192         char *req_target = xseg_get_target(xseg, req);
1193         if (!(req->state & XS_SERVED)) {
1194                 report_request(req);
1195                 goto put;
1196         }
1197
1198         switch (req->op) {
1199         case X_READ:
1200                 fwrite(req_data, 1, req->datalen, stdout);
1201                 break;
1202
1203         case X_WRITE:
1204                 fprintf(stdout, "wrote: ");
1205                 fwrite(req_data, 1, req->datalen, stdout);
1206                 break;
1207         case X_SYNC:
1208         case X_DELETE:
1209                 fprintf(stderr, "deleted %s\n", req_target);
1210                 break;
1211         case X_TRUNCATE:
1212         case X_COMMIT:
1213         case X_CLONE:
1214                 fprintf(stderr, "cloned %s\n", ((struct xseg_request_clone *)req_data)->target);
1215                 break;
1216         case X_INFO:
1217                 fprintf(stderr, "size: %llu\n", (unsigned long long)*((uint64_t *)req_data));
1218                 break;
1219
1220         default:
1221                 break;
1222         }
1223
1224 put:
1225         if (xseg_put_request(xseg, req, srcport))
1226                 fprintf(stderr, "Cannot put reply at port %u\n", req->src_portno);
1227 }
1228
1229 int cmd_wait(uint32_t nr)
1230 {
1231         struct xseg_request *req;
1232         long ret;
1233         init_local_signal(); 
1234
1235         for (;;) {
1236                 req = xseg_receive(xseg, srcport, 0);
1237                 if (req) {
1238                         handle_reply(req);
1239                         nr--;
1240                         if (nr == 0)
1241                                 break;
1242                         continue;
1243                 }
1244
1245                 ret = xseg_prepare_wait(xseg, srcport);
1246                 if (ret)
1247                         return -1;
1248
1249                 ret = xseg_wait_signal(xseg, 1000000);
1250                 ret = xseg_cancel_wait(xseg, srcport);
1251                 if (ret)
1252                         return -1;
1253         }
1254
1255         return 0;
1256 }
1257
1258 int cmd_put_replies(void)
1259 {
1260         struct xseg_request *req;
1261
1262         for (;;) {
1263                 req = xseg_receive(xseg, dstport, 0);
1264                 if (!req)
1265                         break;
1266                 fprintf(stderr, "request: %08llx%08llx\n"
1267                         "     op: %u\n"
1268                         "  state: %u\n",
1269                         0LL, (unsigned long long)req->serial,
1270                         req->op,
1271                         req->state);
1272                 report_request(req);
1273
1274                 //fwrite(req->buffer, 1, req->bufferlen, stdout);
1275
1276                 if (xseg_put_request(xseg, req, srcport))
1277                         fprintf(stderr, "Cannot put reply\n");
1278         }
1279
1280         return 0;
1281 }
1282
1283 int cmd_bind(long portno)
1284 {
1285         struct xseg_port *port = xseg_bind_port(xseg, portno, NULL);
1286         if (!port) {
1287                 fprintf(stderr, "failed to bind port %ld\n", portno);
1288                 return 1;
1289         }
1290
1291         fprintf(stderr, "bound port %u\n", xseg_portno(xseg, port));
1292         return 0;
1293 }
1294
1295 int cmd_signal(uint32_t portno)
1296 {
1297         return xseg_signal(xseg, portno);
1298 }
1299
1300 int parse_ports(char *str)
1301 {
1302         int ret = 0;
1303         char *s = str;
1304
1305         for (;;) {
1306                 if (*s == 0)
1307                         return 0;
1308
1309                 if (*s == ':') {
1310                         *s = 0;
1311                         if ((s > str) && isdigit(str[0])) {
1312                                 srcport = atol(str);
1313                                 ret ++;
1314                         }
1315                         break;
1316                 }
1317                 s ++;
1318         }
1319
1320         s += 1;
1321         str = s;
1322
1323         for (;;) {
1324                 if (*s == 0) {
1325                         if ((s > str) && isdigit(str[0])) {
1326                                 dstport = atol(str);
1327                                 ret ++;
1328                         }
1329                         break;
1330                 }
1331                 s ++;
1332         }
1333
1334         return ret;
1335 }
1336
1337 int main(int argc, char **argv)
1338 {
1339         int i, ret = 0;
1340         char *spec;
1341
1342         if (argc < 3)
1343                 return help();
1344
1345         srcport = -1;
1346         dstport = -1;
1347         spec = argv[1];
1348
1349         if (xseg_parse_spec(spec, &cfg)) {
1350                 fprintf(stderr, "Cannot parse spec\n");
1351                 return -1;
1352         }
1353
1354         if (xseg_initialize()) {
1355                 fprintf(stderr, "cannot initialize!\n");
1356                 return -1;
1357         }
1358
1359         for (i = 2; i < argc; i++) {
1360
1361                 if (!strcmp(argv[i], "create")) {
1362                         ret = cmd_create();
1363                         continue;
1364                 }
1365
1366                 if (!strcmp(argv[i], "join")) {
1367                         ret = cmd_join();
1368                         if (!ret)
1369                                 fprintf(stderr, "Segment joined.\n");
1370                         continue;
1371                 }
1372
1373                 if (!strcmp(argv[i], "destroy")) {
1374                         ret = cmd_destroy();
1375                         continue;
1376                 }
1377
1378                 if (cmd_join())
1379                         return -1;
1380
1381                 if (!strcmp(argv[i], "reportall")) {
1382                         ret = cmd_reportall();
1383                         continue;
1384                 }
1385
1386                 if (!strcmp(argv[i], "bind") && (i + 1 < argc)) {
1387                         ret = cmd_bind(atol(argv[i+1]));
1388                         i += 1;
1389                         continue;
1390                 }
1391
1392                 if (!strcmp(argv[i], "showreqs") && (i + 1 < argc)) {
1393                         ret = cmd_requests(atol(argv[i+1]), REPORT);
1394                         i += 1;
1395                         continue;
1396                 }
1397
1398                 if (!strcmp(argv[i], "signal") && (i + 1 < argc)) {
1399                         ret = cmd_signal(atol(argv[i+1]));
1400                         i += 1;
1401                         continue;
1402                 }
1403
1404                 if (!strcmp(argv[i], "bridge") && (i + 4 < argc)) {
1405                         ret = cmd_bridge(atol(argv[i+1]),
1406                                          atol(argv[i+2]),
1407                                          argv[i+3],
1408                                          argv[i+4]);
1409                         i += 4;
1410                         continue;
1411                 }
1412
1413                 if (srcport == -1) {
1414                         if (!parse_ports(argv[i]))
1415                                 fprintf(stderr, "source port undefined: %s\n", argv[i]);
1416                         continue;
1417                 }
1418
1419                 if (dstport == -1) {
1420                         if (!parse_ports(argv[i]))
1421                                 fprintf(stderr, "destination port undefined: %s\n", argv[i]);
1422                         continue;
1423                 }
1424
1425                 if (!strcmp(argv[i], "failreqs") && (i + 1 < argc)) {
1426                         ret = cmd_requests(atol(argv[i+1]), FAIL);
1427                         i += 1;
1428                         continue;
1429                 }
1430
1431
1432                 if (!strcmp(argv[i], "report")) {
1433                         ret = cmd_report(dstport);
1434                         continue;
1435                 }
1436
1437                 if (!strcmp(argv[i], "alloc_requests") && (i + 1 < argc)) {
1438                         ret = cmd_alloc_requests(atol(argv[i+1]));
1439                         i += 1;
1440                         continue;
1441                 }
1442
1443                 if (!strcmp(argv[i], "free_requests") && (i + 1 < argc)) {
1444                         ret = cmd_free_requests(atol(argv[i+1]));
1445                         i += 1;
1446                         continue;
1447                 }
1448
1449                 if (!strcmp(argv[i], "put_requests")) {
1450                         ret = cmd_put_requests();
1451                         continue;
1452                 }
1453
1454                 if (!strcmp(argv[i], "put_replies")) {
1455                         ret = cmd_put_replies();
1456                         continue;
1457                 }
1458
1459                 if (!strcmp(argv[i], "complete") && (i + 1 < argc)) {
1460                         ret = cmd_finish(atol(argv[i+1]), 0);
1461                         i += 1;
1462                         continue;
1463                 }
1464
1465                 if (!strcmp(argv[i], "fail") && (i + 1 < argc)) {
1466                         ret = cmd_finish(atol(argv[i+1]), 1);
1467                         i += 1;
1468                         continue;
1469                 }
1470
1471                 if (!strcmp(argv[i], "wait") && (i + 1 < argc)) {
1472                         ret = cmd_wait(atol(argv[i+1]));
1473                         i += 1;
1474                         continue;
1475                 }
1476
1477                 if (!strcmp(argv[i], "rndwrite") && (i + 5 < argc)) {
1478                         long nr_loops = atol(argv[i+1]);
1479                         unsigned int seed = atoi(argv[i+2]);
1480                         unsigned int targetlen = atoi(argv[i+3]);
1481                         unsigned int chunksize = atoi(argv[i+4]);
1482                         unsigned long objectsize = atol(argv[i+5]);
1483                         ret = cmd_rndwrite(nr_loops, seed, targetlen, chunksize, objectsize);
1484                         i += 5;
1485                         continue;
1486                 }
1487                 
1488                 if (!strcmp(argv[i], "rnddelete") && (i + 3 < argc)) {
1489                         long nr_loops = atol(argv[i+1]);
1490                         unsigned int seed = atoi(argv[i+2]);
1491                         unsigned int targetlen = atoi(argv[i+3]);
1492                         ret = cmd_rnddelete(nr_loops, seed, targetlen);
1493                         i += 3;
1494                         continue;
1495                 }
1496
1497                 if (!strcmp(argv[i], "rndread") && (i + 5 < argc)) {
1498                         long nr_loops = atol(argv[i+1]);
1499                         unsigned int seed = atoi(argv[i+2]);
1500                         unsigned int targetlen = atoi(argv[i+3]);
1501                         unsigned int chunksize = atoi(argv[i+4]);
1502                         unsigned long objectsize = atol(argv[i+5]);
1503                         ret = cmd_rndread(nr_loops, seed, targetlen, chunksize, objectsize);
1504                         i += 5;
1505                         continue;
1506                 }
1507
1508                 if (!strcmp(argv[i], "submit_reqs") && (i + 3 < argc)) {
1509                         long nr_loops = atol(argv[i+1]);
1510                         long concurrent_reqs = atol(argv[i+2]);
1511                         int op = atoi(argv[i+3]);
1512                         ret = cmd_submit_reqs(nr_loops, concurrent_reqs, op);
1513                         i += 3;
1514                         continue;
1515                 }
1516
1517                 if (!strcmp(argv[i], "read") && (i + 3 < argc)) {
1518                         char *target = argv[i+1];
1519                         uint64_t offset = atol(argv[i+2]);
1520                         uint64_t size   = atol(argv[i+3]);
1521                         ret = cmd_read(target, offset, size);
1522                         i += 3;
1523                         continue;
1524                 }
1525
1526                 if (!strcmp(argv[i], "write") && (i + 2 < argc)) {
1527                         char *target = argv[i+1];
1528                         uint64_t offset = atol(argv[i+2]);
1529                         ret = cmd_write(target, offset);
1530                         i += 2;
1531                         continue;
1532                 }
1533
1534                 if (!strcmp(argv[i], "truncate") && (i + 2 < argc)) {
1535                         char *target = argv[i+1];
1536                         uint64_t offset = atol(argv[i+2]);
1537                         ret = cmd_truncate(target, offset);
1538                         i += 2;
1539                         continue;
1540                 }
1541
1542                 if (!strcmp(argv[i], "delete") && (i + 1 < argc)) {
1543                         char *target = argv[i+1];
1544                         ret = cmd_delete(target);
1545                         i += 1;
1546                         continue;
1547                 }
1548
1549                 if (!strcmp(argv[i], "acquire") && (i + 1 < argc)) {
1550                         char *target = argv[i+1];
1551                         ret = cmd_acquire(target);
1552                         i += 1;
1553                         continue;
1554                 }
1555
1556                 if (!strcmp(argv[i], "release") && (i + 1 < argc)) {
1557                         char *target = argv[i+1];
1558                         ret = cmd_release(target);
1559                         i += 1;
1560                         continue;
1561                 }
1562
1563                 if (!strcmp(argv[i], "copy") && (i + 2) < argc) {
1564                         char *src = argv[i+1];
1565                         char *dst = argv[i+2];
1566                         ret = cmd_copy(src, dst);
1567                         i += 2;
1568                         continue;
1569                 }
1570
1571                 if (!strcmp(argv[i], "clone") && (i + 2 < argc)) {
1572                         char *src = argv[i+1];
1573                         char *dst = argv[i+2];
1574                         ret = cmd_clone(src, dst);
1575                         i += 2;
1576                         continue;
1577                 }
1578
1579                 if (!strcmp(argv[i], "info") && (i + 1 < argc)) {
1580                         char *target = argv[i+1];
1581                         ret = cmd_info(target);
1582                         i += 1;
1583                         continue;
1584                 }
1585
1586
1587                 if (!parse_ports(argv[i]))
1588                         fprintf(stderr, "invalid argument: %s\n", argv[i]);
1589         }
1590
1591         /* xseg_leave(); */
1592         return ret;
1593 }