diff options
Diffstat (limited to 'tools/src/h5repack/h5repack.c')
| -rw-r--r-- | tools/src/h5repack/h5repack.c | 938 |
1 files changed, 938 insertions, 0 deletions
diff --git a/tools/src/h5repack/h5repack.c b/tools/src/h5repack/h5repack.c new file mode 100644 index 0000000..21a5883 --- /dev/null +++ b/tools/src/h5repack/h5repack.c @@ -0,0 +1,938 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "H5private.h" +#include "h5repack.h" +#include "h5tools.h" +#include "h5tools_utils.h" + +/*------------------------------------------------------------------------- + * File: h5repack.c + * Purpose: Public API functions + *------------------------------------------------------------------------- + */ + +static int check_options(pack_opt_t *options); +static int check_objects(const char *fname, pack_opt_t *options); +static const char *get_sfilter(H5Z_filter_t filtn); +static int have_request(pack_opt_t *options); + +/*------------------------------------------------------------------------- + * Function: h5repack + * + * Purpose: locate all high-level HDF5 objects in the file + * and compress/chunk them using options + * + * Algorithm: 2 traversals are made to the file; the 1st builds a list of + * the objects, the 2nd makes a copy of them, using the options; + * the reason for the 1st traversal is to check for invalid + * object name requests + * + * Return: 0, ok, -1, fail + *------------------------------------------------------------------------- + */ +int +h5repack(const char *infile, const char *outfile, pack_opt_t *options) +{ + /* check input */ + if (check_options(options) < 0) + return -1; + + /* check for objects in input that are in the file */ + if (check_objects(infile, options) < 0) + return -1; + + /* copy the objects */ + if (copy_objects(infile, outfile, options) < 0) + return -1; + + return 0; +} /* end h5repack() */ + +/*------------------------------------------------------------------------- + * Function: h5repack_init + * + * Purpose: initialize options + * + * Return: 0, ok, -1, fail + *------------------------------------------------------------------------- + */ +int +h5repack_init(pack_opt_t *options, int verbose, hbool_t latest) +{ + int k, n; + + HDmemset(options, 0, sizeof(pack_opt_t)); + options->min_comp = 0; + options->verbose = verbose; + options->latest = latest; + options->layout_g = H5D_LAYOUT_ERROR; + options->low_bound = H5F_LIBVER_EARLIEST; + options->high_bound = H5F_LIBVER_LATEST; + options->fin_fapl = H5P_DEFAULT; + options->fout_fapl = H5P_DEFAULT; + + for (n = 0; n < H5_REPACK_MAX_NFILTERS; n++) { + options->filter_g[n].filtn = -1; + options->filter_g[n].cd_nelmts = 0; + for (k = 0; k < CD_VALUES; k++) + options->filter_g[n].cd_values[k] = 0; + } + + return (options_table_init(&(options->op_tbl))); +} /* end h5repack_init() */ + +/*------------------------------------------------------------------------- + * Function: h5repack_end + * + * Purpose: free options table + *------------------------------------------------------------------------- + */ + +int +h5repack_end(pack_opt_t *options) +{ + return options_table_free(options->op_tbl); +} /* end h5repack_end() */ + +/*------------------------------------------------------------------------- + * Function: h5repack_addfilter + * + * Purpose: add a compression -f option to table + * Example: -f dset:GZIP=6 + * + * Return: 0, ok, -1, fail + *------------------------------------------------------------------------- + */ +int +h5repack_addfilter(const char *str, pack_opt_t *options) +{ + obj_list_t *obj_list = NULL; /* one object list for the -f and -l option entry */ + filter_info_t filter; /* filter info for the current -f option entry */ + unsigned n_objs; /* number of objects in the current -f or -l option entry */ + int is_glb; /* is the filter global */ + + /* parse the -f (--filter) option */ + if (NULL == (obj_list = parse_filter(str, &n_objs, &filter, options, &is_glb))) + return -1; + + /* if it applies to all objects */ + if (is_glb) { + int n; + + n = options->n_filter_g++; /* increase # of global filters */ + if (options->n_filter_g > H5_REPACK_MAX_NFILTERS) { + error_msg("maximum number of filters exceeded for <%s>\n", str); + HDfree(obj_list); + return -1; + } + + options->filter_g[n] = filter; + } + else + options_add_filter(obj_list, n_objs, filter, options->op_tbl); + + HDfree(obj_list); + return 0; +} /* end h5repack_addfilter() */ + +/*------------------------------------------------------------------------- + * Function: h5repack_addlayout + * + * Purpose: add a layout option + * + * Return: 0, ok, -1, fail + *------------------------------------------------------------------------- + */ +int +h5repack_addlayout(const char *str, pack_opt_t *options) +{ + obj_list_t *obj_list = NULL; /*one object list for the -t and -c option entry */ + unsigned n_objs; /*number of objects in the current -t or -c option entry */ + pack_info_t pack; /*info about layout to extract from parse */ + int j; + int ret_value = -1; + + init_packobject(&pack); + + if (options->all_layout == 1) { + error_msg("invalid layout input: 'all' option is present with other objects <%s>\n", str); + return ret_value; + } + + /* parse the layout option */ + obj_list = parse_layout(str, &n_objs, &pack, options); + if (obj_list) { + /* set layout option */ + options->layout_g = pack.layout; + + /* no individual dataset specified */ + if (options->all_layout == 1) { + if (pack.layout == H5D_CHUNKED) { + /* -2 means the NONE option, remove chunking + and set the global layout to contiguous */ + if (pack.chunk.rank == -2) /* TODO: fix 'magic number' */ + options->layout_g = H5D_CONTIGUOUS; + /* otherwise set the global chunking type */ + else { + options->chunk_g.rank = pack.chunk.rank; + for (j = 0; j < pack.chunk.rank; j++) + options->chunk_g.chunk_lengths[j] = pack.chunk.chunk_lengths[j]; + } + } + } + + /* individual dataset specified */ + if (options->all_layout == 0) + ret_value = options_add_layout(obj_list, n_objs, &pack, options->op_tbl); + + HDfree(obj_list); + ret_value = 0; + } /* end if obj_list exists */ + + return ret_value; +} /* end h5repack_addlayout() */ + +/* Note: The below copy_named_datatype(), named_datatype_free(), copy_attr() + * were located in h5repack_copy.c as static prior to bugfix1726. + * Made shared functions as copy_attr() was needed in h5repack_refs.c. + * However copy_attr() may be obsoleted when H5Acopy is available and put back + * others to static in h5repack_copy.c. + */ +/*------------------------------------------------------------------------- + * Function: copy_named_datatype + * + * Purpose: Copies the specified datatype anonymously, and returns an open + * id for that datatype in the output file. The first time this + * is called it scans every named datatype in travt into a + * private stack, afterwards it simply scans that stack. The id + * returned must be closed after it is no longer needed. + * named_datatype_free must be called before the program exits + * to free the stack. + *------------------------------------------------------------------------- + */ + +hid_t +copy_named_datatype(hid_t type_in, hid_t fidout, named_dt_t **named_dt_head_p, trav_table_t *travt, + pack_opt_t *options) +{ + named_dt_t *dt = NULL; /* Stack pointer */ + named_dt_t *dt_ret = NULL; /* Datatype to return */ + H5O_info2_t oinfo; /* Object info of input dtype */ + int token_cmp; + hid_t ret_value = H5I_INVALID_HID; + + if (H5Oget_info3(type_in, &oinfo, H5O_INFO_BASIC) < 0) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "H5Oget_info failed"); + + if (*named_dt_head_p) { + /* Search the stack for the datatype. */ + for (dt = *named_dt_head_p; dt != NULL; dt = dt->next) { + if (H5Otoken_cmp(type_in, &dt->obj_token, &oinfo.token, &token_cmp) < 0) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "failed to compare object tokens"); + + if (token_cmp == 0) + break; // found it! + } + + dt_ret = dt; + } + else { + /* Create the stack */ + size_t i; + + for (i = 0; i < travt->nobjs; i++) { + if (travt->objs[i].type == H5TRAV_TYPE_NAMED_DATATYPE) { + /* Push onto the stack */ + if (NULL == (dt = (named_dt_t *)HDmalloc(sizeof(named_dt_t)))) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "buffer allocation failed failed"); + dt->next = *named_dt_head_p; + *named_dt_head_p = dt; + + /* Update the token/address and id */ + HDmemcpy(&dt->obj_token, &travt->objs[i].obj_token, sizeof(H5O_token_t)); + dt->id_out = H5I_INVALID_HID; + + /* Check if this type is the one requested */ + if (H5Otoken_cmp(type_in, &oinfo.token, &dt->obj_token, &token_cmp) < 0) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "failed to compare object tokens"); + if (!token_cmp) + dt_ret = dt; + } /* end if named datatype */ + } /* end for each object in traversal table */ + } /* end else (create the stack) */ + + /* Handle the case that the requested datatype was not found. This is + * possible if the datatype was committed anonymously in the input file. + */ + if (!dt_ret) { + /* Push the new datatype onto the stack */ + if (NULL == (dt_ret = (named_dt_t *)HDmalloc(sizeof(named_dt_t)))) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "buffer allocation failed failed"); + dt_ret->next = *named_dt_head_p; + *named_dt_head_p = dt_ret; + + /* Update the token/address and id */ + HDmemcpy(&dt_ret->obj_token, &oinfo.token, sizeof(H5O_token_t)); + dt_ret->id_out = H5I_INVALID_HID; + } /* end if requested datatype not found */ + + /* If the requested datatype does not yet exist in the output file, copy it + * anonymously + */ + if (dt_ret->id_out < 0) { + if (options->use_native == 1) + dt_ret->id_out = H5Tget_native_type(type_in, H5T_DIR_DEFAULT); + else + dt_ret->id_out = H5Tcopy(type_in); + if (dt_ret->id_out < 0) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "H5Tget_native_type-H5Tcopy failed"); + if (H5Tcommit_anon(fidout, dt_ret->id_out, H5P_DEFAULT, H5P_DEFAULT) < 0) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "H5Tcommit_anon failed"); + } /* end if named datatype not yet in output file */ + + /* Set return value */ + ret_value = dt_ret->id_out; + + /* Increment the ref count on id_out, because the calling function will try + * to close it. (TODO: fix scope envy) + */ + if (H5Iinc_ref(ret_value) < 0) + H5TOOLS_GOTO_ERROR(H5I_INVALID_HID, "H5Iinc_ref failed"); + +done: + return ret_value; +} /* end copy_named_datatype() */ + +/*------------------------------------------------------------------------- + * Function: named_datatype_free + * + * Purpose: Frees the stack of named datatypes. + *------------------------------------------------------------------------- + */ +int +named_datatype_free(named_dt_t **named_dt_head_p, int ignore_err) +{ + named_dt_t *dt = *named_dt_head_p; + int ret_value = -1; + + while (dt) { + /* Pop the datatype off the stack and free it */ + if (H5Tclose(dt->id_out) < 0 && !ignore_err) + H5TOOLS_GOTO_ERROR((-1), "H5Tclose failed"); + dt = dt->next; + HDfree(*named_dt_head_p); + *named_dt_head_p = dt; + } + + ret_value = 0; + +done: + return (ret_value); +} /* end named_datatype_free() */ + +/*------------------------------------------------------------------------- + * Function: copy_attr + * + * Purpose: copy attributes located in LOC_IN, which is obtained either from + * loc_id = H5Gopen2( fid, name); + * loc_id = H5Dopen2( fid, name); + * loc_id = H5Topen2( fid, name); + * + * Return: 0, ok, -1 no + *------------------------------------------------------------------------- + */ +int +copy_attr(hid_t loc_in, hid_t loc_out, named_dt_t **named_dt_head_p, trav_table_t *travt, pack_opt_t *options) +{ + hid_t attr_id = H5I_INVALID_HID; /* attr ID */ + hid_t attr_out = H5I_INVALID_HID; /* attr ID */ + hid_t space_id = H5I_INVALID_HID; /* space ID */ + hid_t ftype_id = H5I_INVALID_HID; /* file type ID */ + hid_t wtype_id = H5I_INVALID_HID; /* read/write type ID */ + size_t msize; /* size of type */ + void *buf = NULL; /* data buffer */ + hsize_t nelmts; /* number of elements in dataset */ + int rank; /* rank of dataset */ + htri_t is_named; /* Whether the datatype is named */ + hsize_t dims[H5S_MAX_RANK]; /* dimensions of dataset */ + H5_timer_t timer; /* Timer for read/write operations */ + H5_timevals_t times; /* Elapsed time for each operation */ + static double read_time = 0; + static double write_time = 0; + char name[255]; + H5O_info2_t oinfo; /* object info */ + int j; + unsigned u; + hbool_t is_ref = 0; + H5T_class_t type_class = -1; + int ret_value = 0; + + if (H5Oget_info3(loc_in, &oinfo, H5O_INFO_NUM_ATTRS) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Oget_info failed"); + + /*------------------------------------------------------------------------- + * copy all attributes + *------------------------------------------------------------------------- + */ + for (u = 0; u < (unsigned)oinfo.num_attrs; u++) { + /* open attribute */ + if ((attr_id = H5Aopen_by_idx(loc_in, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)u, H5P_DEFAULT, + H5P_DEFAULT)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Aopen_by_idx failed"); + + if (H5Aget_name(attr_id, (size_t)255, name) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Pclose failed"); + + /* get the file datatype */ + if ((ftype_id = H5Aget_type(attr_id)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Aget_type failed"); + + /* Check if the datatype is committed */ + if ((is_named = H5Tcommitted(ftype_id)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Tcommitted failed"); + if (is_named && travt) { + hid_t fidout = H5I_INVALID_HID; + + /* Create out file id */ + if ((fidout = H5Iget_file_id(loc_out)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Iget_file_id failed"); + + /* Copy named dt */ + if ((wtype_id = copy_named_datatype(ftype_id, fidout, named_dt_head_p, travt, options)) < 0) { + H5Fclose(fidout); + H5TOOLS_GOTO_ERROR((-1), "copy_named_datatype failed"); + } + + if (H5Fclose(fidout) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Fclose failed"); + } /* end if datatype is committed and we have a traversal table */ + else { + if (options->use_native == 1) + wtype_id = H5Tget_native_type(ftype_id, H5T_DIR_DEFAULT); + else + wtype_id = H5Tcopy(ftype_id); + } /* end else: uncommitted datatype and/or no traversal table */ + + /* get the dataspace handle */ + if ((space_id = H5Aget_space(attr_id)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Aget_space failed"); + + /* get dimensions */ + if ((rank = H5Sget_simple_extent_dims(space_id, dims, NULL)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Sget_simple_extent_dims failed"); + + nelmts = 1; + for (j = 0; j < rank; j++) + nelmts *= dims[j]; + + if ((msize = H5Tget_size(wtype_id)) == 0) + H5TOOLS_GOTO_ERROR((-1), "H5Tget_size failed"); + + /*--------------------------------------------------------------------- + * object references are a special case. We cannot just copy the + * buffers, but instead we recreate the reference. + * This is done on a second sweep of the file that just copies the + * referenced objects at copy_refs_attr(). + *--------------------------------------------------------------------- + */ + type_class = H5Tget_class(wtype_id); + is_ref = (type_class == H5T_REFERENCE); + if (type_class == H5T_VLEN || type_class == H5T_ARRAY) { + hid_t base_type = H5I_INVALID_HID; + + base_type = H5Tget_super(ftype_id); + is_ref = (is_ref || (H5Tget_class(base_type) == H5T_REFERENCE)); + if (H5Tclose(base_type) < 0) + H5TOOLS_ERROR((-1), "H5Tclose base_type failed"); + } /* end if type_class is variable length or array */ + + if (type_class == H5T_COMPOUND) { + int nmembers = H5Tget_nmembers(wtype_id); + + for (j = 0; j < nmembers; j++) { + hid_t mtid = H5Tget_member_type(wtype_id, (unsigned)j); + H5T_class_t mtclass = H5Tget_class(mtid); + if (H5Tclose(mtid) < 0) + H5TOOLS_ERROR((-1), "H5Tclose mtid failed"); + + if (mtclass == H5T_REFERENCE) { + is_ref = 1; + break; + } + } /* end for each member */ + } /* end if type_class is H5T_COMPOUND */ + + read_time = 0; + write_time = 0; + + if (!is_ref) { + /*----------------------------------------------------------------- + * read to memory + *----------------------------------------------------------------- + */ + + buf = (void *)HDmalloc((size_t)(nelmts * msize)); + if (buf == NULL) { + H5TOOLS_GOTO_ERROR((-1), "HDmalloc failed"); + } /* end if */ + if (options->verbose == 2) { + H5_timer_init(&timer); + H5_timer_start(&timer); + } + if (H5Aread(attr_id, wtype_id, buf) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Aread failed"); + if (options->verbose == 2) { + H5_timer_stop(&timer); + H5_timer_get_times(timer, ×); + read_time += times.elapsed; + } + + /*----------------------------------------------------------------- + * copy + *----------------------------------------------------------------- + */ + + if ((attr_out = H5Acreate2(loc_out, name, wtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Acreate2 failed on ,%s>", name); + + if (options->verbose == 2) { + H5_timer_init(&timer); + H5_timer_start(&timer); + } + if (H5Awrite(attr_out, wtype_id, buf) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Awrite failed"); + if (options->verbose == 2) { + H5_timer_stop(&timer); + H5_timer_get_times(timer, ×); + write_time += times.elapsed; + } + + /*close*/ + if (H5Aclose(attr_out) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Aclose failed"); + + /* Check if we have VL data and string in the attribute's datatype that must + * be reclaimed */ + if (TRUE == h5tools_detect_vlen(wtype_id)) + H5Treclaim(wtype_id, space_id, H5P_DEFAULT, buf); + + HDfree(buf); + buf = NULL; + } /*H5T_REFERENCE*/ + + if (options->verbose == 2) + HDprintf(FORMAT_OBJ_ATTR_TIME, "attr", read_time, write_time, name); + else + HDprintf(FORMAT_OBJ_ATTR, "attr", name); + + /*--------------------------------------------------------------------- + * close + *--------------------------------------------------------------------- + */ + if (H5Sclose(space_id) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Sclose failed"); + space_id = H5I_INVALID_HID; + if (H5Tclose(wtype_id) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Tclose failed"); + wtype_id = H5I_INVALID_HID; + if (H5Tclose(ftype_id) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Tclose failed"); + ftype_id = H5I_INVALID_HID; + if (H5Aclose(attr_id) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Aclose failed"); + attr_id = H5I_INVALID_HID; + } /* for u (each attribute) */ + +done: + H5E_BEGIN_TRY + { + if (buf) { + /* Check if we have VL data and string in the attribute's + * datatype that must be reclaimed + */ + if (TRUE == h5tools_detect_vlen(wtype_id)) + H5Treclaim(wtype_id, space_id, H5P_DEFAULT, buf); + + /* Free buf */ + HDfree(buf); + } + + H5Aclose(attr_out); + H5Sclose(space_id); + H5Tclose(wtype_id); + H5Tclose(ftype_id); + H5Aclose(attr_id); + } + H5E_END_TRY; + + return ret_value; +} /* end copy_attr() */ + +/*----------------------------------------------------------------------------- + * Function: check_options + * + * Purpose: print options, checks for invalid options + * + * Return: void, return -1 on error + *----------------------------------------------------------------------------- + */ +static int +check_options(pack_opt_t *options) +{ + unsigned int i; + int k, j, has_cp = 0, has_ck = 0; + char slayout[30]; + int ret_value = 0; + + /*------------------------------------------------------------------------- + * Objects to layout + *------------------------------------------------------------------------- + */ + if (options->verbose > 0 && have_request(options)) { + if (options->all_layout == 1) { + HDprintf("All objects to modify layout are...\n"); + switch (options->layout_g) { + case H5D_COMPACT: + strcpy(slayout, "compact"); + break; + case H5D_CONTIGUOUS: + strcpy(slayout, "contiguous"); + break; + case H5D_CHUNKED: + strcpy(slayout, "chunked"); + break; + case H5D_VIRTUAL: + strcpy(slayout, "virtual"); + break; + case H5D_LAYOUT_ERROR: + case H5D_NLAYOUTS: + H5TOOLS_GOTO_ERROR((-1), "invalid layout"); + break; + default: + strcpy(slayout, "invalid layout\n"); + H5TOOLS_GOTO_DONE((-1)); + } + HDprintf(" Apply %s layout to all", slayout); + if (H5D_CHUNKED == options->layout_g) { + HDprintf("with dimension [ "); + for (j = 0; j < options->chunk_g.rank; j++) + HDprintf("%d ", (int)options->chunk_g.chunk_lengths[j]); + HDprintf("]"); + } + HDprintf("\n"); + } + else + HDprintf("No all objects to modify layout\n"); + } /* end if verbose */ + + for (i = 0; i < options->op_tbl->nelems; i++) { + char *name = options->op_tbl->objs[i].path; + + if (options->op_tbl->objs[i].chunk.rank > 0) { + if (options->verbose > 0) { + HDprintf(" <%s> with chunk size ", name); + for (k = 0; k < options->op_tbl->objs[i].chunk.rank; k++) + HDprintf("%d ", (int)options->op_tbl->objs[i].chunk.chunk_lengths[k]); + HDprintf("\n"); + } + has_ck = 1; + } + else if (options->op_tbl->objs[i].chunk.rank == -2) { /* TODO: replace 'magic number' */ + if (options->verbose > 0) + HDprintf(" <%s> %s\n", name, "NONE (contiguous)"); + has_ck = 1; + } + } /* end for each object in options */ + + if (options->all_layout == 1 && has_ck) + H5TOOLS_GOTO_ERROR((-1), "invalid chunking input: 'all' option is present with other objects"); + + /*------------------------------------------------------------------------- + * Objects to filter + *------------------------------------------------------------------------- + */ + + if (options->verbose > 0 && have_request(options)) { + if (options->all_filter == 1) { + HDprintf("All objects to apply filter are...\n"); + for (k = 0; k < options->n_filter_g; k++) { + H5Z_filter_t filtn = options->filter_g[k].filtn; + if (filtn < 0) { + HDprintf(" Unknown\n"); + continue; + } + switch (filtn) { + case H5Z_FILTER_NONE: + HDprintf(" Uncompress all\n"); + break; + case H5Z_FILTER_SHUFFLE: + case H5Z_FILTER_FLETCHER32: + HDprintf(" All with %s\n", get_sfilter(filtn)); + break; + case H5Z_FILTER_SZIP: + case H5Z_FILTER_DEFLATE: + HDprintf(" All with %s, parameter %d\n", get_sfilter(filtn), + options->filter_g[k].cd_values[0]); + break; + default: + HDprintf(" User Defined %d\n", filtn); + break; + } /* end switch */ + } /* end for each filter */ + } /* end if options->all_filter == 1 (TODO: meaning) */ + else + HDprintf("No all objects to apply filter\n"); + } /* end if verbose */ + + for (i = 0; i < options->op_tbl->nelems; i++) { + pack_info_t pack = options->op_tbl->objs[i]; + char *name = pack.path; + + for (j = 0; j < pack.nfilters; j++) { + if (options->verbose > 0) { + if (pack.filter[j].filtn >= 0) { + if (pack.filter[j].filtn > H5Z_FILTER_SCALEOFFSET) { + HDprintf(" <%s> with %s filter %d\n", name, get_sfilter(pack.filter[j].filtn), + pack.filter[j].filtn); + } + else { + HDprintf(" <%s> with %s filter\n", name, get_sfilter(pack.filter[j].filtn)); + } + } + } + has_cp = 1; + } /* end for each filter */ + } /* end for each object in options table */ + + if (options->all_filter == 1 && has_cp) + H5TOOLS_GOTO_ERROR((-1), "invalid compression input: 'all' option is present with other objects"); + + /*------------------------------------------------------------------------- + * Check options for the latest format + *------------------------------------------------------------------------- + */ + + if (options->grp_compact < 0) + H5TOOLS_GOTO_ERROR((-1), "invalid maximum number of links to store as header messages"); + if (options->grp_indexed < 0) + H5TOOLS_GOTO_ERROR((-1), "invalid minimum number of links to store in the indexed format"); + if (options->grp_indexed > options->grp_compact) + H5TOOLS_GOTO_ERROR((-1), "minimum indexed size is greater than the maximum compact size"); + for (i = 0; i < 8; i++) + if (options->msg_size[i] < 0) + H5TOOLS_GOTO_ERROR((-1), "invalid shared message size"); + + /*------------------------------------------------------------------------ + * Verify new user userblock options; file name must be present + *------------------------------------------------------------------------ + */ + if (options->ublock_filename != NULL && options->ublock_size == 0) { + if (options->verbose > 0) { + HDprintf("Warning: user block size missing for file %s. Assigning a default size of 1024...\n", + options->ublock_filename); + options->ublock_size = 1024; + } + } + + if (options->ublock_filename == NULL && options->ublock_size != 0) + H5TOOLS_GOTO_ERROR((-1), "file name missing for user block"); + + /*------------------------------------------------------------------------ + * Verify alignment options; threshold is zero default but alignment not + *------------------------------------------------------------------------ + */ + + if (options->alignment == 0 && options->threshold != 0) + H5TOOLS_GOTO_ERROR((-1), "alignment for H5Pset_alignment missing"); + +done: + return ret_value; +} /* end check_options() */ + +/*------------------------------------------------------------------------- + * Function: check_objects + * + * Purpose: Locate all HDF5 objects in the file and compare with user-supplied + * list. + * + * Return: 0, ok, -1 no + *------------------------------------------------------------------------- + */ +static int +check_objects(const char *fname, pack_opt_t *options) +{ + hid_t fid = H5I_INVALID_HID; + hid_t did = H5I_INVALID_HID; + hid_t sid = H5I_INVALID_HID; + unsigned int i; + int ifil; + trav_table_t *travt = NULL; + int ret_value = 0; + + /* nothing to do */ + if (options->op_tbl->nelems == 0) + H5TOOLS_GOTO_DONE(0); + + /*------------------------------------------------------------------------- + * open the file + *------------------------------------------------------------------------- + */ + if ((fid = h5tools_fopen(fname, H5F_ACC_RDONLY, options->fin_fapl, (options->fin_fapl != H5P_DEFAULT), + NULL, 0)) < 0) + H5TOOLS_GOTO_ERROR((-1), "h5tools_fopen failed <%s>: %s", fname, H5FOPENERROR); + + /*------------------------------------------------------------------------- + * get the list of objects in the file + *------------------------------------------------------------------------- + */ + + /* Initialize indexing options */ + h5trav_set_index(sort_by, sort_order); + /* init table */ + trav_table_init(fid, &travt); + + /* get the list of objects in the file */ + if (h5trav_gettable(fid, travt) < 0) + H5TOOLS_GOTO_ERROR((-1), "h5trav_gettable failed"); + + /*------------------------------------------------------------------------- + * compare with user supplied list + *------------------------------------------------------------------------- + */ + + if (options->verbose > 0) + HDprintf("Opening file. Searching %zu objects to modify ...\n", travt->nobjs); + + for (i = 0; i < options->op_tbl->nelems; i++) { + pack_info_t obj = options->op_tbl->objs[i]; + char *name = obj.path; + + if (options->verbose > 0) + HDprintf(" <%s>", name); + + /* the input object names are present in the file and are valid */ + if (h5trav_getindext(name, travt) < 0) + H5TOOLS_GOTO_ERROR((-1), "%s Could not find <%s> in file <%s>. Exiting...\n", + (options->verbose > 0 ? "\n" : ""), name, fname); + if (options->verbose > 0) + HDprintf("...Found\n"); + + for (ifil = 0; ifil < obj.nfilters; ifil++) { + if (obj.filter[ifil].filtn < 0) + H5TOOLS_GOTO_ERROR((-1), "invalid filter"); + /* check for extra filter conditions */ + switch (obj.filter[ifil].filtn) { + /* chunk size must be smaller than pixels per block */ + case H5Z_FILTER_SZIP: { + int j; + hsize_t csize = 1; + unsigned ppb = obj.filter[ifil].cd_values[0]; + hsize_t dims[H5S_MAX_RANK]; + int rank; + + if (obj.chunk.rank > 0) { + rank = obj.chunk.rank; + for (j = 0; j < rank; j++) + csize *= obj.chunk.chunk_lengths[j]; + } + else { + if ((did = H5Dopen2(fid, name, H5P_DEFAULT)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Dopen2 failed"); + if ((sid = H5Dget_space(did)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Dget_space failed"); + if ((rank = H5Sget_simple_extent_ndims(sid)) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Sget_simple_extent_ndims failed"); + HDmemset(dims, 0, sizeof dims); + if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Sget_simple_extent_dims failed"); + for (j = 0; j < rank; j++) + csize *= dims[j]; + if (H5Sclose(sid) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Sclose failed"); + if (H5Dclose(did) < 0) + H5TOOLS_GOTO_ERROR((-1), "H5Dclose failed"); + } + + if (csize < ppb) { + HDprintf(" <warning: SZIP settings, chunk size is smaller than pixels per block>\n"); + H5TOOLS_GOTO_DONE(0); + } + } /* end case SZIP */ + break; + default: + break; + } /* end switch */ + } /* for ifil (each user-defined filter) */ + } /* for i (each object in options traversal table) */ + +done: + H5E_BEGIN_TRY + { + H5Sclose(sid); + H5Dclose(did); + H5Fclose(fid); + } + H5E_END_TRY; + if (travt) + trav_table_free(travt); + return ret_value; +} /* end check_objects() */ + +/*------------------------------------------------------------------------- + * Function: have_request + * + * Purpose: check if a filter or layout was requested + * + * Return: 1 yes, 0 no + *------------------------------------------------------------------------- + */ +static int +have_request(pack_opt_t *options) +{ + + if (options->all_filter || options->all_layout || options->op_tbl->nelems) + return 1; + + return 0; +} /* end have_request() */ + +/*------------------------------------------------------------------------- + * Function: get_sfilter + * + * Purpose: return the filter as a string name + * + * Return: name of filter, exit on error + *------------------------------------------------------------------------- + */ +static const char * +get_sfilter(H5Z_filter_t filtn) +{ + if (filtn < 0) + return NULL; + else if (filtn == H5Z_FILTER_NONE) + return "NONE"; + else if (filtn == H5Z_FILTER_DEFLATE) + return "GZIP"; + else if (filtn == H5Z_FILTER_SZIP) + return "SZIP"; + else if (filtn == H5Z_FILTER_SHUFFLE) + return "SHUFFLE"; + else if (filtn == H5Z_FILTER_FLETCHER32) + return "FLETCHER32"; + else if (filtn == H5Z_FILTER_NBIT) + return "NBIT"; + else if (filtn == H5Z_FILTER_SCALEOFFSET) + return "SOFF"; + else + return "UD"; +} /* end get_sfilter() */ |
