Expose liberasurecode error codes in PyECLib
... also move exception handing down to the C backend layer, so it is easier to add new error codes. Addresses #61.
This commit is contained in:
parent
43868eaa34
commit
04700a4fcf
|
@ -21,14 +21,17 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from ec_iface import PyECLib_FRAGHDRCHKSUM_Types, ECDriverError, ECDriverInsufficientFragmentError
|
||||
from ec_iface import ECDriverError
|
||||
from ec_iface import ECInsufficientFragments
|
||||
from ec_iface import PyECLib_FRAGHDRCHKSUM_Types
|
||||
|
||||
import math
|
||||
import pyeclib_c
|
||||
from pyeclib_c import error as PyECLibError
|
||||
import sys
|
||||
|
||||
pyver = float('%s.%s' % sys.version_info[:2])
|
||||
|
||||
|
||||
class ECPyECLibDriver(object):
|
||||
|
||||
def __init__(self, k, m, ec_type,
|
||||
|
@ -80,21 +83,9 @@ class ECPyECLibDriver(object):
|
|||
raise ECDriverError("Invalid fragment payload in ECPyECLibDriver.decode")
|
||||
|
||||
if len(fragment_payloads) < self.k:
|
||||
raise ECDriverInsufficientFragmentError("Not enough fragments given in ECPyECLibDriver.decode")
|
||||
raise ECInsufficientFragments("Not enough fragments given in ECPyECLibDriver.decode")
|
||||
|
||||
try:
|
||||
ret = pyeclib_c.decode(self.handle, fragment_payloads, fragment_len, ranges, force_metadata_checks)
|
||||
except PyECLibError as e:
|
||||
if e.message.find("Insufficient number of fragments") < 0:
|
||||
raise ECDriverError(e)
|
||||
else:
|
||||
raise ECDriverInsufficientFragmentError(e)
|
||||
|
||||
# Was there an error decoding
|
||||
if ret is None:
|
||||
raise ECDriverError("Error decoding from fragments in ECPyECLibDriver.decode")
|
||||
|
||||
return ret
|
||||
return pyeclib_c.decode(self.handle, fragment_payloads, fragment_len, ranges, force_metadata_checks)
|
||||
|
||||
def reconstruct(self, fragment_payloads, indexes_to_reconstruct):
|
||||
fragment_len = self._validate_and_return_fragment_size(fragment_payloads)
|
||||
|
@ -112,48 +103,33 @@ class ECPyECLibDriver(object):
|
|||
|
||||
while len(_indexes_to_reconstruct) > 0:
|
||||
index = _indexes_to_reconstruct.pop(0)
|
||||
try:
|
||||
reconstructed = pyeclib_c.reconstruct(
|
||||
self.handle, _fragment_payloads, fragment_len, index)
|
||||
except PyECLibError as e:
|
||||
raise ECDriverError(e)
|
||||
reconstructed = pyeclib_c.reconstruct(
|
||||
self.handle, _fragment_payloads, fragment_len, index)
|
||||
reconstructed_data.append(reconstructed)
|
||||
_fragment_payloads.append(reconstructed)
|
||||
|
||||
return reconstructed_data
|
||||
|
||||
def fragments_needed(self, reconstruct_indexes, exclude_indexes):
|
||||
try:
|
||||
required_fragments = pyeclib_c.get_required_fragments(
|
||||
required_fragments = pyeclib_c.get_required_fragments(
|
||||
self.handle, reconstruct_indexes, exclude_indexes)
|
||||
return required_fragments
|
||||
except PyECLibError as e:
|
||||
raise ECDriverError(e)
|
||||
return required_fragments
|
||||
|
||||
def min_parity_fragments_needed(self):
|
||||
""" FIXME - fix this to return a function of HD """
|
||||
return 1
|
||||
|
||||
def get_metadata(self, fragment, formatted = 0):
|
||||
try:
|
||||
fragment_metadata = pyeclib_c.get_metadata(self.handle, fragment, formatted)
|
||||
return fragment_metadata
|
||||
except PyECLibError as e:
|
||||
raise ECDriverError(e)
|
||||
|
||||
def verify_stripe_metadata(self, fragment_metadata_list):
|
||||
try:
|
||||
success = pyeclib_c.check_metadata(self.handle, fragment_metadata_list)
|
||||
return success
|
||||
except PyECLibError as e:
|
||||
raise ECDriverError(e)
|
||||
|
||||
def get_segment_info(self, data_len, segment_size):
|
||||
try:
|
||||
segment_info = pyeclib_c.get_segment_info(self.handle, data_len, segment_size)
|
||||
return segment_info
|
||||
except PyECLibError as e:
|
||||
raise ECDriverError(e)
|
||||
|
||||
class ECNullDriver(object):
|
||||
|
||||
|
@ -245,7 +221,7 @@ class ECStripingDriver(object):
|
|||
raise ECDriverError(
|
||||
"Decode does not support metadata integrity checks in the striping driver.")
|
||||
if len(fragment_payloads) != self.k:
|
||||
raise ECDriverError(
|
||||
raise ECInsufficientFragments(
|
||||
"Decode requires %d fragments, %d fragments were given" %
|
||||
(len(fragment_payloads), self.k))
|
||||
|
||||
|
|
|
@ -111,25 +111,6 @@ class PyECLib_FRAGHDRCHKSUM_Types(PyECLibEnum):
|
|||
inline_crc32 = 2
|
||||
|
||||
|
||||
# Generic ECDriverException
|
||||
class ECDriverError(Exception):
|
||||
def __init__(self, error):
|
||||
try:
|
||||
self.error_str = str(error)
|
||||
except:
|
||||
self.error_str = 'Error retrieving the error message from %s' \
|
||||
% error.__class__.__name__
|
||||
def __str__(self):
|
||||
return self.error_str
|
||||
|
||||
# Exception specifying insufficient fragments specified for
|
||||
# decode or reconstruction
|
||||
class ECDriverInsufficientFragmentError(Exception):
|
||||
def __init__(self, *args):
|
||||
super(ECDriverInsufficientFragmentError, self).__init__(*args)
|
||||
def __str__(self):
|
||||
return self.error_str
|
||||
|
||||
# Main ECDriver class
|
||||
class ECDriver(object):
|
||||
|
||||
|
@ -158,7 +139,7 @@ class ECDriver(object):
|
|||
self.ec_type = \
|
||||
PyECLib_EC_Types.get_by_name(value)
|
||||
else:
|
||||
raise ECDriverError(
|
||||
raise ECBackendNotSupported(
|
||||
"%s is not a valid EC type for PyECLib!" % value)
|
||||
elif key == "chksum_type":
|
||||
if PyECLib_FRAGHDRCHKSUM_Types.has_enum(value):
|
||||
|
@ -224,7 +205,7 @@ class ECDriver(object):
|
|||
|
||||
:param fragment_payloads: a list of buffers representing a subset of
|
||||
the list generated by encode()
|
||||
:param ranges (optional): a list of byte ranges to return instead of
|
||||
:param ranges (optional): a list of byte ranges to return instead of
|
||||
the entire buffer
|
||||
:param force_metadata_checks (optional): validate collective integrity
|
||||
of the fragments before trying to decode
|
||||
|
@ -402,3 +383,70 @@ class ECDriver(object):
|
|||
recipe[r] = segment_map
|
||||
|
||||
return recipe
|
||||
|
||||
|
||||
# PyECLib Exceptions
|
||||
|
||||
# Generic ECDriverException
|
||||
class ECDriverError(Exception):
|
||||
def __init__(self, error):
|
||||
try:
|
||||
self.error_str = str(error)
|
||||
except Exception:
|
||||
self.error_str = 'Error retrieving the error message from %s' \
|
||||
% error.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
return self.error_str
|
||||
|
||||
|
||||
## More specific exceptions, mapped to liberasurecode error codes
|
||||
|
||||
# Specified EC backend is not supported by PyECLib/liberasurecode
|
||||
class ECBackendNotSupported(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Unsupported EC method
|
||||
class ECMethodNotImplemented(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# liberasurecode backend init error
|
||||
class ECBackendInitializationError(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Specified backend instance is invalid/unavailable
|
||||
class ECBackendInstanceNotAvailable(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Specified backend instance is busy
|
||||
class ECBackendInstanceInUse(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Invalid parameter passed to a method
|
||||
class ECInvalidParameter(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Invalid or incompatible fragment metadata
|
||||
class ECInvalidFragmentMetadata(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Fragment checksum verification failed
|
||||
class ECBadFragmentChecksum(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Insufficient fragments specified for decode or reconstruct operation
|
||||
class ECInsufficientFragments(ECDriverError):
|
||||
pass
|
||||
|
||||
|
||||
# Out of memory
|
||||
class ECOutOfMemory(ECDriverError):
|
||||
pass
|
||||
|
|
|
@ -63,8 +63,6 @@
|
|||
#endif
|
||||
|
||||
|
||||
static PyObject *PyECLibError;
|
||||
|
||||
typedef struct pyeclib_byte_range {
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
|
@ -82,38 +80,63 @@ static PyObject * pyeclib_c_decode(PyObject *self, PyObject *args);
|
|||
static PyObject * pyeclib_c_get_metadata(PyObject *self, PyObject *args);
|
||||
static PyObject * pyeclib_c_check_metadata(PyObject *self, PyObject *args);
|
||||
|
||||
void
|
||||
liberasurecode_errstr(int ret, const char * prefix, char str[])
|
||||
static PyObject *import_class(const char *module, const char *cls)
|
||||
{
|
||||
strcpy(str, prefix);
|
||||
PyObject *s = PyImport_ImportModule(module);
|
||||
return (PyObject *) PyObject_GetAttrString(s, cls);
|
||||
}
|
||||
|
||||
void
|
||||
pyeclib_c_seterr(int ret, const char * prefix)
|
||||
{
|
||||
char err[255];
|
||||
PyObject *eo = NULL;
|
||||
|
||||
strcpy(err, prefix);
|
||||
switch (ret) {
|
||||
case -EBACKENDNOTAVAIL:
|
||||
strcat(str, "Backend instance not found");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECBackendInstanceNotAvailable");
|
||||
strcat(err, "Backend instance not found");
|
||||
break;
|
||||
case -EINSUFFFRAGS:
|
||||
strcat(str, "Insufficient number of fragments");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECInsufficientFragments");
|
||||
strcat(err, "Insufficient number of fragments");
|
||||
break;
|
||||
case -EBACKENDNOTSUPP:
|
||||
strcat(str, "Backend not supported");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECBackendNotSupported");
|
||||
strcat(err, "Backend not supported");
|
||||
break;
|
||||
case -EINVALIDPARAMS:
|
||||
strcat(str, "Invalid arguments");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECInvalidParameter");
|
||||
strcat(err, "Invalid arguments");
|
||||
break;
|
||||
case -EBADCHKSUM:
|
||||
strcat(str, "Fragment integrity check failed");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECBadFragmentChecksum");
|
||||
strcat(err, "Fragment integrity check failed");
|
||||
break;
|
||||
case -EBADHEADER:
|
||||
strcat(str, "Fragment integrity check failed");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECInvalidFragmentMetadata");
|
||||
strcat(err, "Fragment integrity check failed");
|
||||
break;
|
||||
case -ENOMEM:
|
||||
strcat(str, "Out of memory");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECOutOfMemory");
|
||||
strcat(err, "Out of memory");
|
||||
break;
|
||||
default:
|
||||
strcat(str, "Unknown error");
|
||||
eo = import_class("pyeclib.ec_iface",
|
||||
"ECDriverError");
|
||||
strcat(err, "Unknown error");
|
||||
break;
|
||||
}
|
||||
|
||||
strcat(str, ". Please inspect syslog for liberasurecode error report.");
|
||||
strcat(err, ". Please inspect syslog for liberasurecode error report.");
|
||||
PyErr_SetString(eo, err);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,13 +159,14 @@ pyeclib_c_init(PyObject *self, PyObject *args)
|
|||
|
||||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, "iii|iii", &k, &m, &backend_id, &hd, &use_inline_chksum, &use_algsig_chksum)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.init");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_init ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate and initialize the pyeclib object */
|
||||
pyeclib_handle = (pyeclib_t *) alloc_zeroed_buffer(sizeof(pyeclib_t));
|
||||
if (NULL == pyeclib_handle) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_init ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -153,7 +177,7 @@ pyeclib_c_init(PyObject *self, PyObject *args)
|
|||
|
||||
pyeclib_handle->ec_desc = liberasurecode_instance_create(backend_id, &(pyeclib_handle->ec_args));
|
||||
if (pyeclib_handle->ec_desc <= 0) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to liberasurecode_instance_create");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_init ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -169,7 +193,7 @@ pyeclib_c_init(PyObject *self, PyObject *args)
|
|||
|
||||
/* Clean up the allocated memory on error, or update the ref count */
|
||||
if (pyeclib_obj_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Could not encapsulate pyeclib_handle into Python object in pyeclib.init");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_init ERROR: ");
|
||||
goto error;
|
||||
} else {
|
||||
Py_INCREF(pyeclib_obj_handle);
|
||||
|
@ -195,13 +219,13 @@ pyeclib_c_destructor(PyObject *obj)
|
|||
pyeclib_t *pyeclib_handle = NULL; /* pyeclib object to destroy */
|
||||
|
||||
if (!PyCapsule_CheckExact(obj)) {
|
||||
PyErr_SetString(PyECLibError, "Attempted to free a non-Capsule object in pyeclib");
|
||||
pyeclib_c_seterr(-1, "pyeclib_c_destructor ERROR: ");
|
||||
return;
|
||||
}
|
||||
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(obj, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Attempted to free an invalid reference to pyeclib_handle");
|
||||
pyeclib_c_seterr(-1, "pyeclib_c_destructor ERROR: ");
|
||||
} else {
|
||||
check_and_free_buffer(pyeclib_handle);
|
||||
}
|
||||
|
@ -252,12 +276,12 @@ pyeclib_c_get_segment_info(PyObject *self, PyObject *args)
|
|||
|
||||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, "Oii", &pyeclib_obj_handle, &data_len, &segment_size)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.encode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_get_segment_info ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.encode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_get_segment_info ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -324,7 +348,7 @@ pyeclib_c_get_segment_info(PyObject *self, PyObject *args)
|
|||
/* Create and return the python dictionary of segment info */
|
||||
ret_dict = PyDict_New();
|
||||
if (NULL == ret_dict) {
|
||||
PyErr_SetString(PyECLibError, "Error allocating python dict in get_segment_info");
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_get_segment_info ERROR: ");
|
||||
} else {
|
||||
PyDict_SetItem(ret_dict, PyString_FromString("segment_size\0"), PyInt_FromLong(segment_size));
|
||||
PyDict_SetItem(ret_dict, PyString_FromString("last_segment_size\0"), PyInt_FromLong(last_segment_size));
|
||||
|
@ -360,28 +384,25 @@ pyeclib_c_encode(PyObject *self, PyObject *args)
|
|||
|
||||
/* Assume binary data (force "byte array" input) */
|
||||
if (!PyArg_ParseTuple(args, ENCODE_ARGS, &pyeclib_obj_handle, &data, &data_len)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.encode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.encode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = liberasurecode_encode(pyeclib_handle->ec_desc, data, data_len, &encoded_data, &encoded_parity, &fragment_len);
|
||||
|
||||
if (ret < 0) {
|
||||
char err[255];
|
||||
liberasurecode_errstr(ret, "Encode ERROR: ", err);
|
||||
PyErr_SetString(PyECLibError, err);
|
||||
pyeclib_c_seterr(ret, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the python list of fragments to return */
|
||||
list_of_strips = PyList_New(pyeclib_handle->ec_args.k + pyeclib_handle->ec_args.m);
|
||||
if (NULL == list_of_strips) {
|
||||
PyErr_SetString(PyECLibError, "Error allocating python list in encode");
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -431,12 +452,12 @@ pyeclib_c_get_required_fragments(PyObject *self, PyObject *args)
|
|||
|
||||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, "OOO", &pyeclib_obj_handle, &reconstruct_list, &exclude_list)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.get_required_fragments");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.get_required_fragments");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
k = pyeclib_handle->ec_args.k;
|
||||
|
@ -446,6 +467,7 @@ pyeclib_c_get_required_fragments(PyObject *self, PyObject *args)
|
|||
num_missing = (int) PyList_Size(reconstruct_list);
|
||||
c_reconstruct_list = (int *) alloc_zeroed_buffer((num_missing + 1) * sizeof(int));
|
||||
if (NULL == c_reconstruct_list) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
c_reconstruct_list[num_missing] = -1;
|
||||
|
@ -458,6 +480,7 @@ pyeclib_c_get_required_fragments(PyObject *self, PyObject *args)
|
|||
num_exclude = (int) PyList_Size(exclude_list);
|
||||
c_exclude_list = (int *) alloc_zeroed_buffer((num_exclude + 1) * sizeof(int));
|
||||
if (NULL == c_exclude_list) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
goto exit;
|
||||
}
|
||||
c_exclude_list[num_exclude] = -1;
|
||||
|
@ -469,21 +492,21 @@ pyeclib_c_get_required_fragments(PyObject *self, PyObject *args)
|
|||
|
||||
fragments_needed = alloc_zeroed_buffer(sizeof(int) * (k + m));
|
||||
if (NULL == fragments_needed) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = liberasurecode_fragments_needed(pyeclib_handle->ec_desc, c_reconstruct_list,
|
||||
c_exclude_list, fragments_needed);
|
||||
if (ret < 0) {
|
||||
char err[255];
|
||||
liberasurecode_errstr(ret, "Reconstruct_Fragments_Needed ERROR: ", err);
|
||||
PyErr_SetString(PyECLibError, err);
|
||||
pyeclib_c_seterr(ret, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Post-process into a Python list */
|
||||
fragment_idx_list = PyList_New(0);
|
||||
if (NULL == fragment_idx_list) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_get_required_fragments ERROR: ");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -532,18 +555,18 @@ pyeclib_c_reconstruct(PyObject *self, PyObject *args)
|
|||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, "OOii", &pyeclib_obj_handle, &fragments,
|
||||
&fragment_len, &destination_idx)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.reconstruct");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_reconstruct ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.reconstruct");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_reconstruct ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Pre-processing Python data structures */
|
||||
if (!PyList_Check(fragments)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid structure passed in for fragment list");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_reconstruct ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -551,11 +574,13 @@ pyeclib_c_reconstruct(PyObject *self, PyObject *args)
|
|||
|
||||
c_fragments = (char **) alloc_zeroed_buffer(sizeof(char *) * num_fragments);
|
||||
if (NULL == c_fragments) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_reconstruct ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
c_reconstructed = (char*) alloc_zeroed_buffer(sizeof(char) * fragment_len);
|
||||
if (NULL == c_fragments) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_reconstruct ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -573,9 +598,7 @@ pyeclib_c_reconstruct(PyObject *self, PyObject *args)
|
|||
destination_idx,
|
||||
c_reconstructed);
|
||||
if (ret < 0) {
|
||||
char err[255];
|
||||
liberasurecode_errstr(ret, "Reconstruct ERROR: ", err);
|
||||
PyErr_SetString(PyECLibError, err);
|
||||
pyeclib_c_seterr(ret, "pyeclib_c_reconstruct ERROR: ");
|
||||
reconstructed = NULL;
|
||||
} else {
|
||||
reconstructed = PY_BUILDVALUE_OBJ_LEN(c_reconstructed, fragment_len);
|
||||
|
@ -627,7 +650,7 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, "OOi|OO",&pyeclib_obj_handle, &fragments,
|
||||
&fragment_len, &ranges, &metadata_checks_obj)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_decode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -643,11 +666,11 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_decode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyList_Check(fragments)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid structure passed in for available fragments in pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_decode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -658,14 +681,14 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
}
|
||||
|
||||
if (pyeclib_handle->ec_args.k > num_fragments) {
|
||||
PyErr_SetString(PyECLibError, "The fragment list does not have enough entries in pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINSUFFFRAGS, "pyeclib_c_decode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (num_ranges > 0) {
|
||||
c_ranges = (pyeclib_byte_range_t*)malloc(sizeof(pyeclib_byte_range_t) * num_ranges);
|
||||
if (NULL == c_ranges) {
|
||||
PyErr_SetString(PyECLibError, "Could not allocate memory in pyeclib_c.decode");
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_decode ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
|
@ -675,7 +698,7 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
PyObject *py_end = PyTuple_GetItem(tuple, 1);
|
||||
|
||||
if (!PyLong_Check(py_begin) || !PyLong_Check(py_end)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid range passed to pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_decode invalid range ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -683,7 +706,7 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
c_ranges[i].length = PyLong_AsLong(py_end) - c_ranges[i].offset + 1;
|
||||
range_payload_size += c_ranges[i].length;
|
||||
} else {
|
||||
PyErr_SetString(PyECLibError, "Invalid range passed to pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_decode invalid range ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -710,9 +733,7 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
&orig_data_size);
|
||||
|
||||
if (ret < 0) {
|
||||
char err[255];
|
||||
liberasurecode_errstr(ret, "Decode ERROR: ", err);
|
||||
PyErr_SetString(PyECLibError, err);
|
||||
pyeclib_c_seterr(ret, "pyeclib_c_decode ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -721,14 +742,14 @@ pyeclib_c_decode(PyObject *self, PyObject *args)
|
|||
} else {
|
||||
ret_payload = PyList_New(num_ranges);
|
||||
if (NULL == ret_payload) {
|
||||
PyErr_SetString(PyECLibError, "Could not alloc list for range payloads in pyeclib.decode");
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_decode ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
range_payload_size = 0;
|
||||
for (i = 0; i < num_ranges; i++) {
|
||||
/* Check that range is within the original buffer */
|
||||
if (c_ranges[i].offset + c_ranges[i].length > orig_data_size) {
|
||||
PyErr_SetString(PyECLibError, "Invalid range passed to pyeclib.decode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_decode invalid range ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
PyList_SET_ITEM(ret_payload, i,
|
||||
|
@ -846,32 +867,32 @@ fragment_metadata_to_dict(fragment_metadata_t *fragment_metadata)
|
|||
metadata_dict = PyDict_New();
|
||||
|
||||
if (metadata_dict == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Could not allocate dictionary for fragment metadata");
|
||||
pyeclib_c_seterr(-ENOMEM, "fragment_metadata_to_dict ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(metadata_dict, "index",
|
||||
PyLong_FromLong((unsigned long)fragment_metadata->idx)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing index from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict index ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(metadata_dict, "size",
|
||||
PyLong_FromLong(fragment_metadata->size)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing size from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict size ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(metadata_dict, "orig_data_size",
|
||||
PyLong_FromLong(fragment_metadata->orig_data_size)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing orig_data_size from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict orig_data_size ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *chksum_type_str = chksum_type_to_str(fragment_metadata->chksum_type);
|
||||
if (PyDict_SetItemString(metadata_dict, "chksum_type",
|
||||
PyString_FromString(chksum_type_str)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing chksum_type from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict chksum_type ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -879,27 +900,26 @@ fragment_metadata_to_dict(fragment_metadata_t *fragment_metadata)
|
|||
chksum_length(fragment_metadata->chksum_type));
|
||||
if (PyDict_SetItemString(metadata_dict, "chksum",
|
||||
PyString_FromString(encoded_chksum)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing chksum from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict chksum ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(metadata_dict, "chksum_mismatch",
|
||||
PyLong_FromLong((unsigned long)fragment_metadata->chksum_mismatch)) < 0) {
|
||||
|
||||
PyErr_SetString(PyECLibError, "Error parsing chksum mismatch from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict chksum_mismatch ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *backend_id_str = backend_id_to_str(fragment_metadata->backend_id);
|
||||
if (PyDict_SetItemString(metadata_dict, "backend_id",
|
||||
PyString_FromString(backend_id_str)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing backend id from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict backend_id ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyDict_SetItemString(metadata_dict, "backend_version",
|
||||
PyLong_FromLong((unsigned long)fragment_metadata->backend_version)) < 0) {
|
||||
PyErr_SetString(PyECLibError, "Error parsing backend version from fragment metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "fragment_metadata_to_dict backend_version ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -928,28 +948,26 @@ pyeclib_c_get_metadata(PyObject *self, PyObject *args)
|
|||
|
||||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, GET_METADATA_ARGS, &pyeclib_obj_handle, &fragment, &fragment_len, &formatted)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.get_metadata");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_get_metadata ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.get_required_fragments");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_get_metadata ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = liberasurecode_get_fragment_metadata(fragment, &c_fragment_metadata);
|
||||
|
||||
if (ret < 0) {
|
||||
char err[255];
|
||||
liberasurecode_errstr(ret, "Get_Fragment_Metadata ERROR: ", err);
|
||||
PyErr_SetString(PyECLibError, err);
|
||||
pyeclib_c_seterr(ret, "pyeclib_c_get_metadata ERROR: ");
|
||||
fragment_metadata = NULL;
|
||||
} else {
|
||||
if (formatted) {
|
||||
fragment_metadata = fragment_metadata_to_dict(&c_fragment_metadata);
|
||||
} else {
|
||||
fragment_metadata = PY_BUILDVALUE_OBJ_LEN((char*)&c_fragment_metadata,
|
||||
sizeof(fragment_metadata_t));
|
||||
sizeof(fragment_metadata_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,19 +1004,19 @@ pyeclib_c_check_metadata(PyObject *self, PyObject *args)
|
|||
|
||||
/* Obtain and validate the method parameters */
|
||||
if (!PyArg_ParseTuple(args, "OO", &pyeclib_obj_handle, &fragment_metadata_list)) {
|
||||
PyErr_SetString(PyECLibError, "Invalid arguments passed to pyeclib.encode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
pyeclib_handle = (pyeclib_t*)PyCapsule_GetPointer(pyeclib_obj_handle, PYECC_HANDLE_NAME);
|
||||
if (pyeclib_handle == NULL) {
|
||||
PyErr_SetString(PyECLibError, "Invalid handle passed to pyeclib.encode");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
k = pyeclib_handle->ec_args.k;
|
||||
m = pyeclib_handle->ec_args.m;
|
||||
num_fragments = k + m;
|
||||
if (num_fragments != PyList_Size(fragment_metadata_list)) {
|
||||
PyErr_SetString(PyECLibError, "Not enough fragment metadata to perform integrity check");
|
||||
pyeclib_c_seterr(-EINVALIDPARAMS, "pyeclib_c_encode ERROR: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1006,6 +1024,7 @@ pyeclib_c_check_metadata(PyObject *self, PyObject *args)
|
|||
size = sizeof(char * ) * num_fragments;
|
||||
c_fragment_metadata_list = (char **) alloc_zeroed_buffer(size);
|
||||
if (NULL == c_fragment_metadata_list) {
|
||||
pyeclib_c_seterr(-ENOMEM, "pyeclib_c_encode ERROR: ");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1072,13 +1091,5 @@ MOD_INIT(pyeclib_c)
|
|||
if (m == NULL)
|
||||
return MOD_ERROR_VAL;
|
||||
|
||||
PyECLibError = PyErr_NewException("pyeclib.Error", NULL, NULL);
|
||||
if (PyECLibError == NULL) {
|
||||
fprintf(stderr, "Could not create default PyECLib exception object!\n");
|
||||
exit(2);
|
||||
}
|
||||
Py_INCREF(PyECLibError);
|
||||
PyModule_AddObject(m, "error", PyECLibError);
|
||||
|
||||
return MOD_SUCCESS_VAL(m);
|
||||
}
|
||||
|
|
|
@ -27,11 +27,10 @@ import sys
|
|||
import tempfile
|
||||
import unittest
|
||||
from pyeclib.ec_iface import ECDriverError
|
||||
from pyeclib.ec_iface import ECInsufficientFragments
|
||||
|
||||
from pyeclib.ec_iface import ECDriver, VALID_EC_TYPES, ECDriverError, \
|
||||
PyECLib_EC_Types
|
||||
from pyeclib.ec_iface import ECDriver, PyECLib_EC_Types
|
||||
from test_pyeclib_c import _available_backends
|
||||
import pyeclib_c
|
||||
|
||||
if sys.version < '3':
|
||||
def b2i(b):
|
||||
|
@ -519,28 +518,27 @@ class TestPyECLibDriver(unittest.TestCase):
|
|||
self.assertTrue(got_exception)
|
||||
|
||||
def test_liberasurecode_error(self):
|
||||
pyeclib_driver = self.get_available_backend(k=10, m=5, ec_type="flat_xor_hd_3")
|
||||
file_size = self.file_sizes[0]
|
||||
tmp_file = self.files[file_size]
|
||||
tmp_file.seek(0)
|
||||
whole_file_str = tmp_file.read()
|
||||
whole_file_bytes = whole_file_str.encode('utf-8')
|
||||
hit_exception = False
|
||||
pyeclib_driver = self.get_available_backend(k=10, m=5, ec_type="flat_xor_hd_3")
|
||||
file_size = self.file_sizes[0]
|
||||
tmp_file = self.files[file_size]
|
||||
tmp_file.seek(0)
|
||||
whole_file_str = tmp_file.read()
|
||||
whole_file_bytes = whole_file_str.encode('utf-8')
|
||||
hit_exception = False
|
||||
|
||||
fragments = pyeclib_driver.encode(whole_file_bytes)
|
||||
|
||||
#
|
||||
# Test reconstructor with insufficient fragments
|
||||
#
|
||||
try:
|
||||
pyeclib_driver.reconstruct([fragments[0]], [1,2,3,4,5,6])
|
||||
except ECDriverError as e:
|
||||
hit_exception = True
|
||||
print(e.error_str.__str__())
|
||||
self.assertTrue(e.error_str.__str__().find("Insufficient number of fragments") > -1)
|
||||
fragments = pyeclib_driver.encode(whole_file_bytes)
|
||||
|
||||
#
|
||||
# Test reconstructor with insufficient fragments
|
||||
#
|
||||
try:
|
||||
pyeclib_driver.reconstruct([fragments[0]], [1, 2, 3, 4, 5, 6])
|
||||
except ECInsufficientFragments as e:
|
||||
hit_exception = True
|
||||
self.assertTrue(e.error_str.__str__().find("Insufficient number of fragments") > -1)
|
||||
|
||||
self.assertTrue(hit_exception)
|
||||
|
||||
self.assertTrue(hit_exception)
|
||||
|
||||
def test_min_parity_fragments_needed(self):
|
||||
pyeclib_drivers = []
|
||||
pyeclib_drivers.append(ECDriver(k=12, m=2, ec_type="jerasure_rs_vand"))
|
||||
|
|
Loading…
Reference in New Issue