liberasurecode  1.4.0
Erasure Code API library
 All Data Structures Files Functions Variables Typedefs Macros
erasurecode_helpers.c
Go to the documentation of this file.
1 /*
2  * Copyright 2014 Tushar Gohad, Kevin M Greenan, Eric Lambert
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  * liberasurecode API helpers implementation
25  *
26  * vi: set noai tw=79 ts=4 sw=4:
27  */
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdarg.h>
31 #include "erasurecode_backend.h"
32 #include "erasurecode_helpers.h"
33 #include "erasurecode_helpers_ext.h"
34 #include "erasurecode_stdinc.h"
35 #include "erasurecode_version.h"
36 
37 #include "alg_sig.h"
38 #include "erasurecode_log.h"
39 
40 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
41 
42 static bool is_fragment(char *buf)
43 {
44  fragment_header_t *header = (fragment_header_t *) buf;
45 
46  assert(NULL != header);
47  if (header->magic == LIBERASURECODE_FRAG_HEADER_MAGIC) {
48  return true;
49  }
50 
51  return false;
52 }
53 
60 void *get_aligned_buffer16(int size)
61 {
62  void *buf;
63 
68  if (posix_memalign(&buf, 16, size) != 0) {
69  return NULL;
70  }
71 
72  memset(buf, 0, size);
73 
74  return buf;
75 }
76 
83 void * alloc_zeroed_buffer(int size)
84 {
85  return alloc_and_set_buffer(size, 0);
86 }
87 
96 void * alloc_and_set_buffer(int size, int value) {
97  void * buf = NULL; /* buffer to allocate and return */
98 
99  /* Allocate and zero the buffer, or set the appropriate error */
100  buf = malloc((size_t) size);
101  if (buf) {
102  buf = memset(buf, value, (size_t) size);
103  }
104  return buf;
105 }
106 
115 void * check_and_free_buffer(void * buf)
116 {
117  if (buf)
118  free(buf);
119  return NULL;
120 }
121 
122 char *alloc_fragment_buffer(int size)
123 {
124  char *buf;
125  fragment_header_t *header = NULL;
126 
127  size += sizeof(fragment_header_t);
128  buf = get_aligned_buffer16(size);
129 
130  if (buf) {
131  header = (fragment_header_t *) buf;
132  header->magic = LIBERASURECODE_FRAG_HEADER_MAGIC;
133  }
134 
135  return buf;
136 }
137 
138 int free_fragment_buffer(char *buf)
139 {
140  fragment_header_t *header;
141 
142  if (NULL == buf) {
143  return -1;
144  }
145 
146  buf -= sizeof(fragment_header_t);
147 
148  header = (fragment_header_t *) buf;
149  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
150  log_error("Invalid fragment header (free fragment)!");
151  return -1;
152  }
153 
154  free(buf);
155  return 0;
156 }
157 
158 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
159 
167 uint64_t get_fragment_size(char *buf)
168 {
169 
170  if (NULL == buf)
171  return -1;
172 
173  return get_fragment_buffer_size(buf) + sizeof(fragment_header_t);
174  }
175 
184 int get_aligned_data_size(ec_backend_t instance, int data_len)
185 {
186  int k = instance->args.uargs.k;
187  int w = instance->args.uargs.w;
188  int word_size = w / 8;
189  int alignment_multiple;
190  int aligned_size = 0;
191 
192  /*
193  * For Cauchy reed-solomon align to k*word_size*packet_size
194  * For Vandermonde reed-solomon and flat-XOR, align to k*word_size
195  */
196  if (EC_BACKEND_JERASURE_RS_CAUCHY == instance->common.id) {
197  alignment_multiple = k * w * (sizeof(long) * 128);
198  } else {
199  alignment_multiple = k * word_size;
200  }
201 
202  aligned_size = (int)
203  ceill((double) data_len / alignment_multiple) * alignment_multiple;
204 
205  return aligned_size;
206 }
207 
208 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
209 
211 {
212  buf += sizeof(fragment_header_t);
213 
214  return buf;
215 }
216 
217 int get_data_ptr_array_from_fragments(char **data_array, char **fragments,
218  int num_fragments)
219 {
220  int i = 0, num = 0;
221  for (i = 0; i < num_fragments; i++) {
222  char *frag = fragments[i];
223  if (frag == NULL) {
224  data_array[i] = NULL;
225  continue;
226  }
227  data_array[i] = get_data_ptr_from_fragment(frag);
228  num++;
229  }
230  return num;
231 }
232 
233 int get_fragment_ptr_array_from_data(char **frag_array, char **data,
234  int num_data)
235 {
236  int i = 0, num = 0;
237  for (i = 0; i < num_data; i++) {
238  char *data_ptr = frag_array[i];
239  if (data_ptr == NULL) {
240  data[i] = NULL;
241  continue;
242  }
243  data[i] = get_fragment_ptr_from_data(data_ptr);
244  num++;
245  }
246  return num;
247 }
248 
250 {
251  buf -= sizeof(fragment_header_t);
252 
253  return buf;
254 }
255 
257 {
258  fragment_header_t *header;
259 
260  buf -= sizeof(fragment_header_t);
261 
262  header = (fragment_header_t *) buf;
263 
264  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
265  log_error("Invalid fragment header (get header ptr)!\n");
266  return NULL;
267  }
268 
269  return buf;
270 }
271 
272 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
273 
274 int set_fragment_idx(char *buf, int idx)
275 {
276  fragment_header_t *header = (fragment_header_t *) buf;
277 
278  assert(NULL != header);
279  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
280  log_error("Invalid fragment header (idx check)!\n");
281  return -1;
282  }
283 
284  header->meta.idx = idx;
285 
286  return 0;
287 }
288 
289 int get_fragment_idx(char *buf)
290 {
291  fragment_header_t *header = (fragment_header_t *) buf;
292 
293  assert(NULL != header);
294  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
295  log_error("Invalid fragment header (get idx)!");
296  return -1;
297  }
298 
299  return header->meta.idx;
300 }
301 
302 int set_fragment_payload_size(char *buf, int size)
303 {
304  fragment_header_t *header = (fragment_header_t *) buf;
305 
306  assert(NULL != header);
307  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
308  log_error("Invalid fragment header (size check)!");
309  return -1;
310  }
311 
312  header->meta.size = size;
313 
314  return 0;
315 }
316 
318 {
319  fragment_header_t *header = (fragment_header_t *) buf;
320 
321  assert(NULL != header);
322  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
323  log_error("Invalid fragment header (get size)!");
324  return -1;
325  }
326 
327  return header->meta.size;
328 }
329 
330 int set_fragment_backend_metadata_size(char *buf, int size)
331 {
332  fragment_header_t *header = (fragment_header_t *) buf;
333 
334  assert(NULL != header);
335  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
336  log_error("Invalid fragment header (set fragment backend metadata size)!");
337  return -1;
338  }
339 
340  header->meta.frag_backend_metadata_size = size;
341 
342  return 0;
343 }
344 
346 {
347  fragment_header_t *header = (fragment_header_t *) buf;
348 
349  assert(NULL != header);
350  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
351  log_error("Invalid fragment header (get fragment backend metadata size)!");
352  return -1;
353  }
354 
355  return header->meta.frag_backend_metadata_size;
356 }
357 
359 {
360  fragment_header_t *header = (fragment_header_t *) buf;
361 
362  assert(NULL != header);
363  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
364  log_error("Invalid fragment header (get size)!");
365  return -1;
366  }
367 
368  return header->meta.size + header->meta.frag_backend_metadata_size;
369 }
370 
371 int set_orig_data_size(char *buf, int orig_data_size)
372 {
373  fragment_header_t *header = (fragment_header_t *) buf;
374 
375  assert(NULL != header);
376  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
377  log_error("Invalid fragment header (set orig data check)!");
378  return -1;
379  }
380 
381  header->meta.orig_data_size = orig_data_size;
382 
383  return 0;
384 }
385 
386 int get_orig_data_size(char *buf)
387 {
388  fragment_header_t *header = (fragment_header_t *) buf;
389 
390  assert(NULL != header);
391  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
392  log_error("Invalid fragment header (get orig data check)!");
393  return -1;
394  }
395 
396  return header->meta.orig_data_size;
397 }
398 
399 int set_libec_version(char *buf)
400 {
401  if (!is_fragment(buf)) {
402  return -1;
403  }
404  fragment_header_t *header = (fragment_header_t *) buf;
405  header->libec_version = (uint32_t)LIBERASURECODE_VERSION;
406  return 0;
407 }
408 
409 int get_libec_version(char *buf, uint32_t *ver)
410 {
411  if (!is_fragment(buf)) {
412  return -1;
413  }
414  fragment_header_t *header = (fragment_header_t *) buf;
415  *ver = header->libec_version;
416  return 0;
417 }
418 
419 int set_backend_id(char *buf, ec_backend_id_t id)
420 {
421  if (!is_fragment(buf)) {
422  return -1;
423  }
424  fragment_header_t *header = (fragment_header_t *) buf;
425  header->meta.backend_id = (uint8_t)id;
426  return 0;
427 }
428 
429 int get_backend_id(char *buf, ec_backend_id_t *id)
430 {
431  if (!is_fragment(buf)) {
432  return -1;
433  }
434  fragment_header_t *header = (fragment_header_t *) buf;
435  *id = header->meta.backend_id;
436  return 0;
437 }
438 
439 int set_backend_version(char *buf, uint32_t version)
440 {
441  if (!is_fragment(buf)) {
442  return -1;
443  }
444  fragment_header_t *header = (fragment_header_t *) buf;
445  header->meta.backend_version = version;
446  return 0;
447 }
448 
449 int get_backend_version(char *buf, uint32_t *version)
450 {
451  if (!is_fragment(buf)) {
452  return -1;
453  }
454  fragment_header_t *header = (fragment_header_t *) buf;
455  *version = header->meta.backend_version;
456  return 0;
457 }
458 
459 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
460 
461 inline int set_checksum(ec_checksum_type_t ct, char *buf, int blocksize)
462 {
463  fragment_header_t* header = (fragment_header_t*) buf;
464  char *data = get_data_ptr_from_fragment(buf);
465 
466  assert(NULL != header);
467  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
468  log_error("Invalid fragment header (set chksum)!\n");
469  return -1;
470  }
471 
472  header->meta.chksum_type = ct;
473  header->meta.chksum_mismatch = 0;
474 
475  switch(header->meta.chksum_type) {
476  case CHKSUM_CRC32:
477  header->meta.chksum[0] = crc32(0, data, blocksize);
478  break;
479  case CHKSUM_MD5:
480  break;
481  case CHKSUM_NONE:
482  default:
483  break;
484  }
485 
486  return 0;
487 }
488 
489 inline uint32_t* get_chksum(char *buf)
490 {
491  fragment_header_t* header = (fragment_header_t*) buf;
492 
493  assert(NULL != header);
494  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
495  log_error("Invalid fragment header (get chksum)!");
496  return NULL;
497  }
498 
499  return (uint32_t *) header->meta.chksum;
500 }
501 
502 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
503 
504 #if LIBERASURECODE_VERSION >= _VERSION(1,2,0)
505 inline int set_metadata_chksum(char *buf)
506 {
507  fragment_header_t* header = (fragment_header_t*) buf;
508 
509  assert(NULL != header);
510  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
511  log_error("Invalid fragment header (set meta chksum)!\n");
512  return -1;
513  }
514 
515  header->metadata_chksum = crc32(0, &header->meta,
516  sizeof(fragment_metadata_t));
517  return 0;
518 }
519 
520 inline uint32_t* get_metadata_chksum(char *buf)
521 {
522  fragment_header_t* header = (fragment_header_t*) buf;
523 
524  assert(NULL != header);
525  if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
526  log_error("Invalid fragment header (get meta chksum)!");
527  return NULL;
528  }
529 
530  return (uint32_t *) &header->metadata_chksum;
531 }
532 #else
533 inline int set_metadata_chksum(char *buf)
534 {
535  return 0;
536 }
537 
538 inline uint32_t* get_metadata_chksum(char *buf)
539 {
540  return (uint32_t *) 0;
541 }
542 #endif
543 
544 /* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
545 
void * alloc_and_set_buffer(int size, int value)
Allocate a buffer of a specific size and set its&#39; contents to the specified value.
int get_fragment_ptr_array_from_data(char **frag_array, char **data, int num_data)
char * get_fragment_ptr_from_data(char *buf)
int get_data_ptr_array_from_fragments(char **data_array, char **fragments, int num_fragments)
int get_fragment_idx(char *buf)
uint32_t * get_metadata_chksum(char *buf)
char * get_fragment_ptr_from_data_novalidate(char *buf)
int get_aligned_data_size(ec_backend_t instance, int data_len)
Compute a size aligned to the number of data and the underlying wordsize of the EC algorithm...
int get_fragment_buffer_size(char *buf)
char * get_data_ptr_from_fragment(char *buf)
int set_backend_version(char *buf, uint32_t version)
void * alloc_zeroed_buffer(int size)
Allocate a zero-ed buffer of a specific size.
int free_fragment_buffer(char *buf)
int get_orig_data_size(char *buf)
int get_backend_version(char *buf, uint32_t *version)
char * alloc_fragment_buffer(int size)
void * check_and_free_buffer(void *buf)
Deallocate memory buffer if it&#39;s not NULL.
void * get_aligned_buffer16(int size)
Memory Management Methods.
int set_metadata_chksum(char *buf)
int get_fragment_payload_size(char *buf)
int set_checksum(ec_checksum_type_t ct, char *buf, int blocksize)
uint32_t * get_chksum(char *buf)
uint64_t get_fragment_size(char *buf)
Return total fragment length (on-disk, on-wire)
static bool is_fragment(char *buf)
int get_fragment_backend_metadata_size(char *buf)
int crc32(int crc, const void *buf, size_t size)
Definition: crc32.c:119
int get_backend_id(char *buf, ec_backend_id_t *id)
int set_backend_id(char *buf, ec_backend_id_t id)
int set_orig_data_size(char *buf, int orig_data_size)
int get_libec_version(char *buf, uint32_t *ver)
int set_fragment_payload_size(char *buf, int size)
int set_fragment_idx(char *buf, int idx)
int set_fragment_backend_metadata_size(char *buf, int size)
int set_libec_version(char *buf)