diff options
author | Mark Storer <Mark.Storer@evault.com> | 2014-05-27 13:22:39 -0700 |
---|---|---|
committer | Mark Storer <Mark.Storer@evault.com> | 2014-05-27 13:22:39 -0700 |
commit | 53d1679629ba4c9a0d655b42b4a1f43b3e6dc01e (patch) | |
tree | b4680b3135bbe5c8978f4e9fdc4803f3db5c4b6c | |
parent | 0c144dd580d5ce430639caddbe830ce9ef3498e3 (diff) | |
download | pyeclib-53d1679629ba4c9a0d655b42b4a1f43b3e6dc01e.tar.gz |
- Initial implementation of a utility method to alloc and initialize
buffers.
- Updated the init method to utilize the new allocation method and
clean up memory on error.
-rw-r--r-- | src/c/pyeclib_c/pyeclib_c.c | 212 |
1 files changed, 124 insertions, 88 deletions
diff --git a/src/c/pyeclib_c/pyeclib_c.c b/src/c/pyeclib_c/pyeclib_c.c index ecb74db..73f1451 100644 --- a/src/c/pyeclib_c/pyeclib_c.c +++ b/src/c/pyeclib_c/pyeclib_c.c @@ -38,7 +38,6 @@ #include <pyeclib_c.h> #include <bytesobject.h> - /* Python 3 compatibility macros */ #if PY_MAJOR_VERSION >= 3 #define MOD_ERROR_VAL NULL @@ -89,6 +88,14 @@ static PyObject *PyECLibError; + +/* + * Method Prototypes + */ +static PyObject * pyeclib_c_init(PyObject *self, PyObject *args); +static void pyeclib_c_destructor(PyObject *obj); + + /* * Determine if an address is aligned to a particular boundary */ @@ -190,6 +197,31 @@ void* get_aligned_buffer16(int size) return buf; } + +/** + * Allocate a zero-ed buffer of a specific size. On error, return NULL and + * call PyErr_NoMemory. + * + * @param size integer size in bytes of buffer to allocate + * @return pointer to start of allocated buffer or NULL on error + */ +static +void * alloc_zeroed_buffer(int size) +{ + void * buffer = NULL; /* buffer to allocate and return */ + + /* Allocate and zero the buffer, or set the appropriate error */ + buffer = malloc((size_t) size); + if (buffer) { + buffer = memset(buffer, 0, (size_t) size); + } else { + buffer = PyErr_NoMemory(); + } + + return buffer; +} + + static char *alloc_fragment_buffer(int size) { @@ -405,54 +437,6 @@ int free_fragment_buffer(char *buf) return 0; } -static void pyeclib_c_destructor(PyObject *obj) -{ - pyeclib_t *pyeclib_handle = NULL; - - if (!PyCapsule_CheckExact(obj)) { - PyErr_SetString(PyECLibError, "Attempted to free a non-Capsule object in pyeclib"); - 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"); - return; - } -} - -static -int get_fragment_metadata(pyeclib_t *pyeclib_handle, char *fragment_buf, fragment_metadata_t *fragment_metadata) -{ - char *fragment_data = get_data_ptr_from_fragment(fragment_buf); - int fragment_size = get_fragment_size(fragment_buf); - int fragment_idx = get_fragment_idx(fragment_buf); - - memset(fragment_metadata, 0, sizeof(fragment_metadata_t)); - - fragment_metadata->size = fragment_size; - fragment_metadata->idx = fragment_idx; - - /* - * If w \in [8, 16] and using RS_VAND or XOR_CODE, then use Alg_sig - * Else use CRC32 - */ - if (supports_alg_sig(pyeclib_handle)) { - // Compute algebraic signature - compute_alg_sig(pyeclib_handle->alg_sig_desc, fragment_data, fragment_size, fragment_metadata->signature); - } else if (use_inline_chksum(pyeclib_handle)) { - int stored_chksum = get_chksum(fragment_buf); - int computed_chksum = crc32(0, fragment_data, fragment_size); - - if (stored_chksum != computed_chksum) { - fragment_metadata->chksum_mismatch = 1; - } - } - - return 0; -} - /* * Buffers for data, parity and missing_idxs @@ -574,11 +558,75 @@ static int get_decoding_info(pyeclib_t *pyeclib_handle, return 0; } + +static int +get_aligned_data_size(pyeclib_t* pyeclib_handle, int data_len) +{ + int word_size = pyeclib_handle->w / 8; + int alignment_multiple; + int aligned_size = 0; + + /* + * For Cauchy reed-solomon align to k*word_size*packet_size + * + * For Vandermonde reed-solomon and flat-XOR, align to k*word_size + */ + if (pyeclib_handle->type == PYECC_RS_CAUCHY_ORIG) { + alignment_multiple = pyeclib_handle->k * pyeclib_handle->w * PYECC_CAUCHY_PACKETSIZE; + } else { + alignment_multiple = pyeclib_handle->k * word_size; + } + + aligned_size = (int)ceill((double)data_len / alignment_multiple) * alignment_multiple; + + return aligned_size; +} + + +static +int get_minimum_encode_size(pyeclib_t *pyeclib_handle) +{ + return get_aligned_data_size(pyeclib_handle, 1); +} + + +static +int get_fragment_metadata(pyeclib_t *pyeclib_handle, char *fragment_buf, fragment_metadata_t *fragment_metadata) +{ + char *fragment_data = get_data_ptr_from_fragment(fragment_buf); + int fragment_size = get_fragment_size(fragment_buf); + int fragment_idx = get_fragment_idx(fragment_buf); + + memset(fragment_metadata, 0, sizeof(fragment_metadata_t)); + + fragment_metadata->size = fragment_size; + fragment_metadata->idx = fragment_idx; + + /* + * If w \in [8, 16] and using RS_VAND or XOR_CODE, then use Alg_sig + * Else use CRC32 + */ + if (supports_alg_sig(pyeclib_handle)) { + // Compute algebraic signature + compute_alg_sig(pyeclib_handle->alg_sig_desc, fragment_data, fragment_size, fragment_metadata->signature); + } else if (use_inline_chksum(pyeclib_handle)) { + int stored_chksum = get_chksum(fragment_buf); + int computed_chksum = crc32(0, fragment_data, fragment_size); + + if (stored_chksum != computed_chksum) { + fragment_metadata->chksum_mismatch = 1; + } + } + + return 0; +} + + static PyObject * pyeclib_c_init(PyObject *self, PyObject *args) { - pyeclib_t *pyeclib_handle; - PyObject* pyeclib_obj_handle; + pyeclib_t *pyeclib_handle = NULL; + PyObject *pyeclib_obj_handle = NULL; int k, m, w; int use_inline_chksum = 0, use_algsig_chksum = 0; const char *type_str; @@ -589,26 +637,22 @@ pyeclib_c_init(PyObject *self, PyObject *args) return NULL; } - // Validate the arguments + /* Validate the parsed arguments */ type = get_ecc_type(type_str); if (type == PYECC_NOT_FOUND) { PyErr_SetString(PyECLibError, "Invalid type passed to pyeclib.init"); return NULL; } - if (!validate_args(k, m, w, type)) { PyErr_SetString(PyECLibError, "Invalid args passed to pyeclib.init"); return NULL; } - - pyeclib_handle = (pyeclib_t*)malloc(sizeof(pyeclib_t)); - if (pyeclib_handle == NULL) { - PyErr_SetString(PyECLibError, "malloc() returned NULL in pyeclib.init"); - return NULL; - } - memset(pyeclib_handle, 0, sizeof(pyeclib_t)); - + /* Allocate and initialize the pyeclib object */ + pyeclib_handle = (pyeclib_t *) alloc_zeroed_buffer(sizeof(pyeclib_t)); + if (!pyeclib_handle) { + return NULL; + } pyeclib_handle->k = k; pyeclib_handle->m = m; pyeclib_handle->w = w; @@ -645,6 +689,7 @@ pyeclib_c_init(PyObject *self, PyObject *args) break; } + /* Prepare the python object to return */ #ifdef Py_CAPSULE_H pyeclib_obj_handle = PyCapsule_New(pyeclib_handle, PYECC_HANDLE_NAME, pyeclib_c_destructor); @@ -654,43 +699,33 @@ pyeclib_c_init(PyObject *self, PyObject *args) pyeclib_c_destructor); #endif /* Py_CAPSULE_H */ + /* 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"); - return NULL; + free(pyeclib_handle); + } else { + Py_INCREF(pyeclib_obj_handle); } - - Py_INCREF(pyeclib_obj_handle); - + return pyeclib_obj_handle; } -static int -get_aligned_data_size(pyeclib_t* pyeclib_handle, int data_len) + +static void pyeclib_c_destructor(PyObject *obj) { - int word_size = pyeclib_handle->w / 8; - int alignment_multiple; - int aligned_size = 0; + pyeclib_t *pyeclib_handle = NULL; - /* - * For Cauchy reed-solomon align to k*word_size*packet_size - * - * For Vandermonde reed-solomon and flat-XOR, align to k*word_size - */ - if (pyeclib_handle->type == PYECC_RS_CAUCHY_ORIG) { - alignment_multiple = pyeclib_handle->k * pyeclib_handle->w * PYECC_CAUCHY_PACKETSIZE; - } else { - alignment_multiple = pyeclib_handle->k * word_size; + if (!PyCapsule_CheckExact(obj)) { + PyErr_SetString(PyECLibError, "Attempted to free a non-Capsule object in pyeclib"); + return; } - aligned_size = (int)ceill((double)data_len / alignment_multiple) * alignment_multiple; - - return aligned_size; -} - -static -int get_minimum_encode_size(pyeclib_t *pyeclib_handle) -{ - return get_aligned_data_size(pyeclib_handle, 1); + 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"); + return; + } } @@ -1892,6 +1927,7 @@ pyeclib_c_check_metadata(PyObject *self, PyObject *args) return PyLong_FromLong((long)ret); } + static PyMethodDef PyECLibMethods[] = { {"init", pyeclib_c_init, METH_VARARGS, "Initialize a new erasure encoder/decoder"}, {"encode", pyeclib_c_encode, METH_VARARGS, "Create parity using source data"}, |