699 lines
22 KiB
C
699 lines
22 KiB
C
/* * Copyright (c) 2013, Kevin Greenan (kmgreen2@gmail.com)
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
*
|
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
* list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY
|
|
* THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
* EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "xor_code.h"
|
|
#include "xor_hd_code_defs.h"
|
|
|
|
/*
|
|
* Returns -1 if not possible
|
|
*/
|
|
static int fragments_needed_one_data(xor_code_t *code_desc, int *missing_data, int *missing_parity, unsigned int *data_bm, unsigned int *parity_bm)
|
|
{
|
|
int data_index = missing_data[0];
|
|
int parity_index = index_of_connected_parity(code_desc, data_index, missing_parity, missing_data);
|
|
|
|
if (parity_index < 0) {
|
|
return -1;
|
|
}
|
|
|
|
// Include all data elements except for this one
|
|
*data_bm |= (code_desc->parity_bms[parity_index-code_desc->k]);
|
|
|
|
// Include this parity element
|
|
*parity_bm |= (1 << (parity_index-code_desc->k));
|
|
*data_bm &= ~((unsigned int)1 << data_index);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Returns -1 if not possible
|
|
*/
|
|
static int fragments_needed_two_data(xor_code_t *code_desc, int *missing_data, int *missing_parity, unsigned int *data_bm, unsigned int *parity_bm)
|
|
{
|
|
// Verify that missing_data[2] == -1?
|
|
int data_index = missing_data[0];
|
|
int parity_index = index_of_connected_parity(code_desc, data_index, missing_parity, missing_data);
|
|
int ret;
|
|
|
|
if (parity_index < 0) {
|
|
data_index = missing_data[1];
|
|
parity_index = index_of_connected_parity(code_desc, data_index, missing_parity, missing_data);
|
|
if (parity_index < 0) {
|
|
return -1;
|
|
}
|
|
missing_data[1] = -1;
|
|
} else {
|
|
missing_data[0] = missing_data[1];
|
|
missing_data[1] = -1;
|
|
}
|
|
|
|
// Include all data elements except for this one
|
|
*data_bm |= (code_desc->parity_bms[parity_index-code_desc->k]);
|
|
|
|
// Include this parity element
|
|
*parity_bm |= (1 << (parity_index-code_desc->k));
|
|
|
|
ret = fragments_needed_one_data(code_desc, missing_data, missing_parity, data_bm, parity_bm);
|
|
|
|
*data_bm &= ~((unsigned int)1 << data_index);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Returns -1 if not possible
|
|
*/
|
|
static int fragments_needed_three_data(xor_code_t *code_desc, int *missing_data, int *missing_parity, unsigned int *data_bm, unsigned int *parity_bm)
|
|
{
|
|
int i = 0;
|
|
int parity_index = -1;
|
|
int data_index = -1;
|
|
int tmp_parity_bm = -1;
|
|
int contains_2d = -1;
|
|
int contains_3d = -1;
|
|
int ret = 0;
|
|
|
|
/*
|
|
* Try to find a parity that only contains
|
|
* one of the missing data elements.
|
|
*/
|
|
while (missing_data[i] > -1) {
|
|
parity_index = index_of_connected_parity(code_desc, missing_data[i], missing_parity, missing_data);
|
|
if (parity_index > -1) {
|
|
data_index = missing_data[i];
|
|
tmp_parity_bm = code_desc->parity_bms[parity_index-code_desc->k];
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
/*
|
|
* If we cannot find a parity that is connected to only
|
|
* one missing element, we must find a parity that is
|
|
* connected to exactly 2 (P) and another that is connected
|
|
* to exactly 3 (Q) (it should exist!!!).
|
|
*
|
|
* We XOR those parities together and use it to recover
|
|
* the element that is not connected to P.
|
|
*/
|
|
if (parity_index < 0) {
|
|
|
|
for (i=0;i < code_desc->m;i++) {
|
|
int num_missing = num_missing_data_in_parity(code_desc, code_desc->k+i, missing_data);
|
|
if (num_missing == 2 && contains_2d < 0) {
|
|
contains_2d = i;
|
|
} else if (num_missing == 3 && contains_3d < 0) {
|
|
contains_3d = i;
|
|
}
|
|
}
|
|
|
|
if (contains_2d < 0 || contains_3d < 0) {
|
|
return -1;
|
|
}
|
|
|
|
// P XOR Q
|
|
tmp_parity_bm = code_desc->parity_bms[contains_2d] ^ code_desc->parity_bms[contains_3d];
|
|
|
|
i=0;
|
|
data_index = -1;
|
|
while (missing_data[i] > -1) {
|
|
if (is_data_in_parity(missing_data[i], tmp_parity_bm)) {
|
|
data_index = missing_data[i];
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if (data_index < 0) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
remove_from_missing_list(data_index, missing_data);
|
|
|
|
// Include all data elements except for this one
|
|
*data_bm |= (code_desc->parity_bms[parity_index-code_desc->k]);
|
|
|
|
// Include this parity element
|
|
if (parity_index > -1) {
|
|
*parity_bm |= (1 << (parity_index-code_desc->k));
|
|
} else {
|
|
*parity_bm |= (1 << (contains_2d-code_desc->k));
|
|
*parity_bm |= (1 << (contains_3d-code_desc->k));
|
|
}
|
|
|
|
ret = fragments_needed_two_data(code_desc, missing_data, missing_parity, data_bm, parity_bm);
|
|
|
|
*data_bm &= ~((unsigned int)1 << data_index);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int fragments_needed_one_data_local(xor_code_t *code_desc,
|
|
int fragment_to_reconstruct,
|
|
int *fragments_to_exclude,
|
|
unsigned int *data_bm,
|
|
unsigned int *parity_bm)
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, fragments_to_exclude);
|
|
int *missing_parity = get_missing_parity(code_desc, fragments_to_exclude);
|
|
int parity_index = index_of_connected_parity(code_desc, fragment_to_reconstruct, missing_parity, missing_data);
|
|
free(missing_data);
|
|
free(missing_parity);
|
|
|
|
if (parity_index < 0) {
|
|
return -1;
|
|
}
|
|
|
|
// Include all data elements except for this one
|
|
*data_bm |= (code_desc->parity_bms[parity_index-code_desc->k]);
|
|
|
|
// Include this parity element
|
|
*parity_bm |= (1 << (parity_index-code_desc->k));
|
|
*data_bm &= ~((unsigned int)1 << fragment_to_reconstruct);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int xor_hd_fragments_needed(xor_code_t *code_desc, int *fragments_to_reconstruct, int *fragments_to_exclude, int *fragments_needed)
|
|
{
|
|
failure_pattern_t pattern = get_failure_pattern(code_desc, fragments_to_reconstruct);
|
|
unsigned int data_bm = 0, parity_bm = 0;
|
|
int ret = -1;
|
|
int *missing_idxs = NULL;
|
|
int i, j;
|
|
|
|
/**
|
|
* Re-visit this decision (KMG): This is non-optimal, but good enough in most cases.
|
|
* If there is a single data item to reconstruct, then try to find a connected parity
|
|
* with no items in fragments_to_exclude. If there is a single parity item to reconsturct
|
|
* or more than 1 data/parity element missing, then just work fragments_to_exclude into
|
|
* missing_idxs.
|
|
*/
|
|
|
|
if (pattern == FAIL_PATTERN_1D_0P) {
|
|
// Since we have landed on this failure pattern, fragments_to_reconstruct[0] is defined.
|
|
ret = fragments_needed_one_data_local(code_desc, fragments_to_reconstruct[0], fragments_to_exclude, &data_bm, &parity_bm);
|
|
}
|
|
|
|
/**
|
|
* There is either more than one failed element, a failed parity element or
|
|
* we were unable to return the fragments needed for a simple reconstruction.
|
|
*/
|
|
if (ret == -1) {
|
|
/**
|
|
* Add everything to missing_idxs (basically, give up on optimizing).
|
|
*/
|
|
missing_idxs = (int*)malloc(sizeof(int)*(code_desc->k + code_desc->m));
|
|
if (NULL == missing_idxs) {
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
i = 0;
|
|
j = 0;
|
|
while (fragments_to_reconstruct[i] > -1) {
|
|
missing_idxs[j] = fragments_to_reconstruct[i];
|
|
i++;
|
|
j++;
|
|
}
|
|
i = 0;
|
|
while (fragments_to_exclude[i] > -1) {
|
|
missing_idxs[j] = fragments_to_exclude[i];
|
|
i++;
|
|
j++;
|
|
}
|
|
// End of list
|
|
missing_idxs[j] = -1;
|
|
|
|
pattern = get_failure_pattern(code_desc, missing_idxs);
|
|
|
|
switch(pattern) {
|
|
case FAIL_PATTERN_0D_0P:
|
|
break;
|
|
case FAIL_PATTERN_1D_0P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
ret = fragments_needed_one_data(code_desc, missing_data, NULL, &data_bm, &parity_bm);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_2D_0P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
ret = fragments_needed_two_data(code_desc, missing_data, NULL, &data_bm, &parity_bm);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_3D_0P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
ret = fragments_needed_three_data(code_desc, missing_data, NULL, &data_bm, &parity_bm);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_1D_1P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
unsigned int missing_data_bm = missing_elements_bm(code_desc, missing_data, data_bit_lookup);
|
|
ret = fragments_needed_one_data(code_desc, missing_data, missing_parity, &data_bm, &parity_bm);
|
|
// OR all parities
|
|
i=0;
|
|
while (missing_parity[i] > -1) {
|
|
data_bm |= code_desc->parity_bms[missing_parity[i]-code_desc->k];
|
|
data_bm &= ~(missing_data_bm);
|
|
i++;
|
|
}
|
|
free(missing_parity);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_1D_2P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
int missing_data_bm = missing_elements_bm(code_desc, missing_data, data_bit_lookup);
|
|
ret = fragments_needed_one_data(code_desc, missing_data, missing_parity, &data_bm, &parity_bm);
|
|
// OR all parities
|
|
i=0;
|
|
while (missing_parity[i] > -1) {
|
|
data_bm |= code_desc->parity_bms[missing_parity[i]-code_desc->k];
|
|
data_bm &= ~(missing_data_bm);
|
|
i++;
|
|
}
|
|
free(missing_parity);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_2D_1P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
unsigned int missing_data_bm = missing_elements_bm(code_desc, missing_data, data_bit_lookup);
|
|
ret = fragments_needed_two_data(code_desc, missing_data, missing_parity, &data_bm, &parity_bm);
|
|
// OR all parities
|
|
i=0;
|
|
while (missing_parity[i] > -1) {
|
|
data_bm |= code_desc->parity_bms[missing_parity[i]-code_desc->k];
|
|
data_bm &= ~(missing_data_bm);
|
|
i++;
|
|
}
|
|
free(missing_parity);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_0D_1P:
|
|
{
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
// OR all of the parities
|
|
i=0;
|
|
while (missing_parity[i] > -1) {
|
|
data_bm |= code_desc->parity_bms[missing_parity[i]-code_desc->k];
|
|
i++;
|
|
}
|
|
free(missing_parity);
|
|
ret = 0;
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_0D_2P:
|
|
{
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
// OR all of the parities
|
|
i=0;
|
|
while (missing_parity[i] > -1) {
|
|
data_bm |= code_desc->parity_bms[missing_parity[i]-code_desc->k];
|
|
i++;
|
|
}
|
|
free(missing_parity);
|
|
ret = 0;
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_0D_3P:
|
|
{
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
// OR all of the parities
|
|
i=0;
|
|
while (missing_parity[i] > -1) {
|
|
data_bm |= code_desc->parity_bms[missing_parity[i]-code_desc->k];
|
|
i++;
|
|
}
|
|
free(missing_parity);
|
|
ret = 0;
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_GE_HD:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ret >= 0) {
|
|
i=0;
|
|
j=0;
|
|
while (data_bm) {
|
|
if (data_bm & 1) {
|
|
fragments_needed[j] = i;
|
|
j++;
|
|
}
|
|
i++;
|
|
data_bm >>= 1;
|
|
}
|
|
|
|
i=0;
|
|
while (parity_bm) {
|
|
if (parity_bm & 1) {
|
|
fragments_needed[j] = i + code_desc->k;
|
|
j++;
|
|
}
|
|
i++;
|
|
parity_bm >>= 1;
|
|
}
|
|
|
|
fragments_needed[j] = -1;
|
|
}
|
|
|
|
out:
|
|
if (NULL != missing_idxs) {
|
|
free(missing_idxs);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* There is one unavailable data element, so any available parity connected to
|
|
* the data element is sufficient to decode.
|
|
*/
|
|
static void decode_one_data(xor_code_t *code_desc, char **data, char **parity, int *missing_data, int *missing_parity, int blocksize)
|
|
{
|
|
// Verify that missing_data[1] == -1?
|
|
int data_index = missing_data[0];
|
|
int parity_index = index_of_connected_parity(code_desc, data_index, missing_parity, missing_data);
|
|
int i;
|
|
|
|
// Copy the appropriate parity into the data buffer
|
|
fast_memcpy(data[data_index], parity[parity_index-code_desc->k], blocksize);
|
|
|
|
for (i=0; i < code_desc->k; i++) {
|
|
if (i != data_index && is_data_in_parity(i, code_desc->parity_bms[parity_index-code_desc->k])) {
|
|
xor_bufs_and_store(data[i], data[data_index], blocksize);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int decode_two_data(xor_code_t *code_desc, char **data, char **parity, int *missing_data, int *missing_parity, int blocksize)
|
|
{
|
|
// Verify that missing_data[2] == -1?
|
|
int data_index = missing_data[0];
|
|
int parity_index = index_of_connected_parity(code_desc, data_index, missing_parity, missing_data);
|
|
int i;
|
|
|
|
if (parity_index < 0) {
|
|
data_index = missing_data[1];
|
|
parity_index = index_of_connected_parity(code_desc, data_index, missing_parity, missing_data);
|
|
if (parity_index < 0) {
|
|
fprintf(stderr, "Shit is broken, cannot find a proper parity!!!\n");
|
|
return -2;
|
|
}
|
|
missing_data[1] = -1;
|
|
} else {
|
|
missing_data[0] = missing_data[1];
|
|
missing_data[1] = -1;
|
|
}
|
|
|
|
// Copy the appropriate parity into the data buffer
|
|
fast_memcpy(data[data_index], parity[parity_index-code_desc->k], blocksize);
|
|
|
|
for (i=0; i < code_desc->k; i++) {
|
|
if (i != data_index && is_data_in_parity(i, code_desc->parity_bms[parity_index-code_desc->k])) {
|
|
xor_bufs_and_store(data[i], data[data_index], blocksize);
|
|
}
|
|
}
|
|
decode_one_data(code_desc, data, parity, missing_data, missing_parity, blocksize);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int decode_three_data(xor_code_t *code_desc, char **data, char **parity, int *missing_data, int *missing_parity, int blocksize)
|
|
{
|
|
int i = 0;
|
|
int parity_index = -1;
|
|
int data_index = -1;
|
|
unsigned int parity_bm = -1;
|
|
char *parity_buffer = NULL;
|
|
|
|
/*
|
|
* Try to find a parity that only contains
|
|
* one of the missing data elements.
|
|
*/
|
|
while (missing_data[i] > -1) {
|
|
parity_index = index_of_connected_parity(code_desc, missing_data[i], missing_parity, missing_data);
|
|
if (parity_index > -1) {
|
|
data_index = missing_data[i];
|
|
parity_buffer = parity[parity_index-code_desc->k];
|
|
parity_bm = code_desc->parity_bms[parity_index-code_desc->k];
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
/*
|
|
* If we cannot find a parity that is connected to only
|
|
* one missing element, we must find a parity that is
|
|
* connected to exactly 2 (P) and another that is connected
|
|
* to exactly 3 (Q) (it should exist!!!).
|
|
*
|
|
* We XOR those parities together and use it to recover
|
|
* the element that is not connected to P.
|
|
*/
|
|
if (parity_index < 0) {
|
|
int contains_2d = -1;
|
|
int contains_3d = -1;
|
|
|
|
for (i=0;i < code_desc->m;i++) {
|
|
int num_missing = num_missing_data_in_parity(code_desc, code_desc->k+i, missing_data);
|
|
if (num_missing == 2 && contains_2d < 0) {
|
|
contains_2d = i;
|
|
} else if (num_missing == 3 && contains_3d < 0) {
|
|
contains_3d = i;
|
|
}
|
|
}
|
|
|
|
if (contains_2d < 0 || contains_3d < 0) {
|
|
fprintf(stderr, "Shit is broken, cannot find a proper parity (2 and 3-connected parities)!!!\n");
|
|
return -2;
|
|
}
|
|
|
|
if (posix_memalign((void **) &parity_buffer, 16, blocksize) != 0) {
|
|
fprintf(stderr, "Can't get aligned memory!\n");
|
|
return -1;
|
|
}
|
|
|
|
// P XOR Q
|
|
parity_bm = code_desc->parity_bms[contains_2d] ^ code_desc->parity_bms[contains_3d];
|
|
|
|
// Create buffer with P XOR Q -> parity_buffer
|
|
fast_memcpy(parity_buffer, parity[contains_2d], blocksize);
|
|
xor_bufs_and_store(parity[contains_3d], parity_buffer, blocksize);
|
|
|
|
i=0;
|
|
data_index = -1;
|
|
while (missing_data[i] > -1) {
|
|
if (is_data_in_parity(missing_data[i], parity_bm)) {
|
|
data_index = missing_data[i];
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if (data_index < 0) {
|
|
fprintf(stderr, "Shit is broken, cannot construct equations to repair 3 failures!!!\n");
|
|
return -2;
|
|
}
|
|
// Copy the appropriate parity into the data buffer
|
|
fast_memcpy(data[data_index], parity_buffer, blocksize);
|
|
// Free up the buffer we allocated above
|
|
free(parity_buffer);
|
|
} else {
|
|
// Copy the appropriate parity into the data buffer
|
|
fast_memcpy(data[data_index], parity_buffer, blocksize);
|
|
}
|
|
|
|
|
|
for (i=0; i < code_desc->k; i++) {
|
|
if (i != data_index && is_data_in_parity(i, parity_bm)) {
|
|
xor_bufs_and_store(data[i], data[data_index], blocksize);
|
|
}
|
|
}
|
|
|
|
remove_from_missing_list(data_index, missing_data);
|
|
|
|
return decode_two_data(code_desc, data, parity, missing_data, missing_parity, blocksize);
|
|
}
|
|
|
|
int xor_hd_decode(xor_code_t *code_desc, char **data, char **parity, int *missing_idxs, int blocksize, int decode_parity)
|
|
{
|
|
int ret = 0;
|
|
failure_pattern_t pattern = get_failure_pattern(code_desc, missing_idxs);
|
|
|
|
switch(pattern) {
|
|
case FAIL_PATTERN_0D_0P:
|
|
break;
|
|
case FAIL_PATTERN_1D_0P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
decode_one_data(code_desc, data, parity, missing_data, NULL, blocksize);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_2D_0P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
ret = decode_two_data(code_desc, data, parity, missing_data, NULL, blocksize);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_3D_0P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
ret = decode_three_data(code_desc, data, parity, missing_data, NULL, blocksize);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_1D_1P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
decode_one_data(code_desc, data, parity, missing_data, missing_parity, blocksize);
|
|
if (decode_parity) {
|
|
selective_encode(code_desc, data, parity, missing_parity, blocksize);
|
|
}
|
|
free(missing_parity);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_1D_2P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
decode_one_data(code_desc, data, parity, missing_data, missing_parity, blocksize);
|
|
if (decode_parity) {
|
|
selective_encode(code_desc, data, parity, missing_parity, blocksize);
|
|
}
|
|
free(missing_data);
|
|
free(missing_parity);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_2D_1P:
|
|
{
|
|
int *missing_data = get_missing_data(code_desc, missing_idxs);
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
ret = decode_two_data(code_desc, data, parity, missing_data, missing_parity, blocksize);
|
|
if (decode_parity) {
|
|
selective_encode(code_desc, data, parity, missing_parity, blocksize);
|
|
}
|
|
free(missing_parity);
|
|
free(missing_data);
|
|
break;
|
|
}
|
|
case FAIL_PATTERN_0D_1P:
|
|
if (decode_parity) {
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
selective_encode(code_desc, data, parity, missing_parity, blocksize);
|
|
free(missing_parity);
|
|
}
|
|
break;
|
|
case FAIL_PATTERN_0D_2P:
|
|
if (decode_parity) {
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
selective_encode(code_desc, data, parity, missing_parity, blocksize);
|
|
free(missing_parity);
|
|
}
|
|
break;
|
|
case FAIL_PATTERN_0D_3P:
|
|
if (decode_parity) {
|
|
int *missing_parity = get_missing_parity(code_desc, missing_idxs);
|
|
selective_encode(code_desc, data, parity, missing_parity, blocksize);
|
|
free(missing_parity);
|
|
}
|
|
break;
|
|
case FAIL_PATTERN_GE_HD:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
xor_code_t* init_xor_hd_code(int k, int m, int hd)
|
|
{
|
|
xor_code_t *code_desc = NULL;
|
|
int is_valid = 0;
|
|
|
|
if (hd == 3) {
|
|
if (m == 6) {
|
|
if (k <= 15 && k >= 6) {
|
|
is_valid = 1;
|
|
}
|
|
} else if (m == 5) {
|
|
if (k <= 10 && k >= 5) {
|
|
is_valid = 1;
|
|
}
|
|
} else if (m == 3 && k == 3) {
|
|
is_valid = 1;
|
|
}
|
|
}
|
|
|
|
if (hd == 4) {
|
|
if (m == 6) {
|
|
if (k <= 20 && k >= 6) {
|
|
is_valid = 1;
|
|
}
|
|
} else if (m == 5) {
|
|
if (k <= 10 && k >= 5) {
|
|
is_valid = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (is_valid) {
|
|
code_desc = (xor_code_t*)malloc(sizeof(xor_code_t));
|
|
code_desc->parity_bms = PARITY_BM_ARY(k, m, hd);
|
|
code_desc->data_bms = DATA_BM_ARY(k, m, hd);
|
|
code_desc->k = k;
|
|
code_desc->m = m;
|
|
code_desc->hd = hd;
|
|
code_desc->decode = xor_hd_decode;
|
|
code_desc->encode = xor_code_encode;
|
|
code_desc->fragments_needed = xor_hd_fragments_needed;
|
|
}
|
|
|
|
return code_desc;
|
|
}
|
|
|