diff --git a/Makefile b/Makefile index aa69933..0e0336b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ BSLZ4_BUILD_DIR = ./bslz4/build BSLZ4_INC_DIR = $(BSLZ4_SRC_DIR) CC=h5cc -CFLAGS=-DH5_USE_110_API -Wall -g -O2 -fpic -I$(INC_DIR) -I$(BSLZ4_INC_DIR) -std=c89 -shlib +CFLAGS=-DH5_USE_110_API -Wall -g -O2 -fpic -I$(INC_DIR) -I$(BSLZ4_INC_DIR) -std=c99 -shlib .PHONY: plugin plugin: $(BUILD_DIR)/durin-plugin.so diff --git a/src/err.c b/src/err.c index 567f36e..bd38831 100644 --- a/src/err.c +++ b/src/err.c @@ -3,19 +3,18 @@ * Author: Charles Mita */ - -#include #include +#include + #include "err.h" - struct error_stack_t { - char **files; - char **funcs; - int *lines; - int *errors; - char **messages; - int size; + char **files; + char **funcs; + int *lines; + int *errors; + char **messages; + int size; }; static char files_buffer[ERR_MAX_FILENAME_LENGTH * ERR_MAX_STACK_SIZE] = {0}; @@ -30,89 +29,89 @@ static char *messages[ERR_MAX_STACK_SIZE] = {0}; static struct error_stack_t stack = {files, funcs, lines, errors, messages, 0}; +void push_error_stack(const char *file, const char *func, int line, int err, + const char *message) { + if (stack.size >= ERR_MAX_STACK_SIZE) + return; /* unfortunate */ + int idx = stack.size; -void push_error_stack(const char *file, const char *func, int line, int err, const char *message) { - if (stack.size >= ERR_MAX_STACK_SIZE) return; /* unfortunate */ - int idx = stack.size; + /* subtract 1 to ensure room for null byte in buffer */ + sprintf(stack.funcs[idx], "%.*s", ERR_MAX_FUNCNAME_LENGTH - 1, func); + sprintf(stack.files[idx], "%.*s", ERR_MAX_FILENAME_LENGTH - 1, file); + sprintf(stack.messages[idx], "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, message); + stack.lines[idx] = line; + stack.errors[idx] = err; - /* subtract 1 to ensure room for null byte in buffer */ - sprintf(stack.funcs[idx], "%.*s", ERR_MAX_FUNCNAME_LENGTH - 1, func); - sprintf(stack.files[idx], "%.*s", ERR_MAX_FILENAME_LENGTH - 1, file); - sprintf(stack.messages[idx], "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, message); - stack.lines[idx] = line; - stack.errors[idx] = err; - - stack.size++; + stack.size++; } - -herr_t h5e_walk_callback(unsigned int n, const struct H5E_error2_t *err, void *client_data) { - herr_t retval = 0; - /* only read the message for the innermost stack frame - the rest are just noise */ - if (n == 0) { - char message[ERR_MAX_MESSAGE_LENGTH] = {0}; - sprintf(message, "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, err->desc); - push_error_stack(err->file_name, err->func_name, err->line, -1, message); - } else { - push_error_stack(err->file_name, err->func_name, err->line, -1, ""); - } - return retval; +herr_t h5e_walk_callback(unsigned int n, const struct H5E_error2_t *err, + void *client_data) { + herr_t retval = 0; + /* only read the message for the innermost stack frame - the rest are just + * noise */ + if (n == 0) { + char message[ERR_MAX_MESSAGE_LENGTH] = {0}; + sprintf(message, "%.*s", ERR_MAX_MESSAGE_LENGTH - 1, err->desc); + push_error_stack(err->file_name, err->func_name, err->line, -1, message); + } else { + push_error_stack(err->file_name, err->func_name, err->line, -1, ""); + } + return retval; } - int h5e_error_callback(hid_t stack_id, void *client_data) { - int retval = 0; - herr_t err = 0; - err = H5Ewalk2(stack_id, H5E_WALK_UPWARD, &h5e_walk_callback, client_data); - if (err < 0) { - ERROR_JUMP(err, done, "Error walking HDF5 Error stack"); - } + int retval = 0; + herr_t err = 0; + err = H5Ewalk2(stack_id, H5E_WALK_UPWARD, &h5e_walk_callback, client_data); + if (err < 0) { + ERROR_JUMP(err, done, "Error walking HDF5 Error stack"); + } done: - return retval; + return retval; } - void reset_error_stack() { - stack.size = 0; - H5Eclear2(H5E_DEFAULT); /* almost certainly unnecessary */ + stack.size = 0; + H5Eclear2(H5E_DEFAULT); /* almost certainly unnecessary */ } - void dump_error_stack(FILE *out) { - int idx = stack.size; - if (idx > 0) fprintf(out, "Durin plugin error:\n"); - while (idx-- > 0) { - const char *file = stack.files[idx]; - const char *func = stack.funcs[idx]; - const char *message = stack.messages[idx]; - const int line = stack.lines[idx]; - if (message[0] != '\0') { - fprintf(out, "\t%s - line %d in %s:\n\t\t%s\n", file, line, func, message); - } else { - fprintf(out, "\t%s - line %d in %s\n", file, line, func); - } - } + int idx = stack.size; + if (idx > 0) + fprintf(out, "Durin plugin error:\n"); + while (idx-- > 0) { + const char *file = stack.files[idx]; + const char *func = stack.funcs[idx]; + const char *message = stack.messages[idx]; + const int line = stack.lines[idx]; + if (message[0] != '\0') { + fprintf(out, "\t%s - line %d in %s:\n\t\t%s\n", file, line, func, + message); + } else { + fprintf(out, "\t%s - line %d in %s\n", file, line, func); + } + } } - int init_h5_error_handling() { - int retval = 0; - hid_t err = 0; - if ((err = H5Eset_auto2(H5E_DEFAULT, &h5e_error_callback, NULL)) < 0) { - ERROR_JUMP(err, done, "Error configuring HDF5 error callback"); - } + int retval = 0; + hid_t err = 0; + if ((err = H5Eset_auto2(H5E_DEFAULT, &h5e_error_callback, NULL)) < 0) { + ERROR_JUMP(err, done, "Error configuring HDF5 error callback"); + } done: - return retval; + return retval; } int init_error_handling() { - int retval = 0; - int idx = 0; - while (idx < ERR_MAX_STACK_SIZE) { - stack.files[idx] = files_buffer + (idx * ERR_MAX_FILENAME_LENGTH); - stack.funcs[idx] = funcs_buffer + (idx * ERR_MAX_FUNCNAME_LENGTH); - stack.messages[idx] = messages_buffer + (idx * ERR_MAX_MESSAGE_LENGTH); - idx++; - } - return retval; + int retval = 0; + int idx = 0; + while (idx < ERR_MAX_STACK_SIZE) { + stack.files[idx] = files_buffer + (idx * ERR_MAX_FILENAME_LENGTH); + stack.funcs[idx] = funcs_buffer + (idx * ERR_MAX_FUNCNAME_LENGTH); + stack.messages[idx] = messages_buffer + (idx * ERR_MAX_MESSAGE_LENGTH); + idx++; + } + return retval; } diff --git a/src/err.h b/src/err.h index 5830cc1..b342a2c 100644 --- a/src/err.h +++ b/src/err.h @@ -3,46 +3,44 @@ * Author: Charles Mita */ - #ifndef NXS_XDS_ERR_H #define NXS_XDS_ERR_H - #define ERR_MAX_FILENAME_LENGTH 64 #define ERR_MAX_FUNCNAME_LENGTH 128 #define ERR_MAX_MESSAGE_LENGTH 1024 #define ERR_MAX_STACK_SIZE 128 - /* obtain __func__ from GCC if no C99 */ #if __STDC_VERSION__ < 199901L -# if __GNUC__ >= 2 -# define __func__ __FUNCTION__ -# else -# define __func__ "" -# endif +#if __GNUC__ >= 2 +#define __func__ __FUNCTION__ +#else +#define __func__ "" +#endif #endif #if __GNUC__ >= 2 -# define __line__ __LINE__ +#define __line__ __LINE__ #else -# define __line__ 0 +#define __line__ 0 #endif #if __GNUC__ >= 2 -# define __file__ __FILE__ +#define __file__ __FILE__ #else -# define __file__ "unknown" +#define __file__ "unknown" #endif -#define ERROR_JUMP(err, target, message) \ -{ \ - push_error_stack(__file__, __func__, __line__, err, message); \ - retval = err; \ - goto target; \ -} +#define ERROR_JUMP(err, target, message) \ + { \ + push_error_stack(__file__, __func__, __line__, err, message); \ + retval = err; \ + goto target; \ + } -void push_error_stack(const char *file, const char *func, int line, int err, const char *message); +void push_error_stack(const char *file, const char *func, int line, int err, + const char *message); void dump_error_stack(FILE *out); diff --git a/src/file.c b/src/file.c index aa8bb71..8722518 100644 --- a/src/file.c +++ b/src/file.c @@ -3,931 +3,940 @@ * Author: Charles Mita */ - #include #include #include #include #include #include -#include "file.h" + #include "err.h" +#include "file.h" #include "filters.h" - void clear_det_visit_objects(struct det_visit_objects_t *objects) { - if (objects->nxdata) { - H5Oclose(objects->nxdata); - objects->nxdata = 0; - } - if (objects->nxdetector) { - H5Oclose(objects->nxdetector); - objects->nxdetector = 0; - } + if (objects->nxdata) { + H5Oclose(objects->nxdata); + objects->nxdata = 0; + } + if (objects->nxdetector) { + H5Oclose(objects->nxdetector); + objects->nxdetector = 0; + } } - void free_ds_desc(struct ds_desc_t *desc) { - H5Gclose(desc->det_g_id); - H5Gclose(desc->data_g_id); - free(desc); + H5Gclose(desc->det_g_id); + H5Gclose(desc->data_g_id); + free(desc); } -void free_nxs_desc(struct ds_desc_t *desc) { - free_ds_desc(desc); -} +void free_nxs_desc(struct ds_desc_t *desc) { free_ds_desc(desc); } void free_eiger_desc(struct ds_desc_t *desc) { - struct eiger_ds_desc_t *e_desc = (struct eiger_ds_desc_t *) desc; - free(e_desc->block_sizes); - free_ds_desc(desc); + struct eiger_ds_desc_t *e_desc = (struct eiger_ds_desc_t *)desc; + free(e_desc->block_sizes); + free_ds_desc(desc); } -void free_opt_eiger_desc(struct ds_desc_t *desc) { - free_eiger_desc(desc); -} +void free_opt_eiger_desc(struct ds_desc_t *desc) { free_eiger_desc(desc); } - -double scale_from_units(const char* unit_string) { - if (strcasecmp("m", unit_string) == 0 || - strcasecmp("metres", unit_string) == 0 || - strcasecmp("meters", unit_string) == 0) { - return 1.; - } else if (strcasecmp("cm", unit_string) == 0 || - strcasecmp("centimetres", unit_string) == 0 || - strcasecmp("centimeters", unit_string) == 0) { - return 0.01; - } else if (strcasecmp("mm", unit_string) == 0 || - strcasecmp("millimetres", unit_string) == 0 || - strcasecmp("millimeters", unit_string) == 0) { - return 0.001; - } else if (strcasecmp("um", unit_string) == 0 || - strcasecmp("microns", unit_string) == 0 || - strcasecmp("micrometres", unit_string) == 0 || - strcasecmp("micrometers", unit_string) == 0) { - return 0.000001; - } else { - fprintf(stderr, "Unrecognised unit string %s", unit_string); - return 1; - } +double scale_from_units(const char *unit_string) { + if (strcasecmp("m", unit_string) == 0 || + strcasecmp("metres", unit_string) == 0 || + strcasecmp("meters", unit_string) == 0) { + return 1.; + } else if (strcasecmp("cm", unit_string) == 0 || + strcasecmp("centimetres", unit_string) == 0 || + strcasecmp("centimeters", unit_string) == 0) { + return 0.01; + } else if (strcasecmp("mm", unit_string) == 0 || + strcasecmp("millimetres", unit_string) == 0 || + strcasecmp("millimeters", unit_string) == 0) { + return 0.001; + } else if (strcasecmp("um", unit_string) == 0 || + strcasecmp("microns", unit_string) == 0 || + strcasecmp("micrometres", unit_string) == 0 || + strcasecmp("micrometers", unit_string) == 0) { + return 0.000001; + } else { + fprintf(stderr, "Unrecognised unit string %s", unit_string); + return 1; + } } int get_nxs_dataset_dims(struct ds_desc_t *desc) { - hid_t g_id, ds_id, s_id, t_id; - int retval = 0; - int ndims = 0; - int width = 0; - g_id = desc->data_g_id;; + hid_t g_id, ds_id, s_id, t_id; + int retval = 0; + int ndims = 0; + int width = 0; + g_id = desc->data_g_id; + ; - ds_id = H5Dopen2(g_id, "data", H5P_DEFAULT); - if (ds_id <= 0) { - ERROR_JUMP(-1, done, "Unable to open 'data' dataset"); - } + ds_id = H5Dopen2(g_id, "data", H5P_DEFAULT); + if (ds_id <= 0) { + ERROR_JUMP(-1, done, "Unable to open 'data' dataset"); + } - t_id = H5Dget_type(ds_id); - if (t_id <= 0) { - ERROR_JUMP(-1, close_dataset, "Error getting datatype"); - } + t_id = H5Dget_type(ds_id); + if (t_id <= 0) { + ERROR_JUMP(-1, close_dataset, "Error getting datatype"); + } - width = H5Tget_size(t_id); - if (width <= 0) { - ERROR_JUMP(-1, close_type, "Error getting type size"); - } + width = H5Tget_size(t_id); + if (width <= 0) { + ERROR_JUMP(-1, close_type, "Error getting type size"); + } - s_id = H5Dget_space(ds_id); - if (s_id <= 0) { - ERROR_JUMP(-1, close_dataset, "Error getting dataspace"); - } + s_id = H5Dget_space(ds_id); + if (s_id <= 0) { + ERROR_JUMP(-1, close_dataset, "Error getting dataspace"); + } - ndims = H5Sget_simple_extent_ndims(s_id); - if (ndims != 3) { - char message[64]; - sprintf(message, "Dataset rank is %d, expected %d", ndims, 3); - ERROR_JUMP(-1, close_space, message); - } + ndims = H5Sget_simple_extent_ndims(s_id); + if (ndims != 3) { + char message[64]; + sprintf(message, "Dataset rank is %d, expected %d", ndims, 3); + ERROR_JUMP(-1, close_space, message); + } - if (H5Sget_simple_extent_dims(s_id, desc->dims, NULL) < 0) { - ERROR_JUMP(-1, close_space, "Error getting dataset dimensions"); - } + if (H5Sget_simple_extent_dims(s_id, desc->dims, NULL) < 0) { + ERROR_JUMP(-1, close_space, "Error getting dataset dimensions"); + } - desc->data_width = width; + desc->data_width = width; close_space: - H5Sclose(s_id); + H5Sclose(s_id); close_type: - H5Tclose(t_id); + H5Tclose(t_id); close_dataset: - H5Dclose(ds_id); + H5Dclose(ds_id); done: - return retval; + return retval; } -int get_frame_simple(const struct ds_desc_t *desc, - const char *name, - const hsize_t *frame_idx, - const hsize_t *frame_size, - void *buffer) { +int get_frame_simple(const struct ds_desc_t *desc, const char *name, + const hsize_t *frame_idx, const hsize_t *frame_size, + void *buffer) { - int retval = 0; - herr_t err = 0; - hid_t g_id, ds_id, s_id, ms_id, t_id; + int retval = 0; + herr_t err = 0; + hid_t g_id, ds_id, s_id, ms_id, t_id; - g_id = desc->data_g_id; + g_id = desc->data_g_id; - ds_id = H5Dopen2(g_id, name, H5P_DEFAULT); - if (ds_id <= 0) { - char message[64]; - sprintf(message, "Unable to open dataset %.32s", name); - ERROR_JUMP(-1, done, message); - } - s_id = H5Dget_space(ds_id); - if (s_id <= 0) { - ERROR_JUMP(-1, close_dataset, "Error getting dataspace"); - } - t_id = H5Dget_type(ds_id); - if (t_id <= 0) { - ERROR_JUMP(-1, close_type, "Error retrieving datatype"); - } - err = H5Sselect_hyperslab(s_id, H5S_SELECT_SET, frame_idx, NULL, frame_size, NULL); - if (err < 0) { - ERROR_JUMP(-1, close_space, "Error seleting hyperslab"); - } - ms_id = H5Screate_simple(3, frame_size, frame_size); - if (ms_id < 0) { - ERROR_JUMP(-1, close_space, "Could not create dataspace"); - } + ds_id = H5Dopen2(g_id, name, H5P_DEFAULT); + if (ds_id <= 0) { + char message[64]; + sprintf(message, "Unable to open dataset %.32s", name); + ERROR_JUMP(-1, done, message); + } + s_id = H5Dget_space(ds_id); + if (s_id <= 0) { + ERROR_JUMP(-1, close_dataset, "Error getting dataspace"); + } + t_id = H5Dget_type(ds_id); + if (t_id <= 0) { + ERROR_JUMP(-1, close_type, "Error retrieving datatype"); + } + err = H5Sselect_hyperslab(s_id, H5S_SELECT_SET, frame_idx, NULL, frame_size, + NULL); + if (err < 0) { + ERROR_JUMP(-1, close_space, "Error seleting hyperslab"); + } + ms_id = H5Screate_simple(3, frame_size, frame_size); + if (ms_id < 0) { + ERROR_JUMP(-1, close_space, "Could not create dataspace"); + } - err = H5Dread(ds_id, t_id, ms_id, s_id, H5P_DEFAULT, buffer); - if (err < 0) { - ERROR_JUMP(-1, close_mspace, "Error reading dataset"); - } + err = H5Dread(ds_id, t_id, ms_id, s_id, H5P_DEFAULT, buffer); + if (err < 0) { + ERROR_JUMP(-1, close_mspace, "Error reading dataset"); + } close_mspace: - H5Sclose(ms_id); + H5Sclose(ms_id); close_space: - H5Sclose(s_id); + H5Sclose(s_id); close_type: - H5Tclose(t_id); + H5Tclose(t_id); close_dataset: - H5Dclose(ds_id); + H5Dclose(ds_id); done: - return retval; + return retval; } +int get_frame_from_chunk(const struct ds_desc_t *desc, const char *ds_name, + const hsize_t *frame_idx, const hsize_t *frame_size, + void *buffer) { -int get_frame_from_chunk(const struct ds_desc_t *desc, - const char *ds_name, - const hsize_t *frame_idx, - const hsize_t *frame_size, - void *buffer) { + hid_t d_id = 0; + hsize_t c_offset[3] = {frame_idx[0], 0, 0}; + uint32_t c_filter_mask = 0; + hsize_t c_bytes; + void *c_buffer = NULL; + const struct opt_eiger_ds_desc_t *o_eiger_desc = + (struct opt_eiger_ds_desc_t *)desc; + int retval = 0; - hid_t d_id = 0; - hsize_t c_offset[3] = {frame_idx[0], 0, 0}; - uint32_t c_filter_mask = 0; - hsize_t c_bytes; - void *c_buffer = NULL; - const struct opt_eiger_ds_desc_t *o_eiger_desc = (struct opt_eiger_ds_desc_t *) desc; - int retval = 0; + if (frame_idx[1] != 0 || frame_idx[2] != 0) { + char message[64]; + sprintf(message, + "Require frame selection starts at [n, 0, 0], not [n, %llu, %llu]", + frame_idx[1], frame_idx[2]); + ERROR_JUMP(-1, done, message); + } - if (frame_idx[1] != 0 || frame_idx[2] != 0) { - char message[64]; - sprintf(message, "Require frame selection starts at [n, 0, 0], not [n, %llu, %llu]", - frame_idx[1], frame_idx[2]); - ERROR_JUMP(-1, done, message); - } + d_id = H5Dopen(desc->data_g_id, ds_name, H5P_DEFAULT); + if (d_id < 0) { + char message[64]; + sprintf(message, "Error opening dataset %.32s", ds_name); + ERROR_JUMP(-1, done, message); + } - d_id = H5Dopen(desc->data_g_id, ds_name, H5P_DEFAULT); - if (d_id < 0) { - char message[64]; - sprintf(message, "Error opening dataset %.32s", ds_name); - ERROR_JUMP(-1, done, message); - } + if (H5Dget_chunk_storage_size(d_id, c_offset, &c_bytes) < 0) { + char message[96]; + sprintf(message, "Error reading chunk size from %.32s for frame %llu", + ds_name, frame_idx[0]); + ERROR_JUMP(-1, done, message); + } + if (c_bytes == 0) { + char message[96]; + sprintf(message, "Target chunk %llu has zero size for dataset %.32s", + frame_idx[0], ds_name); + ERROR_JUMP(-1, done, message); + } + if (o_eiger_desc->bs_applied) { + c_buffer = malloc(c_bytes); + if (!c_buffer) { + char message[128]; + sprintf(message, + "Unable to allocate chunk buffer for dataset %.32s - frame %llu, " + "size %llu bytes", + ds_name, frame_idx[0], c_bytes); + ERROR_JUMP(-1, done, message); + } + } else { + c_buffer = buffer; + } - if (H5Dget_chunk_storage_size(d_id, c_offset, &c_bytes) < 0) { - char message[96]; - sprintf(message, "Error reading chunk size from %.32s for frame %llu", ds_name, frame_idx[0]); - ERROR_JUMP(-1, done, message); - } - if (c_bytes == 0) { - char message[96]; - sprintf(message, "Target chunk %llu has zero size for dataset %.32s", frame_idx[0], ds_name); - ERROR_JUMP(-1, done, message); - } + if (H5DOread_chunk(d_id, H5P_DEFAULT, c_offset, &c_filter_mask, c_buffer) < + 0) { + char message[128]; + sprintf(message, + "Error reading chunk %llu from dataset %.32s - size %llu bytes", + frame_idx[0], ds_name, c_bytes); + ERROR_JUMP(-1, done, message); + } - if (o_eiger_desc->bs_applied) { - c_buffer = malloc(c_bytes); - if (!c_buffer) { - char message[128]; - sprintf(message, "Unable to allocate chunk buffer for dataset %.32s - frame %llu, size %llu bytes", - ds_name, frame_idx[0], c_bytes); - ERROR_JUMP(-1, done, message); - } - } else { - c_buffer = buffer; - } - - if (H5DOread_chunk(d_id, H5P_DEFAULT, c_offset, &c_filter_mask, c_buffer) < 0) { - char message[128]; - sprintf(message, "Error reading chunk %llu from dataset %.32s - size %llu bytes", - frame_idx[0], ds_name, c_bytes); - ERROR_JUMP(-1, done, message); - } - - if (o_eiger_desc->bs_applied) { - if (bslz4_decompress( - o_eiger_desc->bs_params, - c_bytes, - c_buffer, - desc->data_width * frame_size[1] * frame_size[2], - buffer) < 0) { - char message[128]; - sprintf(message, "Error processing chunk %llu from %.32s with bitshuffle_lz4", - frame_idx[0], ds_name); - ERROR_JUMP(-1, done, message); - } - } + if (o_eiger_desc->bs_applied) { + if (bslz4_decompress(o_eiger_desc->bs_params, c_bytes, c_buffer, + desc->data_width * frame_size[1] * frame_size[2], + buffer) < 0) { + char message[128]; + sprintf(message, + "Error processing chunk %llu from %.32s with bitshuffle_lz4", + frame_idx[0], ds_name); + ERROR_JUMP(-1, done, message); + } + } done: - if (c_buffer && (c_buffer != buffer)) free(c_buffer); - if (d_id) H5Dclose(d_id); - return retval; + if (c_buffer && (c_buffer != buffer)) + free(c_buffer); + if (d_id) + H5Dclose(d_id); + return retval; } - -int get_nxs_frame( - const struct ds_desc_t *desc, - const int nin, - void *buffer) { - /* detector data are the two inner most indices */ - /* TODO: handle ndims > 3 and select appropriately */ - int retval = 0; - int n = nin - desc->image_number_offset; - hsize_t frame_idx[3] = {n, 0, 0}; - hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]}; - if (n < 0 || n >= desc->dims[0]) { - char message[64]; - sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, (int) desc->dims[0] - 1); - ERROR_JUMP(-1, done, message); - } - retval = get_frame_simple(desc, "data", frame_idx, frame_size, buffer); - if (retval < 0) { - ERROR_JUMP(retval, done, ""); - } +int get_nxs_frame(const struct ds_desc_t *desc, const int nin, void *buffer) { + /* detector data are the two inner most indices */ + /* TODO: handle ndims > 3 and select appropriately */ + int retval = 0; + int n = nin - desc->image_number_offset; + hsize_t frame_idx[3] = {n, 0, 0}; + hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]}; + if (n < 0 || n >= desc->dims[0]) { + char message[64]; + sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, + (int)desc->dims[0] - 1); + ERROR_JUMP(-1, done, message); + } + retval = get_frame_simple(desc, "data", frame_idx, frame_size, buffer); + if (retval < 0) { + ERROR_JUMP(retval, done, ""); + } done: - return retval; + return retval; } +int get_dectris_eiger_frame(const struct ds_desc_t *desc, int nin, void *buffer) { -int get_dectris_eiger_frame( - const struct ds_desc_t *desc, - int nin, - void *buffer) { + int retval = 0; + int n = nin - desc->image_number_offset; + int block, frame_count, idx; + struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t *)desc; + char data_name[16] = {0}; + hsize_t frame_idx[3] = {0, 0, 0}; + hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]}; - int retval = 0; - int n = nin - desc->image_number_offset; - int block, frame_count, idx; - struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t*) desc; - char data_name[16] = {0}; - hsize_t frame_idx[3] = {0, 0, 0}; - hsize_t frame_size[3] = {1, desc->dims[1], desc->dims[2]}; + if (n < 0 || n >= desc->dims[0]) { + char message[64]; + sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, + (int)desc->dims[0] - 1); + ERROR_JUMP(-1, done, message); + } - if (n < 0 || n >= desc->dims[0]) { - char message[64]; - sprintf(message, "Selected frame %d is out of range valid range [0, %d]", n, (int) desc->dims[0] - 1); - ERROR_JUMP(-1, done, message); - } - - /* determine the relevant data block */ - frame_count = 0; - block = 0; - while ((frame_count += eiger_desc->block_sizes[block]) <= n) block++; - idx = n - (frame_count - eiger_desc->block_sizes[block]); /* index in current block */ - frame_idx[0] = idx; - sprintf(data_name, "data_%06d", block + 1); - retval = eiger_desc->frame_func(desc, data_name, frame_idx, frame_size, buffer); - if (retval < 0) { - ERROR_JUMP(retval, done, ""); - } + /* determine the relevant data block */ + frame_count = 0; + block = 0; + while ((frame_count += eiger_desc->block_sizes[block]) <= n) + block++; + idx = n - (frame_count - + eiger_desc->block_sizes[block]); /* index in current block */ + frame_idx[0] = idx; + sprintf(data_name, "data_%06d", block + 1); + retval = + eiger_desc->frame_func(desc, data_name, frame_idx, frame_size, buffer); + if (retval < 0) { + ERROR_JUMP(retval, done, ""); + } done: - return retval; + return retval; } - int get_dectris_eiger_dataset_dims(struct ds_desc_t *desc) { - int retval = 0; - int n_datas = 0; - int n = 0; - int data_width = 0; - int ndims = 3; - char ds_name[16] = {0}; /* 12 chars in "data_xxxxxx\0" */ - int *frame_counts = NULL; - hsize_t dims[3] = {0}; - struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t*) desc; + int retval = 0; + int n_datas = 0; + int n = 0; + int data_width = 0; + int ndims = 3; + char ds_name[16] = {0}; /* 12 chars in "data_xxxxxx\0" */ + int *frame_counts = NULL; + hsize_t dims[3] = {0}; + struct eiger_ds_desc_t *eiger_desc = (struct eiger_ds_desc_t *)desc; - /* datasets are "data_%06d % n" - need to determine how many of these there are and what the ranges are */ + /* datasets are "data_%06d % n" - need to determine how many of these there + * are and what the ranges are */ - sprintf(ds_name, "data_%06d", n_datas + 1); - while (H5Lexists(desc->data_g_id, ds_name, H5P_DEFAULT) > 0) { - sprintf(ds_name, "data_%06d", ++n_datas + 1); - } + sprintf(ds_name, "data_%06d", n_datas + 1); + while (H5Lexists(desc->data_g_id, ds_name, H5P_DEFAULT) > 0) { + sprintf(ds_name, "data_%06d", ++n_datas + 1); + } - frame_counts = malloc(n_datas * sizeof(*frame_counts)); + frame_counts = malloc(n_datas * sizeof(*frame_counts)); - for (n = 0; n < n_datas; n++) { - hid_t ds_id, t_id, s_id; - hsize_t block_dims[3] = {0}; - sprintf(ds_name, "data_%06d", n + 1); - ds_id = H5Dopen2(desc->data_g_id, ds_name, H5P_DEFAULT); - if (ds_id < 0) { - char message[64]; - sprintf(message, "Unable to open dataset %.16s", ds_name); - ERROR_JUMP(-1, loop_end, message); - } - t_id = H5Dget_type(ds_id); - if (t_id < 0) { - ERROR_JUMP(-1, close_dataset, "Unable to get datatype") - } - s_id = H5Dget_space(ds_id); - if (s_id < 0) { - ERROR_JUMP(-1, close_type, "Unable to get dataspace"); - } + for (n = 0; n < n_datas; n++) { + hid_t ds_id, t_id, s_id; + hsize_t block_dims[3] = {0}; + sprintf(ds_name, "data_%06d", n + 1); + ds_id = H5Dopen2(desc->data_g_id, ds_name, H5P_DEFAULT); + if (ds_id < 0) { + char message[64]; + sprintf(message, "Unable to open dataset %.16s", ds_name); + ERROR_JUMP(-1, loop_end, message); + } + t_id = H5Dget_type(ds_id); + if (t_id < 0) { + ERROR_JUMP(-1, close_dataset, "Unable to get datatype") + } + s_id = H5Dget_space(ds_id); + if (s_id < 0) { + ERROR_JUMP(-1, close_type, "Unable to get dataspace"); + } - data_width = H5Tget_size(t_id); - if (data_width <= 0) { - ERROR_JUMP(-1, close_space, "Unable to get type size"); - } + data_width = H5Tget_size(t_id); + if (data_width <= 0) { + ERROR_JUMP(-1, close_space, "Unable to get type size"); + } - ndims = H5Sget_simple_extent_ndims(s_id); - if (ndims != 3) { - char message[64]; - sprintf(message, "Dataset %.16s has rank %d, expected %d", ds_name, ndims, 3); - ERROR_JUMP(-1, close_space, message); - } - if (H5Sget_simple_extent_dims(s_id, block_dims, NULL) < 0) { - ERROR_JUMP(-1, close_space, "Unable to read dataset dimensions"); - } + ndims = H5Sget_simple_extent_ndims(s_id); + if (ndims != 3) { + char message[64]; + sprintf(message, "Dataset %.16s has rank %d, expected %d", ds_name, ndims, + 3); + ERROR_JUMP(-1, close_space, message); + } + if (H5Sget_simple_extent_dims(s_id, block_dims, NULL) < 0) { + ERROR_JUMP(-1, close_space, "Unable to read dataset dimensions"); + } - dims[1] = block_dims[1]; - dims[2] = block_dims[2]; + dims[1] = block_dims[1]; + dims[2] = block_dims[2]; - dims[0] += block_dims[0]; - frame_counts[n] = block_dims[0]; + dims[0] += block_dims[0]; + frame_counts[n] = block_dims[0]; -close_space: - H5Sclose(s_id); -close_type: - H5Tclose(t_id); -close_dataset: - H5Dclose(ds_id); -loop_end: - if (retval < 0) break; - } + close_space: + H5Sclose(s_id); + close_type: + H5Tclose(t_id); + close_dataset: + H5Dclose(ds_id); + loop_end: + if (retval < 0) + break; + } - if (retval < 0) { - free(frame_counts); - } else { - memcpy(desc->dims, dims, 3 * sizeof(*dims)); - desc->data_width = data_width; - eiger_desc->n_data_blocks = n_datas; - eiger_desc->block_sizes = frame_counts; - } - return retval; + if (retval < 0) { + free(frame_counts); + } else { + memcpy(desc->dims, dims, 3 * sizeof(*dims)); + desc->data_width = data_width; + eiger_desc->n_data_blocks = n_datas; + eiger_desc->block_sizes = frame_counts; + } + return retval; } - int read_pixel_info(hid_t g_id, const char *path, double *size) { - /* - * NXdetector allows pixel size to be an array (for varied pixel size), - * however XDS only allows for a single value. - * TODO: handle array case (return first value maybe?) - */ + /* + * NXdetector allows pixel size to be an array (for varied pixel size), + * however XDS only allows for a single value. + * TODO: handle array case (return first value maybe?) + */ - /* read the scalar dataset value and scale according to the unit in the attribute */ - /* returned value is in metres */ - int retval = 0; - herr_t err = 0; - hid_t ds_id; - double value = 0; - ds_id = H5Dopen2(g_id, path, H5P_DEFAULT); - if (ds_id < 0) { - char message[64]; - sprintf(message, "Error opening dataset %.32s", path); - ERROR_JUMP(-1, done, message); - } + /* read the scalar dataset value and scale according to the unit in the + * attribute */ + /* returned value is in metres */ + int retval = 0; + herr_t err = 0; + hid_t ds_id; + double value = 0; + ds_id = H5Dopen2(g_id, path, H5P_DEFAULT); + if (ds_id < 0) { + char message[64]; + sprintf(message, "Error opening dataset %.32s", path); + ERROR_JUMP(-1, done, message); + } - err = H5Dread(ds_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value); - if (err < 0) { - char message[64]; - sprintf(message, "Error reading dataset %.32s", path); - ERROR_JUMP(-1, close_dataset, message); - } + err = + H5Dread(ds_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value); + if (err < 0) { + char message[64]; + sprintf(message, "Error reading dataset %.32s", path); + ERROR_JUMP(-1, close_dataset, message); + } - if (H5Aexists(ds_id, "units") > 0) { - /* string may be variable length */ - hid_t a_id, t_id, mt_id; - void *str_buffer = NULL; - int str_size = -1; - double scale = 1; - a_id = H5Aopen(ds_id, "units", H5P_DEFAULT); - if (a_id < 0) { - char message[100]; - sprintf(message, "Error openeing units attribute for %.32s after existence check", path); - ERROR_JUMP(-1, close_dataset, message); - } + if (H5Aexists(ds_id, "units") > 0) { + /* string may be variable length */ + hid_t a_id, t_id, mt_id; + void *str_buffer = NULL; + int str_size = -1; + double scale = 1; + a_id = H5Aopen(ds_id, "units", H5P_DEFAULT); + if (a_id < 0) { + char message[100]; + sprintf(message, + "Error openeing units attribute for %.32s after existence check", + path); + ERROR_JUMP(-1, close_dataset, message); + } - t_id = H5Aget_type(a_id); - if (t_id < 0) { - ERROR_JUMP(-1, close_attribute, "Error getting datatype"); - } - /* TODO: handle multiple strings in attribute (just detect and error) */ - if (H5Tis_variable_str(t_id) > 0) { - str_size = -1; - str_buffer = malloc(sizeof(char*)); - } else { - str_size = H5Tget_size(t_id); - /* do not assume room has been left for null-byte in fixed length string */ - str_buffer = malloc(str_size + 1); - } - if (str_buffer == NULL) { - ERROR_JUMP(-1, close_datatype, "Unable to allocate space for variable length string"); - } - mt_id = H5Tcopy(H5T_C_S1); - if (mt_id < 0) { - ERROR_JUMP(-1, free_string, "Error creating HDF5 String datatype"); - } - err = H5Tset_size(mt_id, str_size == -1 ? H5T_VARIABLE : str_size); - if (err < 0) { - char message[64]; - sprintf(message, "Error setting datatype size to %d", str_size); - ERROR_JUMP(-1, close_mem_datatype, message); - } + t_id = H5Aget_type(a_id); + if (t_id < 0) { + ERROR_JUMP(-1, close_attribute, "Error getting datatype"); + } + /* TODO: handle multiple strings in attribute (just detect and error) */ + if (H5Tis_variable_str(t_id) > 0) { + str_size = -1; + str_buffer = malloc(sizeof(char *)); + } else { + str_size = H5Tget_size(t_id); + /* do not assume room has been left for null-byte in fixed length string + */ + str_buffer = malloc(str_size + 1); + } + if (str_buffer == NULL) { + ERROR_JUMP(-1, close_datatype, + "Unable to allocate space for variable length string"); + } + mt_id = H5Tcopy(H5T_C_S1); + if (mt_id < 0) { + ERROR_JUMP(-1, free_string, "Error creating HDF5 String datatype"); + } + err = H5Tset_size(mt_id, str_size == -1 ? H5T_VARIABLE : str_size); + if (err < 0) { + char message[64]; + sprintf(message, "Error setting datatype size to %d", str_size); + ERROR_JUMP(-1, close_mem_datatype, message); + } - err = H5Aread(a_id, mt_id, str_buffer); - if (err < 0) { - ERROR_JUMP(-1, close_mem_datatype, "Error reading units attribute"); - } - /* ensure last byte is null */ - if (str_size > 0) ((char*) str_buffer)[str_size] = '\0'; + err = H5Aread(a_id, mt_id, str_buffer); + if (err < 0) { + ERROR_JUMP(-1, close_mem_datatype, "Error reading units attribute"); + } + /* ensure last byte is null */ + if (str_size > 0) + ((char *)str_buffer)[str_size] = '\0'; - scale = scale_from_units(str_size == -1 ? *(char**)str_buffer : (char*)str_buffer); - value *= scale; - - if (str_size == -1) { - /* we have to create this dataspace just to indicate we want - * to clear the entire vlen dataset (all 1 element - good job HDF5) - */ - hsize_t dims[1] = {1}; - hid_t s_id = H5Screate_simple(1, dims, NULL); - H5Sselect_all(s_id); - H5Dvlen_reclaim(mt_id, s_id, H5P_DEFAULT, str_buffer); - H5Sclose(s_id); - } -close_mem_datatype: - H5Tclose(mt_id); -free_string: - free(str_buffer); -close_datatype: - H5Tclose(t_id); -close_attribute: - H5Aclose(a_id); - } /* if H5Aexists(...) */ + scale = scale_from_units(str_size == -1 ? *(char **)str_buffer + : (char *)str_buffer); + value *= scale; + if (str_size == -1) { + /* we have to create this dataspace just to indicate we want + * to clear the entire vlen dataset (all 1 element - good job HDF5) + */ + hsize_t dims[1] = {1}; + hid_t s_id = H5Screate_simple(1, dims, NULL); + H5Sselect_all(s_id); + H5Dvlen_reclaim(mt_id, s_id, H5P_DEFAULT, str_buffer); + H5Sclose(s_id); + } + close_mem_datatype: + H5Tclose(mt_id); + free_string: + free(str_buffer); + close_datatype: + H5Tclose(t_id); + close_attribute: + H5Aclose(a_id); + } /* if H5Aexists(...) */ close_dataset: - H5Dclose(ds_id); + H5Dclose(ds_id); done: - if (retval == 0) *size = value; - return retval; + if (retval == 0) + *size = value; + return retval; } - -int get_nxs_pixel_info(const struct ds_desc_t *desc, double *x_size, double *y_size) { - int retval = 0; - if (read_pixel_info(desc->det_g_id, "x_pixel_size", x_size) < 0) { - ERROR_JUMP(-1, done, ""); - } - if (read_pixel_info(desc->det_g_id, "y_pixel_size", y_size) < 0) { - ERROR_JUMP(-1, done, ""); - } +int get_nxs_pixel_info(const struct ds_desc_t *desc, double *x_size, + double *y_size) { + int retval = 0; + if (read_pixel_info(desc->det_g_id, "x_pixel_size", x_size) < 0) { + ERROR_JUMP(-1, done, ""); + } + if (read_pixel_info(desc->det_g_id, "y_pixel_size", y_size) < 0) { + ERROR_JUMP(-1, done, ""); + } done: - return retval; + return retval; } - -int get_dectris_eiger_pixel_info(const struct ds_desc_t *desc, double *x_size, double *y_size) { - int retval = 0; - if (read_pixel_info(desc->det_g_id, "detectorSpecific/x_pixel_size", x_size) < 0) { - ERROR_JUMP(-1, done, ""); - } - if (read_pixel_info(desc->det_g_id, "detectorSpecific/y_pixel_size", y_size) < 0) { - ERROR_JUMP(-1, done, ""); - } +int get_dectris_eiger_pixel_info(const struct ds_desc_t *desc, double *x_size, + double *y_size) { + int retval = 0; + if (read_pixel_info(desc->det_g_id, "detectorSpecific/x_pixel_size", x_size) < + 0) { + ERROR_JUMP(-1, done, ""); + } + if (read_pixel_info(desc->det_g_id, "detectorSpecific/y_pixel_size", y_size) < + 0) { + ERROR_JUMP(-1, done, ""); + } done: - return retval; + return retval; } - int get_nxs_pixel_mask(const struct ds_desc_t *desc, int *buffer) { - int retval = 0; - hid_t ds_id; - herr_t err = 0; + int retval = 0; + hid_t ds_id; + herr_t err = 0; - ds_id = H5Dopen2(desc->det_g_id, "pixel_mask", H5P_DEFAULT); - if (ds_id < 0) { - ERROR_JUMP(-1, done, "Error opening pixel_mask dataset"); - } + ds_id = H5Dopen2(desc->det_g_id, "pixel_mask", H5P_DEFAULT); + if (ds_id < 0) { + ERROR_JUMP(-1, done, "Error opening pixel_mask dataset"); + } - err = H5Dread(ds_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - if (err < 0) { - ERROR_JUMP(-1, close_dataset, "Error reading pixel_mask dataset"); - } + err = H5Dread(ds_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + if (err < 0) { + ERROR_JUMP(-1, close_dataset, "Error reading pixel_mask dataset"); + } close_dataset: - H5Dclose(ds_id); + H5Dclose(ds_id); done: - return retval; + return retval; } - int get_dectris_eiger_pixel_mask(const struct ds_desc_t *desc, int *buffer) { - int retval = 0; - hid_t ds_id; - herr_t err = 0; + int retval = 0; + hid_t ds_id; + herr_t err = 0; - ds_id = H5Dopen2(desc->det_g_id, "detectorSpecific/pixel_mask", H5P_DEFAULT); - if (ds_id < 0) { - ERROR_JUMP(-1, done, "Error opening detectorSpecific/pixel_mask"); - } + ds_id = H5Dopen2(desc->det_g_id, "detectorSpecific/pixel_mask", H5P_DEFAULT); + if (ds_id < 0) { + ERROR_JUMP(-1, done, "Error opening detectorSpecific/pixel_mask"); + } - err = H5Dread(ds_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); - if (err < 0) { - ERROR_JUMP(-1, close_dataset, "Error reading detectorSpecific/pixel_mask"); - } + err = H5Dread(ds_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer); + if (err < 0) { + ERROR_JUMP(-1, close_dataset, "Error reading detectorSpecific/pixel_mask"); + } close_dataset: - H5Dclose(ds_id); + H5Dclose(ds_id); done: - return retval; + return retval; } - int get_null_pixel_mask(const struct ds_desc_t *desc, int *buffer) { - hsize_t buffer_length = desc->dims[1] * desc->dims[2]; - memset(buffer, 0, sizeof(*buffer) * buffer_length); - return 0; + hsize_t buffer_length = desc->dims[1] * desc->dims[2]; + memset(buffer, 0, sizeof(*buffer) * buffer_length); + return 0; } +herr_t det_visit_callback(hid_t root_id, const char *name, + const H5O_info_t *info, void *op_data) { + struct det_visit_objects_t *output_data = op_data; + hid_t g_id; + herr_t retval = 0; + if (info->type != H5O_TYPE_GROUP) + return 0; + g_id = H5Oopen(root_id, name, H5P_DEFAULT); + if (g_id < 0) { + char message[256]; + sprintf(message, "H5OVisit callback: Unable to open group %.128s", name); + ERROR_JUMP(-1, done, message); + } -herr_t det_visit_callback(hid_t root_id, const char *name, const H5O_info_t *info, void *op_data) { - struct det_visit_objects_t *output_data = op_data; - hid_t g_id; - herr_t retval = 0; - if (info->type != H5O_TYPE_GROUP) return 0; - g_id = H5Oopen(root_id, name, H5P_DEFAULT); - if (g_id < 0) { - char message[256]; - sprintf(message, "H5OVisit callback: Unable to open group %.128s", name); - ERROR_JUMP(-1, done, message); - } + /* check for an "NX_class" attribute */ + { + int str_size = 0; + void *buffer = NULL; + hid_t a_id, t_id, mt_id; + if (H5Aexists(g_id, "NX_class") <= 0) { + /* not an error - just close group and allow continuation */ + retval = 0; + goto close_group; + } + a_id = H5Aopen(g_id, "NX_class", H5P_DEFAULT); + if (a_id <= 0) { + char message[256]; + sprintf(message, + "H5OVisit callback: Error opening NX_class attribute on %.128s " + "after existence check", + name); + ERROR_JUMP(-1, close_group, message); + } - /* check for an "NX_class" attribute */ - { - int str_size = 0; - void* buffer = NULL; - hid_t a_id, t_id, mt_id; - if (H5Aexists(g_id, "NX_class") <= 0) { - /* not an error - just close group and allow continuation */ - retval = 0; - goto close_group; - } - a_id = H5Aopen(g_id, "NX_class", H5P_DEFAULT); - if (a_id <= 0) { - char message[256]; - sprintf(message, - "H5OVisit callback: Error opening NX_class attribute on %.128s after existence check", - name); - ERROR_JUMP(-1, close_group, message); - } + t_id = H5Aget_type(a_id); + if (t_id < 0) { + ERROR_JUMP(-1, close_attr, "Error getting datatype"); + } + if (H5Tis_variable_str(t_id) > 0) { + str_size = -1; + buffer = malloc(sizeof(char *)); + } else { + str_size = H5Tget_size(t_id); + buffer = malloc(str_size + 1); + } + if (!buffer) { + ERROR_JUMP(-1, close_type, "Error allocating string buffer"); + } - t_id = H5Aget_type(a_id); - if (t_id < 0) { - ERROR_JUMP(-1, close_attr, "Error getting datatype"); - } - if (H5Tis_variable_str(t_id) > 0) { - str_size = -1; - buffer = malloc(sizeof(char*)); - } else { - str_size = H5Tget_size(t_id); - buffer = malloc(str_size + 1); - } - if (!buffer) { - ERROR_JUMP(-1, close_type, "Error allocating string buffer"); - } + mt_id = H5Tcopy(H5T_C_S1); + if (mt_id < 0) { + ERROR_JUMP(-1, free_buffer, "Error creating HDF5 String datatype"); + } + if (H5Tset_size(mt_id, str_size == -1 ? H5T_VARIABLE : str_size) < 0) { + char message[64]; + sprintf(message, "Error setting string datatype to size %d", str_size); + ERROR_JUMP(-1, close_mtype, message); + } - mt_id = H5Tcopy(H5T_C_S1); - if (mt_id < 0) { - ERROR_JUMP(-1, free_buffer, "Error creating HDF5 String datatype"); - } - if (H5Tset_size(mt_id, str_size == -1 ? H5T_VARIABLE : str_size) < 0) { - char message[64]; - sprintf(message, "Error setting string datatype to size %d", str_size); - ERROR_JUMP(-1, close_mtype, message); - } + if (H5Aread(a_id, mt_id, buffer) < 0) { + char message[256]; + sprintf( + message, + "H5OVisit callback: Error reading NX_class attribute on group %.128s", + name); + ERROR_JUMP(-1, close_mtype, message); + } - if (H5Aread(a_id, mt_id, buffer) < 0) { - char message[256]; - sprintf(message, - "H5OVisit callback: Error reading NX_class attribute on group %.128s", - name); - ERROR_JUMP(-1, close_mtype, message); - } + /* at least one file has been seen where the NX_class attribute was not null + * terminated and extraneous bytes where being read by strcmp - set the end + * byte to null + */ + if (str_size > 0) + ((char *)buffer)[str_size] = '\0'; + /* test for NXdata or NXdetector */ + { + char *nxclass = str_size > 0 ? (char *)buffer : *((char **)buffer); + if (strcmp("NXdata", nxclass) == 0) { + hid_t out_id = H5Gopen(root_id, name, H5P_DEFAULT); + output_data->nxdata = out_id; + } else if (strcmp("NXdetector", nxclass) == 0) { + hid_t out_id = H5Gopen(root_id, name, H5P_DEFAULT); + output_data->nxdetector = out_id; + } + } - /* at least one file has been seen where the NX_class attribute was not null terminated - * and extraneous bytes where being read by strcmp - set the end byte to null - */ - if (str_size > 0) ((char*) buffer)[str_size] = '\0'; - /* test for NXdata or NXdetector */ - { - char *nxclass = str_size > 0 ? (char*) buffer : *((char**) buffer); - if (strcmp("NXdata", nxclass) == 0) { - hid_t out_id = H5Gopen(root_id, name, H5P_DEFAULT); - output_data->nxdata = out_id; - } else if (strcmp("NXdetector", nxclass) == 0) { - hid_t out_id = H5Gopen(root_id, name, H5P_DEFAULT); - output_data->nxdetector = out_id; - } - } + if (str_size == -1) { + hsize_t dims[1] = {1}; + hid_t s_id = H5Screate_simple(1, dims, NULL); + H5Sselect_all(s_id); + H5Dvlen_reclaim(mt_id, s_id, H5P_DEFAULT, buffer); + H5Sclose(s_id); + } - if (str_size == -1) { - hsize_t dims[1] = {1}; - hid_t s_id = H5Screate_simple(1, dims, NULL); - H5Sselect_all(s_id); - H5Dvlen_reclaim(mt_id, s_id, H5P_DEFAULT, buffer); - H5Sclose(s_id); - } - -close_mtype: - H5Tclose(mt_id); -free_buffer: - free(buffer); -close_type: - H5Tclose(t_id); -close_attr: - H5Aclose(a_id); - } + close_mtype: + H5Tclose(mt_id); + free_buffer: + free(buffer); + close_type: + H5Tclose(t_id); + close_attr: + H5Aclose(a_id); + } close_group: - if (H5Gclose(g_id) < 0) { - /* TODO: error trace */ - retval = -1; - } + if (H5Gclose(g_id) < 0) { + /* TODO: error trace */ + retval = -1; + } done: - return retval; + return retval; } -int check_for_chunk_read( - hid_t g_id, - const char* ds_name, - struct opt_eiger_ds_desc_t *desc) { +int check_for_chunk_read(hid_t g_id, const char *ds_name, + struct opt_eiger_ds_desc_t *desc) { - int retval = 0; - int n_filters; - hsize_t cdims[3]; - hid_t ds_id, dcpl, s_id; - unsigned int filter_flags, filter_config; - char filter_name[16]; - size_t name_len = 16; - size_t cd_nelems = BS_H5_N_PARAMS; - hsize_t dims[3]; - H5Z_filter_t filter; + int retval = 0; + int n_filters; + hsize_t cdims[3]; + hid_t ds_id, dcpl, s_id; + unsigned int filter_flags, filter_config; + char filter_name[16]; + size_t name_len = 16; + size_t cd_nelems = BS_H5_N_PARAMS; + hsize_t dims[3]; + H5Z_filter_t filter; - dcpl = 0; - s_id = 0; - ds_id = 0; + dcpl = 0; + s_id = 0; + ds_id = 0; - ds_id = H5Dopen2(g_id, ds_name, H5P_DEFAULT); - if (ds_id < 0) { - char message[64]; - sprintf(message, "Error opening dataset %.32s", ds_name); - ERROR_JUMP(-1, done, message) - } + ds_id = H5Dopen2(g_id, ds_name, H5P_DEFAULT); + if (ds_id < 0) { + char message[64]; + sprintf(message, "Error opening dataset %.32s", ds_name); + ERROR_JUMP(-1, done, message) + } - s_id = H5Dget_space(ds_id); - if (s_id < 0) { - char message[64]; - sprintf(message, "Error opening dataspace for %.32s", ds_name); - ERROR_JUMP(-1, done, message); - } + s_id = H5Dget_space(ds_id); + if (s_id < 0) { + char message[64]; + sprintf(message, "Error opening dataspace for %.32s", ds_name); + ERROR_JUMP(-1, done, message); + } - if (3 != H5Sget_simple_extent_ndims(s_id)) { - goto done; - } + if (3 != H5Sget_simple_extent_ndims(s_id)) { + goto done; + } - if (H5Sget_simple_extent_dims(s_id, dims, NULL) < 0) { - char message[80]; - sprintf(message, "Error retriving dataset dimensions for %.32s", ds_name); - ERROR_JUMP(-1, done, message); - } + if (H5Sget_simple_extent_dims(s_id, dims, NULL) < 0) { + char message[80]; + sprintf(message, "Error retriving dataset dimensions for %.32s", ds_name); + ERROR_JUMP(-1, done, message); + } - dcpl = H5Dget_create_plist(ds_id); - if (dcpl < 0) { - ERROR_JUMP(-1, done, "Error getting dataset creation property list"); - } + dcpl = H5Dget_create_plist(ds_id); + if (dcpl < 0) { + ERROR_JUMP(-1, done, "Error getting dataset creation property list"); + } - /* check the chunk layout matches the layout we expect of - * [1, frame_size_y, frame_size_x] (1 frame == 1 chunk) */ - int cndims = H5Pget_chunk(dcpl, 3, cdims); - if (cndims != 3) { - goto done; - } - if (cdims[0] != 1 || cdims[1] != dims[1] || cdims[2] != dims[2]) { - goto done; - } + /* check the chunk layout matches the layout we expect of + * [1, frame_size_y, frame_size_x] (1 frame == 1 chunk) */ + int cndims = H5Pget_chunk(dcpl, 3, cdims); + if (cndims != 3) { + goto done; + } + if (cdims[0] != 1 || cdims[1] != dims[1] || cdims[2] != dims[2]) { + goto done; + } - /* check for potential filters - only the bitshuffle filter is supported */ - n_filters = H5Pget_nfilters(dcpl); - if (n_filters < 0) { - ERROR_JUMP(-1, done, "Error retrieving number of filters on dataset"); - } else if (n_filters > 1) { - goto done; - } + /* check for potential filters - only the bitshuffle filter is supported */ + n_filters = H5Pget_nfilters(dcpl); + if (n_filters < 0) { + ERROR_JUMP(-1, done, "Error retrieving number of filters on dataset"); + } else if (n_filters > 1) { + goto done; + } - if (n_filters == 1) { - filter = H5Pget_filter2(dcpl, 0, &filter_flags, - &cd_nelems, desc->bs_params, - name_len, filter_name, - &filter_config); - if (filter < 0) { - ERROR_JUMP(-1, done, "Error retrieving filter information"); - } - if (filter != BS_H5_FILTER_ID) { - goto done; - } - if (cd_nelems > BS_H5_N_PARAMS) { - char message[128]; - sprintf(message, - "More than expected number of parameters to bitshuffle filter - expected %d, was %lu", - BS_H5_N_PARAMS, cd_nelems); - ERROR_JUMP(-1, done, message); - } - desc->bs_applied = 1; - } else { - desc->bs_applied = 0; - } + if (n_filters == 1) { + filter = H5Pget_filter2(dcpl, 0, &filter_flags, &cd_nelems, desc->bs_params, + name_len, filter_name, &filter_config); + if (filter < 0) { + ERROR_JUMP(-1, done, "Error retrieving filter information"); + } + if (filter != BS_H5_FILTER_ID) { + goto done; + } + if (cd_nelems > BS_H5_N_PARAMS) { + char message[128]; + sprintf(message, + "More than expected number of parameters to bitshuffle filter - " + "expected %d, was %lu", + BS_H5_N_PARAMS, cd_nelems); + ERROR_JUMP(-1, done, message); + } + desc->bs_applied = 1; + } else { + desc->bs_applied = 0; + } - retval = 1; + retval = 1; done: - if (dcpl) H5Pclose(dcpl); - if (s_id) H5Sclose(s_id); - if (ds_id) H5Dclose(ds_id); - return retval; + if (dcpl) + H5Pclose(dcpl); + if (s_id) + H5Sclose(s_id); + if (ds_id) + H5Dclose(ds_id); + return retval; } -int create_dataset_descriptor(struct ds_desc_t **desc, struct det_visit_objects_t *visit_result) { - int retval = 0; - hid_t g_id, ds_id; - int (*pxl_func)(const struct ds_desc_t*, double*, double*); - int (*pxl_mask_func)(const struct ds_desc_t*, int*); - int (*ds_prop_func)(struct ds_desc_t*); - int (*frame_func)(const struct ds_desc_t*, int, void*); - void (*free_func)(struct ds_desc_t*); - struct ds_desc_t *output; +int create_dataset_descriptor(struct ds_desc_t **desc, + struct det_visit_objects_t *visit_result) { + int retval = 0; + hid_t g_id, ds_id; + int (*pxl_func)(const struct ds_desc_t *, double *, double *); + int (*pxl_mask_func)(const struct ds_desc_t *, int *); + int (*ds_prop_func)(struct ds_desc_t *); + int (*frame_func)(const struct ds_desc_t *, int, void *); + void (*free_func)(struct ds_desc_t *); + struct ds_desc_t *output; - g_id = visit_result->nxdetector; + g_id = visit_result->nxdetector; - /* determine the pixel information location */ - if (H5Lexists(g_id, "x_pixel_size", H5P_DEFAULT) > 0 && - H5Lexists(g_id, "y_pixel_size", H5P_DEFAULT)) { - pxl_func = &get_nxs_pixel_info; - } else if (H5Lexists(g_id, "detectorSpecific", H5P_DEFAULT) > 0 && - H5Lexists(g_id, "detectorSpecific/x_pixel_size", H5P_DEFAULT) > 0 && - H5Lexists(g_id, "detectorSpecific/y_pixel_size", H5P_DEFAULT) > 0) { - pxl_func = &get_dectris_eiger_pixel_info; - } else { - ERROR_JUMP(-1, done, "Could not locate x_pixel_size and y_pixel_size"); - } + /* determine the pixel information location */ + if (H5Lexists(g_id, "x_pixel_size", H5P_DEFAULT) > 0 && + H5Lexists(g_id, "y_pixel_size", H5P_DEFAULT)) { + pxl_func = &get_nxs_pixel_info; + } else if (H5Lexists(g_id, "detectorSpecific", H5P_DEFAULT) > 0 && + H5Lexists(g_id, "detectorSpecific/x_pixel_size", H5P_DEFAULT) > + 0 && + H5Lexists(g_id, "detectorSpecific/y_pixel_size", H5P_DEFAULT) > + 0) { + pxl_func = &get_dectris_eiger_pixel_info; + } else { + ERROR_JUMP(-1, done, "Could not locate x_pixel_size and y_pixel_size"); + } - /* determine pixel mask location */ - if (H5Lexists(g_id, "pixel_mask", H5P_DEFAULT) > 0) { - pxl_mask_func = &get_nxs_pixel_mask; - } else if (H5Lexists(g_id, "detectorSpecific", H5P_DEFAULT) > 0 && - H5Lexists(g_id, "detectorSpecific/pixel_mask", H5P_DEFAULT) > 0) { - pxl_mask_func = &get_dectris_eiger_pixel_mask; - } else { - pxl_mask_func = &get_null_pixel_mask; - fprintf(stderr, "WARNING: Could not find pixel mask - no masking will be applied\n"); - } + /* determine pixel mask location */ + if (H5Lexists(g_id, "pixel_mask", H5P_DEFAULT) > 0) { + pxl_mask_func = &get_nxs_pixel_mask; + } else if (H5Lexists(g_id, "detectorSpecific", H5P_DEFAULT) > 0 && + H5Lexists(g_id, "detectorSpecific/pixel_mask", H5P_DEFAULT) > 0) { + pxl_mask_func = &get_dectris_eiger_pixel_mask; + } else { + pxl_mask_func = &get_null_pixel_mask; + fprintf( + stderr, + "WARNING: Could not find pixel mask - no masking will be applied\n"); + } - /* determine where the data is stored and what strategy to use */ - /* we select the "dectris-eiger" strategy if both are valid due to - * potential confusion with the sizes of a virtual dataset, possible failure - * opening if we're using an old library version, and the potential to use the - * optimised chunk read strategy - */ - if (H5Lexists(visit_result->nxdetector, "data_000001", H5P_DEFAULT) > 0) { - ds_id = visit_result->nxdetector; - ds_prop_func = &get_dectris_eiger_dataset_dims; - frame_func = &get_dectris_eiger_frame; - } else if (H5Lexists(visit_result->nxdetector, "data", H5P_DEFAULT) > 0) { - ds_id = visit_result->nxdetector; - ds_prop_func = &get_nxs_dataset_dims; - frame_func = &get_nxs_frame; - } else if (H5Lexists(visit_result->nxdata, "data_000001", H5P_DEFAULT) > 0) { - ds_id = visit_result->nxdata; - ds_prop_func = &get_dectris_eiger_dataset_dims; - frame_func = &get_dectris_eiger_frame; - } else if (H5Lexists(visit_result->nxdata, "data", H5P_DEFAULT) > 0) { - ds_id = visit_result->nxdata; - ds_prop_func = &get_nxs_dataset_dims; - frame_func = &get_nxs_frame; - } else { - ERROR_JUMP(-1, done, "Could not locate detector dataset"); - } + /* determine where the data is stored and what strategy to use */ + /* we select the "dectris-eiger" strategy if both are valid due to + * potential confusion with the sizes of a virtual dataset, possible failure + * opening if we're using an old library version, and the potential to use the + * optimised chunk read strategy + */ + if (H5Lexists(visit_result->nxdetector, "data_000001", H5P_DEFAULT) > 0) { + ds_id = visit_result->nxdetector; + ds_prop_func = &get_dectris_eiger_dataset_dims; + frame_func = &get_dectris_eiger_frame; + } else if (H5Lexists(visit_result->nxdetector, "data", H5P_DEFAULT) > 0) { + ds_id = visit_result->nxdetector; + ds_prop_func = &get_nxs_dataset_dims; + frame_func = &get_nxs_frame; + } else if (H5Lexists(visit_result->nxdata, "data_000001", H5P_DEFAULT) > 0) { + ds_id = visit_result->nxdata; + ds_prop_func = &get_dectris_eiger_dataset_dims; + frame_func = &get_dectris_eiger_frame; + } else if (H5Lexists(visit_result->nxdata, "data", H5P_DEFAULT) > 0) { + ds_id = visit_result->nxdata; + ds_prop_func = &get_nxs_dataset_dims; + frame_func = &get_nxs_frame; + } else { + ERROR_JUMP(-1, done, "Could not locate detector dataset"); + } + if (ds_prop_func == &get_dectris_eiger_dataset_dims) { - if (ds_prop_func == &get_dectris_eiger_dataset_dims) { + /* setup the "extra info" structs */ + struct eiger_ds_desc_t *eiger_desc; + struct opt_eiger_ds_desc_t *o_eiger_desc; - /* setup the "extra info" structs */ - struct eiger_ds_desc_t *eiger_desc; - struct opt_eiger_ds_desc_t *o_eiger_desc; + eiger_desc = malloc(sizeof(*eiger_desc)); + if (!eiger_desc) { + ERROR_JUMP(-1, done, "Memory error creating data description for Eiger"); + } + memset(eiger_desc, 0, sizeof(*eiger_desc)); + eiger_desc->frame_func = &get_frame_simple; - eiger_desc = malloc(sizeof(*eiger_desc)); - if (!eiger_desc) { - ERROR_JUMP(-1, done, "Memory error creating data description for Eiger"); - } - memset(eiger_desc, 0, sizeof(*eiger_desc)); - eiger_desc->frame_func = &get_frame_simple; + o_eiger_desc = malloc(sizeof(*o_eiger_desc)); + if (!o_eiger_desc) { + free(eiger_desc); + ERROR_JUMP(-1, done, + "Memory error creating data description for optimised Eiger"); + } + o_eiger_desc->base.frame_func = &get_frame_from_chunk; - o_eiger_desc = malloc(sizeof(*o_eiger_desc)); - if (!o_eiger_desc) { - free(eiger_desc); - ERROR_JUMP(-1, done, "Memory error creating data description for optimised Eiger"); - } - o_eiger_desc->base.frame_func = &get_frame_from_chunk; + /* check if we can perform the optimised chunk read */ + retval = check_for_chunk_read(ds_id, "data_000001", o_eiger_desc); + if (retval < 0) { + free(o_eiger_desc); + free(eiger_desc); + ERROR_JUMP(-1, done, ""); + } + if (retval) { + free(eiger_desc); + *(struct opt_eiger_ds_desc_t **)desc = o_eiger_desc; + free_func = &free_opt_eiger_desc; + } else { + free(o_eiger_desc); + *(struct eiger_ds_desc_t **)desc = eiger_desc; + free_func = &free_eiger_desc; + } - /* check if we can perform the optimised chunk read */ - retval = check_for_chunk_read(ds_id, "data_000001", o_eiger_desc); - if (retval < 0) { - free(o_eiger_desc); - free(eiger_desc); - ERROR_JUMP(-1, done, ""); - } - if (retval) { - free(eiger_desc); - *(struct opt_eiger_ds_desc_t**) desc = o_eiger_desc; - free_func = &free_opt_eiger_desc; - } else { - free(o_eiger_desc); - *(struct eiger_ds_desc_t**) desc = eiger_desc; - free_func = &free_eiger_desc; - } + } else { + *desc = malloc(sizeof(struct nxs_ds_desc_t)); + free_func = &free_nxs_desc; + } - } else { - *desc = malloc(sizeof(struct nxs_ds_desc_t)); - free_func = &free_nxs_desc; - } + output = *((struct ds_desc_t **)desc); + output->det_g_id = g_id; + output->data_g_id = ds_id; + output->get_pixel_properties = pxl_func; + output->get_pixel_mask = pxl_mask_func; + output->get_data_frame = frame_func; + output->free_desc = free_func; - output = *((struct ds_desc_t **) desc); - output->det_g_id = g_id; - output->data_g_id = ds_id; - output->get_pixel_properties = pxl_func; - output->get_pixel_mask = pxl_mask_func; - output->get_data_frame = frame_func; - output->free_desc = free_func; - - ds_prop_func(output); + ds_prop_func(output); done: - return retval; + return retval; } +int get_detector_info(const hid_t fid, struct ds_desc_t **desc) { -int get_detector_info( - const hid_t fid, - struct ds_desc_t **desc) { - - int retval = 0; - herr_t err = 0; - struct det_visit_objects_t objects = {0}; - err = H5Ovisit(fid, H5_INDEX_NAME, H5_ITER_INC, &det_visit_callback, &objects); - if (err < 0) { - clear_det_visit_objects(&objects); - ERROR_JUMP(-1, done, "Error during H5Ovisit callback"); - } - if (objects.nxdata == 0) { - fprintf(stderr, "WARNING: Could not locate an NXdata entry\n"); - } - if (objects.nxdetector == 0) { - fprintf(stderr, "WARNING: Could not locate an NXdetector entry\n"); - } - - if ((retval = create_dataset_descriptor(desc, &objects)) < 0) { - ERROR_JUMP(retval, done, ""); - }; + int retval = 0; + herr_t err = 0; + struct det_visit_objects_t objects = {0}; + err = + H5Ovisit(fid, H5_INDEX_NAME, H5_ITER_INC, &det_visit_callback, &objects); + if (err < 0) { + clear_det_visit_objects(&objects); + ERROR_JUMP(-1, done, "Error during H5Ovisit callback"); + } + if (objects.nxdata == 0) { + fprintf(stderr, "WARNING: Could not locate an NXdata entry\n"); + } + if (objects.nxdetector == 0) { + fprintf(stderr, "WARNING: Could not locate an NXdetector entry\n"); + } + if ((retval = create_dataset_descriptor(desc, &objects)) < 0) { + ERROR_JUMP(retval, done, ""); + }; done: - return retval; + return retval; } diff --git a/src/file.h b/src/file.h index 23d923b..0bcc36e 100644 --- a/src/file.h +++ b/src/file.h @@ -3,49 +3,48 @@ * Author: Charles Mita */ - #ifndef NXS_XDS_FILE_H #define NXS_XDS_FILE_H -#include #include "err.h" #include "filters.h" - +#include struct ds_desc_t { - hid_t det_g_id; - hid_t data_g_id; - hsize_t dims[3]; - int data_width; - int image_number_offset; - int (*get_pixel_properties)(const struct ds_desc_t*, double*, double*); - int (*get_pixel_mask)(const struct ds_desc_t*, int*); - int (*get_data_frame)(const struct ds_desc_t*, const int, void*); - void (*free_desc)(struct ds_desc_t*); + hid_t det_g_id; + hid_t data_g_id; + hsize_t dims[3]; + int data_width; + int image_number_offset; + int (*get_pixel_properties)(const struct ds_desc_t *, double *, double *); + int (*get_pixel_mask)(const struct ds_desc_t *, int *); + int (*get_data_frame)(const struct ds_desc_t *, const int, void *); + void (*free_desc)(struct ds_desc_t *); }; struct nxs_ds_desc_t { - struct ds_desc_t base; + struct ds_desc_t base; }; struct eiger_ds_desc_t { - struct ds_desc_t base; - int n_data_blocks; - int *block_sizes; - int (*frame_func)(const struct ds_desc_t*, const char*, const hsize_t*, const hsize_t*, void*); + struct ds_desc_t base; + int n_data_blocks; + int *block_sizes; + int (*frame_func)(const struct ds_desc_t *, const char *, const hsize_t *, + const hsize_t *, void *); }; struct opt_eiger_ds_desc_t { - struct eiger_ds_desc_t base; - int bs_applied; - unsigned int bs_params[BS_H5_N_PARAMS]; + struct eiger_ds_desc_t base; + int bs_applied; + unsigned int bs_params[BS_H5_N_PARAMS]; }; int get_detector_info(const hid_t fid, struct ds_desc_t **desc); struct det_visit_objects_t { - hid_t nxdata; - hid_t nxdetector; + hid_t nxdata; + hid_t nxdetector; }; #endif /* NXS_XDS_FILE_H */ diff --git a/src/filters.c b/src/filters.c index 49369df..1589644 100644 --- a/src/filters.c +++ b/src/filters.c @@ -4,55 +4,55 @@ */ #include -#include "filters.h" -#include "err.h" + #include "bitshuffle.h" +#include "err.h" +#include "filters.h" /* Required prototypes from bitshuffle.c but not included in header */ uint64_t bshuf_read_uint64_BE(const void *buffer); uint32_t bshuf_read_uint32_BE(const void *buffer); - /* - * Derived from the h5 filter code from the bitshuffle project (not included here) + * Derived from the h5 filter code from the bitshuffle project (not included + * here) */ -int bslz4_decompress( - const unsigned int* bs_params, - size_t in_size, - void *in_buffer, - size_t out_size, - void *out_buffer) { +int bslz4_decompress(const unsigned int *bs_params, size_t in_size, + void *in_buffer, size_t out_size, void *out_buffer) { - int retval = 0; - size_t size, elem_size, block_size, u_bytes; + int retval = 0; + size_t size, elem_size, block_size, u_bytes; - elem_size = bs_params[2]; - u_bytes = bshuf_read_uint64_BE(in_buffer); + elem_size = bs_params[2]; + u_bytes = bshuf_read_uint64_BE(in_buffer); - if (u_bytes != out_size) { - char message[64]; - sprintf(message, "Decompressed chunk is %lu bytes, expected %lu", u_bytes, out_size); - ERROR_JUMP(-1, done, message); - } + if (u_bytes != out_size) { + char message[64]; + sprintf(message, "Decompressed chunk is %lu bytes, expected %lu", u_bytes, + out_size); + ERROR_JUMP(-1, done, message); + } - block_size = bshuf_read_uint32_BE((const char *) in_buffer + 8) / elem_size; - if (!block_size) { - ERROR_JUMP(-1, done, "Read block bitshuffle lz4 block size as 0"); - } - /* skip over header */ - in_buffer += 12; - size = u_bytes / elem_size; + block_size = bshuf_read_uint32_BE((const char *)in_buffer + 8) / elem_size; + if (!block_size) { + ERROR_JUMP(-1, done, "Read block bitshuffle lz4 block size as 0"); + } + /* skip over header */ + in_buffer += 12; + size = u_bytes / elem_size; - if (bs_params[4] == BS_H5_PARAM_LZ4_COMPRESS) { - if (bshuf_decompress_lz4(in_buffer, out_buffer, size, elem_size, block_size) < 0) { - ERROR_JUMP(-1, done, "Error performing bitshuffle_lz4 decompression"); - } - } else { - if (bshuf_bitunshuffle(in_buffer, out_buffer, size, elem_size, block_size) < 0) { - ERROR_JUMP(-1, done, "Error performing bit unshuffle"); - } - } + if (bs_params[4] == BS_H5_PARAM_LZ4_COMPRESS) { + if (bshuf_decompress_lz4(in_buffer, out_buffer, size, elem_size, + block_size) < 0) { + ERROR_JUMP(-1, done, "Error performing bitshuffle_lz4 decompression"); + } + } else { + if (bshuf_bitunshuffle(in_buffer, out_buffer, size, elem_size, block_size) < + 0) { + ERROR_JUMP(-1, done, "Error performing bit unshuffle"); + } + } done: - return retval; + return retval; } diff --git a/src/filters.h b/src/filters.h index caa9a37..18dffcb 100644 --- a/src/filters.h +++ b/src/filters.h @@ -10,13 +10,7 @@ #define BS_H5_FILTER_ID 32008 #define BS_H5_PARAM_LZ4_COMPRESS 2 - - -int bslz4_decompress( - const unsigned int* bs_params, - size_t in_size, - void *in_buffer, - size_t out_size, - void *out_buffer); +int bslz4_decompress(const unsigned int *bs_params, size_t in_size, + void *in_buffer, size_t out_size, void *out_buffer); #endif /* NXS_XDS_FILTER_H */ diff --git a/src/plugin.c b/src/plugin.c index 8bb4118..676c38b 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -3,259 +3,251 @@ * Author: Charles Mita */ - #include #include + #include "file.h" #include "filters.h" #include "plugin.h" - -/* XDS does not provide an error callback facility, so just write to stderr for now */ -/* generally regarded as poor practice */ +/* XDS does not provide an error callback facility, so just write to stderr + for now - generally regarded as poor practice */ #define ERROR_OUTPUT stderr +/* mask bits loosely based on what Neggia does and what NeXus says should be + done basically - anything in the low byte (& 0xFF) means "ignore this" + Neggia uses the value -2 if bit 1, 2 or 3 are set */ +#define COPY_AND_MASK(in, out, size, mask) \ + { \ + int i; \ + if (mask) { \ + for (i = 0; i < size; ++i) { \ + out[i] = in[i]; \ + if (mask[i] & 0xFF) \ + out[i] = -1; \ + if (mask[i] & 30) \ + out[i] = -2; \ + } \ + } else { \ + for (i = 0; i < size; i++) { \ + out[i] = in[i]; \ + } \ + } \ + } - -/* mask bits loosely based on what Neggia does and what NeXus says should be done */ -/* basically - anything in the low byte (& 0xFF) means "ignore this" */ -/* Neggia usses the value -2 if bit 1, 2 or 3 are set */ -#define COPY_AND_MASK(in, out, size, mask) \ -{ \ - int i; \ - if (mask) { \ - for (i = 0; i < size; ++i) { \ - out[i] = in[i]; \ - if (mask[i] & 0xFF) out[i] = -1; \ - if (mask[i] & 30) out[i] = -2; \ - } \ - } else { \ - for (i = 0; i < size; i++) { \ - out[i] = in[i]; \ - } \ - } \ -} - -#define APPLY_MASK(buffer, mask, size) \ -{ \ - int i; \ - if (mask) { \ - for (i = 0; i < size; ++i) { \ - if (mask[i] & 0xFF) buffer[i] = -1; \ - if (mask[i] & 30) buffer[i] = -2; \ - } \ - } \ -} - +#define APPLY_MASK(buffer, mask, size) \ + { \ + int i; \ + if (mask) { \ + for (i = 0; i < size; ++i) { \ + if (mask[i] & 0xFF) \ + buffer[i] = -1; \ + if (mask[i] & 30) \ + buffer[i] = -2; \ + } \ + } \ + } static hid_t file_id = 0; static struct ds_desc_t *data_desc = NULL; static int *mask_buffer = NULL; - void fill_info_array(int info[1024]) { - info[0] = DLS_CUSTOMER_ID; - info[1] = VERSION_MAJOR; - info[2] = VERSION_MINOR; - info[3] = VERSION_PATCH; - info[4] = VERSION_TIMESTAMP; + info[0] = DLS_CUSTOMER_ID; + info[1] = VERSION_MAJOR; + info[2] = VERSION_MINOR; + info[3] = VERSION_PATCH; + info[4] = VERSION_TIMESTAMP; } -int convert_to_int_and_mask(void *in_buffer, int d_width, int *out_buffer, int length, int *mask) { - /* transfer data to output buffer, performing data conversion as required */ - int retval = 0; - /* TODO: decide how conversion of data should work */ - /* Should we sign extend? Neggia doesn't (casts from uint*), but may be more intuitive */ - if (d_width == sizeof(signed char)) { - signed char *in = in_buffer; - COPY_AND_MASK(in, out_buffer, length, mask); - } else if (d_width == sizeof(short)) { - short *in = in_buffer; - COPY_AND_MASK(in, out_buffer, length, mask); - } else if (d_width == sizeof(int)) { - int *in = in_buffer; - COPY_AND_MASK(in, out_buffer, length, mask); - } else if (d_width == sizeof(long int)) { - long int *in = in_buffer; - COPY_AND_MASK(in, out_buffer, length, mask); - } else if (d_width == sizeof(long long int)) { - long long int *in = in_buffer; - COPY_AND_MASK(in, out_buffer, length, mask); - } else { - char message[128]; - sprintf(message, "Unsupported conversion of data width %d to %ld (int)", d_width, sizeof(int)); - ERROR_JUMP(-1, done, message); - } +int convert_to_int_and_mask(void *in_buffer, int d_width, int *out_buffer, + int length, int *mask) { + /* transfer data to output buffer, performing data conversion as required */ + int retval = 0; + /* TODO: decide how conversion of data should work */ + /* Should we sign extend? Neggia doesn't (casts from uint*), but may be more + * intuitive */ + if (d_width == sizeof(signed char)) { + signed char *in = in_buffer; + COPY_AND_MASK(in, out_buffer, length, mask); + } else if (d_width == sizeof(short)) { + short *in = in_buffer; + COPY_AND_MASK(in, out_buffer, length, mask); + } else if (d_width == sizeof(int)) { + int *in = in_buffer; + COPY_AND_MASK(in, out_buffer, length, mask); + } else if (d_width == sizeof(long int)) { + long int *in = in_buffer; + COPY_AND_MASK(in, out_buffer, length, mask); + } else if (d_width == sizeof(long long int)) { + long long int *in = in_buffer; + COPY_AND_MASK(in, out_buffer, length, mask); + } else { + char message[128]; + sprintf(message, "Unsupported conversion of data width %d to %ld (int)", + d_width, sizeof(int)); + ERROR_JUMP(-1, done, message); + } done: - return retval; + return retval; } #ifdef __cplusplus extern "C" { #endif -void plugin_open( - const char *filename, - int info[1024], - int *error_flag) { - int retval = 0; - *error_flag = 0; +void plugin_open(const char *filename, int info[1024], int *error_flag) { + int retval = 0; + *error_flag = 0; - init_error_handling(); + init_error_handling(); - if (H5dont_atexit() < 0) { - ERROR_JUMP(-2, done, "Failed configuring HDF5 library behaviour"); - } + if (H5dont_atexit() < 0) { + ERROR_JUMP(-2, done, "Failed configuring HDF5 library behaviour"); + } - if (init_h5_error_handling() < 0) { - ERROR_JUMP(-2, done, "Failed to configure HDF5 error handling"); - } + if (init_h5_error_handling() < 0) { + ERROR_JUMP(-2, done, "Failed to configure HDF5 error handling"); + } - fill_info_array(info); - file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); - if (file_id < 0) { - char message[128] = {0}; - sprintf(message, "Could not open %.100s", filename); - ERROR_JUMP(-4, done, message); - } + fill_info_array(info); + file_id = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); + if (file_id < 0) { + char message[128] = {0}; + sprintf(message, "Could not open %.100s", filename); + ERROR_JUMP(-4, done, message); + } - reset_error_stack(); - retval = get_detector_info(file_id, &data_desc); - if (retval < 0) { - ERROR_JUMP(-4, done, ""); - } + reset_error_stack(); + retval = get_detector_info(file_id, &data_desc); + if (retval < 0) { + ERROR_JUMP(-4, done, ""); + } - data_desc->image_number_offset = 0; - char *cenv; - cenv = getenv("DURIN_IMAGE_NUMBER_OFFSET"); - if (cenv!=NULL) { - data_desc->image_number_offset = atoi(cenv); - } + data_desc->image_number_offset = 0; + char *cenv; + cenv = getenv("DURIN_IMAGE_NUMBER_OFFSET"); + if (cenv!=NULL) { + data_desc->image_number_offset = atoi(cenv); + } - mask_buffer = malloc(data_desc->dims[1] * data_desc->dims[2] * sizeof(int)); - if (mask_buffer) { - retval = data_desc->get_pixel_mask(data_desc, mask_buffer); - if (retval < 0) { - fprintf(ERROR_OUTPUT, "WARNING: Could not read pixel mask - no masking will be applied\n"); - dump_error_stack(ERROR_OUTPUT); - free(mask_buffer); - mask_buffer = NULL; - } - } - retval = 0; + mask_buffer = malloc(data_desc->dims[1] * data_desc->dims[2] * sizeof(int)); + if (mask_buffer) { + retval = data_desc->get_pixel_mask(data_desc, mask_buffer); + if (retval < 0) { + fprintf( + ERROR_OUTPUT, + "WARNING: Could not read pixel mask - no masking will be applied\n"); + dump_error_stack(ERROR_OUTPUT); + free(mask_buffer); + mask_buffer = NULL; + } + } + retval = 0; done: - *error_flag = retval; - if (retval < 0) { - if ((data_desc) && (data_desc->free_desc)) { - data_desc->free_desc(data_desc); - data_desc = NULL; - } - dump_error_stack(ERROR_OUTPUT); - } + *error_flag = retval; + if (retval < 0) { + if ((data_desc) && (data_desc->free_desc)) { + data_desc->free_desc(data_desc); + data_desc = NULL; + } + dump_error_stack(ERROR_OUTPUT); + } } +void plugin_get_header(int *nx, int *ny, int *nbytes, float *qx, float *qy, + int *number_of_frames, int info[1024], int *error_flag) { + int err = 0; + int retval = 0; + double x_pixel_size, y_pixel_size; + reset_error_stack(); + fill_info_array(info); -void plugin_get_header( - int *nx, int *ny, - int *nbytes, - float *qx, float *qy, - int *number_of_frames, - int info[1024], - int *error_flag) { - int err = 0; - int retval = 0; - double x_pixel_size, y_pixel_size; - reset_error_stack(); - fill_info_array(info); + err = + data_desc->get_pixel_properties(data_desc, &x_pixel_size, &y_pixel_size); + if (err < 0) { + ERROR_JUMP(err, done, "Failed to retrieve pixel information"); + } - err = data_desc->get_pixel_properties(data_desc, &x_pixel_size, &y_pixel_size); - if (err < 0) { - ERROR_JUMP(err, done, "Failed to retrieve pixel information"); - } - - *nx = data_desc->dims[2]; - *ny = data_desc->dims[1]; - *nbytes = data_desc->data_width; - *number_of_frames = data_desc->dims[0]; - *qx = (float) x_pixel_size; - *qy = (float) y_pixel_size; + *nx = data_desc->dims[2]; + *ny = data_desc->dims[1]; + *nbytes = data_desc->data_width; + *number_of_frames = data_desc->dims[0]; + *qx = (float)x_pixel_size; + *qy = (float)y_pixel_size; done: - *error_flag = retval; - if (retval < 0) { - dump_error_stack(ERROR_OUTPUT); - } + *error_flag = retval; + if (retval < 0) { + dump_error_stack(ERROR_OUTPUT); + } } +void plugin_get_data(int *frame_number, int *nx, int *ny, int *data_array, + int info[1024], int *error_flag) { -void plugin_get_data( - int *frame_number, - int *nx, int *ny, - int *data_array, - int info[1024], - int *error_flag) { + int retval = 0; + int frame_size_px = data_desc->dims[1] * data_desc->dims[2]; + reset_error_stack(); + fill_info_array(info); - int retval = 0; - int frame_size_px = data_desc->dims[1] * data_desc->dims[2]; - reset_error_stack(); - fill_info_array(info); + void *buffer = NULL; + if (sizeof(*data_array) == data_desc->data_width) { + buffer = data_array; + } else { + buffer = malloc(data_desc->data_width * frame_size_px); + if (!buffer) { + ERROR_JUMP(-1, done, "Unable to allocate data buffer"); + } + } - void *buffer = NULL; - if (sizeof(*data_array) == data_desc->data_width) { - buffer = data_array; - } else { - buffer = malloc(data_desc->data_width * frame_size_px); - if (!buffer) { - ERROR_JUMP(-1, done, "Unable to allocate data buffer"); - } - } + if (data_desc->get_data_frame(data_desc, (*frame_number) - 1, buffer) < 0) { + char message[64] = {0}; + sprintf(message, "Failed to retrieve data for frame %d", *frame_number); + ERROR_JUMP(-2, done, message); + } - if (data_desc->get_data_frame(data_desc, (*frame_number) - 1, buffer) < 0) { - char message[64] = {0}; - sprintf(message, "Failed to retrieve data for frame %d", *frame_number); - ERROR_JUMP(-2, done, message); - } - - if (buffer != data_array) { - if (convert_to_int_and_mask(buffer, data_desc->data_width, data_array, frame_size_px, mask_buffer) < 0) { - char message[64]; - sprintf(message, "Error converting data for frame %d", *frame_number); - ERROR_JUMP(-2, done, message); - } - } else { - APPLY_MASK(data_array, mask_buffer, frame_size_px); - } + if (buffer != data_array) { + if (convert_to_int_and_mask(buffer, data_desc->data_width, data_array, + frame_size_px, mask_buffer) < 0) { + char message[64]; + sprintf(message, "Error converting data for frame %d", *frame_number); + ERROR_JUMP(-2, done, message); + } + } else { + APPLY_MASK(data_array, mask_buffer, frame_size_px); + } done: - *error_flag = retval; - if (retval < 0) { - dump_error_stack(ERROR_OUTPUT); - } - if (buffer && (buffer != data_array)) free(buffer); + *error_flag = retval; + if (retval < 0) { + dump_error_stack(ERROR_OUTPUT); + } + if (buffer && (buffer != data_array)) + free(buffer); } - void plugin_close(int *error_flag) { - if (file_id) { - if (H5Fclose(file_id) < 0) { - /* TODO: backtrace */ - *error_flag = -1; - } - } - file_id = 0; + if (file_id) { + if (H5Fclose(file_id) < 0) { + /* TODO: backtrace */ + *error_flag = -1; + } + } + file_id = 0; - if (mask_buffer) { - free(mask_buffer); - mask_buffer = NULL; - } - if (data_desc->free_desc) { - data_desc->free_desc(data_desc); - data_desc = NULL; - } - if (H5close() < 0) { - *error_flag = -1; - } + if (mask_buffer) { + free(mask_buffer); + mask_buffer = NULL; + } + if (data_desc->free_desc) { + data_desc->free_desc(data_desc); + data_desc = NULL; + } + if (H5close() < 0) { + *error_flag = -1; + } } #ifdef __cplusplus diff --git a/src/plugin.h b/src/plugin.h index bf87a4f..a19bb06 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -15,39 +15,23 @@ extern "C" { #endif -#define DLS_CUSTOMER_ID 0x01 /* pretend we're Dectris, otherwise XDS doesn't work */ +#define DLS_CUSTOMER_ID \ + 0x01 /* pretend we're Dectris, otherwise XDS doesn't work */ #define VERSION_MAJOR 0 #define VERSION_MINOR 0 #define VERSION_PATCH 0 #define VERSION_TIMESTAMP -1 /* good enough for Dectris apparantely */ +void plugin_open(const char *filename, int info[1024], int *error_flag); -void plugin_open( - const char *filename, - int info[1024], - int *error_flag); - - -void plugin_get_header( - int *nx, int *ny, - int *nbytes, - float *qx, float *qy, - int *number_of_frames, - int info[1024], - int *error_flag); - - -void plugin_get_data( - int *frame_number, - int *nx, int *ny, - int *data_array, - int info[1024], - int *error_flag); +void plugin_get_header(int *nx, int *ny, int *nbytes, float *qx, float *qy, + int *number_of_frames, int info[1024], int *error_flag); +void plugin_get_data(int *frame_number, int *nx, int *ny, int *data_array, + int info[1024], int *error_flag); void plugin_close(int *error_flag); - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/test.c b/src/test.c index 68a7ef9..86546bf 100644 --- a/src/test.c +++ b/src/test.c @@ -1,134 +1,141 @@ +#include "err.h" +#include "file.h" +#include #include #include -#include -#include "file.h" -#include "err.h" -#define COPY_AND_MASK(in, out, size, mask) \ -{ \ - int i; \ - if (mask) { \ - for (i = 0; i < size; ++i) { \ - out[i] = in[i]; \ - if (mask[i] & 0xFE) out[i] = -2; \ - if (mask[i] & 0x01) out[i] = -1; \ - } \ - } else { \ - for (i = 0; i < size; i++) { \ - out[i] = in[i]; \ - } \ - } \ -} +#define COPY_AND_MASK(in, out, size, mask) \ + { \ + int i; \ + if (mask) { \ + for (i = 0; i < size; ++i) { \ + out[i] = in[i]; \ + if (mask[i] & 0xFE) \ + out[i] = -2; \ + if (mask[i] & 0x01) \ + out[i] = -1; \ + } \ + } else { \ + for (i = 0; i < size; i++) { \ + out[i] = in[i]; \ + } \ + } \ + } int parse_args(int argc, char **argv, char **file_name, int *frame_idx) { - int retval = 0; - if (argc == 2) { - *frame_idx = 0; - *file_name = argv[1]; - } else if (argc >= 2) { - *file_name = argv[1]; - *frame_idx = atoi(argv[2]); - } else { - ERROR_JUMP(-1, done, "Require filename argument"); - } + int retval = 0; + if (argc == 2) { + *frame_idx = 0; + *file_name = argv[1]; + } else if (argc >= 2) { + *file_name = argv[1]; + *frame_idx = atoi(argv[2]); + } else { + ERROR_JUMP(-1, done, "Require filename argument"); + } done: - return retval; + return retval; } - int main(int argc, char **argv) { - int err = 0; - int retval = 0; - char *test_file = ""; - struct ds_desc_t *desc; - int dims[3] = {0}; - hid_t fid = 0; - int frame_idx = 0; - int *mask = NULL; - int *data = NULL; - void *buffer = NULL; + int err = 0; + int retval = 0; + char *test_file = ""; + struct ds_desc_t *desc; + int dims[3] = {0}; + hid_t fid = 0; + int frame_idx = 0; + int *mask = NULL; + int *data = NULL; + void *buffer = NULL; - init_error_handling(); - if (init_h5_error_handling() < 0) { - ERROR_JUMP(-1, done, ""); - } + init_error_handling(); + if (init_h5_error_handling() < 0) { + ERROR_JUMP(-1, done, ""); + } - if (parse_args(argc, argv, &test_file, &frame_idx) < 0) { - ERROR_JUMP(-1, done, "Failure parsing arguments"); - } + if (parse_args(argc, argv, &test_file, &frame_idx) < 0) { + ERROR_JUMP(-1, done, "Failure parsing arguments"); + } - fid = H5Fopen(test_file, H5F_ACC_RDONLY, H5P_DEFAULT); - if (fid < 0) ERROR_JUMP(-1, done, "Error opening file"); + fid = H5Fopen(test_file, H5F_ACC_RDONLY, H5P_DEFAULT); + if (fid < 0) + ERROR_JUMP(-1, done, "Error opening file"); - err = get_detector_info(fid, &desc); - if (err < 0) { - ERROR_JUMP(err, done, ""); - } - dims[0] = desc->dims[0]; - dims[1] = desc->dims[1]; - dims[2] = desc->dims[2]; + err = get_detector_info(fid, &desc); + if (err < 0) { + ERROR_JUMP(err, done, ""); + } + dims[0] = desc->dims[0]; + dims[1] = desc->dims[1]; + dims[2] = desc->dims[2]; - printf("Dims: %d, %d, %d\n", dims[0], dims[1], dims[2]); + printf("Dims: %d, %d, %d\n", dims[0], dims[1], dims[2]); - mask = malloc(dims[1] * dims[2] * sizeof(*mask)); - if (!mask) { - ERROR_JUMP(err, done, "Failed to allocate space for pixel mask"); - } - err = desc->get_pixel_mask(desc, mask); - if (err < 0) { - ERROR_JUMP(err, done, ""); - } + mask = malloc(dims[1] * dims[2] * sizeof(*mask)); + if (!mask) { + ERROR_JUMP(err, done, "Failed to allocate space for pixel mask"); + } + err = desc->get_pixel_mask(desc, mask); + if (err < 0) { + ERROR_JUMP(err, done, ""); + } - data = malloc(dims[1] * dims[2] * sizeof(*data)); - if (sizeof(*data) != desc->data_width) { - buffer = malloc(dims[1] * dims[2] * desc->data_width); - } else { - buffer = data; - } + data = malloc(dims[1] * dims[2] * sizeof(*data)); + if (sizeof(*data) != desc->data_width) { + buffer = malloc(dims[1] * dims[2] * desc->data_width); + } else { + buffer = data; + } - err = desc->get_data_frame(desc, frame_idx, buffer); - if (err < 0) { - ERROR_JUMP(err, done, ""); - } + err = desc->get_data_frame(desc, frame_idx, buffer); + if (err < 0) { + ERROR_JUMP(err, done, ""); + } - if (buffer != data) { - if (desc->data_width == sizeof(signed char)) { - signed char *in = buffer; - COPY_AND_MASK(in, data, dims[1] * dims[2], mask); - } else if (desc->data_width == sizeof(short)) { - short *in = buffer; - COPY_AND_MASK(in, data, dims[1] * dims[2], mask); - } else if (desc->data_width == sizeof(int)) { - int *in = buffer; - COPY_AND_MASK(in, data, dims[1] * dims[2], mask); - } else if (desc->data_width == sizeof(long int)) { - long int *in = buffer; - COPY_AND_MASK(in, data, dims[1] * dims[2], mask); - } else if (desc->data_width == sizeof(long long int)) { - long long int *in = buffer; - COPY_AND_MASK(in, data, dims[1] * dims[2], mask); - } - } + if (buffer != data) { + if (desc->data_width == sizeof(signed char)) { + signed char *in = buffer; + COPY_AND_MASK(in, data, dims[1] * dims[2], mask); + } else if (desc->data_width == sizeof(short)) { + short *in = buffer; + COPY_AND_MASK(in, data, dims[1] * dims[2], mask); + } else if (desc->data_width == sizeof(int)) { + int *in = buffer; + COPY_AND_MASK(in, data, dims[1] * dims[2], mask); + } else if (desc->data_width == sizeof(long int)) { + long int *in = buffer; + COPY_AND_MASK(in, data, dims[1] * dims[2], mask); + } else if (desc->data_width == sizeof(long long int)) { + long long int *in = buffer; + COPY_AND_MASK(in, data, dims[1] * dims[2], mask); + } + } - { - int i, j; - int max_i = 30; - int max_j = 10; - max_j = max_j < dims[1] ? max_j : dims[1]; - max_i = max_i < dims[2] ? max_i : dims[2]; - for (j = 0; j < max_j; j++) { - for (i = 0; i < max_i; i++) { - printf("%3d ", data[i + j*dims[2]]); - } - printf("\n"); - } - } + { + int i, j; + int max_i = 30; + int max_j = 10; + max_j = max_j < dims[1] ? max_j : dims[1]; + max_i = max_i < dims[2] ? max_i : dims[2]; + for (j = 0; j < max_j; j++) { + for (i = 0; i < max_i; i++) { + printf("%3d ", data[i + j * dims[2]]); + } + printf("\n"); + } + } done: - if (fid > 0) H5Fclose(fid); - if (data) free(data); - if (buffer && (data != buffer)) free(buffer); - if (mask) free(mask); - if (retval != 0) dump_error_stack(stderr); - return retval; + if (fid > 0) + H5Fclose(fid); + if (data) + free(data); + if (buffer && (data != buffer)) + free(buffer); + if (mask) + free(mask); + if (retval != 0) + dump_error_stack(stderr); + return retval; }