Improve maxavro failure handling and error messages

When the creation of the Avro schema would fail for a file that is being
opened, the errors wouldn't be handled properly. Also free all allocated
memory on failure.

All errors that set errno are now properly logged with the error number
and message.
This commit is contained in:
Markus Mäkelä
2017-01-26 15:45:41 +02:00
parent 84040be182
commit 8da655b7cb
2 changed files with 115 additions and 30 deletions

View File

@ -16,10 +16,31 @@
#include <string.h> #include <string.h>
#include <log_manager.h> #include <log_manager.h>
static bool maxavro_read_sync(FILE *file, uint8_t* sync) static bool maxavro_read_sync(FILE *file, uint8_t* sync)
{ {
return fread(sync, 1, SYNC_MARKER_SIZE, file) == SYNC_MARKER_SIZE; bool rval = true;
if (fread(sync, 1, SYNC_MARKER_SIZE, file) != SYNC_MARKER_SIZE)
{
rval = false;
if (ferror(file))
{
char err[STRERROR_BUFLEN];
MXS_ERROR("Failed to read file sync marker: %d, %s", errno,
strerror_r(errno, err, sizeof(err)));
}
else if (feof(file))
{
MXS_ERROR("Short read when reading file sync marker.");
}
else
{
MXS_ERROR("Unspecified error when reading file sync marker.");
}
}
return rval;
} }
bool maxavro_verify_block(MAXAVRO_FILE *file) bool maxavro_verify_block(MAXAVRO_FILE *file)
@ -72,12 +93,24 @@ bool maxavro_read_datablock_start(MAXAVRO_FILE* file)
if (rval) if (rval)
{ {
file->block_size = bytes; long pos = ftell(file->file);
file->records_in_block = records;
file->records_read_from_block = 0; if (pos == -1)
file->data_start_pos = ftell(file->file); {
ss_dassert(file->data_start_pos > file->block_start_pos); rval = false;
file->metadata_read = true; char err[STRERROR_BUFLEN];
MXS_ERROR("Failed to read datablock start: %d, %s", errno,
strerror_r(errno, err, sizeof(err)));
}
else
{
file->block_size = bytes;
file->records_in_block = records;
file->records_read_from_block = 0;
file->data_start_pos = pos;
ss_dassert(file->data_start_pos > file->block_start_pos);
file->metadata_read = true;
}
} }
else if (maxavro_get_error(file) != MAXAVRO_ERR_NONE) else if (maxavro_get_error(file) != MAXAVRO_ERR_NONE)
{ {
@ -153,35 +186,47 @@ MAXAVRO_FILE* maxavro_file_open(const char* filename)
return NULL; return NULL;
} }
MAXAVRO_FILE* avrofile = calloc(1, sizeof(MAXAVRO_FILE)); bool error = false;
if (avrofile) MAXAVRO_FILE* avrofile = calloc(1, sizeof(MAXAVRO_FILE));
char *my_filename = strdup(filename);
char *schema = read_schema(avrofile);
if (avrofile && my_filename && schema)
{ {
avrofile->file = file; avrofile->file = file;
avrofile->filename = strdup(filename); avrofile->filename = my_filename;
char *schema = read_schema(avrofile); avrofile->schema = maxavro_schema_alloc(schema);
avrofile->schema = schema ? maxavro_schema_alloc(schema) : NULL;
avrofile->last_error = MAXAVRO_ERR_NONE; avrofile->last_error = MAXAVRO_ERR_NONE;
if (!schema || !avrofile->schema || if (avrofile->schema &&
!maxavro_read_sync(file, avrofile->sync) || maxavro_read_sync(file, avrofile->sync) &&
!maxavro_read_datablock_start(avrofile)) maxavro_read_datablock_start(avrofile))
{
avrofile->header_end_pos = avrofile->block_start_pos;
}
else
{ {
MXS_ERROR("Failed to initialize avrofile."); MXS_ERROR("Failed to initialize avrofile.");
free(avrofile->schema); maxavro_schema_free(avrofile->schema);
free(avrofile); error = true;
avrofile = NULL;
} }
avrofile->header_end_pos = avrofile->block_start_pos;
free(schema);
} }
else else
{
error = true;
}
if (error)
{ {
fclose(file); fclose(file);
free(avrofile); free(avrofile);
free(my_filename);
avrofile = NULL; avrofile = NULL;
} }
free(schema);
return avrofile; return avrofile;
} }
@ -248,19 +293,43 @@ void maxavro_file_close(MAXAVRO_FILE *file)
GWBUF* maxavro_file_binary_header(MAXAVRO_FILE *file) GWBUF* maxavro_file_binary_header(MAXAVRO_FILE *file)
{ {
long pos = file->header_end_pos; long pos = file->header_end_pos;
fseek(file->file, 0, SEEK_SET); GWBUF *rval = NULL;
GWBUF *rval = gwbuf_alloc(pos);
if (rval) if (fseek(file->file, 0, SEEK_SET) == 0)
{ {
if (fread(GWBUF_DATA(rval), 1, pos, file->file) != pos) if ((rval = gwbuf_alloc(pos)))
{ {
gwbuf_free(rval); if (fread(GWBUF_DATA(rval), 1, pos, file->file) != pos)
rval = NULL; {
if (ferror(file->file))
{
char err[STRERROR_BUFLEN];
MXS_ERROR("Failed to read binary header: %d, %s", errno,
strerror_r(errno, err, sizeof(err)));
}
else if (feof(file->file))
{
MXS_ERROR("Short read when reading binary header.");
}
else
{
MXS_ERROR("Unspecified error when reading binary header.");
}
gwbuf_free(rval);
rval = NULL;
}
}
else
{
MXS_ERROR("Memory allocation failed when allocating %ld bytes.", pos);
} }
} }
else else
{ {
MXS_ERROR("Memory allocation failed when allocating %ld bytes.", pos); char err[STRERROR_BUFLEN];
MXS_ERROR("Failed to read binary header: %d, %s", errno,
strerror_r(errno, err, sizeof(err)));
} }
return rval; return rval;
} }

