/* * Copyright (c) 2016 MariaDB Corporation Ab * * Use of this software is governed by the Business Source License included * in the LICENSE.TXT file and at www.mariadb.com/bsl11. * * Change Date: 2019-07-01 * * On the date above, in accordance with the Business Source License, use * of this software will be governed by version 2 or later of the General * Public License. */ #include "maxavro.h" #include #include #include /** * @file maxavro_datablock.c - Experimental Avro interface for storing data * * TODO: Fix the code and take it into use if the Avro C client library is removed */ /** Encoding values in-memory */ uint64_t maxavro_encode_integer(uint8_t* buffer, uint64_t val); uint64_t maxavro_encode_string(uint8_t* dest, const char* str); uint64_t maxavro_encode_float(uint8_t* dest, float val); uint64_t maxavro_encode_double(uint8_t* dest, double val); /** Writing values straight to disk*/ bool maxavro_write_integer(FILE *file, uint64_t val); bool maxavro_write_string(FILE *file, const char* str); bool maxavro_write_float(FILE *file, float val); bool maxavro_write_double(FILE *file, double val); MAXAVRO_DATABLOCK* maxavro_datablock_allocate(MAXAVRO_FILE *file, size_t buffersize) { MAXAVRO_DATABLOCK *datablock = malloc(sizeof(MAXAVRO_DATABLOCK)); if (datablock && (datablock->buffer = malloc(buffersize))) { datablock->buffersize = buffersize; datablock->avrofile = file; datablock->datasize = 0; datablock->records = 0; } return datablock; } void maxavro_datablock_free(MAXAVRO_DATABLOCK* block) { if (block) { MXS_FREE(block->buffer); MXS_FREE(block); } } bool maxavro_datablock_finalize(MAXAVRO_DATABLOCK* block) { bool rval = true; FILE *file = block->avrofile->file; /** Store the current position so we can truncate the file if a write fails */ long pos = ftell(file); if (!maxavro_write_integer(file, block->records) || !maxavro_write_integer(file, block->datasize) || fwrite(block->buffer, 1, block->datasize, file) != block->datasize || fwrite(block->avrofile->sync, 1, SYNC_MARKER_SIZE, file) != SYNC_MARKER_SIZE) { int fd = fileno(file); ftruncate(fd, pos); fseek(file, 0, SEEK_END); rval = false; } else { /** The current block is successfully written, reset datablock for * a new write. */ block->buffersize = 0; block->records = 0; } return rval; } static bool reallocate_datablock(MAXAVRO_DATABLOCK *block) { void *tmp = realloc(block->buffer, block->buffersize * 2); if (tmp == NULL) { return false; } block->buffer = tmp; block->buffersize *= 2; return true; } bool maxavro_datablock_add_integer(MAXAVRO_DATABLOCK *block, uint64_t val) { if (block->datasize + 9 >= block->buffersize && !reallocate_datablock(block)) { return false; } uint64_t added = maxavro_encode_integer(block->buffer + block->datasize, val); block->datasize += added; return true; } bool maxavro_datablock_add_string(MAXAVRO_DATABLOCK *block, const char* str) { if (block->datasize + 9 + strlen(str) >= block->buffersize && !reallocate_datablock(block)) { return false; } uint64_t added = maxavro_encode_string(block->buffer + block->datasize, str); block->datasize += added; return true; } bool maxavro_datablock_add_float(MAXAVRO_DATABLOCK *block, float val) { if (block->datasize + sizeof(val) >= block->buffersize && !reallocate_datablock(block)) { return false; } uint64_t added = maxavro_encode_float(block->buffer + block->datasize, val); block->datasize += added; return true; } bool maxavro_datablock_add_double(MAXAVRO_DATABLOCK *block, double val) { if (block->datasize + sizeof(val) >= block->buffersize && !reallocate_datablock(block)) { return false; } uint64_t added = maxavro_encode_double(block->buffer + block->datasize, val); block->datasize += added; return true; }