Files
hdf5/tools/src/h5format_convert/h5format_convert.c
Allen Byrne 8f3878de39 1.10 Merge of tools perform reorg and command line args (#960)
* Merge of tools perform reorg and command line args

Also sync tools change with 1.12

* Add missing file
2021-08-25 17:35:34 -05:00

466 lines
15 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Programmer: Vailin Choi; Feb 2015
*/
/*
* We include the private header file so we can get to the uniform
* programming environment it declares.
* HDF5 API functions (except for H5G_basename())
*/
#include "H5private.h"
#include "h5tools.h"
#include "h5tools_utils.h"
#include "h5trav.h"
/* Name of tool */
#define PROGRAMNAME "h5format_convert"
static char *fname_g = NULL;
static char *dname_g = NULL;
static int dset_g = FALSE;
static int noop_g = FALSE;
static int verbose_g = 0;
/*
* Command-line options: The user can specify short or long-named
* parameters.
*/
static const char * s_opts = "hVvd:n";
static struct h5_long_options l_opts[] = {{"help", no_arg, 'h'}, {"version", no_arg, 'V'},
{"verbose", no_arg, 'v'}, {"dname", require_arg, 'd'},
{"noop", no_arg, 'n'}, {"enable-error-stack", no_arg, 'E'},
{NULL, 0, '\0'}};
/*-------------------------------------------------------------------------
* Function: usage
*
* Purpose: print usage
*
* Return: void
*
*-------------------------------------------------------------------------
*/
static void
usage(const char *prog)
{
HDfprintf(stdout, "usage: %s [OPTIONS] file_name\n", prog);
HDfprintf(stdout, " OPTIONS\n");
HDfprintf(stdout, " -h, --help Print a usage message and exit\n");
HDfprintf(stdout, " -V, --version Print version number and exit\n");
HDfprintf(stdout, " -v, --verbose Turn on verbose mode\n");
HDfprintf(stdout, " -d dname, --dname=dataset_name Pathname for the dataset\n");
HDfprintf(stdout, " -n, --noop Perform all the steps except the actual conversion\n");
HDfprintf(stdout, "\n");
HDfprintf(stdout, "Examples of use:\n");
HDfprintf(stdout, "\n");
HDfprintf(stdout, "h5format_convert -d /group/dataset file_name\n");
HDfprintf(stdout, " Convert the dataset </group/dataset> in the HDF5 file <file_name>:\n");
HDfprintf(stdout, " a. chunked dataset: convert the chunk indexing type to version 1 B-tree\n");
HDfprintf(stdout, " b. compact/contiguous dataset: downgrade the layout version to 3\n");
HDfprintf(stdout, " c. virtual dataset: no action\n");
HDfprintf(stdout, "\n");
HDfprintf(stdout, "h5format_convert file_name\n");
HDfprintf(stdout, " Convert all datasets in the HDF5 file <file_name>:\n");
HDfprintf(stdout, " a. chunked dataset: convert the chunk indexing type to version 1 B-tree\n");
HDfprintf(stdout, " b. compact/contiguous dataset: downgrade the layout version to 3\n");
HDfprintf(stdout, " c. virtual dataset: no action\n");
HDfprintf(stdout, "\n");
HDfprintf(stdout, "h5format_convert -n -d /group/dataset file_name\n");
HDfprintf(stdout, " Go through all the steps except the actual conversion when \n");
HDfprintf(stdout, " converting the dataset </group/dataset> in the HDF5 file <file_name>.\n");
} /* usage() */
/*-------------------------------------------------------------------------
* Function: parse_command_line
*
* Purpose: parse command line input
*
* Return: Success: 0
* Failure: 1
*
*-------------------------------------------------------------------------
*/
static int
parse_command_line(int argc, const char **argv)
{
int opt;
/* no arguments */
if (argc == 1) {
usage(h5tools_getprogname());
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
/* parse command line options */
while ((opt = H5_get_option(argc, argv, s_opts, l_opts)) != EOF) {
switch ((char)opt) {
case 'h':
usage(h5tools_getprogname());
h5tools_setstatus(EXIT_SUCCESS);
goto error;
case 'V':
print_version(h5tools_getprogname());
h5tools_setstatus(EXIT_SUCCESS);
goto error;
case 'v':
verbose_g = TRUE;
break;
case 'd': /* -d dname */
if (H5_optarg != NULL && *H5_optarg)
dname_g = HDstrdup(H5_optarg);
if (dname_g == NULL) {
h5tools_setstatus(EXIT_FAILURE);
error_msg("No dataset name\n", H5_optarg);
usage(h5tools_getprogname());
goto error;
}
dset_g = TRUE;
break;
case 'n': /* -n */
noop_g = TRUE;
break;
case 'E':
enable_error_stack = 1;
break;
default:
h5tools_setstatus(EXIT_FAILURE);
usage(h5tools_getprogname());
goto error;
break;
} /* switch */
} /* while */
if (argc <= H5_optind) {
error_msg("missing file name\n");
usage(h5tools_getprogname());
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
fname_g = HDstrdup(argv[H5_optind]);
return 0;
error:
return -1;
;
} /* parse_command_line() */
/*-------------------------------------------------------------------------
* Function: leave
*
* Purpose: Close HDF5
*
* Return: Does not return
*
*-------------------------------------------------------------------------
*/
static void
leave(int ret)
{
h5tools_close();
HDexit(ret);
} /* leave() */
/*-------------------------------------------------------------------------
* Function: convert()
*
* Purpose: To downgrade a dataset's indexing type or layout version:
* For chunked:
* Downgrade the chunk indexing type to version 1 B-tree
* If type is already version 1 B-tree, no further action
* For compact/contiguous:
* Downgrade the layout version from 4 to 3
* If version is already <= 3, no further action
* For virtual:
* No further action
*
* Return: Success: 0
* Failure: 1
*
*-------------------------------------------------------------------------
*/
static int
convert(hid_t fid, const char *dname)
{
hid_t dcpl = H5I_INVALID_HID;
hid_t did = H5I_INVALID_HID;
H5D_layout_t layout_type;
H5D_chunk_index_t idx_type;
/* Open the dataset */
if ((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0) {
error_msg("unable to open dataset \"%s\"\n", dname);
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
else if (verbose_g)
HDfprintf(stdout, "Open the dataset\n");
/* Get the dataset's creation property list */
if ((dcpl = H5Dget_create_plist(did)) < 0) {
error_msg("unable to get the dataset creation property list\n");
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
/* Get the dataset's layout */
if ((layout_type = H5Pget_layout(dcpl)) < 0) {
error_msg("unable to get the dataset layout type\n");
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
else if (verbose_g)
HDfprintf(stdout, "Retrieve the dataset's layout\n");
switch (layout_type) {
case H5D_CHUNKED:
if (verbose_g)
HDfprintf(stdout, "Dataset is a chunked dataset\n");
/* Get the dataset's chunk indexing type */
if (H5Dget_chunk_index_type(did, &idx_type) < 0) {
error_msg("unable to get the chunk indexing type for \"%s\"\n", dname);
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
else if (verbose_g)
HDfprintf(stdout, "Retrieve the dataset's chunk indexing type\n");
if (idx_type == H5D_CHUNK_IDX_BTREE) {
if (verbose_g)
HDfprintf(
stdout,
"Dataset's chunk indexing type is already version 1 B-tree: no further action\n");
h5tools_setstatus(EXIT_SUCCESS);
goto done;
}
else if (verbose_g)
HDfprintf(stdout, "Dataset's chunk indexing type is not version 1 B-tree\n");
break;
case H5D_CONTIGUOUS:
if (verbose_g)
HDfprintf(stdout, "Dataset is a contiguous dataset: downgrade layout version as needed\n");
break;
case H5D_COMPACT:
if (verbose_g)
HDfprintf(stdout, "Dataset is a compact dataset: downgrade layout version as needed\n");
break;
case H5D_VIRTUAL:
if (verbose_g)
HDfprintf(stdout, "No further action for virtual dataset\n");
goto done;
case H5D_NLAYOUTS:
case H5D_LAYOUT_ERROR:
default:
error_msg("unknown layout type for \"%s\"\n", dname);
h5tools_setstatus(EXIT_FAILURE);
goto error;
} /* end switch */
/* No further action if it is a noop */
if (noop_g) {
if (verbose_g)
HDfprintf(stdout, "Not converting the dataset\n");
h5tools_setstatus(EXIT_SUCCESS);
goto done;
}
if (verbose_g)
HDfprintf(stdout, "Converting the dataset...\n");
/* Downgrade the dataset */
if (H5Dformat_convert(did) < 0) {
error_msg("unable to downgrade dataset \"%s\"\n", dname);
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
else if (verbose_g)
HDfprintf(stdout, "Done\n");
done:
/* Close the dataset */
if (H5Dclose(did) < 0) {
error_msg("unable to close dataset \"%s\"\n", dname);
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
else if (verbose_g)
HDfprintf(stdout, "Close the dataset\n");
/* Close the dataset creation property list */
if (H5Pclose(dcpl) < 0) {
error_msg("unable to close dataset creation property list\n");
h5tools_setstatus(EXIT_FAILURE);
goto error;
}
else if (verbose_g)
HDprintf("Close the dataset creation property list\n");
return 0;
error:
if (verbose_g)
HDfprintf(stdout, "Error encountered\n");
H5E_BEGIN_TRY
{
H5Pclose(dcpl);
H5Dclose(did);
}
H5E_END_TRY;
return -1;
} /* convert() */
/*-------------------------------------------------------------------------
* Function: convert_dsets_cb()
*
* Purpose: The callback routine from the traversal to convert the
* chunk indexing type of the dataset object.
*
* Return: Success: 0
* Failure: -1
*-------------------------------------------------------------------------
*/
static int
convert_dsets_cb(const char *path, const H5O_info_t *oi, const char *already_visited, void *_fid)
{
hid_t fid = *(hid_t *)_fid;
/* If the object has already been seen then just return */
if (NULL == already_visited) {
if (oi->type == H5O_TYPE_DATASET) {
if (verbose_g)
HDfprintf(stdout, "Going to process dataset:%s...\n", path);
if (convert(fid, path) < 0)
goto error;
} /* end if */
} /* end if */
return 0;
error:
return -1;
} /* end convert_dsets_cb() */
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose: To convert the chunk indexing type of a dataset in a file to
* version 1 B-tree.
*
* Return: Success: 0
* Failure: 1
*
*-------------------------------------------------------------------------
*/
int
main(int argc, const char *argv[])
{
hid_t fid = H5I_INVALID_HID;
h5tools_setprogname(PROGRAMNAME);
h5tools_setstatus(EXIT_SUCCESS);
/* Initialize h5tools lib */
h5tools_init();
/* Parse command line options */
if (parse_command_line(argc, argv) < 0)
goto done;
else if (verbose_g)
HDfprintf(stdout, "Process command line options\n");
if (noop_g && verbose_g)
HDfprintf(stdout, "It is noop...\n");
/* enable error reporting if command line option */
h5tools_error_report();
/* Open the HDF5 file */
if ((fid = h5tools_fopen(fname_g, H5F_ACC_RDWR, H5P_DEFAULT, FALSE, NULL, 0)) < 0) {
error_msg("unable to open file \"%s\"\n", fname_g);
h5tools_setstatus(EXIT_FAILURE);
goto done;
}
else if (verbose_g)
HDfprintf(stdout, "Open the file %s\n", fname_g);
if (dset_g) { /* Convert a specified dataset in the file */
if (verbose_g)
HDfprintf(stdout, "Going to process dataset: %s...\n", dname_g);
if (convert(fid, dname_g) < 0)
goto done;
}
else { /* Convert all datasets in the file */
if (verbose_g)
HDfprintf(stdout, "Processing all datasets in the file...\n");
if (h5trav_visit(fid, "/", TRUE, TRUE, convert_dsets_cb, NULL, &fid, H5O_INFO_BASIC) < 0)
goto done;
} /* end else */
if (verbose_g) {
if (noop_g) {
HDfprintf(stdout, "Not processing the file's superblock...\n");
h5tools_setstatus(EXIT_SUCCESS);
goto done;
} /* end if */
HDfprintf(stdout, "Processing the file's superblock...\n");
} /* end if */
/* Process superblock */
if (H5Fformat_convert(fid) < 0) {
error_msg("unable to convert file's superblock\"%s\"\n", fname_g);
h5tools_setstatus(EXIT_FAILURE);
goto done;
} /* end if */
done:
/* Close the file */
if (fid >= 0) {
if (H5Fclose(fid) < 0) {
error_msg("unable to close file \"%s\"\n", fname_g);
h5tools_setstatus(EXIT_FAILURE);
}
else if (verbose_g) {
HDfprintf(stdout, "Close the file\n");
}
} /* end if */
if (fname_g)
HDfree(fname_g);
if (dname_g)
HDfree(dname_g);
leave(h5tools_getstatus());
} /* end main() */