Bump version to 0.3.5next
[archipelago] / xseg / peers / user / mapper-version0.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-version0.h>
37
38 /* version 0 functions */
39 #define v0_chunked_read_size (512*1024)
40
41 int read_object_v0(struct map_node *mn, unsigned char *buf)
42 {
43         hexlify(buf, SHA256_DIGEST_SIZE, mn->object);
44         mn->object[HEXLIFIED_SHA256_DIGEST_SIZE] = 0;
45         mn->objectlen = HEXLIFIED_SHA256_DIGEST_SIZE;
46         mn->flags = 0; //MF_OBJECT_WRITABLE;
47
48         return 0;
49 }
50
51 void object_to_map_v0(unsigned char *data, struct map_node *mn)
52 {
53         unhexlify(mn->object, data);
54         //if name == zero block, raize MF_OBJECT_ZERO
55 }
56
57 struct xseg_request * prepare_write_object_v0(struct peer_req *pr, struct map *map,
58                         struct map_node *mn)
59 {
60         struct peerd *peer = pr->peer;
61         struct mapperd *mapper = __get_mapperd(peer);
62         struct xseg_request *req;
63         char *data;
64         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
65                         v0_objectsize_in_map);
66         if (!req){
67                 XSEGLOG2(&lc, E, "Cannot get request for map %s",
68                                 map->volume);
69                 return NULL;
70         }
71
72         req->op = X_WRITE;
73         req->size = v0_objectsize_in_map;
74         req->offset = v0_mapheader_size + mn->objectidx * v0_objectsize_in_map;
75
76         data = xseg_get_data(pr->peer->xseg, req);
77         object_to_map_v0((unsigned char *)data, mn);
78         return req;
79 }
80
81 int read_map_v0(struct map *m, unsigned char * data)
82 {
83         int r;
84         struct map_node *map_node;
85         uint64_t i;
86         uint64_t pos = 0, limit;
87         uint64_t max_read_obj = v0_chunked_read_size / v0_objectsize_in_map;
88         char nulls[SHA256_DIGEST_SIZE];
89         memset(nulls, 0, SHA256_DIGEST_SIZE);
90
91         r = !memcmp(data, nulls, SHA256_DIGEST_SIZE);
92         if (r) {
93                 XSEGLOG2(&lc, E, "Read zeros");
94                 return -1;
95         }
96
97
98         map_node = realloc(m->objects,
99                         (m->nr_objs + max_read_obj) * sizeof(struct map_node));
100         if (!map_node)
101                 return -1;
102         m->objects = map_node;
103         limit = m->nr_objs + max_read_obj;
104         for (i = m->nr_objs; i < limit; i++) {
105                 if (!memcmp(data+pos, nulls, v0_objectsize_in_map))
106                         break;
107                 map_node[i].objectidx = i;
108                 map_node[i].map = m;
109                 map_node[i].waiters = 0;
110                 map_node[i].state = 0;
111                 map_node[i].ref = 1;
112                 map_node[i].cond = st_cond_new(); //FIXME err check;
113                 read_object_v0(&map_node[i], data+pos);
114                 pos += v0_objectsize_in_map;
115         }
116         XSEGLOG2(&lc, D, "Found %llu objects", i);
117         m->size = i * MAPPER_DEFAULT_BLOCKSIZE;
118         m->nr_objs = i;
119         return (limit - m->nr_objs);
120 }
121
122
123 struct xseg_request * __write_map_data_v0(struct peer_req *pr, struct map *map)
124 {
125         int r;
126         struct peerd *peer = pr->peer;
127         struct mapperd *mapper = __get_mapperd(peer);
128         struct xseg_request *req;
129         char *data;
130         uint64_t datalen, pos, i;
131         struct map_node *mn;
132
133         datalen = v0_mapheader_size + map->nr_objs * v0_objectsize_in_map;
134         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
135                         datalen);
136         if (!req){
137                 XSEGLOG2(&lc, E, "Cannot get request for map %s",
138                                 map->volume);
139                 goto out_err;
140         }
141
142
143         data = xseg_get_data(peer->xseg, req);
144
145         req->op = X_WRITE;
146         req->size = datalen;
147         req->offset = 0;
148
149         pos = 0;
150         for (i = 0; i < map->nr_objs; i++) {
151                 mn = &map->objects[i];
152                 object_to_map_v0((unsigned char *)(data+pos), mn);
153                 pos += v0_objectsize_in_map;
154         }
155
156         r = send_request(pr, req);
157         if (r < 0) {
158                 XSEGLOG2(&lc, E, "Cannot send request %p, pr: %p, map: %s",
159                                 req, pr, map->volume);
160                 goto out_put;
161         }
162
163         return req;
164
165 out_put:
166         put_request(pr, req);
167 out_err:
168         XSEGLOG2(&lc, E, "Map write for map %s failed.", map->volume);
169         return NULL;
170 }
171
172 int write_map_data_v0(struct peer_req *pr, struct map *map)
173 {
174         int r = 0;
175         struct xseg_request *req = __write_map_data_v0(pr, map);
176         if (!req)
177                 return -1;
178         wait_on_pr(pr, (!(req->state & XS_FAILED || req->state & XS_SERVED)));
179         if (req->state & XS_FAILED)
180                 r = -1;
181         put_request(pr, req);
182         return r;
183 }
184
185
186 int write_map_metadata_v0(struct peer_req *pr, struct map *map)
187 {
188         /* No metadata */
189         return 0;
190 }
191
192 struct xseg_request * __load_map_data_v0(struct peer_req *pr, struct map *map)
193 {
194         int r;
195         struct xseg_request *req;
196         struct peerd *peer = pr->peer;
197         struct mapperd *mapper = __get_mapperd(peer);
198         uint64_t datalen;
199
200         if (v0_chunked_read_size % v0_objectsize_in_map) {
201                 XSEGLOG2(&lc, E, "v0_chunked_read_size should be a multiple of",
202                                 "v0_objectsize_in_map");
203                 return NULL;
204         }
205
206         datalen = v0_chunked_read_size;
207
208         req = get_request(pr, mapper->mbportno, map->volume, map->volumelen,
209                         datalen);
210         if (!req){
211                 XSEGLOG2(&lc, E, "Cannot get request for map %s", map->volume);
212                 goto out_fail;
213         }
214
215         req->op = X_READ;
216         req->size = datalen;
217         req->offset = v0_mapheader_size + map->nr_objs * v0_objectsize_in_map;
218
219         r = send_request(pr, req);
220         if (r < 0) {
221                 XSEGLOG2(&lc, E, "Cannot send request %p, pr: %p, map: %s",
222                                 req, pr, map->volume);
223                 goto out_put;
224         }
225         return req;
226
227 out_put:
228         put_request(pr, req);
229 out_fail:
230         return NULL;
231 }
232
233 int load_map_data_v0(struct peer_req *pr, struct map *map)
234 {
235         int r = 0;
236         struct xseg_request *req;
237         struct peerd *peer = pr->peer;
238         char *data;
239
240 retry:
241         req = __load_map_data_v0(pr, map);
242         if (!req)
243                 return -1;
244         wait_on_pr(pr, (!(req->state & XS_FAILED || req->state & XS_SERVED)));
245
246         if (req->state & XS_FAILED){
247                 XSEGLOG2(&lc, E, "Map load failed for map %s", map->volume);
248                 put_request(pr, req);
249                 return -1;
250         }
251         //assert req->service == req->size
252         data = xseg_get_data(peer->xseg, req);
253         r = read_map_v0(map, (unsigned char *)data);
254         put_request(pr, req);
255         if (!r)
256                 goto retry;
257         return 0;
258 }
259
260 int read_map_metadata_v0(struct map *map, unsigned char *metadata,
261                 uint32_t metadata_len)
262 {
263         /* No header. Just set defaults */
264         map->version = 0;
265         map->size = 0;
266         map->blocksize = MAPPER_DEFAULT_BLOCKSIZE;
267         map->nr_objs = 0;
268         map->flags = MF_MAP_READONLY;
269         map->epoch = 0;
270         map->objects = NULL;
271
272         return 0;
273 }