liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
libphazr.c
Go to the documentation of this file.
1/*
2 * Copyright 2016 Phazr.IO Inc
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY
13 * THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
20 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
21 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * Phazr.IO libphazr backend
25 *
26 * vi: set noai tw=79 ts=4 sw=4:
27 */
28
29#include <stdio.h>
30#include <stdlib.h>
31
32#include "erasurecode.h"
33#include "erasurecode_backend.h"
34#include "erasurecode_helpers.h"
35
36#define LIBPHAZR_LIB_MAJOR 1
37#define LIBPHAZR_LIB_MINOR 0
38#define LIBPHAZR_LIB_REV 0
39#define LIBPHAZR_LIB_VER_STR "1.0.0"
40#define LIBPHAZR_LIB_NAME "libphazr"
41#if defined(__MACOS__) || defined(__MACOSX__) || defined(__OSX__) || defined(__APPLE__)
42#define LIBPHAZR_SO_NAME "libphazr" LIBERASURECODE_SO_SUFFIX ".dylib"
43#else
44#define LIBPHAZR_SO_NAME "libphazr" LIBERASURECODE_SO_SUFFIX ".so.1"
45#endif
46
47/* Forward declarations */
48struct ec_backend_common backend_libphazr;
49
50typedef int (*pio_matrix_encode_func)(char *, char *, char **, int, int, int, int, int, int);
51typedef int (*pio_matrix_decode_func)(char *, char *, char **, int *, int, int, int, int, int, int);
52typedef int (*pio_matrix_reconstruct_func)(char *, char **, int *, int, int, int, int, int, int);
53typedef char* (*pio_create_precoding_matrix_func)(int);
54typedef char* (*pio_create_inverse_precoding_matrix_func)(int);
55typedef char* (*pio_create_kmux_matrix_func)(int, int, int);
56
58 /* calls required for init */
62
63 /* calls required for encode */
65
66 /* calls required for decode */
68
69 /* calls required for reconstruct */
71
72 /* fields needed to hold state */
73 char *matrix;
76 int k;
77 int m;
78 int w;
79 int hd;
80};
81
82#define DEFAULT_W 64
83
84#define DEFAULT_HD 1
85
86static int get_padded_blocksize(int w, int hd, int blocksize)
87{
88 int word_size = w / 8;
89 return ((blocksize + ((word_size - hd) - 1)) / (word_size - hd)) * word_size;
90}
91
92static int pio_matrix_encode(void *desc, char **data, char **parity, int blocksize)
93{
94 int i, ret = 0;
95 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
96 int padding_size = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize) - blocksize;
97 char **encoded = malloc(sizeof(char*) * (xdesc->k + xdesc->m));
98
99 if (NULL == encoded) {
100 ret = -ENOMEM;
101 goto out;
102 }
103
104 for (i = 0; i < xdesc->k; i++) {
105 encoded[i] = data[i];
106 }
107
108 for (i = 0; i < xdesc->m; i++) {
109 encoded[i + xdesc->k] = parity[i];
110 }
111
112 ret = xdesc->matrix_encode(xdesc->precoding_matrix, xdesc->matrix, encoded,
113 xdesc->k, xdesc->m, xdesc->w, xdesc->hd, blocksize, padding_size);
114
115out:
116 free(encoded);
117
118 return ret;
119}
120
121static int pio_matrix_decode(void *desc, char **data, char **parity,
122 int *missing_idxs, int blocksize)
123{
124 int i, ret = 0;
125 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
126 int padding_size = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize) - blocksize;
127 char **decoded = malloc(sizeof(char*) * (xdesc->k + xdesc->m));
128
129 if (NULL == decoded) {
130 ret = -ENOMEM;
131 goto out;
132 }
133
134 for (i = 0; i < xdesc->k; i++) {
135 decoded[i] = data[i];
136 }
137
138 for (i = 0; i < xdesc->m; i++) {
139 decoded[i + xdesc->k] = parity[i];
140 }
141
142 ret = xdesc->matrix_decode(xdesc->inverse_precoding_matrix, xdesc->matrix, decoded,
143 missing_idxs, xdesc->k, xdesc->m, xdesc->w, xdesc->hd, blocksize, padding_size);
144
145out:
146 free(decoded);
147
148 return ret;
149}
150
151static int pio_matrix_reconstruct(void *desc, char **data, char **parity,
152 int *missing_idxs, int destination_idx, int blocksize)
153{
154 int i, ret = 0;
155 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
156 int padding_size = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize) - blocksize;
157 char **encoded = malloc(sizeof(char*) * (xdesc->k + xdesc->m));
158
159 if (NULL == encoded) {
160 ret = -ENOMEM;
161 goto out;
162 }
163
164 for (i = 0; i < xdesc->k; i++) {
165 encoded[i] = data[i];
166 }
167
168 for (i = 0; i < xdesc->m; i++) {
169 encoded[i + xdesc->k] = parity[i];
170 }
171
172 ret = xdesc->matrix_reconstruct(xdesc->matrix, encoded, missing_idxs,
173 destination_idx, xdesc->k, xdesc->m, xdesc->w, blocksize, padding_size);
174
175out:
176 free(encoded);
177
178 return ret;
179}
180
181static int pio_min_fragments(void *desc, int *missing_idxs,
182 int *fragments_to_exclude, int *fragments_needed)
183{
184 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *)desc;
185 struct ec_bm missing_bm = NEW_BM;
186 convert_list_to_bitmap(fragments_to_exclude, &missing_bm);
187 convert_list_to_bitmap(missing_idxs, &missing_bm);
188 int i;
189 int j = 0;
190 int ret = -1;
191
192 for (i = 0; i < (xdesc->k + xdesc->m); i++) {
193 if (!bm_get_value(&missing_bm, i)) {
194 fragments_needed[j] = i;
195 j++;
196 }
197 if (j == xdesc->k) {
198 ret = 0;
199 fragments_needed[j] = -1;
200 break;
201 }
202 }
203
204 return ret;
205}
206
211static int pio_element_size(void *desc)
212{
213 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *)desc;
214
215 return xdesc->w;
216}
217
218static void * pio_init(struct ec_backend_args *args, void *backend_sohandle)
219{
220 struct libphazr_descriptor *desc = NULL;
221
222 /* allocate and fill in libphazr_descriptor */
223 desc = (struct libphazr_descriptor *)malloc(sizeof(struct libphazr_descriptor));
224 if (NULL == desc) {
225 return NULL;
226 }
227 memset(desc, 0, sizeof(struct libphazr_descriptor));
228
229 desc->k = args->uargs.k;
230 desc->m = args->uargs.m;
231 desc->w = args->uargs.w;
232 desc->hd = args->uargs.hd;
233
234 if (desc->w <= 0)
235 desc->w = DEFAULT_W;
236 args->uargs.w = desc->w;
237
238 if (desc->hd <= 0)
239 desc->hd = DEFAULT_HD;
240 args->uargs.hd = desc->hd;
241
242 /*
243 * ISO C forbids casting a void* to a function pointer.
244 * Since dlsym return returns a void*, we use this union to
245 * "transform" the void* to a function pointer.
246 */
247 union {
248 pio_create_precoding_matrix_func create_precoding_matrix_ptr;
249 pio_create_inverse_precoding_matrix_func create_inverse_precoding_matrix_ptr;
250 pio_create_kmux_matrix_func create_kmux_matrix_ptr;
251 pio_matrix_encode_func matrix_encode_ptr;
252 pio_matrix_decode_func matrix_decode_ptr;
253 pio_matrix_reconstruct_func matrix_reconstruct_ptr;
254 void *vptr;
255 } func_handle = {.vptr = NULL};
256
257 /* fill in function addresses */
258 func_handle.vptr = NULL;
259 func_handle.vptr = dlsym(backend_sohandle, "create_precoding_matrix");
260 desc->create_precoding_matrix = func_handle.create_precoding_matrix_ptr;
261 if (NULL == desc->create_precoding_matrix) {
262 goto error;
263 }
264
265 func_handle.vptr = NULL;
266 func_handle.vptr = dlsym(backend_sohandle, "create_inverse_precoding_matrix");
267 desc->create_inverse_precoding_matrix = func_handle.create_inverse_precoding_matrix_ptr;
268 if (NULL == desc->create_inverse_precoding_matrix) {
269 goto error;
270 }
271
272 func_handle.vptr = NULL;
273 func_handle.vptr = dlsym(backend_sohandle, "create_kmux_matrix");
274 desc->create_kmux_matrix = func_handle.create_kmux_matrix_ptr;
275 if (NULL == desc->create_kmux_matrix) {
276 goto error;
277 }
278
279 func_handle.vptr = NULL;
280 func_handle.vptr = dlsym(backend_sohandle, "matrix_encode");
281 desc->matrix_encode = func_handle.matrix_encode_ptr;
282 if (NULL == desc->matrix_encode) {
283 goto error;
284 }
285
286 func_handle.vptr = NULL;
287 func_handle.vptr = dlsym(backend_sohandle, "matrix_decode");
288 desc->matrix_decode = func_handle.matrix_decode_ptr;
289 if (NULL == desc->matrix_decode) {
290 goto error;
291 }
292
293 func_handle.vptr = NULL;
294 func_handle.vptr = dlsym(backend_sohandle, "matrix_reconstruct");
295 desc->matrix_reconstruct = func_handle.matrix_reconstruct_ptr;
296 if (NULL == desc->matrix_reconstruct) {
297 goto error;
298 }
299
300 if (NULL == desc->precoding_matrix) {
301 desc->precoding_matrix = desc->create_precoding_matrix(desc->k);
302 if (NULL == desc->precoding_matrix) {
303 goto error;
304 }
305 }
306
307 if (NULL == desc->inverse_precoding_matrix) {
309 if (NULL == desc->inverse_precoding_matrix) {
310 goto error;
311 }
312 }
313
314 if (NULL == desc->matrix) {
315 desc->matrix = desc->create_kmux_matrix(desc->k, desc->m, desc->w);
316 if (NULL == desc->create_kmux_matrix) {
317 goto error;
318 }
319 }
320
321 return (void *) desc;
322
323error:
324 free(desc->matrix);
325
326 free(desc->precoding_matrix);
327
328 free(desc->inverse_precoding_matrix);
329
330 free(desc);
331
332 return NULL;
333}
334
335static int pio_exit(void *desc)
336{
337 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor*)desc;
338
339 free(xdesc->matrix);
340
341 free(xdesc->precoding_matrix);
342
343 free(xdesc->inverse_precoding_matrix);
344
345 free(xdesc);
346
347 return 0;
348}
349
350static bool pio_is_compatible_with(uint32_t version)
351{
352 return version == backend_libphazr.ec_backend_version;
353}
354
355static size_t pio_get_backend_metadata_size(void *desc, int blocksize)
356{
357 struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
358 int padded_blocksize = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize);
359 return padded_blocksize - blocksize;
360}
361
362static size_t pio_get_encode_offset(void *desc, int metadata_size)
363{
364 return metadata_size;
365}
366
367
368static struct ec_backend_op_stubs libphazr_op_stubs = {
369 .INIT = pio_init,
370 .EXIT = pio_exit,
371 .ISSYSTEMATIC = 0,
372 .ENCODE = pio_matrix_encode,
373 .DECODE = pio_matrix_decode,
374 .FRAGSNEEDED = pio_min_fragments,
375 .RECONSTRUCT = pio_matrix_reconstruct,
376 .ELEMENTSIZE = pio_element_size,
377 .ISCOMPATIBLEWITH = pio_is_compatible_with,
378 .GETMETADATASIZE = pio_get_backend_metadata_size,
379 .GETENCODEOFFSET = pio_get_encode_offset,
380};
381
382__attribute__ ((visibility ("internal")))
383struct ec_backend_common backend_libphazr = {
384 .id = EC_BACKEND_LIBPHAZR,
385 .name = LIBPHAZR_LIB_NAME,
386 .soname = LIBPHAZR_SO_NAME,
387 .soversion = LIBPHAZR_LIB_VER_STR,
388 .ops = &libphazr_op_stubs,
389 .ec_backend_version = _VERSION(LIBPHAZR_LIB_MAJOR, LIBPHAZR_LIB_MINOR,
391};
392
static void * pio_init(struct ec_backend_args *args, void *backend_sohandle)
Definition: libphazr.c:218
static int pio_matrix_decode(void *desc, char **data, char **parity, int *missing_idxs, int blocksize)
Definition: libphazr.c:121
#define LIBPHAZR_LIB_VER_STR
Definition: libphazr.c:39
static int pio_matrix_reconstruct(void *desc, char **data, char **parity, int *missing_idxs, int destination_idx, int blocksize)
Definition: libphazr.c:151
static int pio_element_size(void *desc)
Return the element-size, which is the number of bits stored on a given device, per codeword.
Definition: libphazr.c:211
char *(* pio_create_inverse_precoding_matrix_func)(int)
Definition: libphazr.c:54
static int pio_matrix_encode(void *desc, char **data, char **parity, int blocksize)
Definition: libphazr.c:92
#define LIBPHAZR_SO_NAME
Definition: libphazr.c:44
static int pio_min_fragments(void *desc, int *missing_idxs, int *fragments_to_exclude, int *fragments_needed)
Definition: libphazr.c:181
static bool pio_is_compatible_with(uint32_t version)
Definition: libphazr.c:350
#define LIBPHAZR_LIB_REV
Definition: libphazr.c:38
#define DEFAULT_HD
Definition: libphazr.c:84
int(* pio_matrix_decode_func)(char *, char *, char **, int *, int, int, int, int, int, int)
Definition: libphazr.c:51
static size_t pio_get_backend_metadata_size(void *desc, int blocksize)
Definition: libphazr.c:355
int(* pio_matrix_encode_func)(char *, char *, char **, int, int, int, int, int, int)
Definition: libphazr.c:50
char *(* pio_create_kmux_matrix_func)(int, int, int)
Definition: libphazr.c:55
#define LIBPHAZR_LIB_NAME
Definition: libphazr.c:40
static int get_padded_blocksize(int w, int hd, int blocksize)
Definition: libphazr.c:86
struct ec_backend_common backend_libphazr
Definition: libphazr.c:48
static size_t pio_get_encode_offset(void *desc, int metadata_size)
Definition: libphazr.c:362
#define LIBPHAZR_LIB_MINOR
Definition: libphazr.c:37
char *(* pio_create_precoding_matrix_func)(int)
Definition: libphazr.c:53
int(* pio_matrix_reconstruct_func)(char *, char **, int *, int, int, int, int, int, int)
Definition: libphazr.c:52
__attribute__((visibility("internal")))
Definition: libphazr.c:382
static int pio_exit(void *desc)
Definition: libphazr.c:335
#define LIBPHAZR_LIB_MAJOR
Definition: libphazr.c:36
static struct ec_backend_op_stubs libphazr_op_stubs
Definition: libphazr.c:368
#define DEFAULT_W
Definition: libphazr.c:82
pio_matrix_decode_func matrix_decode
Definition: libphazr.c:67
pio_create_kmux_matrix_func create_kmux_matrix
Definition: libphazr.c:61
pio_create_inverse_precoding_matrix_func create_inverse_precoding_matrix
Definition: libphazr.c:60
char * inverse_precoding_matrix
Definition: libphazr.c:75
pio_matrix_reconstruct_func matrix_reconstruct
Definition: libphazr.c:70
pio_create_precoding_matrix_func create_precoding_matrix
Definition: libphazr.c:59
pio_matrix_encode_func matrix_encode
Definition: libphazr.c:64
char * precoding_matrix
Definition: libphazr.c:74