241 lines
7.3 KiB
C
241 lines
7.3 KiB
C
/*
|
|
* Copyright 2014 Tushar Gohad
|
|
*
|
|
* 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.
|
|
*
|
|
* liberasurecode null backend
|
|
*
|
|
* vi: set noai tw=79 ts=4 sw=4:
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "erasurecode.h"
|
|
#include "erasurecode_backend.h"
|
|
#define NULL_LIB_MAJOR 1
|
|
#define NULL_LIB_MINOR 0
|
|
#define NULL_LIB_REV 0
|
|
#define NULL_LIB_VER_STR "1.0"
|
|
#define NULL_LIB_NAME "null"
|
|
#if defined(__MACOS__) || defined(__MACOSX__) || defined(__OSX__) || defined(__APPLE__)
|
|
#define NULL_SO_NAME "libnullcode.dylib"
|
|
#else
|
|
#define NULL_SO_NAME "libnullcode.so.1"
|
|
#endif
|
|
/* Forward declarations */
|
|
struct ec_backend null;
|
|
struct ec_backend_op_stubs null_ops;
|
|
|
|
typedef void* (*init_null_code_func)(int, int, int);
|
|
typedef int (*null_code_encode_func)(void *, char **, char **, int);
|
|
typedef int (*null_code_decode_func)(void *, char **, char **, int *, int, int);
|
|
typedef int (*null_reconstruct_func)(char **, int, uint64_t, int, char *);
|
|
typedef int (*null_code_fragments_needed_func)(void *, int *, int *, int *);
|
|
struct null_descriptor {
|
|
/* calls required for init */
|
|
init_null_code_func init_null_code;
|
|
|
|
/* calls required for encode */
|
|
null_code_encode_func null_code_encode;
|
|
|
|
/* calls required for decode */
|
|
null_code_decode_func null_code_decode;
|
|
|
|
/* calls required for reconstruct */
|
|
null_reconstruct_func null_reconstruct;
|
|
|
|
/* set of fragments needed to reconstruct at a minimum */
|
|
null_code_fragments_needed_func null_code_fragments_needed;
|
|
|
|
/* fields needed to hold state */
|
|
int *matrix;
|
|
int k;
|
|
int m;
|
|
int w;
|
|
int arg1;
|
|
};
|
|
|
|
#define DEFAULT_W 32
|
|
|
|
static int null_encode(void *desc, char **data, char **parity, int blocksize)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int null_decode(void *desc, char **data, char **parity,
|
|
int *missing_idxs, int blocksize)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int null_reconstruct(void *desc, char **data, char **parity,
|
|
int *missing_idxs, int destination_idx, int blocksize)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int null_min_fragments(void *desc, int *missing_idxs,
|
|
int *fragments_to_exclude, int *fragments_needed)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Return the element-size, which is the number of bits stored
|
|
* on a given device, per codeword. This is usually just 'w'.
|
|
*/
|
|
static int
|
|
null_element_size(void* desc)
|
|
{
|
|
return DEFAULT_W;
|
|
}
|
|
|
|
static void * null_init(struct ec_backend_args *args, void *backend_sohandle)
|
|
{
|
|
struct null_descriptor *xdesc = NULL;
|
|
|
|
/* allocate and fill in null_descriptor */
|
|
xdesc = (struct null_descriptor *) malloc(sizeof(struct null_descriptor));
|
|
if (NULL == xdesc) {
|
|
return NULL;
|
|
}
|
|
memset(xdesc, 0, sizeof(struct null_descriptor));
|
|
|
|
xdesc->k = args->uargs.k;
|
|
xdesc->m = args->uargs.m;
|
|
xdesc->w = args->uargs.w;
|
|
|
|
if (xdesc->w <= 0)
|
|
xdesc->w = DEFAULT_W;
|
|
|
|
/* Sample on how to pass extra args to the backend */
|
|
xdesc->arg1 = args->uargs.priv_args1.null_args.arg1;
|
|
|
|
/* store w back in args so upper layer can get to it */
|
|
args->uargs.w = DEFAULT_W;
|
|
|
|
/* validate EC arguments */
|
|
{
|
|
long long max_symbols;
|
|
if (xdesc->w != 8 && xdesc->w != 16 && xdesc->w != 32) {
|
|
goto error;
|
|
}
|
|
max_symbols = 1LL << xdesc->w;
|
|
if ((xdesc->k + xdesc->m) > max_symbols) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ISO C forbids casting a void* to a function pointer.
|
|
* Since dlsym return returns a void*, we use this union to
|
|
* "transform" the void* to a function pointer.
|
|
*/
|
|
union {
|
|
init_null_code_func initp;
|
|
null_code_encode_func encodep;
|
|
null_code_decode_func decodep;
|
|
null_reconstruct_func reconp;
|
|
null_code_fragments_needed_func fragsneededp;
|
|
void *vptr;
|
|
} func_handle = {.vptr = NULL};
|
|
|
|
/* fill in function addresses */
|
|
func_handle.vptr = NULL;
|
|
func_handle.vptr = dlsym(backend_sohandle, "null_code_init");
|
|
xdesc->init_null_code = func_handle.initp;
|
|
if (NULL == xdesc->init_null_code) {
|
|
goto error;
|
|
}
|
|
|
|
func_handle.vptr = NULL;
|
|
func_handle.vptr = dlsym(backend_sohandle, "null_code_encode");
|
|
xdesc->null_code_encode = func_handle.encodep;
|
|
if (NULL == xdesc->null_code_encode) {
|
|
goto error;
|
|
}
|
|
|
|
func_handle.vptr = NULL;
|
|
func_handle.vptr = dlsym(backend_sohandle, "null_code_decode");
|
|
xdesc->null_code_decode = func_handle.decodep;
|
|
if (NULL == xdesc->null_code_decode) {
|
|
goto error;
|
|
}
|
|
|
|
func_handle.vptr = NULL;
|
|
func_handle.vptr = dlsym(backend_sohandle, "null_reconstruct");
|
|
xdesc->null_reconstruct = func_handle.reconp;
|
|
if (NULL == xdesc->null_reconstruct) {
|
|
goto error;
|
|
}
|
|
|
|
func_handle.vptr = NULL;
|
|
func_handle.vptr = dlsym(backend_sohandle, "null_code_fragments_needed");
|
|
xdesc->null_code_fragments_needed = func_handle.fragsneededp;
|
|
if (NULL == xdesc->null_code_fragments_needed) {
|
|
goto error;
|
|
}
|
|
|
|
return (void *) xdesc;
|
|
|
|
error:
|
|
free (xdesc);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int null_exit(void *desc)
|
|
{
|
|
struct null_descriptor *xdesc = (struct null_descriptor *) desc;
|
|
|
|
free (xdesc);
|
|
return 0;
|
|
}
|
|
|
|
static bool null_is_compatible_with(uint32_t version) {
|
|
return true;
|
|
}
|
|
|
|
struct ec_backend_op_stubs null_op_stubs = {
|
|
.INIT = null_init,
|
|
.EXIT = null_exit,
|
|
.ENCODE = null_encode,
|
|
.DECODE = null_decode,
|
|
.FRAGSNEEDED = null_min_fragments,
|
|
.RECONSTRUCT = null_reconstruct,
|
|
.ELEMENTSIZE = null_element_size,
|
|
.ISCOMPATIBLEWITH = null_is_compatible_with,
|
|
.GETMETADATASIZE = get_backend_metadata_size_zero,
|
|
.GETENCODEOFFSET = get_encode_offset_zero,
|
|
};
|
|
|
|
struct ec_backend_common backend_null = {
|
|
.id = EC_BACKEND_NULL,
|
|
.name = NULL_LIB_NAME,
|
|
.soname = NULL_SO_NAME,
|
|
.soversion = NULL_LIB_VER_STR,
|
|
.ops = &null_op_stubs,
|
|
.ec_backend_version = _VERSION(NULL_LIB_MAJOR, NULL_LIB_MINOR,
|
|
NULL_LIB_REV),
|
|
};
|
|
|