Statistics
| Branch: | Revision:

root / src / xseg-tool.c @ a86ebfc3

History | View | Annotate | Download (52.3 kB)

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 <xseg/xhash.h>
47
#include <xseg/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
        char *dynamic;
1256
        if (portno >= xseg->config.dynports) {
1257
                dynamic = "True";
1258
        } else {
1259
                dynamic = "False";
1260
        }
1261
        struct xq *fq, *rq, *pq;
1262
        fq = xseg_get_queue(xseg, port, free_queue);
1263
        rq = xseg_get_queue(xseg, port, request_queue);
1264
        pq = xseg_get_queue(xseg, port, reply_queue);
1265
        lock_status(&port->fq_lock, fls, 64);
1266
        lock_status(&port->rq_lock, rls, 64);
1267
        lock_status(&port->pq_lock, pls, 64);
1268
        fprintf(stderr, "port %u (dynamic: %s):\n"
1269
                "   requests: %llu/%llu  next: %u  dst gw: %u  owner:%llu\n"
1270
                "       free_queue [%p] count : %4llu | %s\n"
1271
                "    request_queue [%p] count : %4llu | %s\n"
1272
                "      reply_queue [%p] count : %4llu | %s\n",
1273
                portno, dynamic,
1274
                (unsigned long long)port->alloc_reqs,
1275
                (unsigned long long)port->max_alloc_reqs,
1276
                xseg->path_next[portno],
1277
                xseg->dst_gw[portno],
1278
                port->owner,
1279
                (void *)fq, (unsigned long long)xq_count(fq), fls,
1280
                (void *)rq, (unsigned long long)xq_count(rq), rls,
1281
                (void *)pq, (unsigned long long)xq_count(pq), pls);
1282
        return 0;
