Strip xseg stuff
[archipelago] / xseg / mapper-version1.c
1 /*
2  * Copyright 2013 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 #include <xseg/xseg.h>
36 #include <mapper-version1.h>
37
38 /* v1 functions */
39
40 int read_object_v1(struct map_node *mn, unsigned char *buf)
41 {
42         char c = buf[0];
43         mn->flags = 0;
44         if (c){
45                 mn->flags |= MF_OBJECT_WRITABLE;
46                 mn->flags |= MF_OBJECT_ARCHIP;
47                 strcpy(mn->object, MAPPER_PREFIX);
48                 hexlify(buf+1, SHA256_DIGEST_SIZE, mn->object + MAPPER_PREFIX_LEN);
49                 mn->object[MAX_OBJECT_LEN] = 0;
50                 mn->objectlen = strlen(mn->object);
51         }
52         else {
53                 mn->flags &= ~MF_OBJECT_WRITABLE;
54                 mn->flags &= ~MF_OBJECT_ARCHIP;
55                 hexlify(buf+1, SHA256_DIGEST_SIZE, mn->object);
56                 mn->object[HEXLIFIED_SHA256_DIGEST_SIZE] = 0;
57                 mn->objectlen = strlen(mn->object);
58         }
59         return 0;
60 }
61
62 void object_to_map_v1(unsigned char* buf, struct map_node *mn)
63 {
64         buf[0] = (mn->flags & MF_OBJECT_WRITABLE)? 1 : 0;
65         //assert !(mn->flags & MF_OBJECT_ARCHIP)
66         if (buf[0]){
67                 /* strip common prefix */
68                 unhexlify(mn->object+MAPPER_PREFIX_LEN, (unsigned char *)(buf+1));
69         }
70         else {
71                 unhexlify(mn->object, (unsigned char *)(buf+1));
72         }
73         //if name == zero block, raize MF_OBJECT_ZERO
74 }
75
76 struct xseg_request * prepare_write_object_v1(struct peer_req *pr, struct map *map,
77                                 struct map_node *mn)
78 {
79         struct peerd *peer = pr->peer;
80         struct mapperd *mapper = __get_mapperd(peer);
81         struct xseg_request *req;
82         char *data;
83
84         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
85                         v1_objectsize_in_map);
86         if (!req){
87                 XSEGLOG2(&lc, E, "Cannot get request for map %s",
88                                 map->volume);
89                 return NULL;
90         }
91
92         req->op = X_WRITE;
93         req->size = v1_objectsize_in_map;
94         req->offset = v1_mapheader_size + mn->objectidx * v1_objectsize_in_map;
95
96         data = xseg_get_data(pr->peer->xseg, req);
97         object_to_map_v1((unsigned char *)data, mn);
98         return NULL;
99 }
100
101 int read_map_v1(struct map *m, unsigned char *data)
102 {
103         int r;
104         struct map_node *map_node;
105         uint64_t i;
106         uint64_t pos = 0;
107         uint64_t nr_objs = m->nr_objs;
108         char nulls[SHA256_DIGEST_SIZE];
109         memset(nulls, 0, SHA256_DIGEST_SIZE);
110
111         r = !memcmp(data, nulls, SHA256_DIGEST_SIZE);
112         if (r) {
113                 XSEGLOG2(&lc, E, "Read zeros");
114                 return -1;
115         }
116
117         map_node = calloc(nr_objs, sizeof(struct map_node));
118         if (!map_node)
119                 return -1;
120         m->objects = map_node;
121
122         for (i = 0; i < nr_objs; i++) {
123                 map_node[i].map = m;
124                 map_node[i].objectidx = i;
125                 map_node[i].waiters = 0;
126                 map_node[i].ref = 1;
127                 map_node[i].state = 0;
128                 map_node[i].cond = st_cond_new(); //FIXME err check;
129                 read_object_v1(&map_node[i], data+pos);
130                 pos += v1_objectsize_in_map;
131         }
132         return 0;
133 }
134
135 struct xseg_request * __write_map_data_v1(struct peer_req *pr, struct map *map)
136 {
137         int r;
138         struct peerd *peer = pr->peer;
139         struct mapperd *mapper = __get_mapperd(peer);
140         struct xseg_request *req;
141         char *data;
142         uint64_t i, pos;
143         struct map_node *mn;
144
145         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
146                                 map->nr_objs * v1_objectsize_in_map);
147         if (!req){
148                 XSEGLOG2(&lc, E, "Cannot get request for map %s",
149                                 map->volume);
150                 goto out_err;
151         }
152
153
154         data = xseg_get_data(peer->xseg, req);
155
156         req->op = X_WRITE;
157         req->size = req->datalen;
158         req->offset = v1_mapheader_size;
159
160         pos = 0;
161         for (i = 0; i < map->nr_objs; i++) {
162                 mn = &map->objects[i];
163                 object_to_map_v1((unsigned char *)(data+pos), mn);
164                 pos += v1_objectsize_in_map;
165         }
166
167         r = send_request(pr, req);
168         if (r < 0) {
169                 XSEGLOG2(&lc, E, "Cannot send request %p, pr: %p, map: %s",
170                                 req, pr, map->volume);
171                 goto out_put;
172         }
173
174         return req;
175
176 out_put:
177         put_request(pr, req);
178 out_err:
179         XSEGLOG2(&lc, E, "Map write for map %s failed.", map->volume);
180         return NULL;
181 }
182
183 int write_map_data_v1(struct peer_req *pr, struct map *map)
184 {
185         int r = 0;
186         struct xseg_request *req = __write_map_data_v1(pr, map);
187         if (!req)
188                 return -1;
189         wait_on_pr(pr, (!(req->state & XS_FAILED || req->state & XS_SERVED)));
190         if (req->state & XS_FAILED)
191                 r = -1;
192         put_request(pr, req);
193         return r;
194 }
195
196 struct xseg_request * __write_map_metadata_v1(struct peer_req *pr, struct map *map)
197 {
198         int r;
199         struct peerd *peer = pr->peer;
200         struct mapperd *mapper = __get_mapperd(peer);
201         struct xseg_request *req;
202         char *data;
203         uint64_t pos;
204
205         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
206                         v1_mapheader_size);
207         if (!req){
208                 XSEGLOG2(&lc, E, "Cannot get request for map %s",
209                                 map->volume);
210                 goto out_err;
211         }
212
213
214         data = xseg_get_data(peer->xseg, req);
215
216         pos = 0;
217         memcpy(data + pos, &map->version, sizeof(map->version));
218         pos += sizeof(map->version);
219         memcpy(data + pos, &map->size, sizeof(map->size));
220         pos += sizeof(map->size);
221
222         req->op = X_WRITE;
223         req->size = req->datalen;
224         req->offset = 0;
225
226         r = send_request(pr, req);
227         if (r < 0) {
228                 XSEGLOG2(&lc, E, "Cannot send request %p, pr: %p, map: %s",
229                                 req, pr, map->volume);
230                 goto out_put;
231         }
232
233         return req;
234
235 out_put:
236         put_request(pr, req);
237 out_err:
238         XSEGLOG2(&lc, E, "Map write for map %s failed.", map->volume);
239         return NULL;
240 }
241 int write_map_metadata_v1(struct peer_req *pr, struct map *map)
242 {
243         int r = 0;
244         struct xseg_request *req = __write_map_metadata_v1(pr, map);
245         if (!req)
246                 return -1;
247         wait_on_pr(pr, (!(req->state & XS_FAILED || req->state & XS_SERVED)));
248         if (req->state & XS_FAILED)
249                 r = -1;
250         put_request(pr, req);
251         return r;
252 }
253
254 struct xseg_request * __load_map_data_v1(struct peer_req *pr, struct map *map)
255 {
256         int r;
257         struct xseg_request *req;
258         struct peerd *peer = pr->peer;
259         struct mapperd *mapper = __get_mapperd(peer);
260         uint64_t datalen;
261
262
263         datalen = calc_map_obj(map) * v1_objectsize_in_map;
264         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
265                         datalen);
266         if (!req){
267                 XSEGLOG2(&lc, E, "Cannot get request for map %s", map->volume);
268                 goto out_fail;
269         }
270
271         req->op = X_READ;
272         req->size = datalen;
273         req->offset = v1_mapheader_size;
274
275         r = send_request(pr, req);
276         if (r < 0) {
277                 XSEGLOG2(&lc, E, "Cannot send request %p, pr: %p, map: %s",
278                                 req, pr, map->volume);
279                 goto out_put;
280         }
281         return req;
282
283 out_put:
284         put_request(pr, req);
285 out_fail:
286         return NULL;
287 }
288
289 int load_map_data_v1(struct peer_req *pr, struct map *map)
290 {
291         int r = 0;
292         struct xseg_request *req;
293         struct peerd *peer = pr->peer;
294         char *data;
295
296         req = __load_map_data_v1(pr, map);
297         if (!req)
298                 return -1;
299         wait_on_pr(pr, (!(req->state & XS_FAILED || req->state & XS_SERVED)));
300
301         if (req->state & XS_FAILED){
302                 XSEGLOG2(&lc, E, "Map load failed for map %s", map->volume);
303                 put_request(pr, req);
304                 return -1;
305         }
306         //assert req->service == req->size
307         data = xseg_get_data(peer->xseg, req);
308         r = read_map_v1(map, (unsigned char *)data);
309         put_request(pr, req);
310         return r;
311 }
312
313 int read_map_metadata_v1(struct map *map, unsigned char *metadata,
314                 uint32_t metadata_len)
315 {
316         uint64_t pos;
317         if (metadata_len < v1_mapheader_size) {
318                 XSEGLOG2(&lc, E, "Metadata len < v1_mapheader_size");
319                 return -1;
320         }
321         /* read header */
322         pos = 0;
323         map->version = *(uint32_t *)(metadata + pos);
324         pos += sizeof(uint32_t);
325         map->size = *(uint64_t *)(metadata + pos);
326         pos += sizeof(uint64_t);
327
328         /* set defaults */
329         map->flags = 0;
330         map->epoch = 0;
331         map->objects = NULL;
332         map->blocksize = MAPPER_DEFAULT_BLOCKSIZE;
333         map->nr_objs = calc_map_obj(map);;
334
335         return 0;
336 }
337