liberasurecode 1.8.0
Erasure Code API library
Loading...
Searching...
No Matches
xor_code.c
Go to the documentation of this file.
1/* * Copyright (c) 2013, Kevin Greenan (kmgreen2@gmail.com)
2 * All rights reserved.
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
25#ifdef INTEL_SSE2
26#include <emmintrin.h> //SSE2
27#endif
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <time.h>
32#include "xor_code.h"
33
34static const int g_bit_lookup[] = {0x1, 0x2, 0x4, 0x8,
35 0x10, 0x20, 0x40, 0x80,
36 0x100, 0x200, 0x400, 0x800,
37 0x1000, 0x2000, 0x4000, 0x8000,
38 0x10000, 0x20000, 0x40000, 0x80000,
39 0x100000, 0x200000, 0x400000, 0x800000,
40 0x1000000, 0x2000000, 0x4000000, 0x8000000,
41 0x10000000, 0x20000000, 0x40000000, 0x80000000};
42
43__attribute__ ((visibility ("internal")))
44int is_data_in_parity(int data_idx, unsigned int parity_bm)
45{
46 return ((g_bit_lookup[data_idx] & parity_bm) == g_bit_lookup[data_idx]);
47}
48
49__attribute__ ((visibility ("internal")))
50int does_parity_have_data(int parity_idx, unsigned int data_bm)
51{
52 return ((g_bit_lookup[parity_idx] & data_bm) == g_bit_lookup[parity_idx]);
53}
54
55__attribute__ ((visibility ("internal")))
56int parity_bit_lookup(xor_code_t *code_desc, int index)
57{
58 return g_bit_lookup[code_desc->k - index];
59}
60
61__attribute__ ((visibility ("internal")))
62int data_bit_lookup(xor_code_t *code_desc, int index)
63{
64 return g_bit_lookup[index];
65}
66
67__attribute__ ((visibility ("internal")))
68int missing_elements_bm(xor_code_t *code_desc, int *missing_elements, int (*bit_lookup_func)(xor_code_t *code_desc, int index))
69{
70 int i = 0;
71 int bm = 0;
72
73 while (missing_elements[i] > -1) {
74 bm |= bit_lookup_func(code_desc, missing_elements[i]);
75 i++;
76 }
77
78 return bm;
79}
80
81__attribute__ ((visibility ("internal")))
82failure_pattern_t get_failure_pattern(xor_code_t *code_desc, int *missing_idxs)
83{
84 int i = 0;
85 int num_failures = 0;
86 failure_pattern_t pattern = FAIL_PATTERN_0D_0P;
87
88 while (missing_idxs[i] > -1) {
89 num_failures++;
90 if (num_failures >= code_desc->hd) {
91 pattern = FAIL_PATTERN_GE_HD;
92 }
93 switch(pattern) {
94 case FAIL_PATTERN_0D_0P:
95 pattern = (missing_idxs[i] < code_desc->k) ? FAIL_PATTERN_1D_0P : FAIL_PATTERN_0D_1P;
96 break;
97 case FAIL_PATTERN_1D_0P:
98 pattern = (missing_idxs[i] < code_desc->k) ? FAIL_PATTERN_2D_0P : FAIL_PATTERN_1D_1P;
99 break;
100 case FAIL_PATTERN_2D_0P:
101 pattern = (missing_idxs[i] < code_desc->k) ? FAIL_PATTERN_3D_0P : FAIL_PATTERN_2D_1P;
102 break;
103 case FAIL_PATTERN_3D_0P:
104 pattern = FAIL_PATTERN_GE_HD;
105 break;
106 case FAIL_PATTERN_1D_1P:
107 pattern = (missing_idxs[i] < code_desc->k) ? FAIL_PATTERN_2D_1P : FAIL_PATTERN_1D_2P;
108 break;
109 case FAIL_PATTERN_1D_2P:
110 pattern = FAIL_PATTERN_GE_HD;
111 break;
112 case FAIL_PATTERN_2D_1P:
113 pattern = FAIL_PATTERN_GE_HD;
114 break;
115 case FAIL_PATTERN_0D_1P:
116 pattern = (missing_idxs[i] < code_desc->k) ? FAIL_PATTERN_1D_1P : FAIL_PATTERN_0D_2P;
117 break;
118 case FAIL_PATTERN_0D_2P:
119 pattern = (missing_idxs[i] < code_desc->k) ? FAIL_PATTERN_1D_2P : FAIL_PATTERN_0D_3P;
120 break;
121 case FAIL_PATTERN_0D_3P:
122 pattern = FAIL_PATTERN_GE_HD;
123 break;
124 case FAIL_PATTERN_GE_HD:
125 default:
126 break;
127 }
128 if (pattern == FAIL_PATTERN_GE_HD) {
129 break;
130 }
131 i++;
132 }
133
134 return pattern;
135}
136
137__attribute__ ((visibility ("internal")))
138void fast_memcpy(char *dst, char *src, int size)
139{
140 // Use _mm_stream_si128((__m128i*) _buf2, sum);
141 memcpy(dst, src, size);
142}
143
144/*
145 * Buffers must be aligned to 16-byte boundaries
146 *
147 * Store in buf2 (opposite of memcpy convention... Maybe change?)
148 */
149__attribute__ ((visibility ("internal")))
150void xor_bufs_and_store(char *buf1, char *buf2, int blocksize)
151{
152#ifdef INTEL_SSE2
153 int residual_bytes = num_unaligned_end(blocksize);
154 int fast_blocksize = blocksize > residual_bytes ? (blocksize - residual_bytes) : 0;
155 int fast_int_blocksize = fast_blocksize / sizeof(__m128i);
156 int i;
157 __m128i *_buf1 = (__m128i*)buf1;
158 __m128i *_buf2 = (__m128i*)buf2;
159
160 /*
161 * XOR aligned region using 128-bit XOR
162 */
163 for (i=0; i < fast_int_blocksize; i++) {
164 _buf2[i] = _mm_xor_si128(_buf1[i], _buf2[i]);
165 }
166#else
167 int residual_bytes = num_unaligned_end(blocksize);
168 int fast_blocksize = blocksize > residual_bytes ? (blocksize - residual_bytes) : 0;
169 int fast_int_blocksize = fast_blocksize / sizeof(unsigned long);
170 int i;
171
172 unsigned long*_buf1 = (unsigned long*)buf1;
173 unsigned long*_buf2 = (unsigned long*)buf2;
174
175 for (i=0; i < fast_int_blocksize; i++) {
176 _buf2[i] = _buf1[i] ^ _buf2[i];
177 }
178#endif
179
180 /*
181 * XOR unaligned end of region
182 */
183 for (i=fast_blocksize; i < blocksize; i++)
184 {
185 buf2[i] ^= buf1[i];
186 }
187}
188
189void xor_code_encode(xor_code_t *code_desc, char **data, char **parity, int blocksize)
190{
191 int i, j;
192
193 for (i=0; i < code_desc->k; i++) {
194 for (j=0; j < code_desc->m; j++) {
195 if (is_data_in_parity(i, code_desc->parity_bms[j])) {
196 xor_bufs_and_store(data[i], parity[j], blocksize);
197 }
198 }
199 }
200}
201
202__attribute__ ((visibility ("internal")))
203void selective_encode(xor_code_t *code_desc, char **data, char **parity, int *missing_parity, int blocksize)
204{
205 int i;
206 for (i=0; i < code_desc->k; i++) {
207 int j=0;
208 while (missing_parity[j] > -1) {
209 int parity_index = missing_parity[j] - code_desc->k;
210 if (is_data_in_parity(i, code_desc->parity_bms[parity_index])) {
211 xor_bufs_and_store(data[i], parity[parity_index], blocksize);
212 }
213 j++;
214 }
215 }
216}
217
218__attribute__ ((visibility ("internal")))
219int * get_missing_parity(xor_code_t *code_desc, int *missing_idxs)
220{
221 int *missing_parity = (int*)malloc(sizeof(int)*MAX_PARITY);
222 int i = 0, j = 0;
223
224 while (missing_idxs[i] > -1) {
225 if (missing_idxs[i] >= code_desc->k) {
226 missing_parity[j] = missing_idxs[i];
227 j++;
228 }
229 i++;
230 }
231
232 missing_parity[j] = -1;
233 return missing_parity;
234}
235
236__attribute__ ((visibility ("internal")))
237int * get_missing_data(xor_code_t *code_desc, int *missing_idxs)
238{
239 int *missing_data = (int*)malloc(sizeof(int)*MAX_DATA);
240 int i = 0, j = 0;
241
242 while (missing_idxs[i] > -1) {
243 if (missing_idxs[i] < code_desc->k) {
244 missing_data[j] = missing_idxs[i];
245 j++;
246 }
247 i++;
248 }
249
250 missing_data[j] = -1;
251 return missing_data;
252}
253
254/*
255 * Reconstruct a single missing symbol, given other symbols may be missing
256 */
257int xor_reconstruct_one(xor_code_t *code_desc, char **data, char **parity, int *missing_idxs, int index_to_reconstruct, int blocksize)
258{
259 int *missing_data = get_missing_data(code_desc, missing_idxs);
260 int *missing_parity = get_missing_parity(code_desc, missing_idxs);
261 int i, ret;
262
263 // If it is a data symbol, we need to figure out
264 // what data+parity symbols are needed to reconstruct
265 // If there is not at least one parity equation with
266 // one missing data element (the index to resonstruct),
267 // just call the underlying decode function
268 if (index_to_reconstruct < code_desc->k) {
269 int connected_parity_idx = index_of_connected_parity(code_desc, index_to_reconstruct, missing_parity, missing_data);
270
271 if (connected_parity_idx >= 0) {
272 // Can do a cheap reoncstruction!
273 int relative_parity_idx = connected_parity_idx - code_desc->k;
274 int parity_bm = code_desc->parity_bms[relative_parity_idx];
275
276 fast_memcpy(data[index_to_reconstruct], parity[relative_parity_idx], blocksize);
277
278 for (i=0; i < code_desc->k; i++) {
279 if (parity_bm & (1 << i)) {
280 if (i != index_to_reconstruct) {
281 xor_bufs_and_store(data[i], data[index_to_reconstruct], blocksize);
282 }
283 }
284 }
285 ret = 0;
286 } else {
287 // Just call decode
288 ret = code_desc->decode(code_desc, data, parity, missing_idxs, blocksize, 1);
289 }
290
291 } else {
292
293 // If it is a parity symbol, we need to figure out
294 // what data symbols are needed to reconstruct the
295 // parity. If *any* data symbols in the parity
296 // equation are missing, we are better off calling
297 // the underlying decode function.
298 int num_data_missing = num_missing_data_in_parity(code_desc, index_to_reconstruct, missing_data);
299
300 if (num_data_missing == 0) {
301 int relative_parity_idx = index_to_reconstruct - code_desc->k;
302 int parity_bm = code_desc->parity_bms[relative_parity_idx];
303
304 memset(parity[relative_parity_idx], 0, blocksize);
305
306 for (i=0; i < code_desc->k; i++) {
307 if (parity_bm & (1 << i)) {
308 xor_bufs_and_store(data[i], parity[relative_parity_idx], blocksize);
309 }
310 }
311 ret = 0;
312 } else {
313 // Just call decode
314 ret = code_desc->decode(code_desc, data, parity, missing_idxs, blocksize, 1);
315 }
316 }
317 free(missing_data);
318 free(missing_parity);
319 return ret;
320}
321
322__attribute__ ((visibility ("internal")))
323int num_missing_data_in_parity(xor_code_t *code_desc, int parity_idx, int *missing_data)
324{
325 int i = 0;
326 int num_missing_data = 0;
327 int relative_parity_index = parity_idx - code_desc->k;
328 if (missing_data == NULL) {
329 return 0;
330 }
331
332 while (missing_data[i] > -1) {
333 if (does_parity_have_data(relative_parity_index, code_desc->data_bms[missing_data[i]]) > 0) {
334 num_missing_data++;
335 }
336 i++;
337 }
338
339 return num_missing_data;
340}
341
342__attribute__ ((visibility ("internal")))
343int index_of_connected_parity(xor_code_t *code_desc, int data_index, int *missing_parity, int *missing_data)
344{
345 int parity_index = -1;
346 int i;
347
348 for (i=0; i < code_desc->m; i++) {
349 if (num_missing_data_in_parity(code_desc, i + code_desc->k, missing_data) > 1) {
350 continue;
351 }
352 if (is_data_in_parity(data_index, code_desc->parity_bms[i])) {
353 int j=0;
354 int is_missing = 0;
355 if (missing_parity == NULL) {
356 parity_index = i;
357 break;
358 }
359 while (missing_parity[j] > -1) {
360 if ((code_desc->k + i) == missing_parity[j]) {
361 is_missing = 1;
362 break;
363 }
364 j++;
365 }
366 if (!is_missing) {
367 parity_index = i;
368 break;
369 }
370 }
371 }
372
373 // Must add k to get the absolute
374 // index of the parity in the stripe
375 return parity_index > -1 ? parity_index + code_desc->k : parity_index;
376}
377
378__attribute__ ((visibility ("internal")))
379void remove_from_missing_list(int element, int *missing_list)
380{
381 int i = 0;
382 int elem_idx = -1;
383 int num_elems = 0;
384
385 while (missing_list[i] > -1) {
386 if (missing_list[i] == element) {
387 elem_idx = i;
388 missing_list[i] = -1;
389 }
390 i++;
391 }
392
393 num_elems = i;
394
395 for (i=elem_idx;i < num_elems-1;i++) {
396 int tmp = missing_list[i+1];
397 missing_list[i+1] = missing_list[i];
398 missing_list[i] = tmp;
399 }
400}
401
int is_missing(int *missing_idxs, int index_to_check)
static const int g_bit_lookup[]
Definition: xor_code.c:34
__attribute__((visibility("internal")))
Definition: xor_code.c:43
int xor_reconstruct_one(xor_code_t *code_desc, char **data, char **parity, int *missing_idxs, int index_to_reconstruct, int blocksize)
Definition: xor_code.c:257
void xor_code_encode(xor_code_t *code_desc, char **data, char **parity, int blocksize)
Definition: xor_code.c:189