liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
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 <zlib.h>
32#include "erasurecode_backend.h"
33#include "erasurecode_helpers.h"
34#include "erasurecode_helpers_ext.h"
35#include "erasurecode_stdinc.h"
36#include "erasurecode_version.h"
37
38#include "alg_sig.h"
39#include "erasurecode_log.h"
40
41/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
42
43static bool is_fragment(char *buf)
44{
45 fragment_header_t *header = (fragment_header_t *) buf;
46
47 assert(NULL != header);
48 if (header->magic == LIBERASURECODE_FRAG_HEADER_MAGIC) {
49 return true;
50 }
51
52 return false;
53}
54
61__attribute__ ((visibility ("internal")))
62void *get_aligned_buffer16(int size)
63{
64 void *buf;
65
70 if (posix_memalign(&buf, 16, size) != 0) {
71 return NULL;
72 }
73
74 memset(buf, 0, size);
75
76 return buf;
77}
78
85__attribute__ ((visibility ("internal")))
86void * alloc_zeroed_buffer(int size)
87{
88 return alloc_and_set_buffer(size, 0);
89}
90
99void * alloc_and_set_buffer(int size, int value) {
100 void * buf = NULL; /* buffer to allocate and return */
101
102 /* Allocate and zero the buffer, or set the appropriate error */
103 buf = malloc((size_t) size);
104 if (buf) {
105 buf = memset(buf, value, (size_t) size);
106 }
107 return buf;
108}
109
118__attribute__ ((visibility ("internal")))
119void * check_and_free_buffer(void * buf)
120{
121 if (buf)
122 free(buf);
123 return NULL;
124}
125
126__attribute__ ((visibility ("internal")))
127char *alloc_fragment_buffer(int size)
128{
129 char *buf;
130 fragment_header_t *header = NULL;
131
132 size += sizeof(fragment_header_t);
133 buf = get_aligned_buffer16(size);
134
135 if (buf) {
136 header = (fragment_header_t *) buf;
137 header->magic = LIBERASURECODE_FRAG_HEADER_MAGIC;
138 }
139
140 return buf;
141}
142
143__attribute__ ((visibility ("internal")))
144int free_fragment_buffer(char *buf)
145{
146 fragment_header_t *header;
147
148 if (NULL == buf) {
149 return -1;
150 }
151
152 buf -= sizeof(fragment_header_t);
153
154 header = (fragment_header_t *) buf;
155 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
156 log_error("Invalid fragment header (free fragment)!");
157 return -1;
158 }
159
160 free(buf);
161 return 0;
162}
163
164/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
165
173__attribute__ ((visibility ("internal")))
174uint64_t get_fragment_size(char *buf)
175{
176
177 if (NULL == buf)
178 return -1;
179
180 return get_fragment_buffer_size(buf) + sizeof(fragment_header_t);
181 }
182
191__attribute__ ((visibility ("internal")))
192int get_aligned_data_size(ec_backend_t instance, int data_len)
193{
194 int k = instance->args.uargs.k;
195 int w = instance->args.uargs.w;
196 int word_size = w / 8;
197 int alignment_multiple;
198 int aligned_size = 0;
199
200 /*
201 * For Cauchy reed-solomon align to k*word_size*packet_size
202 * For Vandermonde reed-solomon and flat-XOR, align to k*word_size
203 */
204 if (EC_BACKEND_JERASURE_RS_CAUCHY == instance->common.id) {
205 alignment_multiple = k * w * (sizeof(long) * 128);
206 } else {
207 alignment_multiple = k * word_size;
208 }
209
210 aligned_size = ((data_len + alignment_multiple - 1) / alignment_multiple)
211 * alignment_multiple;
212
213 return aligned_size;
214}
215
216/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
217
219{
220 buf += sizeof(fragment_header_t);
221
222 return buf;
223}
224
225__attribute__ ((visibility ("internal")))
226int get_data_ptr_array_from_fragments(char **data_array, char **fragments,
227 int num_fragments)
228{
229 int i = 0, num = 0;
230 for (i = 0; i < num_fragments; i++) {
231 char *frag = fragments[i];
232 if (frag == NULL) {
233 data_array[i] = NULL;
234 continue;
235 }
236 data_array[i] = get_data_ptr_from_fragment(frag);
237 num++;
238 }
239 return num;
240}
241
242__attribute__ ((visibility ("internal")))
243int get_fragment_ptr_array_from_data(char **frag_array, char **data,
244 int num_data)
245{
246 int i = 0, num = 0;
247 for (i = 0; i < num_data; i++) {
248 char *data_ptr = frag_array[i];
249 if (data_ptr == NULL) {
250 data[i] = NULL;
251 continue;
252 }
253 data[i] = get_fragment_ptr_from_data(data_ptr);
254 num++;
255 }
256 return num;
257}
258
259__attribute__ ((visibility ("internal")))
260char *get_fragment_ptr_from_data_novalidate(char *buf)
261{
262 buf -= sizeof(fragment_header_t);
263
264 return buf;
265}
266
267__attribute__ ((visibility ("internal")))
268char *get_fragment_ptr_from_data(char *buf)
269{
270 fragment_header_t *header;
271
272 buf -= sizeof(fragment_header_t);
273
274 header = (fragment_header_t *) buf;
275
276 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
277 log_error("Invalid fragment header (get header ptr)!\n");
278 return NULL;
279 }
280
281 return buf;
282}
283
284/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
285
286__attribute__ ((visibility ("internal")))
287int set_fragment_idx(char *buf, int idx)
288{
289 fragment_header_t *header = (fragment_header_t *) buf;
290
291 assert(NULL != header);
292 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
293 log_error("Invalid fragment header (idx check)!\n");
294 return -1;
295 }
296
297 header->meta.idx = idx;
298
299 return 0;
300}
301
302__attribute__ ((visibility ("internal")))
303int get_fragment_idx(char *buf)
304{
305 fragment_header_t *header = (fragment_header_t *) buf;
306
307 assert(NULL != header);
308 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
309 log_error("Invalid fragment header (get idx)!");
310 return -1;
311 }
312
313 return header->meta.idx;
314}
315
316__attribute__ ((visibility ("internal")))
317int set_fragment_payload_size(char *buf, int size)
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 (size check)!");
324 return -1;
325 }
326
327 header->meta.size = size;
328
329 return 0;
330}
331
332__attribute__ ((visibility ("internal")))
333int get_fragment_payload_size(char *buf)
334{
335 fragment_header_t *header = (fragment_header_t *) buf;
336
337 assert(NULL != header);
338 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
339 log_error("Invalid fragment header (get size)!");
340 return -1;
341 }
342
343 return header->meta.size;
344}
345
346__attribute__ ((visibility ("internal")))
347int set_fragment_backend_metadata_size(char *buf, int size)
348{
349 fragment_header_t *header = (fragment_header_t *) buf;
350
351 assert(NULL != header);
352 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
353 log_error("Invalid fragment header (set fragment backend metadata size)!");
354 return -1;
355 }
356
357 header->meta.frag_backend_metadata_size = size;
358
359 return 0;
360}
361
362__attribute__ ((visibility ("internal")))
363int get_fragment_backend_metadata_size(char *buf)
364{
365 fragment_header_t *header = (fragment_header_t *) buf;
366
367 assert(NULL != header);
368 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
369 log_error("Invalid fragment header (get fragment backend metadata size)!");
370 return -1;
371 }
372
373 return header->meta.frag_backend_metadata_size;
374}
375
376__attribute__ ((visibility ("internal")))
377int get_fragment_buffer_size(char *buf)
378{
379 fragment_header_t *header = (fragment_header_t *) buf;
380
381 assert(NULL != header);
382 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
383 log_error("Invalid fragment header (get size)!");
384 return -1;
385 }
386
387 return header->meta.size + header->meta.frag_backend_metadata_size;
388}
389
390__attribute__ ((visibility ("internal")))
391int set_orig_data_size(char *buf, int orig_data_size)
392{
393 fragment_header_t *header = (fragment_header_t *) buf;
394
395 assert(NULL != header);
396 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
397 log_error("Invalid fragment header (set orig data check)!");
398 return -1;
399 }
400
401 header->meta.orig_data_size = orig_data_size;
402
403 return 0;
404}
405
406__attribute__ ((visibility ("internal")))
407int get_orig_data_size(char *buf)
408{
409 fragment_header_t *header = (fragment_header_t *) buf;
410
411 assert(NULL != header);
412 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
413 log_error("Invalid fragment header (get orig data check)!");
414 return -1;
415 }
416
417 return header->meta.orig_data_size;
418}
419
420__attribute__ ((visibility ("internal")))
421int set_libec_version(char *buf)
422{
423 if (!is_fragment(buf)) {
424 return -1;
425 }
426 fragment_header_t *header = (fragment_header_t *) buf;
427 header->libec_version = (uint32_t)LIBERASURECODE_VERSION;
428 return 0;
429}
430
431int get_libec_version(char *buf, uint32_t *ver)
432{
433 if (!is_fragment(buf)) {
434 return -1;
435 }
436 fragment_header_t *header = (fragment_header_t *) buf;
437 *ver = header->libec_version;
438 return 0;
439}
440
441__attribute__ ((visibility ("internal")))
442int set_backend_id(char *buf, ec_backend_id_t id)
443{
444 if (!is_fragment(buf)) {
445 return -1;
446 }
447 fragment_header_t *header = (fragment_header_t *) buf;
448 header->meta.backend_id = (uint8_t)id;
449 return 0;
450}
451
452int get_backend_id(char *buf, ec_backend_id_t *id)
453{
454 if (!is_fragment(buf)) {
455 return -1;
456 }
457 fragment_header_t *header = (fragment_header_t *) buf;
458 *id = header->meta.backend_id;
459 return 0;
460}
461
462__attribute__ ((visibility ("internal")))
463int set_backend_version(char *buf, uint32_t version)
464{
465 if (!is_fragment(buf)) {
466 return -1;
467 }
468 fragment_header_t *header = (fragment_header_t *) buf;
469 header->meta.backend_version = version;
470 return 0;
471}
472
473int get_backend_version(char *buf, uint32_t *version)
474{
475 if (!is_fragment(buf)) {
476 return -1;
477 }
478 fragment_header_t *header = (fragment_header_t *) buf;
479 *version = header->meta.backend_version;
480 return 0;
481}
482
483/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
484
485__attribute__ ((visibility ("internal")))
486inline int set_checksum(ec_checksum_type_t ct, char *buf, int blocksize)
487{
488 fragment_header_t* header = (fragment_header_t*) buf;
489 char *data = get_data_ptr_from_fragment(buf);
490 char *flag;
491
492 assert(NULL != header);
493 if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
494 log_error("Invalid fragment header (set chksum)!\n");
495 return -1;
496 }
497
498 header->meta.chksum_type = ct;
499 header->meta.chksum_mismatch = 0;
500
501 switch(header->meta.chksum_type) {
502 case CHKSUM_CRC32:
503 flag = getenv("LIBERASURECODE_WRITE_LEGACY_CRC");
504 if (flag && !(flag[0] == '\0' || (flag[0] == '0' && flag[1] == '\0'))) {
505 header->meta.chksum[0] = liberasurecode_crc32_alt(0, data, blocksize);
506 } else {
507 header->meta.chksum[0] = crc32(0, (unsigned char *) data, blocksize);
508 }
509 break;
510 case CHKSUM_MD5:
511 break;
512 case CHKSUM_NONE:
513 default:
514 break;
515 }
516
517 return 0;
518}
519
520/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */
int liberasurecode_crc32_alt(int crc, const void *buf, size_t size)
Definition: crc32.c:92
int get_backend_version(char *buf, uint32_t *version)
void * alloc_and_set_buffer(int size, int value)
Allocate a buffer of a specific size and set its' contents to the specified value.
int get_backend_id(char *buf, ec_backend_id_t *id)
char * get_data_ptr_from_fragment(char *buf)
__attribute__((visibility("internal")))
Memory Management Methods.
int get_libec_version(char *buf, uint32_t *ver)
static bool is_fragment(char *buf)