fix log_io printing beyond end-of-string garbage
[archipelago] / xseg / peers / 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 <xseg/xseg.h>
13
14 int help(void)
15 {
16         printf("xseg <spec> [[[<src_port>]:[<dst_port>]] [<command> <arg>]* ]*\n"
17                 "spec:\n"
18                 "    <type:name:nr_ports:nr_requests:request_size:extra_size:page_shift>\n"
19                 "global commands:\n"
20                 "    reportall\n"
21                 "    create\n"
22                 "    destroy\n"
23                 "    bind <portno>\n"
24                 "    signal <portno>\n"
25                 "    bridge <portno1> <portno2> <logfile> {full|summary|stats}\n"
26                 "port commands:\n"
27                 "    report\n"
28                 "    alloc_requests (to source) <nr>\n"
29                 "    free_requests (from source) <nr>\n"
30                 "    put_requests (all from dest)\n"
31                 "    put_replies (all from dest)\n"
32                 "    wait     <nr_replies>\n"
33                 "    complete <nr_requests>\n"
34                 "    fail     <nr_requests>\n"
35                 "    rndwrite <nr_loops> <seed> <namesize> <datasize> <objectsize>\n"
36                 "    rndread  <nr_loops> <seed> <namesize> <datasize> <objectsize>\n"
37                 "    info     <name>\n"
38                 "    read     <name> <offset> <size>\n"
39                 "    write    <name> <offset> < data\n"
40                 "    truncate <name> <size>\n"
41                 "    delete   <name>\n"
42                 "    acquire  <name>\n"
43                 "    release  <name>\n"
44                 "    copy     <src>  <dst>\n"
45                 "    clone    <src>  <dst>\n"
46         );
47         return 1;
48 }
49
50 char *namebuf;
51 char *chunk;
52 struct xseg_config cfg;
53 struct xseg *xseg;
54 uint32_t srcport, dstport;
55
56
57 #define mkname mkname_heavy
58 /* heavy distributes duplicates much more widely than light
59  * ./xseg-tool random 100000 | cut -d' ' -f2- | sort | uniq -d -c |wc -l
60  */
61
62 void mkname_heavy(char *name, uint32_t namesize, uint32_t seed)
63 {
64         int i;
65         char c;
66         for (i = 0; i < namesize; i += 1) {
67                 c = seed + (seed >> 8) + (seed >> 16) + (seed >> 24);
68                 c = '0' + ((c + (c >> 4)) & 0xf);
69                 if (c > '9')
70                         c += 'a'-'0'-10;
71                 name[i] = c;
72                 seed *= ((seed % 137911) | 1) * 137911;
73         }
74 }
75
76 void mkname_light(char *name, uint32_t namesize, uint32_t seed)
77 {
78         int i;
79         char c;
80         for (i = 0; i < namesize; i += 1) {
81                 c = seed;
82                 name[i] = 'A' + (c & 0xf);
83                 seed += 1;
84         }
85 }
86
87 uint64_t pick(uint64_t size)
88 {
89         return (uint64_t)((double)(RAND_MAX) / random());
90 }
91
92 void mkchunk(   char *chunk, uint32_t datasize,
93                 char *name, uint32_t namesize, uint64_t offset)
94 {
95         long i, r, bufsize = namesize + 16;
96         char buf[bufsize];
97         r = datasize % bufsize;
98         snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, name);
99
100         for (i = 0; i <= (long)datasize - bufsize; i += bufsize)
101                 memcpy(chunk + i, buf, bufsize);
102
103         memcpy(chunk + datasize - r, buf, r);
104 }
105
106 int chkchunk(   char *chunk, uint32_t datasize,
107                 char *name, uint32_t namesize, uint64_t offset)
108 {
109         long i, r;
110         int bufsize = namesize + 16;
111         char buf[bufsize];
112         r = datasize % namesize;
113         snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, name);
114
115         for (i = 0; i <= (long)datasize - bufsize; i += bufsize)
116                 if (memcmp(chunk + i, buf, bufsize)) {
117                         /*printf("mismatch: '%*s'* vs '%*s'\n",
118                                 bufsize, buf, datasize, chunk);
119                         */
120                         return 0;
121                 }
122
123         if (memcmp(chunk + datasize - r, buf, r))
124                 return 0;
125
126         return 1;
127 }
128
129
130 #define ALLOC_MIN 4096
131 #define ALLOC_MAX 1048576
132
133 void inputbuf(FILE *fp, char **retbuf, uint64_t *retsize)
134 {
135         static uint64_t alloc_size;
136         static char *buf;
137         uint64_t size = 0;
138         char *p;
139         size_t r;
140
141         if (alloc_size < ALLOC_MIN)
142                 alloc_size = ALLOC_MIN;
143
144         if (alloc_size > ALLOC_MAX)
145                 alloc_size = ALLOC_MAX;
146
147         p = realloc(buf, alloc_size);
148         if (!p) {
149                 if (buf)
150                         free(buf);
151                 buf = NULL;
152                 goto out;
153         }
154
155         buf = p;
156
157         while (!feof(fp)) {
158                 r = fread(buf + size, 1, alloc_size - size, fp);
159                 if (!r)
160                         break;
161                 size += r;
162                 if (size >= alloc_size) {
163                         p = realloc(buf, alloc_size * 2);
164                         if (!p) {
165                                 if (buf)
166                                         free(buf);
167                                 buf = NULL;
168                                 size = 0;
169                                 goto out;
170                         }
171                         buf = p;
172                         alloc_size *= 2;
173                 }
174         }
175
176 out:
177         *retbuf = buf;
178         *retsize = size;
179 }
180
181 void report_request(struct xseg_request *req)
182 {
183         uint32_t max = req->datasize;
184         if (max > 128)
185                 max = 128;
186         req->data[max-1] = 0;
187         printf("request %llu state %u\n", (unsigned long long)req->serial, req->state);
188         printf("data: %s\n", req->data);
189 }
190
191 int cmd_info(char *name)
192 {
193         return 0;
194 }
195
196 int cmd_read(char *name, uint64_t offset, uint64_t size)
197 {
198         uint32_t namesize = strlen(name);
199         int r;
200         xserial srl;
201         struct xseg_request *req = xseg_get_request(xseg, srcport);
202         if (!req) {
203                 printf("No request\n");
204                 return -1;
205         }
206
207         r = xseg_prep_request(req, namesize, size);
208         if (r < 0) {
209                 printf("Cannot prepare request! (%lu, %llu)\n",
210                         (unsigned long)namesize, (unsigned long long)size);
211                 xseg_put_request(xseg, srcport, req);
212                 return -1;
213         }
214
215         strncpy(req->name, name, namesize);
216         req->offset = offset;
217         req->size = size;
218         req->op = X_READ;
219
220         srl = xseg_submit(xseg, dstport, req);
221         if (srl == None)
222                 return -1;
223
224         xseg_signal(xseg, dstport);
225         return 0;
226 }
227
228 int cmd_write(char *name, uint64_t offset)
229 {
230         char *buf = NULL;
231         int r;
232         xserial srl;
233         uint64_t size = 0;
234         uint32_t namesize = strlen(name);
235         struct xseg_request *req;
236
237         inputbuf(stdin, &buf, &size);
238         if (!size) {
239                 printf("No input\n");
240                 return -1;
241         }
242
243         req = xseg_get_request(xseg, srcport);
244         if (!req) {
245                 printf("No request\n");
246                 return -1;
247         }
248
249         r = xseg_prep_request(req, namesize, size);
250         if (r < 0) {
251                 printf("Cannot prepare request! (%lu, %llu)\n",
252                         (unsigned long)namesize, (unsigned long long)size);
253                 xseg_put_request(xseg, srcport, req);
254                 return -1;
255         }
256
257         strncpy(req->name, name, namesize);
258         memcpy(req->buffer, buf, size);
259         req->offset = offset;
260         req->size = size;
261         req->op = X_WRITE;
262
263         srl = xseg_submit(xseg, dstport, req);
264         if (srl == None) {
265                 printf("Cannot submit\n");
266                 return -1;
267         }
268
269         return 0;
270 }
271
272 int cmd_truncate(char *name, uint64_t offset)
273 {
274         return 0;
275 }
276
277 int cmd_delete(char *name)
278 {
279         return 0;
280 }
281
282 int cmd_acquire(char *name)
283 {
284         return 0;
285 }
286
287 int cmd_release(char *name)
288 {
289         return 0;
290 }
291
292 int cmd_copy(char *src, char *dst)
293 {
294         return 0;
295 }
296
297 int cmd_clone(char *src, char *dst)
298 {
299         return 0;
300 }
301
302 void log_req(   uint32_t portno2, uint32_t portno1, int op, int method,
303                 struct xseg_request *req)
304 {
305         return;
306 }
307
308 #define LOG_ACCEPT  0
309 #define LOG_RECEIVE 1
310
311 int cmd_bridge(uint32_t portno1, uint32_t portno2, char *logfile, char *how)
312 {
313         struct xseg_request *req;
314         int logfd, method;
315         if (!strcmp(logfile, "-"))
316                 logfd = 1;
317         else {
318                 logfd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0600);
319                 if (logfd < 0) {
320                         perror(logfile);
321                         return -1;
322                 }
323         }
324
325         if (!strcmp(how, "full"))
326                 method = 0;
327         else if (!strcmp(how, "full"))
328                 method = 1;
329         else
330                 method = 2;
331
332         for (;;) {
333                 int reloop = 0, active;
334                 xseg_prepare_wait(xseg, portno1);
335                 xseg_prepare_wait(xseg, portno2);
336                 req = NULL;
337
338                 for (;;) {
339                         active = 0;
340
341                         req = xseg_accept(xseg, portno1);
342                         if (req) {
343                                 xseg_submit(xseg, portno2, req);
344                                 log_req(portno1, portno2, LOG_ACCEPT, method, req);
345                                 active += 1;
346                         }
347
348                         req = xseg_accept(xseg, portno2);
349                         if (req) {
350                                 xseg_submit(xseg, portno1, req);
351                                 log_req(portno2, portno1, LOG_ACCEPT, method, req);
352                                 active += 1;
353                         }
354
355                         req = xseg_receive(xseg, portno1);
356                         if (req) {
357                                 xseg_respond(xseg, portno2, req);
358                                 log_req(portno1, portno2, LOG_RECEIVE, method, req);
359                                 active += 1;
360                         }
361
362                         req = xseg_receive(xseg, portno2);
363                         if (req) {
364                                 xseg_respond(xseg, portno1, req);
365                                 log_req(portno2, portno1, LOG_RECEIVE, method, req);
366                                 active += 1;
367                         }
368
369                         if (active == 0) {
370                                 if (reloop)
371                                         break;
372                                 /* wait on multiple queues? */
373                                 xseg_wait_signal(xseg, portno1, 100000);
374                                 break;
375                         } else {
376                                 xseg_cancel_wait(xseg, portno1);        
377                                 xseg_cancel_wait(xseg, portno2);        
378                                 reloop = 1;
379                         }
380                 }
381         }
382
383         return 0;
384 }
385
386 int cmd_rndwrite(long loops, int32_t seed, uint32_t namesize, uint32_t chunksize, uint64_t size)
387 {
388         if (loops < 0)
389                 return help();
390
391         if (namesize >= chunksize) {
392                 printf("namesize >= chunksize\n");
393                 return -1;
394         }
395
396         char *p = realloc(namebuf, namesize+1);
397         if (!p) {
398                 printf("Cannot allocate memory\n");
399                 return -1;
400         }
401         namebuf = p;
402
403         p = realloc(chunk, chunksize);
404         if (!p) {
405                 printf("Cannot allocate memory\n");
406                 return -1;
407         }
408         chunk = p;
409         memset(chunk, 0, chunksize);
410
411         srandom(seed);
412
413         struct xseg_request *submitted = NULL, *received;
414         long nr_submitted = 0, nr_received = 0, nr_failed = 0;
415         int reported = 0, r;
416         uint64_t offset;
417         xserial srl;
418
419         for (;;) {
420                 xseg_prepare_wait(xseg, srcport);
421                 if (nr_submitted < loops &&
422                     (submitted = xseg_get_request(xseg, srcport))) {
423                         xseg_cancel_wait(xseg, srcport);
424                         r = xseg_prep_request(submitted, namesize, chunksize);
425                         if (r < 0) {
426                                 printf("Cannot prepare request! (%u, %u)\n",
427                                         namesize, chunksize);
428                                 xseg_put_request(xseg, submitted->portno, submitted);
429                                 return -1;
430                         }
431
432                         nr_submitted += 1;
433                         reported = 0;
434                         seed = random();
435                         mkname(namebuf, namesize, seed);
436                         namebuf[namesize] = 0;
437                         //printf("%ld: %s\n", nr_submitted, namebuf);
438                         strncpy(submitted->name, namebuf, namesize);
439                         offset = 0;// pick(size);
440                         mkchunk(submitted->buffer, chunksize, namebuf, namesize, offset);
441
442                         submitted->offset = offset;
443                         submitted->size = chunksize;
444                         submitted->op = X_WRITE;
445                         submitted->flags |= XF_NOSYNC;
446
447                         srl = xseg_submit(xseg, dstport, submitted);
448                         (void)srl;
449                         xseg_signal(xseg, dstport);
450                 }
451
452                 received = xseg_receive(xseg, srcport);
453                 if (received) {
454                         xseg_cancel_wait(xseg, srcport);
455                         nr_received += 1;
456                         if (!(received->state & XS_SERVED)) {
457                                 nr_failed += 1;
458                                 report_request(received);
459                         }
460                         if (xseg_put_request(xseg, received->portno, received))
461                                 printf("Cannot put request at port %u\n", received->portno);
462                 }
463
464                 if (!submitted && !received)
465                         xseg_wait_signal(xseg, srcport, 1000000);
466
467                         if (nr_submitted % 1000 == 0 && !reported) {
468                                 reported = 1;
469                                 printf("submitted %ld, received %ld, failed %ld\n",
470                                         nr_submitted, nr_received, nr_failed);
471                         }
472
473                         if (nr_received >= loops)
474                                 break;
475         }
476
477         printf("submitted %ld, received %ld, failed %ld\n",
478                 nr_submitted, nr_received, nr_failed);
479         return 0;
480 }
481
482 /* note:
483  * prepare/wait rhythm,
484  * files are converted to independent chunk access patterns,
485 */
486
487 int cmd_rndread(long loops, int32_t seed, uint32_t namesize, uint32_t chunksize, uint64_t size)
488 {
489         if (loops < 0)
490                 return help();
491
492         if (namesize >= chunksize) {
493                 printf("namesize >= chunksize\n");
494                 return -1;
495         }
496
497         char *p = realloc(namebuf, namesize+1);
498         if (!p) {
499                 printf("Cannot allocate memory\n");
500                 return -1;
501         }
502         namebuf = p;
503
504         p = realloc(chunk, chunksize);
505         if (!p) {
506                 printf("Cannot allocate memory\n");
507                 return -1;
508         }
509         chunk = p;
510         memset(chunk, 0, chunksize);
511
512         srandom(seed);
513
514         struct xseg_request *submitted = NULL, *received;
515         long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0;
516         int reported = 0, r;
517         uint64_t offset;
518         xserial srl;
519
520         for (;;) {
521                 submitted = NULL;
522                 xseg_prepare_wait(xseg, srcport);
523                 if (nr_submitted < loops &&
524                     (submitted = xseg_get_request(xseg, srcport))) {
525                         xseg_cancel_wait(xseg, srcport);
526                         r = xseg_prep_request(submitted, namesize, chunksize);
527                         if (r < 0) {
528                                 printf("Cannot prepare request! (%u, %u)\n",
529                                         namesize, chunksize);
530                                 xseg_put_request(xseg, submitted->portno, submitted);
531                                 return -1;
532                         }
533
534                         nr_submitted += 1;
535                         reported = 0;
536                         seed = random();
537                         mkname(namebuf, namesize, seed);
538                         namebuf[namesize] = 0;
539                         //printf("%ld: %s\n", nr_submitted, namebuf);
540                         offset = 0;//pick(size);
541
542                         strncpy(submitted->name, namebuf, namesize);
543                         submitted->offset = offset;
544                         submitted->size = chunksize;
545                         submitted->op = X_READ;
546
547                         srl = xseg_submit(xseg, dstport, submitted);
548                         (void)srl;
549                         xseg_signal(xseg, dstport);
550                 }
551
552                 received = xseg_receive(xseg, srcport);
553                 if (received) {
554                         xseg_cancel_wait(xseg, srcport);
555                         nr_received += 1;
556                         if (!(received->state & XS_SERVED)) {
557                                 nr_failed += 1;
558                                 report_request(received);
559                         } else if (!chkchunk(received->data, received->datasize,
560                                         received->name, received->namesize, received->offset)) {
561                                 nr_mismatch += 1;
562                         }
563
564                         if (xseg_put_request(xseg, received->portno, received))
565                                 printf("Cannot put request at port %u\n", received->portno);
566                 }
567
568                 if (!submitted && !received)
569                         xseg_wait_signal(xseg, srcport, 1000000);
570
571                 if (nr_submitted % 1000 == 0 && !reported) {
572                         reported = 1;
573                         printf("submitted %ld, received %ld, failed %ld, mismatched %ld\n",
574                         nr_submitted, nr_received, nr_failed, nr_mismatch);
575                 }
576
577                 if (nr_received >= loops)
578                         break;
579         }
580
581         printf("submitted %ld, received %ld, failed %ld, mismatched %ld\n",
582                 nr_submitted, nr_received, nr_failed, nr_mismatch);
583         return 0;
584 }
585
586 int cmd_report(uint32_t port)
587 {
588         struct xq *fq, *rq, *pq;
589         fq = &xseg->ports[port].free_queue;
590         rq = &xseg->ports[port].request_queue;
591         pq = &xseg->ports[port].reply_queue;
592         printf("port %u:\n"
593                 "       free_queue [%p] count : %u\n"
594                 "    request_queue [%p] count : %u\n"
595                 "      reply_queue [%p] count : %u\n",
596                 port,
597                 (void *)fq, xq_count(fq),
598                 (void *)rq, xq_count(rq),
599                 (void *)pq, xq_count(pq));
600         return 0;
601 }
602
603 int cmd_join(void)
604 {
605         if (xseg)
606                 return 0;
607
608         xseg = xseg_join(cfg.type, cfg.name);
609         if (!xseg) {
610                 printf("cannot join segment!\n");
611                 return -1;
612         }
613         return 0;
614 }
615
616 int cmd_reportall(void)
617 {
618         uint32_t t;
619
620         if (cmd_join())
621                 return -1;
622
623         printf("global free requests: %u\n", xq_count(xseg->free_requests));
624         for (t = 0; t < xseg->config.nr_ports; t++)
625                 cmd_report(t);
626
627         return 0;
628 }
629
630 int cmd_create(void)
631 {
632         int r = xseg_create(&cfg);
633         if (r) {
634                 printf("cannot create segment!\n");
635                 return -1;
636         }
637
638         printf("Segment initialized.\n");
639         return 0;
640 }
641
642 int cmd_destroy(void)
643 {
644         if (!xseg && cmd_join())
645                 return -1;
646         xseg_destroy(xseg);
647         xseg = NULL;
648         printf("Segment destroyed.\n");
649         return 0;
650 }
651
652 int cmd_alloc_requests(unsigned long nr)
653 {
654         return xseg_alloc_requests(xseg, srcport, nr);
655 }
656
657 int cmd_free_requests(unsigned long nr)
658 {
659         return xseg_free_requests(xseg, srcport, nr);
660 }
661
662 int cmd_put_requests(void)
663 {
664         struct xseg_request *req;
665
666         for (;;) {
667                 req = xseg_accept(xseg, dstport);
668                 if (!req)
669                         break;
670                 if (xseg_put_request(xseg, req->portno, req))
671                         printf("Cannot put request at port %u\n", req->portno);
672         }
673
674         return 0;
675 }
676
677 int cmd_finish(unsigned long nr, int fail)
678 {
679         struct xseg_request *req;
680
681         for (; nr--;) {
682                 req = xseg_accept(xseg, srcport);
683                 if (!req)
684                         break;
685                 if (fail)
686                         req->state &= ~XS_SERVED;
687                 else
688                         req->state |= XS_SERVED;
689                 xseg_respond(xseg, dstport, req);
690                 xseg_signal(xseg, dstport);
691         }
692
693         return 0;
694 }
695
696 void handle_reply(struct xseg_request *req)
697 {
698         if (!(req->state & XS_SERVED)) {
699                 report_request(req);
700                 goto put;
701         }
702
703         switch (req->op) {
704         case X_READ:
705                 fwrite(req->data, 1, req->datasize, stdout);
706                 break;
707
708         case X_WRITE:
709         case X_SYNC:
710         case X_DELETE:
711         case X_TRUNCATE:
712         case X_COMMIT:
713         case X_CLONE:
714         default:
715                 break;
716         }
717
718 put:
719         if (xseg_put_request(xseg, req->portno, req))
720                 fprintf(stderr, "Cannot put reply at port %u\n", req->portno);
721 }
722
723 int cmd_wait(uint32_t nr)
724 {
725         struct xseg_request *req;
726         long ret;
727
728         for (;;) {
729                 req = xseg_receive(xseg, srcport);
730                 if (req) {
731                         handle_reply(req);
732                         nr--;
733                         if (nr == 0)
734                                 break;
735                         continue;
736                 }
737
738                 ret = xseg_prepare_wait(xseg, srcport);
739                 if (ret)
740                         return -1;
741
742                 ret = xseg_wait_signal(xseg, srcport, 1000000);
743                 ret = xseg_cancel_wait(xseg, srcport);
744                 if (ret)
745                         return -1;
746         }
747
748         return 0;
749 }
750
751 int cmd_put_replies(void)
752 {
753         struct xseg_request *req;
754
755         for (;;) {
756                 req = xseg_receive(xseg, dstport);
757                 if (!req)
758                         break;
759                 printf("request: %08llx%08llx\n"
760                         "     op: %u\n"
761                         "  state: %u\n",
762                         0LL, (unsigned long long)req->serial,
763                         req->op,
764                         req->state);
765                 report_request(req);
766
767                 //fwrite(req->buffer, 1, req->buffersize, stdout);
768
769                 if (xseg_put_request(xseg, req->portno, req))
770                         fprintf(stderr, "Cannot put reply\n");
771         }
772
773         return 0;
774 }
775
776 int cmd_bind(long portno)
777 {
778         struct xseg_port *port = xseg_bind_port(xseg, portno);
779         if (!port) {
780                 printf("failed to bind port %ld\n", portno);
781                 return 1;
782         }
783
784         printf("bound port %u\n", xseg_portno(xseg, port));
785         return 0;
786 }
787
788 int cmd_signal(uint32_t portno)
789 {
790         return xseg_signal(xseg, portno);
791 }
792
793 int parse_ports(char *str)
794 {
795         int ret = 0;
796         char *s = str;
797
798         for (;;) {
799                 if (*s == 0)
800                         return 0;
801
802                 if (*s == ':') {
803                         *s = 0;
804                         if ((s > str) && isdigit(str[0])) {
805                                 srcport = atol(str);
806                                 ret ++;
807                         }
808                         break;
809                 }
810                 s ++;
811         }
812
813         s += 1;
814         str = s;
815
816         for (;;) {
817                 if (*s == 0) {
818                         if ((s > str) && isdigit(str[0])) {
819                                 dstport = atol(str);
820                                 ret ++;
821                         }
822                         break;
823                 }
824                 s ++;
825         }
826
827         return ret;
828 }
829
830 int main(int argc, char **argv) {
831
832         int i, ret = 0;
833         char *spec;
834
835         if (argc < 3)
836                 return help();
837
838         srcport = -1;
839         dstport = -1;
840         spec = argv[1];
841
842         if (xseg_parse_spec(spec, &cfg)) {
843                 printf("Cannot parse spec\n");
844                 return -1;
845         }
846
847         if (xseg_initialize("posix")) {
848                 printf("cannot initialize!\n");
849                 return -1;
850         }
851
852         for (i = 2; i < argc; i++) {
853
854                 if (!strcmp(argv[i], "create")) {
855                         ret = cmd_create();
856                         continue;
857                 }
858
859                 if (!strcmp(argv[i], "join")) {
860                         ret = cmd_join();
861                         if (!ret)
862                                 printf("Segment joined.\n");
863                         continue;
864                 }
865
866                 if (!strcmp(argv[i], "destroy")) {
867                         ret = cmd_destroy();
868                         continue;
869                 }
870
871                 if (cmd_join())
872                         return -1;
873
874                 if (!strcmp(argv[i], "reportall")) {
875                         ret = cmd_reportall();
876                         continue;
877                 }
878
879                 if (!strcmp(argv[i], "bind") && (i + 1 < argc)) {
880                         ret = cmd_bind(atol(argv[i+1]));
881                         i += 1;
882                         continue;
883                 }
884
885                 if (!strcmp(argv[i], "signal") && (i + 1 < argc)) {
886                         ret = cmd_signal(atol(argv[i+1]));
887                         i += 1;
888                         continue;
889                 }
890
891                 if (!strcmp(argv[i], "bridge") && (i + 4 < argc)) {
892                         ret = cmd_bridge(atol(argv[i+1]),
893                                          atol(argv[i+2]),
894                                          argv[i+3],
895                                          argv[i+4]);
896                         i += 4;
897                         continue;
898                 }
899
900                 if (srcport == -1) {
901                         if (!parse_ports(argv[i]))
902                                 printf("source port undefined: %s\n", argv[i]);
903                         continue;
904                 }
905
906                 if (dstport == -1) {
907                         if (!parse_ports(argv[i]))
908                                 printf("destination port undefined: %s\n", argv[i]);
909                         continue;
910                 }
911
912                 if (!strcmp(argv[i], "report")) {
913                         ret = cmd_report(dstport);
914                         continue;
915                 }
916
917                 if (!strcmp(argv[i], "alloc_requests") && (i + 1 < argc)) {
918                         ret = cmd_alloc_requests(atol(argv[i+1]));
919                         i += 1;
920                         continue;
921                 }
922
923                 if (!strcmp(argv[i], "free_requests") && (i + 1 < argc)) {
924                         ret = cmd_free_requests(atol(argv[i+1]));
925                         i += 1;
926                         continue;
927                 }
928
929                 if (!strcmp(argv[i], "put_requests")) {
930                         ret = cmd_put_requests();
931                         continue;
932                 }
933
934                 if (!strcmp(argv[i], "put_replies")) {
935                         ret = cmd_put_replies();
936                         continue;
937                 }
938
939                 if (!strcmp(argv[i], "complete") && (i + 1 < argc)) {
940                         ret = cmd_finish(atol(argv[i+1]), 0);
941                         i += 1;
942                         continue;
943                 }
944
945                 if (!strcmp(argv[i], "fail") && (i + 1 < argc)) {
946                         ret = cmd_finish(atol(argv[i+1]), 1);
947                         i += 1;
948                         continue;
949                 }
950
951                 if (!strcmp(argv[i], "wait") && (i + 1 < argc)) {
952                         ret = cmd_wait(atol(argv[i+1]));
953                         i += 1;
954                         continue;
955                 }
956
957                 if (!strcmp(argv[i], "rndwrite") && (i + 5 < argc)) {
958                         long nr_loops = atol(argv[i+1]);
959                         unsigned int seed = atoi(argv[i+2]);
960                         unsigned int namesize = atoi(argv[i+3]);
961                         unsigned int chunksize = atoi(argv[i+4]);
962                         unsigned long objectsize = atol(argv[i+5]);
963                         ret = cmd_rndwrite(nr_loops, seed, namesize, chunksize, objectsize);
964                         i += 5;
965                         continue;
966                 }
967
968                 if (!strcmp(argv[i], "rndread") && (i + 5 < argc)) {
969                         long nr_loops = atol(argv[i+1]);
970                         unsigned int seed = atoi(argv[i+2]);
971                         unsigned int namesize = atoi(argv[i+3]);
972                         unsigned int chunksize = atoi(argv[i+4]);
973                         unsigned long objectsize = atol(argv[i+5]);
974                         ret = cmd_rndread(nr_loops, seed, namesize, chunksize, objectsize);
975                         i += 5;
976                         continue;
977                 }
978
979                 if (!strcmp(argv[i], "read") && (i + 3 < argc)) {
980                         char *name = argv[i+1];
981                         uint64_t offset = atol(argv[i+2]);
982                         uint64_t size   = atol(argv[i+3]);
983                         ret = cmd_read(name, offset, size);
984                         i += 3;
985                         continue;
986                 }
987
988                 if (!strcmp(argv[i], "write") && (i + 2 < argc)) {
989                         char *name = argv[i+1];
990                         uint64_t offset = atol(argv[i+2]);
991                         ret = cmd_write(name, offset);
992                         i += 2;
993                         continue;
994                 }
995
996                 if (!strcmp(argv[i], "truncate") && (i + 2 < argc)) {
997                         char *name = argv[i+1];
998                         uint64_t offset = atol(argv[i+2]);
999                         ret = cmd_truncate(name, offset);
1000                         i += 2;
1001                         continue;
1002                 }
1003
1004                 if (!strcmp(argv[i], "delete") && (i + 1 < argc)) {
1005                         char *name = argv[i+1];
1006                         ret = cmd_delete(name);
1007                         i += 1;
1008                         continue;
1009                 }
1010
1011                 if (!strcmp(argv[i], "acquire") && (i + 1 < argc)) {
1012                         char *name = argv[i+1];
1013                         ret = cmd_acquire(name);
1014                         i += 1;
1015                         continue;
1016                 }
1017
1018                 if (!strcmp(argv[i], "release") && (i + 1 < argc)) {
1019                         char *name = argv[i+1];
1020                         ret = cmd_release(name);
1021                         i += 1;
1022                         continue;
1023                 }
1024
1025                 if (!strcmp(argv[i], "copy") && (i + 2) < argc) {
1026                         char *src = argv[i+1];
1027                         char *dst = argv[i+2];
1028                         ret = cmd_copy(src, dst);
1029                         i += 2;
1030                         continue;
1031                 }
1032
1033                 if (!strcmp(argv[i], "clone") && (i + 2 < argc)) {
1034                         char *src = argv[i+1];
1035                         char *dst = argv[i+2];
1036                         ret = cmd_clone(src, dst);
1037                         i += 2;
1038                         continue;
1039                 }
1040
1041                 if (!parse_ports(argv[i]))
1042                         printf("invalid argument: %s\n", argv[i]);
1043         }
1044
1045         /* xseg_leave(); */
1046         return ret;
1047 }