1283
}
1284

    
1285
int cmd_join(void)
1286
{
1287
        if (xseg)
1288
                return 0;
1289

    
1290
        xseg = xseg_join(cfg.type, cfg.name, "posix", NULL);
1291
        if (!xseg) {
1292
                fprintf(stderr, "cannot join segment!\n");
1293
                return -1;
1294
        }
1295
        return 0;
1296
}
1297
static void print_hanlder(char *name, struct xobject_h *obj_h)
1298
{
1299
        char ls[64];
1300
        lock_status(&obj_h->lock, ls, 64);
1301
        fprintf(stderr, "%20s: free: %4llu, allocated: %4llu, allocated space: %7llu (object size: %llu), Lock %s\n",
1302
                        name,
1303
                        (unsigned long long) obj_h->nr_free,
1304
                        (unsigned long long) obj_h->nr_allocated,
1305
                        (unsigned long long) obj_h->allocated_space,
1306
                        (unsigned long long) obj_h->obj_size, ls);
1307
}
1308

    
1309
//FIXME ugly
1310
static void print_heap(struct xseg *xseg)
1311
{
1312
        char *UNIT[4];
1313
        UNIT[0] = "B";
1314
        UNIT[1] = "KiB";
1315
        UNIT[2] = "MiB";
1316
        UNIT[3] = "GiB";
1317
        uint64_t MULT[4];
1318
        MULT[0] = 1;
1319
        MULT[1] = 1024;
1320
        MULT[2] = 1024*1024;
1321
        MULT[3] = 1024*1024*1024;
1322

    
1323
        int u;
1324
        uint64_t t;
1325
        fprintf(stderr, "Heap usage: ");
1326
        u = 0;
1327
        t = xseg->heap->cur;
1328
        while (t > 0) {
1329
                t /= 1024;
1330
                u++;
1331
        }
1332
        if (!t)
1333
                u--;
1334
        t = xseg->heap->cur / MULT[u];
1335
        if (t < 10){
1336
                float tf = ((float)(xseg->heap->cur))/((float)MULT[u]);
1337
                fprintf(stderr, "%2.1f %s/", tf, UNIT[u]);
1338
        }
1339
        else {
1340
                unsigned int tu = xseg->heap->cur / MULT[u];
1341
                fprintf(stderr, "%3u %s/", tu, UNIT[u]);
1342
        }
1343

    
1344
        u = 0;
1345
        t = xseg->config.heap_size;
1346
        while (t > 0) {
1347
                t /= 1024;
1348
                u++;
1349
        }
1350
        if (!t)
1351
                u--;
1352
        t = xseg->config.heap_size/MULT[u];
1353
        if (t < 10){
1354
                float tf = ((float)(xseg->config.heap_size))/(float)MULT[u];
1355
                fprintf(stderr, "%2.1f %s ", tf, UNIT[u]);
1356
        }
1357
        else {
1358
                unsigned int tu = xseg->config.heap_size / MULT[u];
1359
                fprintf(stderr, "%3u %s ", tu, UNIT[u]);
1360
        }
1361
        char ls[64];
1362
        lock_status(&xseg->heap->lock, ls, 64);
1363
        fprintf(stderr, "(%llu / %llu), %s\n",
1364
                        (unsigned long long)xseg->heap->cur,
1365
                        (unsigned long long)xseg->config.heap_size,
1366
                        ls);
1367
}
1368

    
1369
int cmd_reportall(void)
1370
{
1371
        uint32_t t;
1372

    
1373
        if (cmd_join())
1374
                return -1;
1375

    
1376
        fprintf(stderr, "Segment lock: %s\n",
1377
                (xseg->shared->flags & XSEG_F_LOCK) ? "Locked" : "Unlocked");
1378
        print_heap(xseg);
1379
        /* fprintf(stderr, "Heap usage: %llu / %llu\n", */
1380
        /*                 (unsigned long long)xseg->heap->cur, */
1381
        /*                 (unsigned long long)xseg->config.heap_size); */
1382
        fprintf(stderr, "Handlers: \n");
1383
        print_hanlder("Requests handler", xseg->request_h);
1384
        print_hanlder("Ports handler", xseg->port_h);
1385
        print_hanlder("Objects handler", xseg->object_handlers);
1386
        fprintf(stderr, "\n");
1387

    
1388
        for (t = 0; t < xseg->config.nr_ports; t++)
1389
                cmd_report(t);
1390

    
1391
        return 0;
1392
}
1393

    
1394

    
1395
int finish_req(struct xseg_request *req, enum req_action action)
1396
{
1397
        if (action == COMPLETE){
1398
                req->state &= ~XS_FAILED;
1399
                req->state |= XS_SERVED;
1400
        } else {
1401
                req->state |= XS_FAILED;
1402
                req->state &= ~XS_SERVED;
1403
        }
1404
        req->serviced = 0;
1405
        xport p = xseg_respond(xseg, req, srcport, X_ALLOC);
1406
        if (p == NoPort)
1407
                xseg_put_request(xseg, req, srcport);
1408
        else
1409
                xseg_signal(xseg, p);
1410
        return 0;
1411
}
1412

    
1413
//FIXME this should be in xseg lib?
1414
static int isDangling(struct xseg_request *req)
1415
{
1416
        xport i;
1417
        struct xseg_port *port;
1418
        for (i = 0; i < xseg->config.nr_ports; i++) {
1419
                if (xseg->ports[i]){
1420
                        port = xseg_get_port(xseg, i);
1421
                        if (!port){
1422
                                fprintf(stderr, "Inconsisten port <-> portno mapping %u", i);
1423
                                continue;
1424
                        }
1425
                        struct xq *fq, *rq, *pq;
1426
                        fq = xseg_get_queue(xseg, port, free_queue);
1427
                        rq = xseg_get_queue(xseg, port, request_queue);
1428
                        pq = xseg_get_queue(xseg, port, reply_queue);
1429
                        xlock_acquire(&port->fq_lock, srcport);
1430
                        if (__xq_check(fq, XPTR_MAKE(req, xseg->segment))){
1431
                                        xlock_release(&port->fq_lock);
1432
                                        return 0;
1433
                        }
1434
                        xlock_release(&port->fq_lock);
1435
                        xlock_acquire(&port->rq_lock, srcport);
1436
                        if (__xq_check(rq, XPTR_MAKE(req, xseg->segment))){
1437
                                        xlock_release(&port->rq_lock);
1438
                                        return 0;
1439
                        }
1440
                        xlock_release(&port->rq_lock);
1441
                        xlock_acquire(&port->pq_lock, srcport);
1442
                        if (__xq_check(pq, XPTR_MAKE(req, xseg->segment))){
1443
                                        xlock_release(&port->pq_lock);
1444
                                        return 0;
1445
                        }
1446
                        xlock_release(&port->pq_lock);
1447
                }
1448
        }
1449
        return 1;
1450
}
1451

    
1452
int prompt_user(char *msg)
1453
{
1454
        int c = 0, r = -1;
1455
        printf("%s [y/n]: ", msg);
1456
        while (1) {
1457
                c = fgetc(stdin);
1458
                if (c == 'y' || c == 'Y')
1459
                        r = 1;
1460
                else if (c == 'n' || c == 'N')
1461
                        r = 0;
1462
                else if (c == '\n'){
1463
                        if (r == -1)
1464
                                printf("%s [y/n]: ", msg);
1465
                        else
1466
                                break;
1467
                }
1468
        }
1469
        return r;
1470
}
1471

    
1472
//FIXME this should be in xseg lib?
1473
int cmd_verify(int fix)
1474
{
1475
        if (cmd_join())
1476
                return -1;
1477
        //segment lock
1478
        if (xseg->shared->flags & XSEG_F_LOCK){
1479
                fprintf(stderr, "Segment lock: Locked\n");
1480
                if (fix && prompt_user("Unlock it ?"))
1481
                        xseg->shared->flags &= ~XSEG_F_LOCK;
1482
        }
1483
        //heap lock
1484
        if (xseg->heap->lock.owner != Noone){
1485
                fprintf(stderr, "Heap lock: Locked (Owner: %llu)\n",
1486
                        (unsigned long long)xseg->heap->lock.owner);
1487
                if (fix && prompt_user("Unlock it ?"))
1488
                        xlock_release(&xseg->heap->lock);
1489
        }
1490
        //obj_h locks
1491
        if (xseg->request_h->lock.owner != Noone){
1492
                fprintf(stderr, "Requests handler lock: Locked (Owner: %llu)\n",
1493
                        (unsigned long long)xseg->request_h->lock.owner);
1494
                if (fix && prompt_user("Unlock it ?"))
1495
                        xlock_release(&xseg->request_h->lock);
1496
        }
1497
        if (xseg->port_h->lock.owner != Noone){
1498
                fprintf(stderr, "Ports handler lock: Locked (Owner: %llu)\n",
1499
                        (unsigned long long)xseg->port_h->lock.owner);
1500
                if (fix && prompt_user("Unlock it ?"))
1501
                        xlock_release(&xseg->port_h->lock);
1502
        }
1503
        if (xseg->object_handlers->lock.owner != Noone){
1504
                fprintf(stderr, "Objects handler lock: Locked (Owner: %llu)\n",
1505
                        (unsigned long long)xseg->object_handlers->lock.owner);
1506
                if (fix && prompt_user("Unlock it ?"))
1507
                        xlock_release(&xseg->object_handlers->lock);
1508
        }
1509
        //take segment lock?
1510
        xport i;
1511
        struct xseg_port *port;
1512
        for (i = 0; i < xseg->config.nr_ports; i++) {
1513
                if (xseg->ports[i]){
1514
                        port = xseg_get_port(xseg, i);
1515
                        if (!port){
1516
                                fprintf(stderr, "Inconsisten port <-> portno mapping %u", i);
1517
                                continue;
1518
                        }
1519
                        if (port->fq_lock.owner != Noone) {
1520
                                fprintf(stderr, "Free queue lock of port %u locked (Owner %llu)\n",
1521
                                                i, (unsigned long long)port->fq_lock.owner);
1522
                                if (fix && prompt_user("Unlock it ?"))
1523
                                        xlock_release(&port->fq_lock);
1524
                        }
1525
                        if (port->rq_lock.owner != Noone) {
1526
                                fprintf(stderr, "Request queue lock of port %u locked (Owner %llu)\n",
1527
                                                i, (unsigned long long)port->rq_lock.owner);
1528
                                if (fix && prompt_user("Unlock it ?"))
1529
                                        xlock_release(&port->rq_lock);
1530
                        }
1531
                        if (port->pq_lock.owner != Noone) {
1532
                                fprintf(stderr, "Reply queue lock of port %u locked (Owner %llu)\n",
1533
                                                i, (unsigned long long)port->pq_lock.owner);
1534
                                if (fix && prompt_user("Unlock it ?"))
1535
                                        xlock_release(&port->pq_lock);
1536
                        }
1537
                }
1538
        }
1539

    
1540
        struct xobject_h *obj_h = xseg->request_h;
1541
        struct xobject_iter it;
1542

    
1543
        struct xseg_request *req;
1544
        xlock_acquire(&obj_h->lock, srcport);
1545
        xobj_iter_init(obj_h, &it);
1546
        while (xobj_iterate(obj_h, &it, (void **)&req)){
1547
                //FIXME this will not work cause obj->magic - req->serial is not
1548
                //touched when a request is get
1549
                /* if (obj->magic != MAGIC_REQ && t->src_portno == portno){ */
1550
                if (isDangling(req) && !__xobj_isFree(obj_h, req)){
1551
                        report_request(req);
1552
                        if (fix && prompt_user("Fail it ?")){
1553
                                printf("Finishing ...\n");
1554
                                finish_req(req, FAIL);
1555
                        }
1556
                }
1557
        }
1558
        xlock_release(&obj_h->lock);
1559
        return 0;
1560
}
1561

    
1562

    
1563
int cmd_failport(long portno)
1564
{
1565
        if (cmd_join())
1566
                return -1;
1567

    
1568
        struct xobject_h *obj_h = xseg->request_h;
1569
        struct xobject_iter it;
1570

    
1571
        struct xseg_request *req;
1572
        xlock_acquire(&obj_h->lock, srcport);
1573
        xobj_iter_init(obj_h, &it);
1574
        while (xobj_iterate(obj_h, &it, (void **)&req)){
1575
                //FIXME this will not work cause obj->magic - req->serial is not
1576
                //touched when a request is get
1577
                /* if (obj->magic != MAGIC_REQ && t->src_portno == portno){ */
1578
                if (isDangling(req) && !__xobj_isFree(obj_h, req)){
1579
                        if (req->transit_portno == (uint32_t)portno) {
1580
                                report_request(req);
1581
                                printf("Finishing...\n");
1582
                                finish_req(req, FAIL);
1583
                        }
1584
                }
1585
        }
1586
        xlock_release(&obj_h->lock);
1587

    
1588
        return 0;
1589
}
1590

    
1591
int cmd_inspectq(xport portno, enum queue qt)
1592
{
1593
        if (cmd_join())
1594
                return -1;
1595

    
1596
        struct xq *q;
1597
        struct xlock *l;
1598
        struct xseg_port *port = xseg_get_port(xseg, portno);
1599
        if (!port)
1600
                return -1;
1601
        if (qt == FREE_QUEUE){
1602
                q = xseg_get_queue(xseg, port, free_queue);
1603
                l = &port->fq_lock;
1604
        }
1605
        else if (qt == REQUEST_QUEUE){
1606
                q = xseg_get_queue(xseg, port, request_queue);
1607
                l = &port->rq_lock;
1608
        }
1609
        else if (qt == REPLY_QUEUE) {
1610
                q = xseg_get_queue(xseg, port, reply_queue);
1611
                l = &port->rq_lock;
1612
        }
1613
        else
1614
                return -1;
1615
        xlock_acquire(l, srcport);
1616
        xqindex i,c = xq_count(q);
1617
        if (c) {
1618
                struct xseg_request *req;
1619
                xptr xqi;
1620
                for (i = 0; i < c; i++) {
1621
                        xqi = __xq_pop_head(q);
1622
                        req = XPTR_TAKE(xqi, xseg->segment);
1623
                        report_request(req);
1624
                        __xq_append_tail(q, xqi);
1625
                }
1626
        }
1627
        else {
1628
                fprintf(stderr, "Queue is empty\n\n");
1629
        }
1630
        xlock_release(l);
1631
        return 0;
1632
}
1633

    
1634

    
1635
int cmd_request(struct xseg_request *req, enum req_action action)
1636
{
1637
        if (cmd_join())
1638
                return -1;
1639

    
1640
        struct xobject_h *obj_h = xseg->request_h;
1641
        if (!xobj_check(obj_h, req))
1642
                return -1;
1643

    
1644
        if (action == REPORT)
1645
                report_request(req);
1646
        else if (action == FAIL){
1647
                report_request(req);
1648
                if (prompt_user("fail it ?")){
1649
                        printf("Finishing ...\n");
1650
                        finish_req(req, FAIL);
1651
                }
1652
        }
1653
        else if (action == COMPLETE){
1654
                report_request(req);
1655
                if (prompt_user("Complete it ?")){
1656
                        printf("Finishing ...\n");
1657
                        finish_req(req, COMPLETE);
1658
                }
1659
        }
1660
        return 0;
1661
}
1662

    
1663
int cmd_create(void)
1664
{
1665
        int r = xseg_create(&cfg);
1666
        if (r) {
1667
                fprintf(stderr, "cannot create segment!\n");
1668
                return -1;
1669
        }
1670

    
1671
        fprintf(stderr, "Segment initialized.\n");
1672
        return 0;
1673
}
1674

    
1675
int cmd_destroy(void)
1676
{
1677
        if (!xseg && cmd_join())
1678
                return -1;
1679
        xseg_leave(xseg);
1680
        xseg_destroy(xseg);
1681
        xseg = NULL;
1682
        fprintf(stderr, "Segment destroyed.\n");
1683
        return 0;
1684
}
1685

    
1686
int cmd_alloc_requests(unsigned long nr)
1687
{
1688
        return xseg_alloc_requests(xseg, srcport, nr);
1689
}
1690

    
1691
int cmd_free_requests(unsigned long nr)
1692
{
1693
        return xseg_free_requests(xseg, srcport, nr);
1694
}
1695

    
1696
int cmd_put_requests(void)
1697
{
1698
        struct xseg_request *req;
1699

    
1700
        for (;;) {
1701
                req = xseg_accept(xseg, dstport, 0);
1702
                if (!req)
1703
                        break;
1704
                if (xseg_put_request(xseg, req, srcport))
1705
                        fprintf(stderr, "Cannot put request at port %u\n", req->src_portno);
1706
        }
1707

    
1708
        return 0;
1709
}
1710

    
1711
int cmd_finish(unsigned long nr, int fail)
1712
{
1713
        struct xseg_request *req;
1714
        char *buf = malloc(sizeof(char) * 8128);
1715
        char *req_target, *req_data;
1716
        xseg_bind_port(xseg, srcport, NULL);
1717
        init_local_signal();
1718
        xport p;
1719

    
1720
        for (; nr--;) {
1721
                xseg_prepare_wait(xseg, srcport);
1722
                req = xseg_accept(xseg, srcport, 0);
1723
                if (req) {
1724
                        req_target = xseg_get_target(xseg, req);
1725
                        req_data = xseg_get_data(xseg, req);
1726
                        xseg_cancel_wait(xseg, srcport);
1727
                        if (fail == 1)
1728
                                req->state &= ~XS_SERVED;
1729
                        else {
1730
                                if (req->op == X_READ)
1731
                                        mkchunk(req_data, req->datalen, req_target, req->targetlen, req->offset);
1732
                                else if (req->op == X_WRITE) 
1733
                                        memcpy(buf, req_data, (sizeof(*buf) > req->datalen) ? req->datalen : sizeof(*buf));
1734
                                else if (req->op == X_INFO)
1735
                                        *((uint64_t *) req->data) = 4294967296;
1736
                                
1737
                                req->state |= XS_SERVED;
1738
                                req->serviced = req->size;
1739
                        }
1740

    
1741
                        p = xseg_respond(xseg, req, srcport, X_ALLOC);
1742
                        xseg_signal(xseg, p);
1743
                        continue;
1744
                }
1745
                ++nr;
1746
                xseg_wait_signal(xseg, sd, 10000000L);
1747
        }
1748

    
1749
        free(buf);
1750

    
1751
        return 0;
1752
}
1753

    
1754
void handle_reply(struct xseg_request *req)
1755
{
1756
        char *req_data = xseg_get_data(xseg, req);
1757
        char *req_target = xseg_get_target(xseg, req);
1758
        if (!(req->state & XS_SERVED)) {
1759
                report_request(req);
1760
                goto put;
1761
        }
1762

    
1763
        switch (req->op) {
1764
        case X_READ:
1765
                fwrite(req_data, 1, req->datalen, stdout);
1766
                break;
1767

    
1768
        case X_WRITE:
1769
                fprintf(stdout, "wrote: ");
1770
                fwrite(req_data, 1, req->datalen, stdout);
1771
                break;
1772
        case X_SYNC:
1773
        case X_DELETE:
1774
                fprintf(stderr, "deleted %s\n", req_target);
1775
                break;
1776
        case X_TRUNCATE:
1777
        case X_COMMIT:
1778
        case X_CLONE:
1779
                fprintf(stderr, "cloned %s\n", ((struct xseg_request_clone *)req_data)->target);
1780
                break;
1781
        case X_INFO:
1782
                fprintf(stderr, "size: %llu\n", (unsigned long long)*((uint64_t *)req_data));
1783
                break;
1784
        case X_COPY:
1785
                fprintf(stderr, "copied %s\n", ((struct xseg_request_copy *)req_data)->target);
1786
                break;
1787
        case X_CLOSE:
1788
                fprintf(stderr, "Closed %s\n", req_target);
1789
                break;
1790
        case X_OPEN:
1791
                fprintf(stderr, "Opened %s\n", req_target);
1792
                break;
1793
        case X_SNAPSHOT:
1794
                fprintf(stderr, "Snapshotted %s\n", req_target);
1795
                break;
1796
        default:
1797
                break;
1798
        }
1799

    
1800
put:
1801
        if (xseg_put_request(xseg, req, srcport))
1802
                fprintf(stderr, "Cannot put reply at port %u\n", req->src_portno);
1803
}
1804

    
1805
int cmd_wait(uint32_t nr)
1806
{
1807
        struct xseg_request *req;
1808
        long ret;
1809
        init_local_signal(); 
1810

    
1811
        for (;;) {
1812
                req = xseg_receive(xseg, srcport, 0);
1813
                if (req) {
1814
                        handle_reply(req);
1815
                        nr--;
1816
                        if (nr == 0)
1817
                                break;
1818
                        continue;
1819
                }
1820

    
1821
                ret = xseg_prepare_wait(xseg, srcport);
1822
                if (ret)
1823
                        return -1;
1824

    
1825
                ret = xseg_wait_signal(xseg, sd, 1000000);
1826
                ret = xseg_cancel_wait(xseg, srcport);
1827
                if (ret)
1828
                        return -1;
1829
        }
1830

    
1831
        return 0;
1832
}
1833

    
1834
int cmd_put_replies(void)
1835
{
1836
        struct xseg_request *req;
1837

    
1838
        for (;;) {
1839
                req = xseg_receive(xseg, dstport, 0);
1840
                if (!req)
1841
                        break;
1842
                fprintf(stderr, "request: %08llx%08llx\n"
1843
                        "     op: %u\n"
1844
                        "  state: %u\n",
1845
                        0LL, (unsigned long long)req->serial,
1846
                        req->op,
1847
                        req->state);
1848
                report_request(req);
1849

    
1850
                //fwrite(req->buffer, 1, req->bufferlen, stdout);
1851

    
1852
                if (xseg_put_request(xseg, req, srcport))
1853
                        fprintf(stderr, "Cannot put reply\n");
1854
        }
1855

    
1856
        return 0;
1857
}
1858

    
1859
int cmd_bind(long portno)
1860
{
1861
        struct xseg_port *port = xseg_bind_port(xseg, portno, NULL);
1862
        if (!port) {
1863
                fprintf(stderr, "failed to bind port %ld\n", portno);
1864
                return 1;
1865
        }
1866

    
1867
        fprintf(stderr, "bound port %u\n", xseg_portno(xseg, port));
1868
        return 0;
1869
}
1870

    
1871
int cmd_free(long portno)
1872
{
1873
        struct xseg_port *port;
1874
        int r;
1875
        if (portno < xseg->config.dynports) {
1876
                return 0;
1877
        }
1878

    
1879
        port = xseg_get_port(xseg, portno);
1880
        if (!port) {
1881
                fprintf(stderr, "Failed to get port %ld\n", portno);
1882
                return 1;
1883
        }
1884

    
1885
        r = xseg_leave_dynport(xseg, port);
1886
        if (r < 0) {
1887
                fprintf(stderr, "Failed to free dynamic port %ld\n", portno);
1888
                return 1;
1889
        }
1890

    
1891
        fprintf(stderr, "Freed port %ld\n", portno);
1892
        return 0;
1893
}
1894

    
1895
int cmd_signal(uint32_t portno)
1896
{
1897
        return xseg_signal(xseg, portno);
1898
}
1899

    
1900
int cmd_set_next(xport portno, xport next)
1901
{
1902
        xseg->path_next[portno] = next;
1903
        return 0;
1904
}
1905

    
1906
int parse_ports(char *str)
1907
{
1908
        int ret = 0;
1909
        char *s = str;
1910

    
1911
        for (;;) {
1912
                if (*s == 0)
1913
                        return 0;
1914

    
1915
                if (*s == ':') {
1916
                        *s = 0;
1917
                        if ((s > str) && isdigit(str[0])) {
1918
                                srcport = atol(str);
1919
                                ret ++;
1920
                        }
1921
                        break;
1922
                }
1923
                s ++;
1924
        }
1925

    
1926
        s += 1;
1927
        str = s;
1928

    
1929
        for (;;) {
1930
                if (*s == 0) {
1931
                        if ((s > str) && isdigit(str[0])) {
1932
                                dstport = atol(str);
1933
                                ret ++;
1934
                        }
1935
                        break;
1936
                }
1937
                s ++;
1938
        }
1939

    
1940
        return ret;
1941
}
1942

    
1943
int main(int argc, char **argv)
1944
{
1945
        int i, ret = 0;
1946
        char *spec;
1947

    
1948
        if (argc < 3)
1949
                return help();
1950

    
1951
        srcport = -1;
1952
        dstport = -1;
1953
        spec = argv[1];
1954

    
1955
        if (xseg_parse_spec(spec, &cfg)) {
1956
                fprintf(stderr, "Cannot parse spec\n");
1957
                return -1;
1958
        }
1959

    
1960
        if (xseg_initialize()) {
1961
                fprintf(stderr, "cannot initialize!\n");
1962
                return -1;
1963
        }
1964

    
1965
        for (i = 2; i < argc; i++) {
1966

    
1967
                if (!strcmp(argv[i], "create")) {
1968
                        ret = cmd_create();
1969
                        continue;
1970
                }
1971

    
1972
                if (!strcmp(argv[i], "join")) {
1973
                        ret = cmd_join();
1974
                        if (!ret)
1975
                                fprintf(stderr, "Segment joined.\n");
1976
                        continue;
1977
                }
1978

    
1979
                if (!strcmp(argv[i], "destroy")) {
1980
                        ret = cmd_destroy();
1981
                        continue;
1982
                }
1983

    
1984
                if (cmd_join())
1985
                        return -1;
1986

    
1987
                if (!strcmp(argv[i], "reportall")) {
1988
                        ret = cmd_reportall();
1989
                        continue;
1990
                }
1991

    
1992
                if (!strcmp(argv[i], "bind") && (i + 1 < argc)) {
1993
                        ret = cmd_bind(atol(argv[i+1]));
1994
                        i += 1;
1995
                        continue;
1996
                }
1997

    
1998
                if (!strcmp(argv[i], "free") && (i + 1 < argc)) {
1999
                        ret = cmd_free(atol(argv[i+1]));
2000
                        i += 1;
2001
                        continue;
2002
                }
2003

    
2004
                if (!strcmp(argv[i], "set-next") && (i + 2 < argc)) {
2005
                        ret = cmd_set_next(atol(argv[i+1]), atol(argv[i+2]));
2006
                        i += 2;
2007
                        continue;
2008
                }
2009

    
2010
                if (!strcmp(argv[i], "signal") && (i + 1 < argc)) {
2011
                        ret = cmd_signal(atol(argv[i+1]));
2012
                        i += 1;
2013
                        continue;
2014
                }
2015

    
2016
                if (!strcmp(argv[i], "bridge") && (i + 4 < argc)) {
2017
                        ret = cmd_bridge(atol(argv[i+1]),
2018
                                         atol(argv[i+2]),
2019
                                         argv[i+3],
2020
                                         argv[i+4]);
2021
                        i += 4;
2022
                        continue;
2023
                }
2024

    
2025
                if (srcport == -1) {
2026
                        if (!parse_ports(argv[i]))
2027
                                fprintf(stderr, "source port undefined: %s\n", argv[i]);
2028
                        continue;
2029
                }
2030

    
2031
                if (dstport == -1) {
2032
                        if (!parse_ports(argv[i]))
2033
                                fprintf(stderr, "destination port undefined: %s\n", argv[i]);
2034
                        continue;
2035
                }
2036

    
2037
                if (!strcmp(argv[i], "failport") && (i + 1 < argc)) {
2038
                        ret = cmd_failport(atol(argv[i+1]));
2039
                        i += 1;
2040
                        continue;
2041
                }
2042

    
2043
                if (!strcmp(argv[i], "verify")) {
2044
                        ret = cmd_verify(0);
2045
                        continue;
2046
                }
2047

    
2048
                if (!strcmp(argv[i], "verify-fix")) {
2049
                        ret = cmd_verify(1);
2050
                        continue;
2051
                }
2052

    
2053
                if (!strcmp(argv[i], "failreq") && (i + 1 < argc)) {
2054
                        struct xseg_request *req;
2055
                        sscanf(argv[i+1], "%lx", (unsigned long *)&req);
2056
                        ret = cmd_request(req, FAIL);
2057
                        i += 1;
2058
                        continue;
2059
                }
2060

    
2061
                if (!strcmp(argv[i], "inspect-freeq") && (i + 1 < argc)) {
2062
                        ret = cmd_inspectq(atol(argv[i+1]), FREE_QUEUE);
2063
                        i += 1;
2064
                        continue;
2065
                }
2066

    
2067
                if (!strcmp(argv[i], "inspect-requestq") && (i + 1 < argc)) {
2068
                        ret = cmd_inspectq(atol(argv[i+1]), REQUEST_QUEUE);
2069
                        i += 1;
2070
                        continue;
2071
                }
2072

    
2073
                if (!strcmp(argv[i], "inspect-replyq") && (i + 1 < argc)) {
2074
                        ret = cmd_inspectq(atol(argv[i+1]), REPLY_QUEUE);
2075
                        i += 1;
2076
                        continue;
2077
                }
2078

    
2079
                if (!strcmp(argv[i], "report")) {
2080
                        ret = cmd_report(dstport);
2081
                        continue;
2082
                }
2083

    
2084
                if (!strcmp(argv[i], "alloc_requests") && (i + 1 < argc)) {
2085
                        ret = cmd_alloc_requests(atol(argv[i+1]));
2086
                        i += 1;
2087
                        continue;
2088
                }
2089

    
2090
                if (!strcmp(argv[i], "free_requests") && (i + 1 < argc)) {
2091
                        ret = cmd_free_requests(atol(argv[i+1]));
2092
                        i += 1;
2093
                        continue;
2094
                }
2095

    
2096
                if (!strcmp(argv[i], "put_requests")) {
2097
                        ret = cmd_put_requests();
2098
                        continue;
2099
                }
2100

    
2101
                if (!strcmp(argv[i], "put_replies")) {
2102
                        ret = cmd_put_replies();
2103
                        continue;
2104
                }
2105

    
2106
                if (!strcmp(argv[i], "complete") && (i + 1 < argc)) {
2107
                        ret = cmd_finish(atol(argv[i+1]), 0);
2108
                        i += 1;
2109
                        continue;
2110
                }
2111

    
2112
                if (!strcmp(argv[i], "fail") && (i + 1 < argc)) {
2113
                        ret = cmd_finish(atol(argv[i+1]), 1);
2114
                        i += 1;
2115
                        continue;
2116
                }
2117

    
2118
                if (!strcmp(argv[i], "wait") && (i + 1 < argc)) {
2119
                        ret = cmd_wait(atol(argv[i+1]));
2120
                        i += 1;
2121
                        continue;
2122
                }
2123

    
2124
                if (!strcmp(argv[i], "rndwrite") && (i + 5 < argc)) {
2125
                        long nr_loops = atol(argv[i+1]);
2126
                        unsigned int seed = atoi(argv[i+2]);
2127
                        unsigned int targetlen = atoi(argv[i+3]);
2128
                        unsigned int chunksize = atoi(argv[i+4]);
2129
                        unsigned long objectsize = atol(argv[i+5]);
2130
                        ret = cmd_rndwrite(nr_loops, seed, targetlen, chunksize, objectsize);
2131
                        i += 5;
2132
                        continue;
2133
                }
2134
                
2135
                if (!strcmp(argv[i], "rnddelete") && (i + 3 < argc)) {
2136
                        long nr_loops = atol(argv[i+1]);
2137
                        unsigned int seed = atoi(argv[i+2]);
2138
                        unsigned int targetlen = atoi(argv[i+3]);
2139
                        ret = cmd_rnddelete(nr_loops, seed, targetlen);
2140
                        i += 3;
2141
                        continue;
2142
                }
2143

    
2144
                if (!strcmp(argv[i], "rndread") && (i + 5 < argc)) {
2145
                        long nr_loops = atol(argv[i+1]);
2146
                        unsigned int seed = atoi(argv[i+2]);
2147
                        unsigned int targetlen = atoi(argv[i+3]);
2148
                        unsigned int chunksize = atoi(argv[i+4]);
2149
                        unsigned long objectsize = atol(argv[i+5]);
2150
                        ret = cmd_rndread(nr_loops, seed, targetlen, chunksize, objectsize);
2151
                        i += 5;
2152
                        continue;
2153
                }
2154

    
2155
                if (!strcmp(argv[i], "submit_reqs") && (i + 3 < argc)) {
2156
                        long nr_loops = atol(argv[i+1]);
2157
                        long concurrent_reqs = atol(argv[i+2]);
2158
                        int op = atoi(argv[i+3]);
2159
                        ret = cmd_submit_reqs(nr_loops, concurrent_reqs, op);
2160
                        i += 3;
2161
                        continue;
2162
                }
2163

    
2164
                if (!strcmp(argv[i], "read") && (i + 3 < argc)) {
2165
                        char *target = argv[i+1];
2166
                        uint64_t offset = atol(argv[i+2]);
2167
                        uint64_t size   = atol(argv[i+3]);
2168
                        ret = cmd_read(target, offset, size);
2169
                        i += 3;
2170
                        continue;
2171
                }
2172

    
2173
                if (!strcmp(argv[i], "write") && (i + 2 < argc)) {
2174
                        char *target = argv[i+1];
2175
                        uint64_t offset = atol(argv[i+2]);
2176
                        ret = cmd_write(target, offset);
2177
                        i += 2;
2178
                        continue;
2179
                }
2180

    
2181
                if (!strcmp(argv[i], "truncate") && (i + 2 < argc)) {
2182
                        char *target = argv[i+1];
2183
                        uint64_t offset = atol(argv[i+2]);
2184
                        ret = cmd_truncate(target, offset);
2185
                        i += 2;
2186
                        continue;
2187
                }
2188

    
2189
                if (!strcmp(argv[i], "delete") && (i + 1 < argc)) {
2190
                        char *target = argv[i+1];
2191
                        ret = cmd_delete(target);
2192
                        i += 1;
2193
                        continue;
2194
                }
2195

    
2196
                if (!strcmp(argv[i], "acquire") && (i + 1 < argc)) {
2197
                        char *target = argv[i+1];
2198
                        ret = cmd_acquire(target);
2199
                        i += 1;
2200
                        continue;
2201
                }
2202

    
2203
                if (!strcmp(argv[i], "release") && (i + 1 < argc)) {
2204
                        char *target = argv[i+1];
2205
                        ret = cmd_release(target);
2206
                        i += 1;
2207
                        continue;
2208
                }
2209

    
2210
                if (!strcmp(argv[i], "copy") && (i + 2) < argc) {
2211
                        char *src = argv[i+1];
2212
                        char *dst = argv[i+2];
2213
                        ret = cmd_copy(src, dst);
2214
                        i += 2;
2215
                        continue;
2216
                }
2217

    
2218
                if (!strcmp(argv[i], "clone") && (i + 3 < argc)) {
2219
                        char *src = argv[i+1];
2220
                        char *dst = argv[i+2];
2221
                        long size = atol(argv[i+3]);
2222
                        ret = cmd_clone(src, dst, size);
2223
                        i += 3;
2224
                        continue;
2225
                }
2226
                if (!strcmp(argv[i], "snapshot") && (i + 2 < argc)) {
2227
                        char *src = argv[i+1];
2228
                        char *dst = argv[i+2];
2229
                        ret = cmd_snapshot(src, dst, 4096*1024*1024UL);
2230
                        i += 2;
2231
                        continue;
2232
                }
2233

    
2234
                if (!strcmp(argv[i], "info") && (i + 1 < argc)) {
2235
                        char *target = argv[i+1];
2236
                        ret = cmd_info(target);
2237
                        i += 1;
2238
                        continue;
2239
                }
2240

    
2241

    
2242
                if (!parse_ports(argv[i]))
2243
                        fprintf(stderr, "invalid argument: %s\n", argv[i]);
2244
        }
2245

    
2246
        /* xseg_leave(); */
2247
        return ret;
2248
}