liberasurecode  1.6.2
Erasure Code API library
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.dylib"
43 #else
44 #define LIBPHAZR_SO_NAME "libphazr.so.1"
45 #endif
46 
47 /* Forward declarations */
48 struct ec_backend libphazr;
49 struct ec_backend_op_stubs libphazr_ops;
50 struct ec_backend_common backend_libphazr;
51 
52 typedef int (*pio_matrix_encode_func)(char *, char *, char **, int, int, int, int, int, int);
53 typedef int (*pio_matrix_decode_func)(char *, char *, char **, int *, int, int, int, int, int, int);
54 typedef int (*pio_matrix_reconstruct_func)(char *, char **, int *, int, int, int, int, int, int);
55 typedef char* (*pio_create_precoding_matrix_func)(int);
56 typedef char* (*pio_create_inverse_precoding_matrix_func)(int);
57 typedef char* (*pio_create_kmux_matrix_func)(int, int, int);
58 
60  /* calls required for init */
64 
65  /* calls required for encode */
67 
68  /* calls required for decode */
70 
71  /* calls required for reconstruct */
73 
74  /* fields needed to hold state */
75  char *matrix;
78  int k;
79  int m;
80  int w;
81  int hd;
82 };
83 
84 #define DEFAULT_W 64
85 
86 #define DEFAULT_HD 1
87 
88 static int get_padded_blocksize(int w, int hd, int blocksize)
89 {
90  int word_size = w / 8;
91  return ((blocksize + ((word_size - hd) - 1)) / (word_size - hd)) * word_size;
92 }
93 
94 static int pio_matrix_encode(void *desc, char **data, char **parity, int blocksize)
95 {
96  int i, ret = 0;
97  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
98  int padding_size = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize) - blocksize;
99  char **encoded = malloc(sizeof(char*) * (xdesc->k + xdesc->m));
100 
101  if (NULL == encoded) {
102  ret = -ENOMEM;
103  goto out;
104  }
105 
106  for (i = 0; i < xdesc->k; i++) {
107  encoded[i] = data[i];
108  }
109 
110  for (i = 0; i < xdesc->m; i++) {
111  encoded[i + xdesc->k] = parity[i];
112  }
113 
114  ret = xdesc->matrix_encode(xdesc->precoding_matrix, xdesc->matrix, encoded,
115  xdesc->k, xdesc->m, xdesc->w, xdesc->hd, blocksize, padding_size);
116 
117 out:
118  free(encoded);
119 
120  return ret;
121 }
122 
123 static int pio_matrix_decode(void *desc, char **data, char **parity,
124  int *missing_idxs, int blocksize)
125 {
126  int i, ret = 0;
127  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
128  int padding_size = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize) - blocksize;
129  char **decoded = malloc(sizeof(char*) * (xdesc->k + xdesc->m));
130 
131  if (NULL == decoded) {
132  ret = -ENOMEM;
133  goto out;
134  }
135 
136  for (i = 0; i < xdesc->k; i++) {
137  decoded[i] = data[i];
138  }
139 
140  for (i = 0; i < xdesc->m; i++) {
141  decoded[i + xdesc->k] = parity[i];
142  }
143 
144  ret = xdesc->matrix_decode(xdesc->inverse_precoding_matrix, xdesc->matrix, decoded,
145  missing_idxs, xdesc->k, xdesc->m, xdesc->w, xdesc->hd, blocksize, padding_size);
146 
147 out:
148  free(decoded);
149 
150  return ret;
151 }
152 
153 static int pio_matrix_reconstruct(void *desc, char **data, char **parity,
154  int *missing_idxs, int destination_idx, int blocksize)
155 {
156  int i, ret = 0;
157  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
158  int padding_size = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize) - blocksize;
159  char **encoded = malloc(sizeof(char*) * (xdesc->k + xdesc->m));
160 
161  if (NULL == encoded) {
162  ret = -ENOMEM;
163  goto out;
164  }
165 
166  for (i = 0; i < xdesc->k; i++) {
167  encoded[i] = data[i];
168  }
169 
170  for (i = 0; i < xdesc->m; i++) {
171  encoded[i + xdesc->k] = parity[i];
172  }
173 
174  ret = xdesc->matrix_reconstruct(xdesc->matrix, encoded, missing_idxs,
175  destination_idx, xdesc->k, xdesc->m, xdesc->w, blocksize, padding_size);
176 
177 out:
178  free(encoded);
179 
180  return ret;
181 }
182 
183 static int pio_min_fragments(void *desc, int *missing_idxs,
184  int *fragments_to_exclude, int *fragments_needed)
185 {
186  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *)desc;
187  uint64_t exclude_bm = convert_list_to_bitmap(fragments_to_exclude);
188  uint64_t missing_bm = convert_list_to_bitmap(missing_idxs) | exclude_bm;
189  int i;
190  int j = 0;
191  int ret = -1;
192 
193  for (i = 0; i < (xdesc->k + xdesc->m); i++) {
194  if (!(missing_bm & (1 << i))) {
195  fragments_needed[j] = i;
196  j++;
197  }
198  if (j == xdesc->k) {
199  ret = 0;
200  fragments_needed[j] = -1;
201  break;
202  }
203  }
204 
205  return ret;
206 }
207 
212 static int pio_element_size(void *desc)
213 {
214  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *)desc;
215 
216  return xdesc->w;
217 }
218 
219 static void * pio_init(struct ec_backend_args *args, void *backend_sohandle)
220 {
221  struct libphazr_descriptor *desc = NULL;
222 
223  /* allocate and fill in libphazr_descriptor */
224  desc = (struct libphazr_descriptor *)malloc(sizeof(struct libphazr_descriptor));
225  if (NULL == desc) {
226  return NULL;
227  }
228  memset(desc, 0, sizeof(struct libphazr_descriptor));
229 
230  desc->k = args->uargs.k;
231  desc->m = args->uargs.m;
232  desc->w = args->uargs.w;
233  desc->hd = args->uargs.hd;
234 
235  if (desc->w <= 0)
236  desc->w = DEFAULT_W;
237  args->uargs.w = desc->w;
238 
239  if (desc->hd <= 0)
240  desc->hd = DEFAULT_HD;
241  args->uargs.hd = desc->hd;
242 
243  /*
244  * ISO C forbids casting a void* to a function pointer.
245  * Since dlsym return returns a void*, we use this union to
246  * "transform" the void* to a function pointer.
247  */
248  union {
249  pio_create_precoding_matrix_func create_precoding_matrix_ptr;
250  pio_create_inverse_precoding_matrix_func create_inverse_precoding_matrix_ptr;
251  pio_create_kmux_matrix_func create_kmux_matrix_ptr;
252  pio_matrix_encode_func matrix_encode_ptr;
253  pio_matrix_decode_func matrix_decode_ptr;
254  pio_matrix_reconstruct_func matrix_reconstruct_ptr;
255  void *vptr;
256  } func_handle = {.vptr = NULL};
257 
258  /* fill in function addresses */
259  func_handle.vptr = NULL;
260  func_handle.vptr = dlsym(backend_sohandle, "create_precoding_matrix");
261  desc->create_precoding_matrix = func_handle.create_precoding_matrix_ptr;
262  if (NULL == desc->create_precoding_matrix) {
263  goto error;
264  }
265 
266  func_handle.vptr = NULL;
267  func_handle.vptr = dlsym(backend_sohandle, "create_inverse_precoding_matrix");
268  desc->create_inverse_precoding_matrix = func_handle.create_inverse_precoding_matrix_ptr;
269  if (NULL == desc->create_inverse_precoding_matrix) {
270  goto error;
271  }
272 
273  func_handle.vptr = NULL;
274  func_handle.vptr = dlsym(backend_sohandle, "create_kmux_matrix");
275  desc->create_kmux_matrix = func_handle.create_kmux_matrix_ptr;
276  if (NULL == desc->create_kmux_matrix) {
277  goto error;
278  }
279 
280  func_handle.vptr = NULL;
281  func_handle.vptr = dlsym(backend_sohandle, "matrix_encode");
282  desc->matrix_encode = func_handle.matrix_encode_ptr;
283  if (NULL == desc->matrix_encode) {
284  goto error;
285  }
286 
287  func_handle.vptr = NULL;
288  func_handle.vptr = dlsym(backend_sohandle, "matrix_decode");
289  desc->matrix_decode = func_handle.matrix_decode_ptr;
290  if (NULL == desc->matrix_decode) {
291  goto error;
292  }
293 
294  func_handle.vptr = NULL;
295  func_handle.vptr = dlsym(backend_sohandle, "matrix_reconstruct");
296  desc->matrix_reconstruct = func_handle.matrix_reconstruct_ptr;
297  if (NULL == desc->matrix_reconstruct) {
298  goto error;
299  }
300 
301  if (NULL == desc->precoding_matrix) {
302  desc->precoding_matrix = desc->create_precoding_matrix(desc->k);
303  if (NULL == desc->precoding_matrix) {
304  goto error;
305  }
306  }
307 
308  if (NULL == desc->inverse_precoding_matrix) {
310  if (NULL == desc->inverse_precoding_matrix) {
311  goto error;
312  }
313  }
314 
315  if (NULL == desc->matrix) {
316  desc->matrix = desc->create_kmux_matrix(desc->k, desc->m, desc->w);
317  if (NULL == desc->create_kmux_matrix) {
318  goto error;
319  }
320  }
321 
322  return (void *) desc;
323 
324 error:
325  free(desc->matrix);
326 
327  free(desc->precoding_matrix);
328 
329  free(desc->inverse_precoding_matrix);
330 
331  free(desc);
332 
333  return NULL;
334 }
335 
336 static int pio_exit(void *desc)
337 {
338  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor*)desc;
339 
340  free(xdesc->matrix);
341 
342  free(xdesc->precoding_matrix);
343 
344  free(xdesc->inverse_precoding_matrix);
345 
346  free(xdesc);
347 
348  return 0;
349 }
350 
351 static bool pio_is_compatible_with(uint32_t version)
352 {
353  return version == backend_libphazr.ec_backend_version;
354 }
355 
356 static size_t pio_get_backend_metadata_size(void *desc, int blocksize)
357 {
358  struct libphazr_descriptor *xdesc = (struct libphazr_descriptor *) desc;
359  int padded_blocksize = get_padded_blocksize(xdesc->w, xdesc->hd, blocksize);
360  return padded_blocksize - blocksize;
361 }
362 
363 static size_t pio_get_encode_offset(void *desc, int metadata_size)
364 {
365  return metadata_size;
366 }
367 
368 
369 struct ec_backend_op_stubs libphazr_op_stubs = {
370  .INIT = pio_init,
371  .EXIT = pio_exit,
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 struct ec_backend_common backend_libphazr = {
383  .id = EC_BACKEND_LIBPHAZR,
384  .name = LIBPHAZR_LIB_NAME,
385  .soname = LIBPHAZR_SO_NAME,
386  .soversion = LIBPHAZR_LIB_VER_STR,
387  .ops = &libphazr_op_stubs,
388  .ec_backend_version = _VERSION(LIBPHAZR_LIB_MAJOR, LIBPHAZR_LIB_MINOR,
390 };
391 
pio_matrix_reconstruct
static int pio_matrix_reconstruct(void *desc, char **data, char **parity, int *missing_idxs, int destination_idx, int blocksize)
Definition: libphazr.c:153
DEFAULT_HD
#define DEFAULT_HD
Definition: libphazr.c:86
pio_matrix_encode_func
int(* pio_matrix_encode_func)(char *, char *, char **, int, int, int, int, int, int)
Definition: libphazr.c:52
pio_matrix_encode
static int pio_matrix_encode(void *desc, char **data, char **parity, int blocksize)
Definition: libphazr.c:94
LIBPHAZR_LIB_MAJOR
#define LIBPHAZR_LIB_MAJOR
Definition: libphazr.c:36
pio_create_kmux_matrix_func
char *(* pio_create_kmux_matrix_func)(int, int, int)
Definition: libphazr.c:57
libphazr
struct ec_backend libphazr
Definition: libphazr.c:48
libphazr_descriptor::k
int k
Definition: libphazr.c:78
LIBPHAZR_LIB_NAME
#define LIBPHAZR_LIB_NAME
Definition: libphazr.c:40
pio_matrix_reconstruct_func
int(* pio_matrix_reconstruct_func)(char *, char **, int *, int, int, int, int, int, int)
Definition: libphazr.c:54
libphazr_descriptor
Definition: libphazr.c:59
libphazr_descriptor::create_kmux_matrix
pio_create_kmux_matrix_func create_kmux_matrix
Definition: libphazr.c:63
LIBPHAZR_LIB_REV
#define LIBPHAZR_LIB_REV
Definition: libphazr.c:38
LIBPHAZR_SO_NAME
#define LIBPHAZR_SO_NAME
Definition: libphazr.c:44
libphazr_descriptor::create_inverse_precoding_matrix
pio_create_inverse_precoding_matrix_func create_inverse_precoding_matrix
Definition: libphazr.c:62
get_padded_blocksize
static int get_padded_blocksize(int w, int hd, int blocksize)
Definition: libphazr.c:88
pio_init
static void * pio_init(struct ec_backend_args *args, void *backend_sohandle)
Definition: libphazr.c:219
pio_element_size
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:212
libphazr_descriptor::matrix_decode
pio_matrix_decode_func matrix_decode
Definition: libphazr.c:69
libphazr_descriptor::inverse_precoding_matrix
char * inverse_precoding_matrix
Definition: libphazr.c:77
LIBPHAZR_LIB_VER_STR
#define LIBPHAZR_LIB_VER_STR
Definition: libphazr.c:39
DEFAULT_W
#define DEFAULT_W
Definition: libphazr.c:84
libphazr_descriptor::hd
int hd
Definition: libphazr.c:81
libphazr_descriptor::m
int m
Definition: libphazr.c:79
libphazr_descriptor::matrix_encode
pio_matrix_encode_func matrix_encode
Definition: libphazr.c:66
pio_is_compatible_with
static bool pio_is_compatible_with(uint32_t version)
Definition: libphazr.c:351
pio_matrix_decode
static int pio_matrix_decode(void *desc, char **data, char **parity, int *missing_idxs, int blocksize)
Definition: libphazr.c:123
pio_matrix_decode_func
int(* pio_matrix_decode_func)(char *, char *, char **, int *, int, int, int, int, int, int)
Definition: libphazr.c:53
backend_libphazr
struct ec_backend_common backend_libphazr
Definition: libphazr.c:50
pio_get_backend_metadata_size
static size_t pio_get_backend_metadata_size(void *desc, int blocksize)
Definition: libphazr.c:356
pio_get_encode_offset
static size_t pio_get_encode_offset(void *desc, int metadata_size)
Definition: libphazr.c:363
libphazr_descriptor::create_precoding_matrix
pio_create_precoding_matrix_func create_precoding_matrix
Definition: libphazr.c:61
libphazr_descriptor::w
int w
Definition: libphazr.c:80
libphazr_ops
struct ec_backend_op_stubs libphazr_ops
Definition: libphazr.c:49
libphazr_descriptor::matrix
char * matrix
Definition: libphazr.c:75
libphazr_descriptor::matrix_reconstruct
pio_matrix_reconstruct_func matrix_reconstruct
Definition: libphazr.c:72
pio_create_inverse_precoding_matrix_func
char *(* pio_create_inverse_precoding_matrix_func)(int)
Definition: libphazr.c:56
libphazr_descriptor::precoding_matrix
char * precoding_matrix
Definition: libphazr.c:76
LIBPHAZR_LIB_MINOR
#define LIBPHAZR_LIB_MINOR
Definition: libphazr.c:37
pio_exit
static int pio_exit(void *desc)
Definition: libphazr.c:336
pio_min_fragments
static int pio_min_fragments(void *desc, int *missing_idxs, int *fragments_to_exclude, int *fragments_needed)
Definition: libphazr.c:183
libphazr_op_stubs
struct ec_backend_op_stubs libphazr_op_stubs
Definition: libphazr.c:369
pio_create_precoding_matrix_func
char *(* pio_create_precoding_matrix_func)(int)
Definition: libphazr.c:55