Fix LFSR behavior
[archipelago] / xseg / peers / user / bench-utils.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 <unistd.h>
39 #include <sys/syscall.h>
40 #include <sys/types.h>
41 #include <pthread.h>
42 #include <xseg/xseg.h>
43 #include <peer.h>
44 #include <time.h>
45 #include <sys/util.h>
46 #include <signal.h>
47 #include <bench-xseg.h>
48
49 struct timespec delay = {0, 4000000};
50
51 /*
52  * Convert string to size in bytes.
53  * If syntax is invalid, return 0. Values such as zero and non-integer
54  * multiples of segment's page size should not be accepted.
55  */
56 uint64_t str2num(char *str)
57 {
58         char *unit;
59         uint64_t num;
60
61         num = strtoll(str, &unit, 10);
62         if (strlen(unit) > 1) //Invalid syntax
63                 return 0;
64         else if (strlen(unit) < 1) //Plain number in bytes
65                 return num;
66
67         switch (*unit) {
68                 case 'g':
69                 case 'G':
70                         num *= 1024;
71                 case 'm':
72                 case 'M':
73                         num *= 1024;
74                 case 'k':
75                 case 'K':
76                         num *= 1024;
77                         break;
78                 default:
79                         num = 0;
80         }
81         return num;
82 }
83
84 int read_insanity(char *insanity)
85 {
86         if (strcmp(insanity, "sane") == 0)
87                 return TM_SANE;
88         if (strcmp(insanity, "eccentric") == 0)
89                 return TM_ECCENTRIC;
90         if (strcmp(insanity, "manic") == 0)
91                 return TM_MANIC;
92         if (strcmp(insanity, "paranoid") == 0)
93                 return TM_PARANOID;
94         return -1;
95 }
96
97 int read_op(char *op)
98 {
99         if (strcmp(op, "read") == 0)
100                 return X_READ;
101         if (strcmp(op, "write") == 0)
102                 return X_WRITE;
103         if (strcmp(op, "info") == 0)
104                 return X_INFO;
105         if (strcmp(op, "delete") == 0)
106                 return X_DELETE;
107         return -1;
108 }
109
110 int read_pattern(char *pattern)
111 {
112         if (strcmp(pattern, "seq") == 0)
113                 return IO_SEQ;
114         if (strcmp(pattern, "rand") == 0)
115                 return IO_RAND;
116         return -1;
117 }
118
119 void print_res(struct tm_result res, char *type)
120 {
121         printf("\n");
122         printf("      %s\n", type);
123         printf("================================\n");
124         printf("       |-s-||-ms-|-us-|-ns-|\n");
125         printf("Time:   %03lu. %03lu  %03lu  %03lu\n",
126                         res.s, res.ms, res.us, res.ns);
127 }
128
129 /*
130  * Seperates a timespec struct in seconds, msec, usec, nsec
131  */
132 void separate_by_order(struct timespec src, struct tm_result *res)
133 {
134         res->ns = src.tv_nsec % 1000;
135         src.tv_nsec /= 1000;
136         res->us = src.tv_nsec % 1000;
137         res->ms = src.tv_nsec / 1000;
138         res->s = src.tv_sec;
139 }
140
141 void create_target(struct bench *prefs, struct xseg_request *req,
142                 uint64_t new)
143 {
144         struct xseg *xseg = prefs->peer->xseg;
145         char *req_target;
146
147         req_target = xseg_get_target(xseg, req);
148
149         //For read/write, the target object does not correspond to `new`, which is
150         //actually the chunk number. We need to div this number with the number of
151         //chunks in an object.
152         //FIXME: Make it more elegant
153         if (prefs->op == X_READ || prefs->op == X_WRITE)
154                 new = new / (prefs->os / prefs->bs);
155         snprintf(req_target, TARGETLEN, "%s-%016lu", global_id, new);
156         XSEGLOG2(&lc, D, "Target name of request is %s\n", req_target);
157 }
158
159 void create_chunk(struct bench *prefs, struct xseg_request *req, uint64_t new)
160 {/*
161         struct xseg *xseg = prefs->peer->xseg;
162         char *req_data;
163
164         //TODO: Fill data depening on validation level
165         req_data = xseg_get_data(xseg, req);
166         */
167 }
168
169 uint64_t determine_next(struct bench *prefs)
170 {
171         if ((prefs->flags & (1 << PATTERN_FLAG)) == IO_SEQ)
172                 return prefs->sub_tm->completed;
173         else {
174                 return lfsr_next(prefs->lfsr);
175         }
176 }
177
178 //FIXME: this looks like a hack, handle it more elegantly
179 void create_id()
180 {
181         struct timespec seed;
182
183         clock_gettime(CLOCK_MONOTONIC_RAW, &seed);
184
185         global_seed = seed.tv_nsec;
186         //nanoseconds can't be more than 9 digits
187         snprintf(global_id, IDLEN, "bench-%09lu", global_seed);
188         XSEGLOG2(&lc, I, "Global ID is %s\n", global_id);
189 }