diff options
author | Dana Robinson <derobins@hdfgroup.org> | 2017-01-26 19:34:12 (GMT) |
---|---|---|
committer | Dana Robinson <derobins@hdfgroup.org> | 2017-01-26 19:34:12 (GMT) |
commit | 2cac1c063735f2989988b279ff0233d6e9f335a3 (patch) | |
tree | 7a134078846919680b95c36d1772466793fe3da3 /test/use_disable_mdc_flushes.c | |
parent | 768636dbd77ea787a6a04dfc321ff3e862791db7 (diff) | |
download | hdf5-2cac1c063735f2989988b279ff0233d6e9f335a3.zip hdf5-2cac1c063735f2989988b279ff0233d6e9f335a3.tar.gz hdf5-2cac1c063735f2989988b279ff0233d6e9f335a3.tar.bz2 |
Moved remaining SWMR-related test files to develop.
Diffstat (limited to 'test/use_disable_mdc_flushes.c')
-rw-r--r-- | test/use_disable_mdc_flushes.c | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/test/use_disable_mdc_flushes.c b/test/use_disable_mdc_flushes.c new file mode 100644 index 0000000..2915cc3 --- /dev/null +++ b/test/use_disable_mdc_flushes.c @@ -0,0 +1,549 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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 files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This is copied from use_append_chunk.c with modifications to show + * the usage of H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled public routines. + */ + +#include "h5test.h" + +/* This test uses many POSIX things that are not available on + * Windows. We're using a check for fork(2) here as a proxy for + * all POSIX/Unix/Linux things until this test can be made + * more platform-independent. + */ +#ifdef H5_HAVE_FORK + +#define H5D_FRIEND /*suppress error about including H5Dpkg */ +#define H5D_TESTING +#include "H5Dpkg.h" + +/* Global Variable definitions */ +const char *progname_g="use_disable_mdc_flushes"; /* program name */ + +/* these two definitions must match each other */ +#define UC_DATATYPE H5T_NATIVE_SHORT /* use case HDF5 data type */ +#define UC_CTYPE short /* use case C data type */ +#define UC_RANK 3 /* use case dataset rank */ +#define Chunksize_DFT 256 /* chunksize default */ +#define Hgoto_error(val) {ret_value=val; goto done;} + + +char *filename_g; +hsize_t nplanes_g; +int use_swmr_g; +int chunkplanes_g; +int chunksize_g; +hsize_t dims_g[UC_RANK]; +hsize_t max_dims_g[UC_RANK]; +hsize_t chunkdims_g[UC_RANK]; + +static void usage(const char *prog); +static int parse_option(int argc, char * const argv[]); +static void show_parameters(void); +static int create_file(void); +static int setup_parameters(int argc, char * const argv[]); + +/* + * Note: Long options are not yet implemented. + * + * usage: use_disable_mdc_flushes [OPTIONS] + * OPTIONS + * -h, --help Print a usage message and exit + * -f FN Test file name [default: use_disable_mdc_flushes.h5] + * -n N, --nplanes=N Number of planes to write. [default: 1000] + * -s N, --swmr=N Use SWMR mode (0: no, non-0: yes) default is yes + * -z N, --chunksize=N Chunk size [default: 256] + * -y N, --chunkplanes=N Number of planes per chunk [default: 1] + */ +static void +usage(const char *prog) +{ + fprintf(stderr, "usage: %s [OPTIONS]\n", prog); + fprintf(stderr, " OPTIONS\n"); + fprintf(stderr, " -h Print a usage message and exit\n"); + fprintf(stderr, " -f FN Test file name [default: %s.h5]\n", prog); + fprintf(stderr, " -n N Number of planes to write. [default: 1000]\n"); + fprintf(stderr, " -s N Use SWMR mode (0: no, non-0: yes) default is yes\n"); + fprintf(stderr, " -z N Chunk size [default: %d]\n", Chunksize_DFT); + fprintf(stderr, " -y N Number of planes per chunk [default: 1]\n"); + fprintf(stderr, "\n"); +} /* usage() */ + + +/* + * Setup Use Case parameters by parsing command line options. + * Setup default values if not set by options. */ +static int +parse_option(int argc, char * const argv[]) +{ + int ret_value=0; + int c; + /* command line options: See function usage for a description */ + const char *cmd_options = "f:hn:s:y:z:"; + + /* suppress getopt from printing error */ + opterr = 0; + + while (1){ + c = getopt (argc, argv, cmd_options); + if (-1 == c) + break; + switch (c) { + case 'h': + usage(progname_g); + exit(0); + break; + case 'f': /* usecase data file name */ + filename_g = optarg; + break; + case 'n': /* number of planes to write/read */ + if ((nplanes_g = atoi(optarg)) <= 0){ + fprintf(stderr, "bad number of planes %s, must be a positive integer\n", optarg); + usage(progname_g); + Hgoto_error(-1); + }; + break; + case 's': /* use swmr file open mode */ + if ((use_swmr_g = atoi(optarg)) < 0){ + fprintf(stderr, "swmr value should be 0(no) or 1(yes)\n"); + usage(progname_g); + Hgoto_error(-1); + }; + break; + case 'y': /* Number of planes per chunk */ + if ((chunkplanes_g = atoi(optarg)) <= 0){ + fprintf(stderr, "bad number of planes per chunk %s, must be a positive integer\n", optarg); + usage(progname_g); + Hgoto_error(-1); + }; + break; + case 'z': /* size of chunk=(z,z) */ + if ((chunksize_g = atoi(optarg)) <= 0){ + fprintf(stderr, "bad chunksize %s, must be a positive integer\n", optarg); + usage(progname_g); + Hgoto_error(-1); + }; + break; + case '?': + fprintf(stderr, "getopt returned '%c'.\n", c); + Hgoto_error(-1); + default: + fprintf(stderr, "getopt returned unexpected value.\n"); + fprintf(stderr, "Unexpected value is %d\n", c); + Hgoto_error(-1); + } + } + + /* set test file name if not given */ + if (!filename_g){ + /* default data file name is <progname>.h5 */ + if ((filename_g = (char*)HDmalloc(HDstrlen(progname_g)+4))==NULL) { + fprintf(stderr, "malloc: failed\n"); + Hgoto_error(-1); + }; + HDstrcpy(filename_g, progname_g); + HDstrcat(filename_g, ".h5"); + } + +done: + /* All done. */ + return(ret_value); +} /* parse_option() */ + +/* Show parameters used for this use case */ +static void +show_parameters(void) +{ + printf("===Parameters used:===\n"); + printf("chunk dims=(%llu, %llu, %llu)\n", (unsigned long long)chunkdims_g[0], + (unsigned long long)chunkdims_g[1], (unsigned long long)chunkdims_g[2]); + printf("dataset max dims=(%llu, %llu, %llu)\n", (unsigned long long)max_dims_g[0], + (unsigned long long)max_dims_g[1], (unsigned long long)max_dims_g[2]); + printf("number of planes to write=%llu\n", (unsigned long long)nplanes_g); + printf("using SWMR mode=%s\n", use_swmr_g ? "yes(1)" : "no(0)"); + printf("data filename=%s\n", filename_g); + printf("===Parameters shown===\n"); +} /* show_parameters() */ + +/* + * Setup parameters for the use case. + * Return: 0 succeed; -1 fail. + */ +static int +setup_parameters(int argc, char * const argv[]) +{ + /* use case defaults */ + chunksize_g = Chunksize_DFT; + use_swmr_g = 1; /* use swmr open */ + chunkplanes_g = 1; + + /* parse options */ + if (parse_option(argc, argv) < 0){ + return(-1); + } + /* set chunk dims */ + chunkdims_g[0] = chunkplanes_g; + chunkdims_g[1]= chunkdims_g[2] = chunksize_g; + + /* set dataset initial and max dims */ + dims_g[0] = 0; + max_dims_g[0] = H5S_UNLIMITED; + dims_g[1] = dims_g[2] = max_dims_g[1] = max_dims_g[2] = chunksize_g; + + /* set nplanes */ + if (nplanes_g == 0) + nplanes_g = chunksize_g; + + /* show parameters and return */ + show_parameters(); + return(0); +} /* setup_parameters() */ + +/* + * Create the skeleton use case file for testing. + * It has one 3d dataset using chunked storage. + * The dataset is (unlimited, chunksize, chunksize). + * Dataset type is 2 bytes integer. + * It starts out "empty", i.e., first dimension is 0. + * + * Return: 0 succeed; -1 fail. + */ +static int +create_file(void) +{ + hsize_t dims[3]; /* Dataset starting dimensions */ + hid_t fid; /* File ID for new HDF5 file */ + hid_t dcpl; /* Dataset creation property list */ + hid_t sid; /* Dataspace ID */ + hid_t dsid; /* Dataset ID */ + hid_t fapl; /* File access property list */ + H5D_chunk_index_t idx_type; /* Chunk index type */ + + /* Create the file */ + if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + return -1; + if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + return -1; + if((fid = H5Fcreate(filename_g, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) + return -1; + + /* Set up dimension sizes */ + dims[0] = 0; + dims[1] = dims[2] = max_dims_g[1]; + + /* Create dataspace for creating datasets */ + if((sid = H5Screate_simple(3, dims, max_dims_g)) < 0) + return -1; + + /* Create dataset creation property list */ + if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) + return -1; + if(H5Pset_chunk(dcpl, 3, chunkdims_g) < 0) + return -1; + + /* create dataset of progname */ + if((dsid = H5Dcreate2(fid, progname_g, UC_DATATYPE, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) + return -1; + + /* Check that the chunk index type is not version 1 B-tree. + * Version 1 B-trees are not supported under SWMR. + */ + if(H5D__layout_idx_type_test(dsid, &idx_type) < 0) + return -1; + if(idx_type == H5D_CHUNK_IDX_BTREE) { + fprintf(stderr, "ERROR: Chunk index is version 1 B-tree: aborting.\n"); + return -1; + } + + /* Close everything */ + if(H5Dclose(dsid) < 0) + return -1; + if(H5Pclose(fapl) < 0) + return -1; + if(H5Pclose(dcpl) < 0) + return -1; + if(H5Sclose(sid) < 0) + return -1; + if(H5Fclose(fid) < 0) + return -1; + + return 0; +} /* create_file() */ + +/* + * Append planes, each of (1,2*chunksize,2*chunksize) to the dataset. + * In other words, 4 chunks are appended to the dataset at a time. + * Fill each plane with the plane number and then write it at the nth plane. + * Increase the plane number and repeat till the end of dataset, when it + * reaches chunksize long. End product is a (2*chunksize)^3 cube. + * + * Return: 0 succeed; -1 fail. + */ +static int +write_file(void) +{ + hid_t fid; /* File ID for new HDF5 file */ + hid_t dsid; /* dataset ID */ + hid_t fapl; /* File access property list */ + hid_t dcpl; /* Dataset creation property list */ + char *name; + UC_CTYPE *buffer, *bufptr; /* data buffer */ + hsize_t cz=chunksize_g; /* Chunk size */ + hid_t f_sid; /* dataset file space id */ + hid_t m_sid; /* memory space id */ + int rank; /* rank */ + hsize_t chunk_dims[3]; /* Chunk dimensions */ + hsize_t dims[3]; /* Dataspace dimensions */ + hsize_t memdims[3]; /* Memory space dimensions */ + hsize_t start[3] = {0,0,0}, count[3]; /* Hyperslab selection values */ + hbool_t disabled; /* Object's disabled status */ + hsize_t i, j, k; + + name = filename_g; + + /* Open the file */ + if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) + return -1; + if(use_swmr_g) + if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) + return -1; + if((fid = H5Fopen(name, H5F_ACC_RDWR | (use_swmr_g ? H5F_ACC_SWMR_WRITE : 0), fapl)) < 0){ + fprintf(stderr, "H5Fopen failed\n"); + return -1; + } + + /* Open the dataset of the program name */ + if((dsid = H5Dopen2(fid, progname_g, H5P_DEFAULT)) < 0){ + fprintf(stderr, "H5Dopen2 failed\n"); + return -1; + } + + /* Disabled mdc flushed for the dataset */ + if(H5Odisable_mdc_flushes(dsid) < 0) { + fprintf(stderr, "H5Odisable_mdc_flushes failed\n"); + return -1; + } + + /* Get mdc disabled status of the dataset */ + if(H5Oare_mdc_flushes_disabled(dsid, &disabled) < 0) { + fprintf(stderr, "H5Oare_mdc_flushes_disabled failed\n"); + return -1; + } else if(disabled) + printf("Dataset has disabled mdc flushes.\n"); + else + printf("Dataset should have disabled its mdc flushes.\n"); + + /* Find chunksize used */ + if ((dcpl = H5Dget_create_plist(dsid)) < 0){ + fprintf(stderr, "H5Dget_create_plist failed\n"); + return -1; + } + if (H5D_CHUNKED != H5Pget_layout(dcpl)){ + fprintf(stderr, "storage layout is not chunked\n"); + return -1; + } + if ((rank = H5Pget_chunk(dcpl, 3, chunk_dims)) != 3){ + fprintf(stderr, "storage rank is not 3\n"); + return -1; + } + + /* verify chunk_dims against set paramenters */ + if (chunk_dims[0]!= chunkdims_g[0] || chunk_dims[1] != cz || chunk_dims[2] != cz){ + fprintf(stderr, "chunk size is not as expected. Got dims=(%llu,%llu,%llu)\n", + (unsigned long long)chunk_dims[0], (unsigned long long)chunk_dims[1], + (unsigned long long)chunk_dims[2]); + return -1; + } + + /* allocate space for data buffer 1 X dims[1] X dims[2] of UC_CTYPE */ + memdims[0]=1; + memdims[1] = dims_g[1]; + memdims[2] = dims_g[2]; + if ((buffer=(UC_CTYPE*)HDmalloc((size_t)memdims[1]*(size_t)memdims[2]*sizeof(UC_CTYPE)))==NULL) { + fprintf(stderr, "malloc: failed\n"); + return -1; + }; + + /* + * Get dataset rank and dimension. + */ + f_sid = H5Dget_space(dsid); /* Get filespace handle first. */ + rank = H5Sget_simple_extent_ndims(f_sid); + if (rank != UC_RANK){ + fprintf(stderr, "rank(%d) of dataset does not match\n", rank); + return -1; + } + if (H5Sget_simple_extent_dims(f_sid, dims, NULL) < 0){ + fprintf(stderr, "H5Sget_simple_extent_dims got error\n"); + return -1; + } + printf("dataset rank %d, dimensions %llu x %llu x %llu\n", + rank, (unsigned long long)(dims[0]), (unsigned long long)(dims[1]), + (unsigned long long)(dims[2])); + /* verify that file space dims are as expected and are consistent with memory space dims */ + if (dims[0] != 0 || dims[1] != memdims[1] || dims[2] != memdims[2]){ + fprintf(stderr, "dataset is not empty. Got dims=(%llu,%llu,%llu)\n", + (unsigned long long)dims[0], (unsigned long long)dims[1], + (unsigned long long)dims[2]); + return -1; + } + + /* setup mem-space for buffer */ + if ((m_sid=H5Screate_simple(rank, memdims, NULL))<0){ + fprintf(stderr, "H5Screate_simple for memory failed\n"); + return -1; + }; + + /* write planes */ + count[0]=1; + count[1]=dims[1]; + count[2]=dims[2]; + for (i=0; i<nplanes_g; i++){ + /* fill buffer with value i+1 */ + bufptr = buffer; + for (j=0; j<dims[1]; j++) + for (k=0; k<dims[2]; k++) + *bufptr++ = i; + + /* extend the dataset by one for new plane */ + dims[0]=i+1; + if(H5Dset_extent(dsid, dims) < 0){ + fprintf(stderr, "H5Dset_extent failed\n"); + return -1; + } + + /* Get the dataset's dataspace */ + if((f_sid = H5Dget_space(dsid)) < 0){ + fprintf(stderr, "H5Dset_extent failed\n"); + return -1; + } + + start[0]=i; + /* Choose the next plane to write */ + if(H5Sselect_hyperslab(f_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0){ + fprintf(stderr, "Failed H5Sselect_hyperslab\n"); + return -1; + } + + /* Write plane to the dataset */ + if(H5Dwrite(dsid, UC_DATATYPE, m_sid, f_sid, H5P_DEFAULT, buffer) < 0){ + fprintf(stderr, "Failed H5Dwrite\n"); + return -1; + } + + /* Flush the dataset for every "chunkplanes_g" planes */ + if(!((i + 1) % (hsize_t)chunkplanes_g)) { + if(H5Dflush(dsid) < 0) { + fprintf(stderr, "Failed to H5Dflush dataset\n"); + return -1; + } + } + } + + if(H5Dflush(dsid) < 0) { + fprintf(stderr, "Failed to H5Dflush dataset\n"); + return -1; + } + + /* Enable mdc flushes for the dataset */ + /* Closing the dataset later will enable mdc flushes automatically if this is not done */ + if(disabled) + if(H5Oenable_mdc_flushes(dsid) < 0) { + fprintf(stderr, "Failed to H5Oenable_mdc_flushes\n"); + return -1; + } + + /* Done writing. Free/Close all resources including data file */ + HDfree(buffer); + + if(H5Dclose(dsid) < 0){ + fprintf(stderr, "Failed to close datasete\n"); + return -1; + } + if(H5Sclose(m_sid) < 0){ + fprintf(stderr, "Failed to close memory space\n"); + return -1; + } + if(H5Sclose(f_sid) < 0){ + fprintf(stderr, "Failed to close file space\n"); + return -1; + } + if(H5Pclose(fapl) < 0){ + fprintf(stderr, "Failed to property list\n"); + return -1; + } + if(H5Fclose(fid) < 0){ + fprintf(stderr, "Failed to close file id\n"); + return -1; + } + + return 0; +} /* write_file() */ + + + +/* Overall Algorithm: + * Parse options from user; + * Generate/pre-created test files needed and close it; + * Write to the file. + */ +int +main(int argc, char *argv[]) +{ + int ret_value = 0; + + /* initialization */ + if(setup_parameters(argc, argv) < 0) + Hgoto_error(1); + + /* ============*/ + /* Create file */ + /* ============*/ + printf("Creating skeleton data file for testing H5Odisable_mdc_flushes()...\n"); + if(create_file() < 0) { + fprintf(stderr, "***encounter error\n"); + Hgoto_error(1); + } /* end if */ + else + printf("File created.\n"); + + printf("writing to the file\n"); + if(write_file() < 0) { + fprintf(stderr, "write_file encountered error\n"); + Hgoto_error(1); + } + +done: + /* Print result and exit */ + if(ret_value != 0) + printf("Error(s) encountered\n"); + else + printf("All passed\n"); + + return(ret_value); +} + +#else /* H5_HAVE_FORK */ + +int +main(void) +{ + HDfprintf(stderr, "Non-POSIX platform. Skipping.\n"); + return EXIT_SUCCESS; +} /* end main() */ + +#endif /* H5_HAVE_FORK */ + |