View File

@ -120,6 +120,7 @@ MAXAVRO_SCHEMA* maxavro_schema_alloc(const char* json)
if (rval) if (rval)
{ {
bool error = false;
json_error_t err; json_error_t err;
json_t *schema = json_loads(json, 0, &err); json_t *schema = json_loads(json, 0, &err);
@ -139,7 +140,7 @@ MAXAVRO_SCHEMA* maxavro_schema_alloc(const char* json)
char *key; char *key;
json_t *value_obj; json_t *value_obj;
if (json_unpack(object, "{s:s s:o}", "name", &key, "type", &value_obj) == 0) if (object && json_unpack(object, "{s:s s:o}", "name", &key, "type", &value_obj) == 0)
{ {
rval->fields[i].name = strdup(key); rval->fields[i].name = strdup(key);
rval->fields[i].type = unpack_to_type(value_obj, &rval->fields[i]); rval->fields[i].type = unpack_to_type(value_obj, &rval->fields[i]);
@ -147,26 +148,41 @@ MAXAVRO_SCHEMA* maxavro_schema_alloc(const char* json)
else else
{ {
MXS_ERROR("Failed to unpack JSON Object \"name\": %s", json); MXS_ERROR("Failed to unpack JSON Object \"name\": %s", json);
error = true;
for (int j = 0; j < i; j++)
{
free(rval->fields[j].name);
}
break;
} }
} }
} }
else else
{ {
MXS_ERROR("Failed to unpack JSON Object \"fields\": %s", json); MXS_ERROR("Failed to unpack JSON Object \"fields\": %s", json);
error = true;
} }
json_decref(schema); json_decref(schema);
} }
else else
{ {
MXS_ERROR("Failed to read JSON schema: %s", json); MXS_ERROR("Failed to read JSON schema: %s", json);
error = true;
}
if (error)
{
free(rval);
rval = NULL;
} }
} }
else else
{ {
MXS_ERROR("Memory allocation failed."); MXS_ERROR("Memory allocation failed.");
} }
return rval; return rval;
} }