[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/openstack/liberasurecode/master/src/erasurecode_helpers.c [Back]  [Original]

/*
 * Copyright 2014 Tushar Gohad, Kevin M Greenan, Eric Lambert
 *
 * 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 API helpers implementation
 *
 * vi: set noai tw=79 ts=4 sw=4:
 */
#include "erasurecode_helpers.h"
#include "erasurecode_backend.h"
#include "erasurecode_helpers_ext.h"
#include "erasurecode_stdinc.h"
#include "erasurecode_version.h"
#include 
#include 
#include 
#include 

#include "alg_sig.h"
#include "erasurecode_log.h"

/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */

static bool is_fragment(char *buf)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic == LIBERASURECODE_FRAG_HEADER_MAGIC) {
        return true;
    }

    return false;
}

/**
 * Memory Management Methods
 *
 * The following methods provide wrappers for allocating and deallocating
 * memory.
 */
__attribute__((visibility("internal"))) void *get_aligned_buffer16(int size)
{
    void *buf;

    /**
     * Ensure all memory is aligned to 16-byte boundaries
     * to support 128-bit operations
     */
    if (posix_memalign(&buf, 16, size) != 0) {
        return NULL;
    }

    memset(buf, 0, size);

    return buf;
}

/**
 * Allocate a zero-ed buffer of a specific size.
 *
 * @param size integer size in bytes of buffer to allocate
 * @return pointer to start of allocated buffer or NULL on error
 */
__attribute__((visibility("internal"))) void *alloc_zeroed_buffer(int size)
{
    return alloc_and_set_buffer(size, 0);
}

/**
 * Allocate a buffer of a specific size and set its' contents
 * to the specified value.
 *
 * @param size integer size in bytes of buffer to allocate
 * @param value
 * @return pointer to start of allocated buffer or NULL on error
 */
void *alloc_and_set_buffer(int size, int value)
{
    void *buf = NULL; /* buffer to allocate and return */

    /* Allocate and zero the buffer, or set the appropriate error */
    buf = malloc((size_t)size);
    if (buf) {
        buf = memset(buf, value, (size_t)size);
    }
    return buf;
}

/**
 * Deallocate memory buffer if it's not NULL.  This methods returns NULL so
 * that you can free and reset a buffer using a single line as follows:
 *
 * my_ptr = check_and_free_buffer(my_ptr);
 *
 * @return NULL
 */
__attribute__((visibility("internal"))) void *check_and_free_buffer(void *buf)
{
    if (buf)
        free(buf);
    return NULL;
}

__attribute__((visibility("internal"))) char *alloc_fragment_buffer(int size)
{
    char *buf;
    fragment_header_t *header = NULL;

    size += sizeof(fragment_header_t);
    buf = get_aligned_buffer16(size);

    if (buf) {
        header = (fragment_header_t *)buf;
        header->magic = LIBERASURECODE_FRAG_HEADER_MAGIC;
    }

    return buf;
}

__attribute__((visibility("internal"))) int free_fragment_buffer(char *buf)
{
    fragment_header_t *header;

    if (NULL == buf) {
        return -1;
    }

    buf -= sizeof(fragment_header_t);

    header = (fragment_header_t *)buf;
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (free fragment)!");
        return -1;
    }

    free(buf);
    return 0;
}

/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */

/**
 * Return total fragment length (on-disk, on-wire)
 *
 * @param buf - pointer to fragment buffer
 *
 * @return fragment size on disk
 */
__attribute__((visibility("internal"))) uint64_t get_fragment_size(char *buf)
{

    if (NULL == buf)
        return -1;

    return get_fragment_buffer_size(buf) + sizeof(fragment_header_t);
}

/**
 * Compute a size aligned to the number of data and the underlying wordsize
 * of the EC algorithm.
 *
 * @param instance - ec_backend_t instance (to extract args)
 * @param data_len - integer length of data in bytes
 * @return integer data length aligned with wordsize of EC algorithm
 */
__attribute__((visibility("internal"))) int get_aligned_data_size(
    ec_backend_t instance, int data_len)
{
    int k = instance->args.uargs.k;
    int w = instance->args.uargs.w;
    int word_size = 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 (EC_BACKEND_JERASURE_RS_CAUCHY == instance->common.id) {
        alignment_multiple = k * w * (sizeof(long) * 128);
    } else {
        alignment_multiple = k * word_size;
    }

    aligned_size = ((data_len + alignment_multiple - 1) / alignment_multiple) * alignment_multiple;

    return aligned_size;
}

/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */

char *get_data_ptr_from_fragment(char *buf)
{
    buf += sizeof(fragment_header_t);

    return buf;
}

__attribute__((visibility("internal"))) int get_data_ptr_array_from_fragments(
    char **data_array, char **fragments, int num_fragments)
{
    int i = 0, num = 0;
    for (i = 0; i < num_fragments; i++) {
        char *frag = fragments[i];
        if (frag == NULL) {
            data_array[i] = NULL;
            continue;
        }
        data_array[i] = get_data_ptr_from_fragment(frag);
        num++;
    }
    return num;
}

__attribute__((visibility("internal"))) int get_fragment_ptr_array_from_data(
    char **frag_array, char **data, int num_data)
{
    int i = 0, num = 0;
    for (i = 0; i < num_data; i++) {
        char *data_ptr = frag_array[i];
        if (data_ptr == NULL) {
            data[i] = NULL;
            continue;
        }
        data[i] = get_fragment_ptr_from_data(data_ptr);
        num++;
    }
    return num;
}

