Bump version to 0.3.5next
[archipelago] / xseg / peers / user / xseg-tool.c
1 /*
2  * Copyright 2012 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *   2. Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials
14  *      provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * The views and conclusions contained in the software and
30  * documentation are those of the authors and should not be
31  * interpreted as representing official policies, either expressed
32  * or implied, of GRNET S.A.
33  */
34
35 #define _GNU_SOURCE
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <stdint.h>
40 #include <ctype.h>
41 #include <sys/stat.h>
42 #include <sys/types.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45
46 #include <xtypes/xhash.h>
47 #include <xtypes/xobj.h>
48 #include <xseg/xseg.h>
49 #include <xseg/protocol.h>
50 int help(void)
51 {
52         printf("xseg <spec> [[[<src_port>]:[<dst_port>]] [<command> <arg>*] ]*\n"
53                 "spec:\n"
54                 "    <type:name:nr_ports:nr_requests:request_size:extra_size:page_shift>\n"
55                 "global commands:\n"
56                 "    reportall\n"
57                 "    create\n"
58                 "    destroy\n"
59                 "    bind <portno>\n"
60                 "    signal <portno>\n"
61                 "    bridge <portno1> <portno2> <logfile> {full|summary|stats}\n"
62                 "port commands:\n"
63                 "    report\n"
64                 "    alloc_requests (to source) <nr>\n"
65                 "    free_requests (from source) <nr>\n"
66                 "    put_requests (all from dest)\n"
67                 "    put_replies (all from dest)\n"
68                 "    wait        <nr_replies>\n"
69                 "    complete    <nr_requests>\n"
70                 "    fail        <nr_requests>\n"
71                 "    rndwrite    <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
72                 "    rndread     <nr_loops> <seed> <targetlen> <datalen> <objectsize>\n"
73                 "    submit_reqs <nr_loops> <concurrent_reqs>\n"
74                 "    info        <target>\n"
75                 "    read        <target> <offset> <size>\n"
76                 "    write       <target> <offset> < data\n"
77                 "    truncate    <target> <size>\n"
78                 "    delete      <target>\n"
79                 "    acquire     <target>\n"
80                 "    release     <target>\n"
81                 "    copy        <src>  <dst>\n"
82                 "    clone       <src>  <dst>\n"
83         );
84         return 1;
85 }
86
87
88 enum req_action {
89         REPORT = 1,
90         FAIL = 2,
91         COMPLETE = 3
92 };
93
94 enum queue {
95         FREE_QUEUE = 0,
96         REQUEST_QUEUE = 1,
97         REPLY_QUEUE = 2
98 };
99
100 char *namebuf;
101 char *chunk;
102 struct xseg_config cfg;
103 struct xseg *xseg;
104 uint32_t srcport, dstport;
105 uint64_t reqs;
106 #define mkname mkname_heavy
107 /* heavy distributes duplicates much more widely than light
108  * ./xseg-tool random 100000 | cut -d' ' -f2- | sort | uniq -d -c |wc -l
109  */
110
111 xport sport = NoPort;
112 void *sd;
113
114 static void init_local_signal() 
115 {
116         struct xseg_port *port;
117         if (xseg && sport != srcport){
118                 xseg_init_local_signal(xseg, srcport);
119                 sport = srcport;
120                 port = xseg_get_port(xseg, srcport);
121                 sd = xseg_get_signal_desc(xseg, port);
122         }
123 }
124
125 void mkname_heavy(char *name, uint32_t namelen, uint32_t seed)
126 {
127         int i;
128         char c;
129         for (i = 0; i < namelen; i += 1) {
130                 c = seed + (seed >> 8) + (seed >> 16) + (seed >> 24);
131                 c = '0' + ((c + (c >> 4)) & 0xf);
132                 if (c > '9')
133                         c += 'a'-'0'-10;
134                 name[i] = c;
135                 seed *= ((seed % 137911) | 1) * 137911;
136         }
137 }
138
139 void mkname_light(char *name, uint32_t namelen, uint32_t seed)
140 {
141         int i;
142         char c;
143         for (i = 0; i < namelen; i += 1) {
144                 c = seed;
145                 name[i] = 'A' + (c & 0xf);
146                 seed += 1;
147         }
148 }
149
150 uint64_t pick(uint64_t size)
151 {
152         return (uint64_t)((double)(RAND_MAX) / random());
153 }
154
155 void mkchunk(   char *chunk, uint32_t datalen,
156                 char *target, uint32_t targetlen, uint64_t offset)
157 {
158         long i, r, bufsize = targetlen + 16;
159         char buf[bufsize];
160         r = datalen % bufsize;
161         snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
162
163         for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
164                 memcpy(chunk + i, buf, bufsize);
165
166         memcpy(chunk + datalen - r, buf, r);
167 }
168
169 int chkchunk(   char *chunk, uint32_t datalen,
170                 char *target, uint32_t targetlen, uint64_t offset)
171 {
172         long i, r;
173         int bufsize = targetlen + 16;
174         char buf[bufsize];
175         r = datalen % targetlen;
176         snprintf(buf, bufsize, "%016llx%s", (unsigned long long)offset, target);
177
178         for (i = 0; i <= (long)datalen - bufsize; i += bufsize)
179                 if (memcmp(chunk + i, buf, bufsize)) {
180                         /*printf("mismatch: '%*s'* vs '%*s'\n",
181                                 bufsize, buf, datalen, chunk);
182                         */
183                         return 0;
184                 }
185
186         if (memcmp(chunk + datalen - r, buf, r))
187                 return 0;
188
189         return 1;
190 }
191
192
193 #define ALLOC_MIN 4096
194 #define ALLOC_MAX 1048576
195
196 void inputbuf(FILE *fp, char **retbuf, uint64_t *retsize)
197 {
198         static uint64_t alloc_size;
199         static char *buf;
200         uint64_t size = 0;
201         char *p;
202         size_t r;
203
204         if (alloc_size < ALLOC_MIN)
205                 alloc_size = ALLOC_MIN;
206
207         if (alloc_size > ALLOC_MAX)
208                 alloc_size = ALLOC_MAX;
209
210         p = realloc(buf, alloc_size);
211         if (!p) {
212                 if (buf)
213                         free(buf);
214                 buf = NULL;
215                 goto out;
216         }
217
218         buf = p;
219
220         while (!feof(fp)) {
221                 r = fread(buf + size, 1, alloc_size - size, fp);
222                 if (!r)
223                         break;
224                 size += r;
225                 if (size >= alloc_size) {
226                         p = realloc(buf, alloc_size * 2);
227                         if (!p) {
228                                 if (buf)
229                                         free(buf);
230                                 buf = NULL;
231                                 size = 0;
232                                 goto out;
233                         }
234                         buf = p;
235                         alloc_size *= 2;
236                 }
237         }
238
239 out:
240         *retbuf = buf;
241         *retsize = size;
242 }
243
244 void report_request(struct xseg_request *req)
245 {
246         char target[64], data[64];
247         char *req_target, *req_data;
248         unsigned int end = (req->targetlen> 63) ? 63 : req->targetlen;
249         req_target = xseg_get_target(xseg, req);
250         req_data = xseg_get_data(xseg, req);
251
252         strncpy(target, req_target, end);
253         target[end] = 0;
254         strncpy(data, req_data, 63);
255         data[63] = 0;
256         fprintf(stderr,
257                 "Request %lx: target[%u](xptr: %llu): %s, data[%llu](xptr: %llu): %s \n\t"
258                 "offset: %llu, size: %llu, serviced; %llu, op: %u, state: %u, flags: %u \n\t"
259                 "src: %u, transit: %u, dst: %u, effective dst: %u\n",
260                 (unsigned long) req, req->targetlen, (unsigned long long)req->target,
261                 target,
262                 (unsigned long long) req->datalen, (unsigned long long) req->data,
263                 data,
264                 (unsigned long long) req->offset, (unsigned long long) req->size,
265                 (unsigned long long) req->serviced, req->op, req->state, req->flags,
266                 (unsigned int) req->src_portno, (unsigned int) req->transit_portno,
267                 (unsigned int) req->dst_portno, (unsigned int) req->effective_dst_portno);
268
269
270 }
271
272 int cmd_info(char *target)
273 {
274         uint32_t targetlen = strlen(target);
275         size_t size = sizeof(uint64_t);
276         int r;
277         xport p;
278         struct xseg_request *req;
279         char *req_target;
280
281         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
282         if (!req) {
283                 fprintf(stderr, "No request!\n");
284                 return -1;
285         }
286
287         r = xseg_prep_request(xseg, req, targetlen, size);
288         if (r < 0) {
289                 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
290                         (unsigned long) targetlen, (unsigned long) size);
291                 xseg_put_request(xseg, req, srcport);
292                 return -1;
293         }
294
295         req_target = xseg_get_target(xseg, req);
296         strncpy(req_target, target, targetlen);
297         req->offset = 0;
298         req->size = size;
299         req->op = X_INFO;
300
301         p = xseg_submit(xseg, req, srcport, X_ALLOC);
302         if (p == NoPort)
303                 return -1;
304
305         xseg_signal(xseg, p);
306
307         return 0;
308 }
309
310 int cmd_read(char *target, uint64_t offset, uint64_t size)
311 {
312         uint32_t targetlen = strlen(target);
313         int r;
314         xport p;
315         char *req_target;
316         struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
317         if (!req) {
318                 fprintf(stderr, "No request\n");
319                 return -1;
320         }
321
322         r = xseg_prep_request(xseg, req, targetlen, size);
323         if (r < 0) {
324                 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
325                         (unsigned long)targetlen, (unsigned long long)size);
326                 xseg_put_request(xseg, req, srcport);
327                 return -1;
328         }
329
330         req_target = xseg_get_target(xseg, req);
331         strncpy(req_target, target, targetlen);
332         req->offset = offset;
333         req->size = size;
334         req->op = X_READ;
335         report_request(req);
336         p = xseg_submit(xseg, req, srcport, X_ALLOC);
337         if (p == NoPort)
338                 return -1;
339
340         xseg_signal(xseg, p);
341         return 0;
342 }
343
344 int cmd_write(char *target, uint64_t offset)
345 {
346         char *buf = NULL;
347         int r;
348         xport p;
349         uint64_t size = 0;
350         char *req_target, *req_data;
351         uint32_t targetlen = strlen(target);
352         struct xseg_request *req;
353
354         inputbuf(stdin, &buf, &size);
355         if (!size) {
356                 fprintf(stderr, "No input\n");
357                 return -1;
358         }
359
360         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
361         if (!req) {
362                 fprintf(stderr, "No request\n");
363                 return -1;
364         }
365
366         r = xseg_prep_request(xseg, req, targetlen, size);
367         if (r < 0) {
368                 fprintf(stderr, "Cannot prepare request! (%lu, %llu)\n",
369                         (unsigned long)targetlen, (unsigned long long)size);
370                 xseg_put_request(xseg, req, srcport);
371                 return -1;
372         }
373
374         req_target = xseg_get_target(xseg, req);
375         strncpy(req_target, target, targetlen);
376         
377         req_data = xseg_get_data(xseg, req);
378         memcpy(req_data, buf, size);
379         req->offset = offset;
380         req->size = size;
381         req->op = X_WRITE;
382
383         p = xseg_submit(xseg, req, srcport, X_ALLOC);
384         if (p == NoPort) {
385                 fprintf(stderr, "Cannot submit\n");
386                 return -1;
387         }
388         xseg_signal(xseg, p);
389
390         return 0;
391 }
392
393 int cmd_truncate(char *target, uint64_t offset)
394 {
395         return 0;
396 }
397
398 int cmd_delete(char *target)
399 {
400         uint32_t targetlen = strlen(target);
401         int r;
402         struct xseg_request *req;
403         init_local_signal();
404         xseg_bind_port(xseg, srcport, NULL);
405
406         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
407         if (!req) {
408                 fprintf(stderr, "No request!\n");
409                 return -1;
410         }
411
412         r = xseg_prep_request(xseg, req, targetlen, 0);
413         if (r < 0) {
414                 fprintf(stderr, "Cannot prepare request! (%lu, %lu)\n",
415                         (unsigned long) targetlen, (unsigned long) req->bufferlen - targetlen);
416                 xseg_put_request(xseg, req, srcport);
417                 return -1;
418         }
419
420         char *reqtarget = xseg_get_target(xseg, req);
421         strncpy(reqtarget, target, targetlen);
422         req->op = X_DELETE;
423
424         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
425         if (p == NoPort){
426                 fprintf(stderr, "Couldn't submit request\n");
427                 xseg_put_request(xseg, req, srcport);
428                 return -1;
429         }
430
431         xseg_signal(xseg, p);
432
433         return 0;
434 }
435
436 int cmd_acquire(char *target)
437 {
438         uint32_t targetlen = strlen(target);
439         int r;
440         xport p;
441         char *req_target;
442         struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
443         if (!req) {
444                 fprintf(stderr, "No request\n");
445                 return -1;
446         }
447
448         r = xseg_prep_request(xseg, req, targetlen, 0);
449         if (r < 0) {
450                 fprintf(stderr, "Cannot prepare request! (%lu, 0)\n",
451                         (unsigned long)targetlen);
452                 xseg_put_request(xseg, req, srcport);
453                 return -1;
454         }
455
456         req_target = xseg_get_target(xseg, req);
457         strncpy(req_target, target, targetlen);
458         req->offset = 0;
459         req->size = 0;
460         req->op = X_ACQUIRE;
461         req->flags = XF_NOSYNC;
462         p = xseg_submit(xseg, req, srcport, X_ALLOC);
463         if (p == NoPort)
464                 return -1;
465
466         xseg_signal(xseg, p);
467         return 0;
468 }
469
470 int cmd_release(char *target)
471 {
472         uint32_t targetlen = strlen(target);
473         int r;
474         xport p;
475         char *req_target;
476         struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
477         if (!req) {
478                 fprintf(stderr, "No request\n");
479                 return -1;
480         }
481
482         r = xseg_prep_request(xseg, req, targetlen, 0);
483         if (r < 0) {
484                 fprintf(stderr, "Cannot prepare request! (%lu, 0)\n",
485                         (unsigned long)targetlen);
486                 xseg_put_request(xseg, req, srcport);
487                 return -1;
488         }
489
490         req_target = xseg_get_target(xseg, req);
491         strncpy(req_target, target, targetlen);
492         req->offset = 0;
493         req->size = 0;
494         req->op = X_RELEASE;
495         //req->flags = XF_FORCE;
496         req->flags = 0;
497         p = xseg_submit(xseg, req, srcport, X_ALLOC);
498         if (p == NoPort)
499                 return -1;
500
501         xseg_signal(xseg, p);
502         return 0;
503         return 0;
504 }
505
506 int cmd_open(char *target)
507 {
508         uint32_t targetlen = strlen(target);
509         int r;
510         xport p;
511         char *req_target;
512         struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
513         if (!req) {
514                 fprintf(stderr, "No request\n");
515                 return -1;
516         }
517
518         r = xseg_prep_request(xseg, req, targetlen, 0);
519         if (r < 0) {
520                 fprintf(stderr, "Cannot prepare request! (%lu, 0)\n",
521                         (unsigned long)targetlen);
522                 xseg_put_request(xseg, req, srcport);
523                 return -1;
524         }
525
526         req_target = xseg_get_target(xseg, req);
527         strncpy(req_target, target, targetlen);
528         req->offset = 0;
529         req->size = 0;
530         req->op = X_OPEN;
531         p = xseg_submit(xseg, req, srcport, X_ALLOC);
532         if (p == NoPort)
533                 return -1;
534
535         xseg_signal(xseg, p);
536         return 0;
537 }
538
539 int cmd_close(char *target)
540 {
541         uint32_t targetlen = strlen(target);
542         int r;
543         xport p;
544         char *req_target;
545         struct xseg_request *req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
546         if (!req) {
547                 fprintf(stderr, "No request\n");
548                 return -1;
549         }
550
551         r = xseg_prep_request(xseg, req, targetlen, 0);
552         if (r < 0) {
553                 fprintf(stderr, "Cannot prepare request! (%lu, 0)\n",
554                         (unsigned long)targetlen);
555                 xseg_put_request(xseg, req, srcport);
556                 return -1;
557         }
558
559         req_target = xseg_get_target(xseg, req);
560         strncpy(req_target, target, targetlen);
561         req->offset = 0;
562         req->size = 0;
563         req->op = X_CLOSE;
564         req->flags = XF_FORCE;
565         p = xseg_submit(xseg, req, srcport, X_ALLOC);
566         if (p == NoPort)
567                 return -1;
568
569         xseg_signal(xseg, p);
570         return 0;
571         return 0;
572 }
573
574 int cmd_copy(char *src, char *dst)
575 {
576         uint32_t targetlen = strlen(dst);
577         uint32_t parentlen = strlen(src);
578         struct xseg_request *req;
579         struct xseg_request_copy *xcopy;
580         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
581         if (!req) {
582                 fprintf(stderr, "No request\n");
583                 return -1;
584         }
585
586         int r = xseg_prep_request(xseg, req, targetlen,
587                         sizeof(struct xseg_request_copy));
588         if (r < 0) {
589                 fprintf(stderr, "Cannot prepare request!\n");
590                 xseg_put_request(xseg, req, srcport);
591                 return -1;
592         }
593
594         char *target = xseg_get_target(xseg, req);
595         char *data = xseg_get_data(xseg, req);
596
597         strncpy(target, dst, targetlen);
598         xcopy = (struct xseg_request_copy *) data;
599         strncpy(xcopy->target, src, parentlen);
600         xcopy->targetlen = parentlen;
601         req->offset = 0;
602         req->size = sizeof(struct xseg_request_copy);
603         req->op = X_COPY;
604
605         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
606         if (p == NoPort){
607                 fprintf(stderr, "Cannot submit request\n");
608                 return -1;
609         }
610         xseg_signal(xseg, p);
611
612         return 0;
613         return 0;
614 }
615
616 int cmd_clone(char *src, char *dst, long size)
617 {
618
619         uint32_t targetlen = strlen(dst);
620         uint32_t parentlen = strlen(src);
621         struct xseg_request *req;
622         struct xseg_request_clone *xclone;
623         xseg_bind_port(xseg, srcport, NULL);
624         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
625         if (!req) {
626                 fprintf(stderr, "No request\n");
627                 return -1;
628         }
629
630         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_clone));
631         if (r < 0) {
632                 fprintf(stderr, "Cannot prepare request!\n");
633                 xseg_put_request(xseg, req, srcport);
634                 return -1;
635         }
636
637         char *target = xseg_get_target(xseg, req);
638         char *data = xseg_get_data(xseg, req);
639
640         strncpy(target, dst, targetlen);
641         xclone = (struct xseg_request_clone *) data;
642         strncpy(xclone->target, src, parentlen);
643         xclone->targetlen = parentlen;
644         if (size) {
645                 xclone->size = (uint64_t)size;
646                 xclone->size *= 1024*1024;
647         } else {
648                 xclone->size = 0;
649         }
650         req->offset = 0;
651         req->size = sizeof(struct xseg_request_clone);
652         req->op = X_CLONE;
653
654         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
655         if (p == NoPort){
656                 fprintf(stderr, "Cannot submit request\n");
657                 return -1;
658         }
659         xseg_signal(xseg, p);
660
661         return 0;
662 }
663
664 int cmd_snapshot(char *src, char *dst, long block_size)
665 {
666
667         uint32_t targetlen = strlen(src);
668         uint32_t parentlen = strlen(dst);
669         struct xseg_request *req;
670         struct xseg_request_snapshot *xsnapshot;
671         xseg_bind_port(xseg, srcport, NULL);
672         req = xseg_get_request(xseg, srcport, dstport, X_ALLOC);
673         if (!req) {
674                 fprintf(stderr, "No request\n");
675                 return -1;
676         }
677
678         int r = xseg_prep_request(xseg, req, targetlen, sizeof(struct xseg_request_snapshot));
679         if (r < 0) {
680                 fprintf(stderr, "Cannot prepare request!\n");
681                 xseg_put_request(xseg, req, srcport);
682                 return -1;
683         }
684
685         char *target = xseg_get_target(xseg, req);
686         char *data = xseg_get_data(xseg, req);
687
688         fprintf(stdout, "Snapshotting %s(%u) to %s(%u)\n", src, targetlen, dst, parentlen);
689         strncpy(target, src, targetlen);
690         xsnapshot = (struct xseg_request_snapshot *) data;
691         strncpy(xsnapshot->target, dst, parentlen);
692         xsnapshot->targetlen = parentlen;
693         req->offset = 0;
694         req->size = (uint64_t) block_size;
695         req->op = X_SNAPSHOT;
696
697         xport p = xseg_submit(xseg, req, srcport, X_ALLOC);
698         if (p == NoPort){
699                 fprintf(stderr, "Cannot submit request\n");
700                 return -1;
701         }
702         xseg_signal(xseg, p);
703
704         return 0;
705 }
706
707 void log_req(int logfd, uint32_t portno2, uint32_t portno1, int op, int method,
708                 struct xseg_request *req)
709 {
710         FILE *logfp;
711         char target[64], data[64];
712         char *req_target, *req_data;
713         /* null terminate name in case of req->target is less than 63 characters,
714          * and next character after name (aka first byte of next buffer) is not
715          * null
716          */
717         unsigned int end = (req->targetlen > 63) ? 63 : req->targetlen;
718         
719         req_target = xseg_get_target(xseg, req);
720         req_data = xseg_get_data(xseg, req);
721
722         logfp = fdopen(logfd, "a");
723         if (!logfp)
724                 return;
725
726         switch(method) {
727         case 0:
728                 strncpy(target, req_target, end);
729                 target[end] = 0;
730                 strncpy(data, req_data, 63);
731                 data[63] = 0;
732
733                 fprintf(logfp,
734                         "src port: %u, dst port: %u,  op:%u offset: %llu size: %lu, reqstate: %u\n"
735                         "target[%u]: '%s', data[%llu]:\n%s------------------\n\n",
736                         (unsigned int)portno1,
737                         (unsigned int)portno2,
738                         (unsigned int)req->op,
739                         (unsigned long long)req->offset,
740                         (unsigned long)req->size,
741                         (unsigned int)req->state,
742                         (unsigned int)req->targetlen, target,
743                         (unsigned long long)req->datalen, data);
744                 break;
745         case 1:
746                 fprintf(logfp,
747                         "src port: %u, dst port: %u, op: %u\n",
748                         (unsigned int)portno1,
749                         (unsigned int)portno2,
750                         (unsigned int)req->op);
751                 break;
752         case 2:
753                 fprintf(logfp, "src port: %u, dst port: %u, reqs: %llu\n",
754                         (unsigned int)portno1,
755                         (unsigned int)portno2,
756                         (unsigned long long)++reqs);
757         }
758
759         fclose(logfp);
760         return;
761 }
762
763 #define LOG_ACCEPT  0
764 #define LOG_RECEIVE 1
765 int cmd_bridge(uint32_t portno1, uint32_t portno2, char *logfile, char *how)
766 {
767 #if 0
768         struct xseg_request *req;
769         int logfd, method;
770         if (!strcmp(logfile, "-"))
771                 logfd = 1;
772         else {
773                 logfd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0600);
774                 if (logfd < 0) {
775                         perror(logfile);
776                         return -1;
777                 }
778         }
779
780         if (!strcmp(how, "full"))
781                 method = 0;
782         else if (!strcmp(how, "summary"))
783                 method = 1;
784         else
785                 method = 2;
786
787         for (;;) {
788                 int reloop = 0, active;
789                 xseg_prepare_wait(xseg, portno1);
790                 xseg_prepare_wait(xseg, portno2);
791                 req = NULL;
792
793                 for (;;) {
794                         active = 0;
795
796                         //FIXME
797                         req = xseg_accept(xseg, portno1, 0);
798                         if (req) {
799                                 xseg_submit(xseg, req, portno2, X_ALLOC);
800                                 log_req(logfd, portno1, portno2, LOG_ACCEPT, method, req);
801                                 active += 1;
802                         }
803
804                         req = xseg_accept(xseg, portno2, 0);
805                         if (req) {
806                                 xseg_submit(xseg, req, portno1, X_ALLOC);
807                                 log_req(logfd, portno2, portno1, LOG_ACCEPT, method, req);
808                                 active += 1;
809                         }
810
811                         req = xseg_receive(xseg, portno1, 0);
812                         if (req) {
813                                 xseg_respond(xseg, req, portno2, X_ALLOC);
814                                 log_req(logfd, portno1, portno2, LOG_RECEIVE, method, req);
815                                 active += 1;
816                         }
817
818                         req = xseg_receive(xseg, portno2, 0);
819                         if (req) {
820                                 xseg_respond(xseg, req, portno1, X_ALLOC);
821                                 log_req(logfd, portno2, portno1, LOG_RECEIVE, method, req);
822                                 active += 1;
823                         }
824
825                         if (active == 0) {
826                                 if (reloop)
827                                         break;
828                                 /* wait on multiple queues? */
829                                 xseg_wait_signal(xseg, 100000);
830                                 break;
831                         } else {
832                                 xseg_cancel_wait(xseg, portno1);        
833                                 xseg_cancel_wait(xseg, portno2);        
834                                 reloop = 1;
835                         }
836                 }
837         }
838
839         close(logfd);
840 #endif
841         return 0;
842 }
843
844 int cmd_rndwrite(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
845 {
846         if (loops < 0)
847                 return help();
848
849         if (targetlen >= chunksize) {
850                 fprintf(stderr, "targetlen >= chunksize\n");
851                 return -1;
852         }
853
854         char *p = realloc(namebuf, targetlen+1);
855         if (!p) {
856                 fprintf(stderr, "Cannot allocate memory\n");
857                 return -1;
858         }
859         namebuf = p;
860
861         p = realloc(chunk, chunksize);
862         if (!p) {
863                 fprintf(stderr, "Cannot allocate memory\n");
864                 return -1;
865         }
866         chunk = p;
867         memset(chunk, 0, chunksize);
868
869         srandom(seed);
870
871         struct xseg_request *submitted = NULL, *received;
872         long nr_submitted = 0, nr_received = 0, nr_failed = 0;
873         int reported = 0, r;
874         uint64_t offset;
875         xport port;
876         char *req_data, *req_target;
877         seed = random();
878         init_local_signal();
879
880         for (;;) {
881                 xseg_prepare_wait(xseg, srcport);
882                 if (nr_submitted < loops &&
883                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
884                         xseg_cancel_wait(xseg, srcport);
885                         r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
886                         if (r < 0) {
887                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
888                                         targetlen, chunksize);
889                                 xseg_put_request(xseg, submitted, srcport);
890                                 return -1;
891                         }
892                         
893                         req_target = xseg_get_target(xseg, submitted);
894                         req_data = xseg_get_data(xseg, submitted);
895
896                         reported = 0;
897                         mkname(namebuf, targetlen, seed);
898                         namebuf[targetlen] = 0;
899                         //printf("%ld: %s\n", nr_submitted, namebuf);
900                         strncpy(req_target, namebuf, targetlen);
901                         offset = 0;// pick(size);
902                         mkchunk(req_data, chunksize, namebuf, targetlen, offset);
903
904                         submitted->offset = offset;
905                         submitted->size = chunksize;
906                         submitted->op = X_WRITE;
907                         submitted->flags |= XF_NOSYNC;
908
909                         port =  xseg_submit(xseg, submitted, srcport, X_ALLOC);
910                         if (port == NoPort) {
911                                 xseg_put_request(xseg, submitted, srcport);
912                         } else {
913                                 seed = random();
914                                 nr_submitted += 1;
915                                 xseg_signal(xseg, port);
916                         }
917                 }
918
919                 received = xseg_receive(xseg, srcport, 0);
920                 if (received) {
921                         xseg_cancel_wait(xseg, srcport);
922                         nr_received += 1;
923                         if (!(received->state & XS_SERVED)) {
924                                 nr_failed += 1;
925                                 report_request(received);
926                         }
927                         if (xseg_put_request(xseg, received, srcport))
928                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
929                 }
930
931                 if (!submitted && !received)
932                         xseg_wait_signal(xseg, sd, 1000000);
933
934                         if (nr_submitted % 1000 == 0 && !reported) {
935                                 reported = 1;
936                                 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
937                                         nr_submitted, nr_received, nr_failed);
938                         }
939
940                         if (nr_received >= loops)
941                                 break;
942         }
943
944         fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
945                 nr_submitted, nr_received, nr_failed);
946         return 0;
947 }
948
949 int cmd_rnddelete(long loops, int32_t seed, uint32_t targetlen)
950 {
951         if (loops < 0)
952                 return help();
953         char *p = realloc(namebuf, targetlen+1);
954         if (!p) {
955                 fprintf(stderr, "Cannot allocate memory\n");
956                 return -1;
957         }
958         namebuf = p;
959
960         srandom(seed);
961
962         struct xseg_request *submitted = NULL, *received;
963         long nr_submitted = 0, nr_received = 0, nr_failed = 0;
964         int reported = 0, r;
965         xport port;
966         char *req_target;
967         seed = random();
968         init_local_signal();
969
970         for (;;) {
971                 xseg_prepare_wait(xseg, srcport);
972                 if (nr_submitted < loops &&
973                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
974                         xseg_cancel_wait(xseg, srcport);
975                         r = xseg_prep_request(xseg, submitted, targetlen, 0);
976                         if (r < 0) {
977                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
978                                         targetlen, 0);
979                                 xseg_put_request(xseg, submitted, srcport);
980                                 return -1;
981                         }
982                         
983                         req_target = xseg_get_target(xseg, submitted);
984
985                         reported = 0;
986                         mkname(namebuf, targetlen, seed);
987                         namebuf[targetlen] = 0;
988                         //printf("%ld: %s\n", nr_submitted, namebuf);
989                         strncpy(req_target, namebuf, targetlen);
990                         submitted->offset = 0;
991                         submitted->size = 0;
992                         submitted->op = X_DELETE;
993                         submitted->flags = 0;
994
995                         port =  xseg_submit(xseg, submitted, srcport, X_ALLOC);
996                         if (port == NoPort) {
997                                 xseg_put_request(xseg, submitted, srcport);
998                         } else {
999                                 seed = random();
1000                                 nr_submitted += 1;
1001                                 xseg_signal(xseg, port);
1002                         }
1003                 }
1004
1005                 received = xseg_receive(xseg, srcport, 0);
1006                 if (received) {
1007                         xseg_cancel_wait(xseg, srcport);
1008                         nr_received += 1;
1009                         if (!(received->state & XS_SERVED)) {
1010                                 nr_failed += 1;
1011                                 report_request(received);
1012                         }
1013                         if (xseg_put_request(xseg, received, srcport))
1014                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
1015                 }
1016
1017                 if (!submitted && !received)
1018                         xseg_wait_signal(xseg, sd, 1000000);
1019
1020                         if (nr_submitted % 1000 == 0 && !reported) {
1021                                 reported = 1;
1022                                 fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
1023                                         nr_submitted, nr_received, nr_failed);
1024                         }
1025
1026                         if (nr_received >= loops)
1027                                 break;
1028         }
1029
1030         fprintf(stderr, "submitted %ld, received %ld, failed %ld\n",
1031                 nr_submitted, nr_received, nr_failed);
1032         return 0;
1033 }
1034 /* note:
1035  * prepare/wait rhythm,
1036  * files are converted to independent chunk access patterns,
1037 */
1038
1039 int cmd_rndread(long loops, int32_t seed, uint32_t targetlen, uint32_t chunksize, uint64_t size)
1040 {
1041         if (loops < 0)
1042                 return help();
1043
1044         if (targetlen >= chunksize) {
1045                 fprintf(stderr, "targetlen >= chunksize\n");
1046                 return -1;
1047         }
1048
1049         char *p = realloc(namebuf, targetlen+1);
1050         if (!p) {
1051                 fprintf(stderr, "Cannot allocate memory\n");
1052                 return -1;
1053         }
1054         namebuf = p;
1055
1056         p = realloc(chunk, chunksize);
1057         if (!p) {
1058                 fprintf(stderr, "Cannot allocate memory\n");
1059                 return -1;
1060         }
1061         chunk = p;
1062         memset(chunk, 0, chunksize);
1063
1064         srandom(seed);
1065
1066         struct xseg_request *submitted = NULL, *received;
1067         long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0;
1068         int reported = 0, r;
1069         uint64_t offset;
1070         xport port;
1071         char *req_data, *req_target;
1072         init_local_signal();
1073
1074         seed = random();
1075         for (;;) {
1076                 submitted = NULL;
1077                 xseg_prepare_wait(xseg, srcport);
1078                 if (nr_submitted < loops &&
1079                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
1080                         xseg_cancel_wait(xseg, srcport);
1081                         r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
1082                         if (r < 0) {
1083                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
1084                                         targetlen, chunksize);
1085                                 xseg_put_request(xseg, submitted, srcport);
1086                                 return -1;
1087                         }
1088
1089                         req_target = xseg_get_target(xseg, submitted);
1090                         reported = 0;
1091                         mkname(namebuf, targetlen, seed);
1092                         namebuf[targetlen] = 0;
1093                         //printf("%ld: %s\n", nr_submitted, namebuf);
1094                         offset = 0;//pick(size);
1095
1096                         strncpy(req_target, namebuf, targetlen);
1097                         submitted->offset = offset;
1098                         submitted->size = chunksize;
1099                         submitted->op = X_READ;
1100                         port = xseg_submit(xseg, submitted, srcport, X_ALLOC);
1101                         if (port == NoPort) {
1102                                 xseg_put_request(xseg, submitted, srcport);
1103                         } else {
1104                                 seed = random();
1105                                 nr_submitted += 1;
1106                                 xseg_signal(xseg, port);
1107                         }
1108                 }
1109
1110                 received = xseg_receive(xseg, srcport, 0);
1111                 if (received) {
1112                         xseg_cancel_wait(xseg, srcport);
1113                         nr_received += 1;
1114                         req_target = xseg_get_target(xseg, received);
1115                         req_data = xseg_get_data(xseg, received);
1116                         if (!(received->state & XS_SERVED)) {
1117                                 nr_failed += 1;
1118                                 report_request(received);
1119                         } else if (!chkchunk(req_data, received->datalen,
1120                                         req_target, received->targetlen, received->offset)) {
1121         //                      report_request(received);
1122                                 nr_mismatch += 1;
1123                         }
1124
1125                         if (xseg_put_request(xseg, received, srcport))
1126                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
1127                 }
1128
1129                 if (!submitted && !received)
1130                         xseg_wait_signal(xseg, sd, 1000000);
1131
1132                 if (nr_submitted % 1000 == 0 && !reported) {
1133                         reported = 1;
1134                         fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
1135                         nr_submitted, nr_received, nr_failed, nr_mismatch);
1136                 }
1137
1138                 if (nr_received >= loops)
1139                         break;
1140         }
1141
1142         fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
1143                 nr_submitted, nr_received, nr_failed, nr_mismatch);
1144         return 0;
1145 }
1146
1147 int cmd_submit_reqs(long loops, long concurrent_reqs, int op)
1148 {
1149         if (loops < 0)
1150                 return help();
1151
1152         struct xseg_request *submitted = NULL, *received;
1153         long nr_submitted = 0, nr_received = 0, nr_failed = 0, nr_mismatch = 0, nr_flying = 0;
1154         int r;
1155         uint64_t offset;
1156         uint32_t targetlen = 10, chunksize = 4096;
1157         struct timeval tv1, tv2;
1158         xport p;
1159         char *req_data, *req_target;
1160
1161         xseg_bind_port(xseg, srcport, NULL);
1162
1163         gettimeofday(&tv1, NULL);
1164         for (;;) {
1165                 submitted = NULL;
1166                 xseg_prepare_wait(xseg, srcport);
1167                 if (nr_submitted < loops &&  nr_flying < concurrent_reqs &&
1168                     (submitted = xseg_get_request(xseg, srcport, dstport, X_ALLOC))) {
1169                         xseg_cancel_wait(xseg, srcport);
1170                         r = xseg_prep_request(xseg, submitted, targetlen, chunksize);
1171                         if (r < 0) {
1172                                 fprintf(stderr, "Cannot prepare request! (%u, %u)\n",
1173                                         targetlen, chunksize);
1174                                 xseg_put_request(xseg, submitted, srcport);
1175                                 return -1;
1176                         }
1177                         
1178                         //FIXME
1179                         ++nr_flying;
1180                         nr_submitted += 1;
1181                         offset = 0;//pick(size);
1182
1183                         submitted->offset = offset;
1184                         submitted->size = chunksize;
1185                         req_target = xseg_get_target(xseg, submitted);
1186                         req_data = xseg_get_data(xseg, submitted);
1187
1188                         if (op == 0)
1189                                 submitted->op = X_INFO;
1190                         else if (op == 1)
1191                                 submitted->op = X_READ;
1192                         else if (op == 2) {
1193                                 submitted->op = X_WRITE;
1194                                 mkchunk(req_data, submitted->datalen, req_target, submitted->targetlen, submitted->offset);
1195                         }
1196
1197                         p = xseg_submit(xseg, submitted, srcport, X_ALLOC);
1198                         if ( p != NoPort){
1199                                 if (xseg_signal(xseg, p) < 0)
1200                                         perror("Cannot signal peer");
1201                         }
1202                 }
1203                 received = xseg_receive(xseg, srcport, 0);
1204                 if (received) {
1205                         xseg_cancel_wait(xseg, srcport);
1206                         --nr_flying;
1207                         if (nr_received == 0)
1208                                 fprintf(stderr, "latency (time for the first req to complete): %llu usecs\n",
1209                                         (unsigned long long)received->elapsed);
1210                         nr_received += 1;
1211                         if (!(received->state & XS_SERVED)) {
1212                                 nr_failed += 1;
1213                                 //report_request(received);
1214                         }
1215
1216                         if (xseg_put_request(xseg, received, srcport))
1217                                 fprintf(stderr, "Cannot put request at port %u\n", received->src_portno);
1218                 }
1219
1220                 if (!submitted && !received)
1221                         xseg_wait_signal(xseg, sd, 10000000L);
1222
1223                 if (nr_received >= loops)
1224                         break;
1225         }
1226         gettimeofday(&tv2, NULL);
1227
1228         fprintf(stderr, "submitted %ld, received %ld, failed %ld, mismatched %ld\n",
1229                 nr_submitted, nr_received, nr_failed, nr_mismatch);
1230         long t = (tv2.tv_sec - tv1.tv_sec)*1000000 + (tv2.tv_usec - tv1.tv_usec);
1231         fprintf(stderr, "elpased time: %lf secs, throughput: %lf reqs/sec\n", (double) t / 1000000.0, (double) nr_submitted / (t / 1000000.0));
1232
1233         return 0;
1234 }
1235
1236 static void lock_status(struct xlock *lock, char *buf, int len)
1237 {
1238         int r;
1239         if (lock->owner == Noone)
1240                 r = snprintf(buf, len, "Locked: No");
1241         else
1242                 r = snprintf(buf, len, "Locked: Yes (Owner: %lu)", lock->owner);
1243         if (r >= len)
1244                 buf[len-1] = 0;
1245 }
1246
1247 int cmd_report(uint32_t portno)
1248 {
1249         char fls[64], rls[64], pls[64]; // buffer to store lock status
1250         struct xseg_port *port = xseg_get_port(xseg, portno);
1251         if (!port) {
1252                 printf("port %u is not assigned\n", portno);
1253                 return 0;
1254         }
1255         struct xq *fq, *rq, *pq;
1256         fq = xseg_get_queue(xseg, port, free_queue);
1257         rq = xseg_get_queue(xseg, port, request_queue);
1258         pq = xseg_get_queue(xseg, port, reply_queue);
1259         lock_status(&port->fq_lock, fls, 64);
1260         lock_status(&port->rq_lock, rls, 64);
1261         lock_status(&port->pq_lock, pls, 64);
1262         fprintf(stderr, "port %u:\n"
1263                 "   requests: %llu/%llu  next: %u  dst gw: %u\n"
1264                 "       free_queue [%p] count : %4llu | %s\n"
1265                 "    request_queue [%p] count : %4llu | %s\n"
1266                 "      reply_queue [%p] count : %4llu | %s\n",
1267                 portno, (unsigned long long)port->alloc_reqs, 
1268                 (unsigned long long)port->max_alloc_reqs,
1269                 xseg->path_next[portno],
1270                 xseg->dst_gw[portno],
1271                 (void *)fq, (unsigned long long)xq_count(fq), fls,
1272                 (void *)rq, (unsigned long long)xq_count(rq), rls,
1273                 (void *)pq, (unsigned long long)xq_count(pq), pls);
1274         return 0;
1275 }
1276
1277 int cmd_join(void)
1278 {
1279         if (xseg)
1280                 return 0;
1281
1282         xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
1283         if (!xseg) {
1284                 fprintf(stderr, "cannot join segment!\n");
1285                 return -1;
1286         }
1287         return 0;
1288 }
1289 static void print_hanlder(char *name, struct xobject_h *obj_h)
1290 {
1291         char ls[64];
1292         lock_status(&obj_h->lock, ls, 64);
1293         fprintf(stderr, "%20s: free: %4llu, allocated: %4llu, allocated space: %7llu (object size: %llu), Lock %s\n",
1294                         name,
1295                         (unsigned long long) obj_h->nr_free,
1296                         (unsigned long long) obj_h->nr_allocated,
1297                         (unsigned long long) obj_h->allocated_space,
1298                         (unsigned long long) obj_h->obj_size, ls);
1299 }
1300
1301 //FIXME ugly
1302 static void print_heap(struct xseg *xseg)
1303 {
1304         char *UNIT[4];
1305         UNIT[0] = "B";
1306         UNIT[1] = "KiB";
1307         UNIT[2] = "MiB";
1308         UNIT[3] = "GiB";
1309         uint64_t MULT[4];
1310         MULT[0] = 1;
1311         MULT[1] = 1024;
1312         MULT[2] = 1024*1024;
1313         MULT[3] = 1024*1024*1024;
1314
1315         int u;
1316         uint64_t t;
1317         fprintf(stderr, "Heap usage: ");
1318         u = 0;
1319         t = xseg->heap->cur;
1320         while (t > 0) {
1321                 t /= 1024;
1322                 u++;
1323         }
1324         if (!t)
1325                 u--;
1326         t = xseg->heap->cur / MULT[u];
1327         if (t < 10){
1328                 float tf = ((float)(xseg->heap->cur))/((float)MULT[u]);
1329                 fprintf(stderr, "%2.1f %s/", tf, UNIT[u]);
1330         }
1331         else {
1332                 unsigned int tu = xseg->heap->cur / MULT[u];
1333                 fprintf(stderr, "%3u %s/", tu, UNIT[u]);
1334         }
1335
1336         u = 0;
1337         t = xseg->config.heap_size;
1338         while (t > 0) {
1339                 t /= 1024;
1340                 u++;
1341         }
1342         if (!t)
1343                 u--;
1344         t = xseg->config.heap_size/MULT[u];
1345         if (t < 10){
1346                 float tf = ((float)(xseg->config.heap_size))/(float)MULT[u];
1347                 fprintf(stderr, "%2.1f %s ", tf, UNIT[u]);
1348         }
1349         else {
1350                 unsigned int tu = xseg->config.heap_size / MULT[u];
1351                 fprintf(stderr, "%3u %s ", tu, UNIT[u]);
1352         }
1353         char ls[64];
1354         lock_status(&xseg->heap->lock, ls, 64);
1355         fprintf(stderr, "(%llu / %llu), %s\n",
1356                         (unsigned long long)xseg->heap->cur,
1357                         (unsigned long long)xseg->config.heap_size,
1358                         ls);
1359 }
1360
1361 int cmd_reportall(void)
1362 {
1363         uint32_t t;
1364
1365         if (cmd_join())
1366                 return -1;
1367
1368         fprintf(stderr, "Segment lock: %s\n",
1369                 (xseg->shared->flags & XSEG_F_LOCK) ? "Locked" : "Unlocked");
1370         print_heap(xseg);
1371         /* fprintf(stderr, "Heap usage: %llu / %llu\n", */
1372         /*              (unsigned long long)xseg->heap->cur, */
1373         /*              (unsigned long long)xseg->config.heap_size); */
1374         fprintf(stderr, "Handlers: \n");
1375         print_hanlder("Requests handler", xseg->request_h);
1376         print_hanlder("Ports handler", xseg->port_h);
1377         print_hanlder("Objects handler", xseg->object_handlers);
1378         fprintf(stderr, "\n");
1379
1380         for (t = 0; t < xseg->config.nr_ports; t++)
1381                 cmd_report(t);
1382
1383         return 0;
1384 }
1385
1386
1387 int finish_req(struct xseg_request *req, enum req_action action)
1388 {
1389         if (action == COMPLETE){
1390                 req->state &= ~XS_FAILED;
1391                 req->state |= XS_SERVED;
1392         } else {
1393                 req->state |= XS_FAILED;
1394                 req->state &= ~XS_SERVED;
1395         }
1396         req->serviced = 0;
1397         xport p = xseg_respond(xseg, req, srcport, X_ALLOC);
1398         if (p == NoPort)
1399                 xseg_put_request(xseg, req, srcport);
1400         else
1401                 xseg_signal(xseg, p);
1402         return 0;
1403 }
1404
1405 //FIXME this should be in xseg lib?
1406 static int isDangling(struct xseg_request *req)
1407 {
1408         xport i;
1409         struct xseg_port *port;
1410         for (i = 0; i < xseg->config.nr_ports; i++) {
1411                 if (xseg->ports[i]){
1412                         port = xseg_get_port(xseg, i);
1413                         if (!port){
1414                                 fprintf(stderr, "Inconsisten port <-> portno mapping %u", i);
1415                                 continue;
1416                         }
1417                         struct xq *fq, *rq, *pq;
1418                         fq = xseg_get_queue(xseg, port, free_queue);
1419                         rq = xseg_get_queue(xseg, port, request_queue);
1420                         pq = xseg_get_queue(xseg, port, reply_queue);
1421                         xlock_acquire(&port->fq_lock, srcport);
1422                         if (__xq_check(fq, XPTR_MAKE(req, xseg->segment))){
1423                                         xlock_release(&port->fq_lock);
1424                                         return 0;
1425                         }
1426                         xlock_release(&port->fq_lock);
1427                         xlock_acquire(&port->rq_lock, srcport);
1428                         if (__xq_check(rq, XPTR_MAKE(req, xseg->segment))){
1429                                         xlock_release(&port->rq_lock);
1430                                         return 0;
1431                         }
1432                         xlock_release(&port->rq_lock);
1433                         xlock_acquire(&port->pq_lock, srcport);
1434                         if (__xq_check(pq, XPTR_MAKE(req, xseg->segment))){
1435                                         xlock_release(&port->pq_lock);
1436                                         return 0;
1437                         }
1438                         xlock_release(&port->pq_lock);
1439                 }
1440         }
1441         return 1;
1442 }
1443
1444 int prompt_user(char *msg)
1445 {
1446         int c = 0, r = -1;
1447         printf("%s [y/n]: ", msg);
1448         while (1) {
1449                 c = fgetc(stdin);
1450                 if (c == 'y' || c == 'Y')
1451                         r = 1;
1452                 else if (c == 'n' || c == 'N')
1453                         r = 0;
1454                 else if (c == '\n'){
1455                         if (r == -1)
1456                                 printf("%s [y/n]: ", msg);
1457                         else
1458                                 break;
1459                 }
1460         }
1461         return r;
1462 }
1463
1464 //FIXME this should be in xseg lib?
1465 int cmd_verify(int fix)
1466 {
1467         if (cmd_join())
1468                 return -1;
1469         //segment lock
1470         if (xseg->shared->flags & XSEG_F_LOCK){
1471                 fprintf(stderr, "Segment lock: Locked\n");
1472                 if (fix && prompt_user("Unlock it ?"))
1473                         xseg->shared->flags &= ~XSEG_F_LOCK;
1474         }
1475         //heap lock
1476         if (xseg->heap->lock.owner != Noone){
1477                 fprintf(stderr, "Heap lock: Locked (Owner: %llu)\n",
1478                         (unsigned long long)xseg->heap->lock.owner);
1479                 if (fix && prompt_user("Unlock it ?"))
1480                         xlock_release(&xseg->heap->lock);
1481         }
1482         //obj_h locks
1483         if (xseg->request_h->lock.owner != Noone){
1484                 fprintf(stderr, "Requests handler lock: Locked (Owner: %llu)\n",
1485                         (unsigned long long)xseg->request_h->lock.owner);
1486                 if (fix && prompt_user("Unlock it ?"))
1487                         xlock_release(&xseg->request_h->lock);
1488         }
1489         if (xseg->port_h->lock.owner != Noone){
1490                 fprintf(stderr, "Ports handler lock: Locked (Owner: %llu)\n",
1491                         (unsigned long long)xseg->port_h->lock.owner);
1492                 if (fix && prompt_user("Unlock it ?"))
1493                         xlock_release(&xseg->port_h->lock);
1494         }
1495         if (xseg->object_handlers->lock.owner != Noone){
1496                 fprintf(stderr, "Objects handler lock: Locked (Owner: %llu)\n",
1497                         (unsigned long long)xseg->object_handlers->lock.owner);
1498                 if (fix && prompt_user("Unlock it ?"))
1499                         xlock_release(&xseg->object_handlers->lock);
1500         }
1501         //take segment lock?
1502         xport i;
1503         struct xseg_port *port;
1504         for (i = 0; i < xseg->config.nr_ports; i++) {
1505                 if (xseg->ports[i]){
1506                         port = xseg_get_port(xseg, i);
1507                         if (!port){
1508                                 fprintf(stderr, "Inconsisten port <-> portno mapping %u", i);
1509                                 continue;
1510                         }
1511                         if (port->fq_lock.owner != Noone) {
1512                                 fprintf(stderr, "Free queue lock of port %u locked (Owner %llu)\n",
1513                                                 i, (unsigned long long)port->fq_lock.owner);
1514                                 if (fix && prompt_user("Unlock it ?"))
1515                                         xlock_release(&port->fq_lock);
1516                         }
1517                         if (port->rq_lock.owner != Noone) {
1518                                 fprintf(stderr, "Request queue lock of port %u locked (Owner %llu)\n",
1519                                                 i, (unsigned long long)port->rq_lock.owner);
1520                                 if (fix && prompt_user("Unlock it ?"))
1521                                         xlock_release(&port->rq_lock);
1522                         }
1523                         if (port->pq_lock.owner != Noone) {
1524                                 fprintf(stderr, "Reply queue lock of port %u locked (Owner %llu)\n",
1525                                                 i, (unsigned long long)port->pq_lock.owner);
1526                                 if (fix && prompt_user("Unlock it ?"))
1527                                         xlock_release(&port->pq_lock);
1528                         }
1529                 }
1530         }
1531
1532         struct xobject_h *obj_h = xseg->request_h;
1533         struct xobject_iter it;
1534
1535         struct xseg_request *req;
1536         xlock_acquire(&obj_h->lock, srcport);
1537         xobj_iter_init(obj_h, &it);
1538         while (xobj_iterate(obj_h, &it, (void **)&req)){
1539                 //FIXME this will not work cause obj->magic - req->serial is not
1540                 //touched when a request is get
1541                 /* if (obj->magic != MAGIC_REQ && t->src_portno == portno){ */
1542                 if (isDangling(req) && !__xobj_isFree(obj_h, req)){
1543                         report_request(req);
1544                         if (fix && prompt_user("Fail it ?")){
1545                                 printf("Finishing ...\n");
1546                                 finish_req(req, FAIL);
1547                         }
1548                 }
1549         }
1550         xlock_release(&obj_h->lock);
1551         return 0;
1552 }
1553
1554 int cmd_inspectq(xport portno, enum queue qt)
1555 {
1556         if (cmd_join())
1557                 return -1;
1558
1559         struct xq *q;
1560         struct xlock *l;
1561         struct xseg_port *port = xseg_get_port(xseg, portno);
1562         if (!port)
1563                 return -1;
1564         if (qt == FREE_QUEUE){
1565                 q = xseg_get_queue(xseg, port, free_queue);
1566                 l = &port->fq_lock;
1567         }
1568         else if (qt == REQUEST_QUEUE){
1569                 q = xseg_get_queue(xseg, port, request_queue);
1570                 l = &port->rq_lock;
1571         }
1572         else if (qt == REPLY_QUEUE) {
1573                 q = xseg_get_queue(xseg, port, reply_queue);
1574                 l = &port->rq_lock;
1575         }
1576         else
1577                 return -1;
1578         xlock_acquire(l, srcport);
1579         xqindex i,c = xq_count(q);
1580         if (c) {
1581                 struct xseg_request *req;
1582                 xptr xqi;
1583                 for (i = 0; i < c; i++) {
1584                         xqi = __xq_pop_head(q);
1585                         req = XPTR_TAKE(xqi, xseg->segment);
1586                         report_request(req);
1587                         __xq_append_tail(q, xqi);
1588                 }
1589         }
1590         else {
1591                 fprintf(stderr, "Queue is empty\n\n");
1592         }
1593         xlock_release(l);
1594         return 0;
1595 }
1596
1597
1598 int cmd_request(struct xseg_request *req, enum req_action action)
1599 {
1600         if (cmd_join())
1601                 return -1;
1602
1603         struct xobject_h *obj_h = xseg->request_h;
1604         if (!xobj_check(obj_h, req))
1605                 return -1;
1606
1607         if (action == REPORT)
1608                 report_request(req);
1609         else if (action == FAIL){
1610                 report_request(req);
1611                 if (prompt_user("fail it ?")){
1612                         printf("Finishing ...\n");
1613                         finish_req(req, FAIL);
1614                 }
1615         }
1616         else if (action == COMPLETE){
1617                 report_request(req);
1618                 if (prompt_user("Complete it ?")){
1619                         printf("Finishing ...\n");
1620                         finish_req(req, COMPLETE);
1621                 }
1622         }
1623         return 0;
1624 }
1625
1626 int cmd_create(void)
1627 {
1628         int r = xseg_create(&cfg);
1629         if (r) {
1630                 fprintf(stderr, "cannot create segment!\n");
1631                 return -1;
1632         }
1633
1634         fprintf(stderr, "Segment initialized.\n");
1635         return 0;
1636 }
1637
1638 int cmd_destroy(void)
1639 {
1640         if (!xseg && cmd_join())
1641                 return -1;
1642         xseg_leave(xseg);
1643         xseg_destroy(xseg);
1644         xseg = NULL;
1645         fprintf(stderr, "Segment destroyed.\n");
1646         return 0;
1647 }
1648
1649 int cmd_alloc_requests(unsigned long nr)
1650 {
1651         return xseg_alloc_requests(xseg, srcport, nr);
1652 }
1653
1654 int cmd_free_requests(unsigned long nr)
1655 {
1656         return xseg_free_requests(xseg, srcport, nr);
1657 }
1658
1659 int cmd_put_requests(void)
1660 {
1661         struct xseg_request *req;
1662
1663         for (;;) {
1664                 req = xseg_accept(xseg, dstport, 0);
1665                 if (!req)
1666                         break;
1667                 if (xseg_put_request(xseg, req, srcport))
1668                         fprintf(stderr, "Cannot put request at port %u\n", req->src_portno);
1669         }
1670
1671         return 0;
1672 }
1673
1674 int cmd_finish(unsigned long nr, int fail)
1675 {
1676         struct xseg_request *req;
1677         char *buf = malloc(sizeof(char) * 8128);
1678         char *req_target, *req_data;
1679         xseg_bind_port(xseg, srcport, NULL);
1680         init_local_signal();
1681         xport p;
1682
1683         for (; nr--;) {
1684                 xseg_prepare_wait(xseg, srcport);
1685                 req = xseg_accept(xseg, srcport, 0);
1686                 if (req) {
1687                         req_target = xseg_get_target(xseg, req);
1688                         req_data = xseg_get_data(xseg, req);
1689                         xseg_cancel_wait(xseg, srcport);
1690                         if (fail == 1)
1691                                 req->state &= ~XS_SERVED;
1692                         else {
1693                                 if (req->op == X_READ)
1694                                         mkchunk(req_data, req->datalen, req_target, req->targetlen, req->offset);
1695                                 else if (req->op == X_WRITE) 
1696                                         memcpy(buf, req_data, (sizeof(*buf) > req->datalen) ? req->datalen : sizeof(*buf));
1697                                 else if (req->op == X_INFO)
1698                                         *((uint64_t *) req->data) = 4294967296;
1699                                 
1700                                 req->state |= XS_SERVED;
1701                                 req->serviced = req->size;
1702                         }
1703
1704                         p = xseg_respond(xseg, req, srcport, X_ALLOC);
1705                         xseg_signal(xseg, p);
1706                         continue;
1707                 }
1708                 ++nr;
1709                 xseg_wait_signal(xseg, sd, 10000000L);
1710         }
1711
1712         free(buf);
1713
1714         return 0;
1715 }
1716
1717 void handle_reply(struct xseg_request *req)
1718 {
1719         char *req_data = xseg_get_data(xseg, req);
1720         char *req_target = xseg_get_target(xseg, req);
1721         if (!(req->state & XS_SERVED)) {
1722                 report_request(req);
1723                 goto put;
1724         }
1725
1726         switch (req->op) {
1727         case X_READ:
1728                 fwrite(req_data, 1, req->datalen, stdout);
1729                 break;
1730
1731         case X_WRITE:
1732                 fprintf(stdout, "wrote: ");
1733                 fwrite(req_data, 1, req->datalen, stdout);
1734                 break;
1735         case X_SYNC:
1736         case X_DELETE:
1737                 fprintf(stderr, "deleted %s\n", req_target);
1738                 break;
1739         case X_TRUNCATE:
1740         case X_COMMIT:
1741         case X_CLONE:
1742                 fprintf(stderr, "cloned %s\n", ((struct xseg_request_clone *)req_data)->target);
1743                 break;
1744         case X_INFO:
1745                 fprintf(stderr, "size: %llu\n", (unsigned long long)*((uint64_t *)req_data));
1746                 break;
1747         case X_COPY:
1748                 fprintf(stderr, "copied %s\n", ((struct xseg_request_copy *)req_data)->target);
1749                 break;
1750         case X_CLOSE:
1751                 fprintf(stderr, "Closed %s\n", req_target);
1752                 break;
1753         case X_OPEN:
1754                 fprintf(stderr, "Opened %s\n", req_target);
1755                 break;
1756         case X_SNAPSHOT:
1757                 fprintf(stderr, "Snapshotted %s\n", req_target);
1758                 break;
1759         default:
1760                 break;
1761         }
1762
1763 put:
1764         if (xseg_put_request(xseg, req, srcport))
1765                 fprintf(stderr, "Cannot put reply at port %u\n", req->src_portno);
1766 }
1767
1768 int cmd_wait(uint32_t nr)
1769 {
1770         struct xseg_request *req;
1771         long ret;
1772         init_local_signal(); 
1773
1774         for (;;) {
1775                 req = xseg_receive(xseg, srcport, 0);
1776                 if (req) {
1777                         handle_reply(req);
1778                         nr--;
1779                         if (nr == 0)
1780                                 break;
1781                         continue;
1782                 }
1783
1784                 ret = xseg_prepare_wait(xseg, srcport);
1785                 if (ret)
1786                         return -1;
1787
1788                 ret = xseg_wait_signal(xseg, sd, 1000000);
1789                 ret = xseg_cancel_wait(xseg, srcport);
1790                 if (ret)
1791                         return -1;
1792         }
1793
1794         return 0;
1795 }
1796
1797 int cmd_put_replies(void)
1798 {
1799         struct xseg_request *req;
1800
1801         for (;;) {
1802                 req = xseg_receive(xseg, dstport, 0);
1803                 if (!req)
1804                         break;
1805                 fprintf(stderr, "request: %08llx%08llx\n"
1806                         "     op: %u\n"
1807                         "  state: %u\n",
1808                         0LL, (unsigned long long)req->serial,
1809                         req->op,
1810                         req->state);
1811                 report_request(req);
1812
1813                 //fwrite(req->buffer, 1, req->bufferlen, stdout);
1814
1815                 if (xseg_put_request(xseg, req, srcport))
1816                         fprintf(stderr, "Cannot put reply\n");
1817         }
1818
1819         return 0;
1820 }
1821
1822 int cmd_bind(long portno)
1823 {
1824         struct xseg_port *port = xseg_bind_port(xseg, portno, NULL);
1825         if (!port) {
1826                 fprintf(stderr, "failed to bind port %ld\n", portno);
1827                 return 1;
1828         }
1829
1830         fprintf(stderr, "bound port %u\n", xseg_portno(xseg, port));
1831         return 0;
1832 }
1833
1834 int cmd_signal(uint32_t portno)
1835 {
1836         return xseg_signal(xseg, portno);
1837 }
1838
1839 int cmd_set_next(xport portno, xport next)
1840 {
1841         xseg->path_next[portno] = next;
1842         return 0;
1843 }
1844
1845 int parse_ports(char *str)
1846 {
1847         int ret = 0;
1848         char *s = str;
1849
1850         for (;;) {
1851                 if (*s == 0)
1852                         return 0;
1853
1854                 if (*s == ':') {
1855                         *s = 0;
1856                         if ((s > str) && isdigit(str[0])) {
1857                                 srcport = atol(str);
1858                                 ret ++;
1859                         }
1860                         break;
1861                 }
1862                 s ++;
1863         }
1864
1865         s += 1;
1866         str = s;
1867
1868         for (;;) {
1869                 if (*s == 0) {
1870                         if ((s > str) && isdigit(str[0])) {
1871                                 dstport = atol(str);
1872                                 ret ++;
1873                         }
1874                         break;
1875                 }
1876                 s ++;
1877         }
1878
1879         return ret;
1880 }
1881
1882 int main(int argc, char **argv)
1883 {
1884         int i, ret = 0;
1885         char *spec;
1886
1887         if (argc < 3)
1888                 return help();
1889
1890         srcport = -1;
1891         dstport = -1;
1892         spec = argv[1];
1893
1894         if (xseg_parse_spec(spec, &cfg)) {
1895                 fprintf(stderr, "Cannot parse spec\n");
1896                 return -1;
1897         }
1898
1899         if (xseg_initialize()) {
1900                 fprintf(stderr, "cannot initialize!\n");
1901                 return -1;
1902         }
1903
1904         for (i = 2; i < argc; i++) {
1905
1906                 if (!strcmp(argv[i], "create")) {
1907                         ret = cmd_create();
1908                         continue;
1909                 }
1910
1911                 if (!strcmp(argv[i], "join")) {
1912                         ret = cmd_join();
1913                         if (!ret)
1914                                 fprintf(stderr, "Segment joined.\n");
1915                         continue;
1916                 }
1917
1918                 if (!strcmp(argv[i], "destroy")) {
1919                         ret = cmd_destroy();
1920                         continue;
1921                 }
1922
1923                 if (cmd_join())
1924                         return -1;
1925
1926                 if (!strcmp(argv[i], "reportall")) {
1927                         ret = cmd_reportall();
1928                         continue;
1929                 }
1930
1931                 if (!strcmp(argv[i], "bind") && (i + 1 < argc)) {
1932                         ret = cmd_bind(atol(argv[i+1]));
1933                         i += 1;
1934                         continue;
1935                 }
1936
1937                 if (!strcmp(argv[i], "set-next") && (i + 2 < argc)) {
1938                         ret = cmd_set_next(atol(argv[i+1]), atol(argv[i+2]));
1939                         i += 2;
1940                         continue;
1941                 }
1942
1943                 if (!strcmp(argv[i], "signal") && (i + 1 < argc)) {
1944                         ret = cmd_signal(atol(argv[i+1]));
1945                         i += 1;
1946                         continue;
1947                 }
1948
1949                 if (!strcmp(argv[i], "bridge") && (i + 4 < argc)) {
1950                         ret = cmd_bridge(atol(argv[i+1]),
1951                                          atol(argv[i+2]),
1952                                          argv[i+3],
1953                                          argv[i+4]);
1954                         i += 4;
1955                         continue;
1956                 }
1957
1958                 if (srcport == -1) {
1959                         if (!parse_ports(argv[i]))
1960                                 fprintf(stderr, "source port undefined: %s\n", argv[i]);
1961                         continue;
1962                 }
1963
1964                 if (dstport == -1) {
1965                         if (!parse_ports(argv[i]))
1966                                 fprintf(stderr, "destination port undefined: %s\n", argv[i]);
1967                         continue;
1968                 }
1969
1970                 if (!strcmp(argv[i], "verify")) {
1971                         ret = cmd_verify(0);
1972                         continue;
1973                 }
1974
1975                 if (!strcmp(argv[i], "verify-fix")) {
1976                         ret = cmd_verify(1);
1977                         continue;
1978                 }
1979
1980                 if (!strcmp(argv[i], "failreq") && (i + 1 < argc)) {
1981                         struct xseg_request *req;
1982                         sscanf(argv[i+1], "%lx", (unsigned long *)&req);
1983                         ret = cmd_request(req, FAIL);
1984                         i += 1;
1985                         continue;
1986                 }
1987
1988                 if (!strcmp(argv[i], "inspect-freeq") && (i + 1 < argc)) {
1989                         ret = cmd_inspectq(atol(argv[i+1]), FREE_QUEUE);
1990                         i += 1;
1991                         continue;
1992                 }
1993
1994                 if (!strcmp(argv[i], "inspect-requestq") && (i + 1 < argc)) {
1995                         ret = cmd_inspectq(atol(argv[i+1]), REQUEST_QUEUE);
1996                         i += 1;
1997                         continue;
1998                 }
1999
2000                 if (!strcmp(argv[i], "inspect-replyq") && (i + 1 < argc)) {
2001                         ret = cmd_inspectq(atol(argv[i+1]), REPLY_QUEUE);
2002                         i += 1;
2003                         continue;
2004                 }
2005
2006                 if (!strcmp(argv[i], "report")) {
2007                         ret = cmd_report(dstport);
2008                         continue;
2009                 }
2010
2011                 if (!strcmp(argv[i], "alloc_requests") && (i + 1 < argc)) {
2012                         ret = cmd_alloc_requests(atol(argv[i+1]));
2013                         i += 1;
2014                         continue;
2015                 }
2016
2017                 if (!strcmp(argv[i], "free_requests") && (i + 1 < argc)) {
2018                         ret = cmd_free_requests(atol(argv[i+1]));
2019                         i += 1;
2020                         continue;
2021                 }
2022
2023                 if (!strcmp(argv[i], "put_requests")) {
2024                         ret = cmd_put_requests();
2025                         continue;
2026                 }
2027
2028                 if (!strcmp(argv[i], "put_replies")) {
2029                         ret = cmd_put_replies();
2030                         continue;
2031                 }
2032
2033                 if (!strcmp(argv[i], "complete") && (i + 1 < argc)) {
2034                         ret = cmd_finish(atol(argv[i+1]), 0);
2035                         i += 1;
2036                         continue;
2037                 }
2038
2039                 if (!strcmp(argv[i], "fail") && (i + 1 < argc)) {
2040                         ret = cmd_finish(atol(argv[i+1]), 1);
2041                         i += 1;
2042                         continue;
2043                 }
2044
2045                 if (!strcmp(argv[i], "wait") && (i + 1 < argc)) {
2046                         ret = cmd_wait(atol(argv[i+1]));
2047                         i += 1;
2048                         continue;
2049                 }
2050
2051                 if (!strcmp(argv[i], "rndwrite") && (i + 5 < argc)) {
2052                         long nr_loops = atol(argv[i+1]);
2053                         unsigned int seed = atoi(argv[i+2]);
2054                         unsigned int targetlen = atoi(argv[i+3]);
2055                         unsigned int chunksize = atoi(argv[i+4]);
2056                         unsigned long objectsize = atol(argv[i+5]);
2057                         ret = cmd_rndwrite(nr_loops, seed, targetlen, chunksize, objectsize);
2058                         i += 5;
2059                         continue;
2060                 }
2061                 
2062                 if (!strcmp(argv[i], "rnddelete") && (i + 3 < argc)) {
2063                         long nr_loops = atol(argv[i+1]);
2064                         unsigned int seed = atoi(argv[i+2]);
2065                         unsigned int targetlen = atoi(argv[i+3]);
2066                         ret = cmd_rnddelete(nr_loops, seed, targetlen);
2067                         i += 3;
2068                         continue;
2069                 }
2070
2071                 if (!strcmp(argv[i], "rndread") && (i + 5 < argc)) {
2072                         long nr_loops = atol(argv[i+1]);
2073                         unsigned int seed = atoi(argv[i+2]);
2074                         unsigned int targetlen = atoi(argv[i+3]);
2075                         unsigned int chunksize = atoi(argv[i+4]);
2076                         unsigned long objectsize = atol(argv[i+5]);
2077                         ret = cmd_rndread(nr_loops, seed, targetlen, chunksize, objectsize);
2078                         i += 5;
2079                         continue;
2080                 }
2081
2082                 if (!strcmp(argv[i], "submit_reqs") && (i + 3 < argc)) {
2083                         long nr_loops = atol(argv[i+1]);
2084                         long concurrent_reqs = atol(argv[i+2]);
2085                         int op = atoi(argv[i+3]);
2086                         ret = cmd_submit_reqs(nr_loops, concurrent_reqs, op);
2087                         i += 3;
2088                         continue;
2089                 }
2090
2091                 if (!strcmp(argv[i], "read") && (i + 3 < argc)) {
2092                         char *target = argv[i+1];
2093                         uint64_t offset = atol(argv[i+2]);
2094                         uint64_t size   = atol(argv[i+3]);
2095                         ret = cmd_read(target, offset, size);
2096                         i += 3;
2097                         continue;
2098                 }
2099
2100                 if (!strcmp(argv[i], "write") && (i + 2 < argc)) {
2101                         char *target = argv[i+1];
2102                         uint64_t offset = atol(argv[i+2]);
2103                         ret = cmd_write(target, offset);
2104                         i += 2;
2105                         continue;
2106                 }
2107
2108                 if (!strcmp(argv[i], "truncate") && (i + 2 < argc)) {
2109                         char *target = argv[i+1];
2110                         uint64_t offset = atol(argv[i+2]);
2111                         ret = cmd_truncate(target, offset);
2112                         i += 2;
2113                         continue;
2114                 }
2115
2116                 if (!strcmp(argv[i], "delete") && (i + 1 < argc)) {
2117                         char *target = argv[i+1];
2118                         ret = cmd_delete(target);
2119                         i += 1;
2120                         continue;
2121                 }
2122
2123                 if (!strcmp(argv[i], "acquire") && (i + 1 < argc)) {
2124                         char *target = argv[i+1];
2125                         ret = cmd_acquire(target);
2126                         i += 1;
2127                         continue;
2128                 }
2129
2130                 if (!strcmp(argv[i], "release") && (i + 1 < argc)) {
2131                         char *target = argv[i+1];
2132                         ret = cmd_release(target);
2133                         i += 1;
2134                         continue;
2135                 }
2136
2137                 if (!strcmp(argv[i], "copy") && (i + 2) < argc) {
2138                         char *src = argv[i+1];
2139                         char *dst = argv[i+2];
2140                         ret = cmd_copy(src, dst);
2141                         i += 2;
2142                         continue;
2143                 }
2144
2145                 if (!strcmp(argv[i], "clone") && (i + 3 < argc)) {
2146                         char *src = argv[i+1];
2147                         char *dst = argv[i+2];
2148                         long size = atol(argv[i+3]);
2149                         ret = cmd_clone(src, dst, size);
2150                         i += 3;
2151                         continue;
2152                 }
2153                 if (!strcmp(argv[i], "snapshot") && (i + 2 < argc)) {
2154                         char *src = argv[i+1];
2155                         char *dst = argv[i+2];
2156                         ret = cmd_snapshot(src, dst, 4096*1024*1024UL);
2157                         i += 2;
2158                         continue;
2159                 }
2160
2161                 if (!strcmp(argv[i], "info") && (i + 1 < argc)) {
2162                         char *target = argv[i+1];
2163                         ret = cmd_info(target);
2164                         i += 1;
2165                         continue;
2166                 }
2167
2168
2169                 if (!parse_ports(argv[i]))
2170                         fprintf(stderr, "invalid argument: %s\n", argv[i]);
2171         }
2172
2173         /* xseg_leave(); */
2174         return ret;
2175 }