__attribute__((visibility("internal"))) char *get_fragment_ptr_from_data_novalidate(char *buf)
{
    buf -= sizeof(fragment_header_t);

    return buf;
}

__attribute__((visibility("internal"))) char *get_fragment_ptr_from_data(char *buf)
{
    fragment_header_t *header;

    buf -= sizeof(fragment_header_t);

    header = (fragment_header_t *)buf;

    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (get header ptr)!\n");
        return NULL;
    }

    return buf;
}

/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */

__attribute__((visibility("internal"))) int set_fragment_idx(char *buf, int idx)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (idx check)!\n");
        return -1;
    }

    header->meta.idx = idx;

    return 0;
}

__attribute__((visibility("internal"))) int get_fragment_idx(char *buf)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (get idx)!");
        return -1;
    }

    return header->meta.idx;
}

__attribute__((visibility("internal"))) int set_fragment_payload_size(char *buf, int size)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (size check)!");
        return -1;
    }

    header->meta.size = size;

    return 0;
}

__attribute__((visibility("internal"))) int get_fragment_payload_size(char *buf)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (get size)!");
        return -1;
    }

    return header->meta.size;
}

__attribute__((visibility("internal"))) int set_fragment_backend_metadata_size(char *buf, int size)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (set fragment backend metadata size)!");
        return -1;
    }

    header->meta.frag_backend_metadata_size = size;

    return 0;
}

__attribute__((visibility("internal"))) int get_fragment_backend_metadata_size(char *buf)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (get fragment backend metadata size)!");
        return -1;
    }

    return header->meta.frag_backend_metadata_size;
}

__attribute__((visibility("internal"))) int get_fragment_buffer_size(char *buf)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (get size)!");
        return -1;
    }

    return header->meta.size + header->meta.frag_backend_metadata_size;
}

__attribute__((visibility("internal"))) int set_orig_data_size(char *buf, int orig_data_size)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (set orig data check)!");
        return -1;
    }

    header->meta.orig_data_size = orig_data_size;

    return 0;
}

__attribute__((visibility("internal"))) int get_orig_data_size(char *buf)
{
    fragment_header_t *header = (fragment_header_t *)buf;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (get orig data check)!");
        return -1;
    }

    return header->meta.orig_data_size;
}

__attribute__((visibility("internal"))) int set_libec_version(char *buf)
{
    if (!is_fragment(buf)) {
        return -1;
    }
    fragment_header_t *header = (fragment_header_t *)buf;
    header->libec_version = (uint32_t)LIBERASURECODE_VERSION;
    return 0;
}

int get_libec_version(char *buf, uint32_t *ver)
{
    if (!is_fragment(buf)) {
        return -1;
    }
    fragment_header_t *header = (fragment_header_t *)buf;
    *ver = header->libec_version;
    return 0;
}

__attribute__((visibility("internal"))) int set_backend_id(char *buf, ec_backend_id_t id)
{
    if (!is_fragment(buf)) {
        return -1;
    }
    fragment_header_t *header = (fragment_header_t *)buf;
    header->meta.backend_id = (uint8_t)id;
    return 0;
}

int get_backend_id(char *buf, ec_backend_id_t *id)
{
    if (!is_fragment(buf)) {
        return -1;
    }
    fragment_header_t *header = (fragment_header_t *)buf;
    *id = header->meta.backend_id;
    return 0;
}

__attribute__((visibility("internal"))) int set_backend_version(char *buf, uint32_t version)
{
    if (!is_fragment(buf)) {
        return -1;
    }
    fragment_header_t *header = (fragment_header_t *)buf;
    header->meta.backend_version = version;
    return 0;
}

int get_backend_version(char *buf, uint32_t *version)
{
    if (!is_fragment(buf)) {
        return -1;
    }
    fragment_header_t *header = (fragment_header_t *)buf;
    *version = header->meta.backend_version;
    return 0;
}

/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */

__attribute__((visibility("internal"))) inline int set_checksum(
    ec_checksum_type_t ct, char *buf, int blocksize)
{
    fragment_header_t *header = (fragment_header_t *)buf;
    char *data = get_data_ptr_from_fragment(buf);
    char *flag;

    assert(NULL != header);
    if (header->magic != LIBERASURECODE_FRAG_HEADER_MAGIC) {
        log_error("Invalid fragment header (set chksum)!\n");
        return -1;
    }

    header->meta.chksum_type = ct;
    header->meta.chksum_mismatch = 0;

    switch (header->meta.chksum_type) {
    case CHKSUM_CRC32:
        flag = getenv("LIBERASURECODE_WRITE_LEGACY_CRC");
        if (flag && !(flag[0] == '\0' || (flag[0] == '0' && flag[1] == '\0'))) {
            header->meta.chksum[0] = liberasurecode_crc32_alt(0, data, blocksize);
        } else {
            header->meta.chksum[0] = crc32(0, (unsigned char *)data, blocksize);
        }
        break;
    case CHKSUM_MD5:
        break;
    case CHKSUM_NONE:
    default:
        break;
    }

    return 0;
}

/* ==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~==~=*=~== */

Web Proxy Viewer  |  New URL  |  Original Page