diff options
Diffstat (limited to 'testpar/t_cache_image.c')
| -rw-r--r-- | testpar/t_cache_image.c | 3717 |
1 files changed, 3717 insertions, 0 deletions
diff --git a/testpar/t_cache_image.c b/testpar/t_cache_image.c new file mode 100644 index 0000000..65c892d --- /dev/null +++ b/testpar/t_cache_image.c @@ -0,0 +1,3717 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: John Mainzer + * 7/13/15 + * + * This file contains tests specific to the cache image + * feature implemented in H5C.c + */ +#include "testphdf5.h" + +#include "cache_common.h" +#include "genall5.h" + +#define TEST_FILES_TO_CONSTRUCT 2 +#define CHUNK_SIZE 10 +#define DSET_SIZE (40 * CHUNK_SIZE) +#define MAX_NUM_DSETS 256 +#define PAR_NUM_DSETS 32 +#define PAGE_SIZE (4 * 1024) +#define PB_SIZE (64 * PAGE_SIZE) + +/* global variable declarations: */ + +const char *FILENAMES[] = {"t_cache_image_00", "t_cache_image_01", "t_cache_image_02", NULL}; + +/* local utility function declarations */ + +static void create_data_sets(hid_t file_id, int min_dset, int max_dset); +#if 0 /* keep pending full parallel cache image */ +static void delete_data_sets(hid_t file_id, int min_dset, int max_dset); +#endif + +static void open_hdf5_file(const hbool_t create_file, const hbool_t mdci_sbem_expected, + const hbool_t read_only, const hbool_t set_mdci_fapl, const hbool_t config_fsm, + const hbool_t enable_page_buffer, const char *hdf_file_name, + const unsigned cache_image_flags, hid_t *file_id_ptr, H5F_t **file_ptr_ptr, + H5C_t **cache_ptr_ptr, MPI_Comm comm, MPI_Info info, int l_facc_type, + const hbool_t all_coll_metadata_ops, const hbool_t coll_metadata_write, + const int md_write_strat); + +static void verify_data_sets(hid_t file_id, int min_dset, int max_dset); + +/* local test function declarations */ + +static unsigned construct_test_file(int test_file_index); +static void par_create_dataset(int dset_num, hid_t file_id, int mpi_rank, int mpi_size); +static void par_delete_dataset(int dset_num, hid_t file_id, int mpi_rank); +static void par_verify_dataset(int dset_num, hid_t file_id, int mpi_rank); + +static hbool_t serial_insert_cache_image(int file_name_idx, int mpi_size); +static void serial_verify_dataset(int dset_num, hid_t file_id, int mpi_size); + +/* top level test function declarations */ +static unsigned verify_cache_image_RO(int file_name_id, int md_write_strat, int mpi_rank); +static unsigned verify_cache_image_RW(int file_name_id, int md_write_strat, int mpi_rank); + +static hbool_t smoke_check_1(MPI_Comm mpi_comm, MPI_Info mpi_info, int mpi_rank, int mpi_size); + +/****************************************************************************/ +/***************************** Utility Functions ****************************/ +/****************************************************************************/ + +/*------------------------------------------------------------------------- + * Function: construct_test_file() + * + * Purpose: This function attempts to mimic the typical "poor man's + * parallel use case in which the file is passed between + * processes, each of which open the file, write some data, + * close the file, and then pass control on to the next + * process. + * + * In this case, we create one group for each process, and + * populate it with a "zoo" of HDF5 objects selected to + * (ideally) exercise all HDF5 on disk data structures. + * + * The end result is a test file used verify that PHDF5 + * can open a file with a cache image. + * + * Cycle of operation + * + * 1) Create a HDF5 file with the cache image FAPL entry. + * + * Verify that the cache is informed of the cache image + * FAPL entry. + * + * Set all cache image flags, forcing full functionality. + * + * 2) Create a data set in the file. + * + * 3) Close the file. + * + * 4) Open the file. + * + * Verify that the metadata cache is instructed to load + * the metadata cache image. + * + * 5) Create a data set in the file. + * + * 6) Close the file. If enough datasets have been created + * goto 7. Otherwise return to 4. + * + * 7) Open the file R/O. + * + * Verify that the file contains a metadata cache image + * superblock extension message. + * + * 8) Verify all data sets. + * + * Verify that the cache image has been loaded. + * + * 9) close the file. + * + * Return: void + * + * Programmer: John Mainzer + * 1/25/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static unsigned +construct_test_file(int test_file_index) +{ + const char *fcn_name = "construct_test_file()"; + char filename[512]; + hbool_t show_progress = FALSE; + hid_t file_id = -1; + H5F_t *file_ptr = NULL; + H5C_t *cache_ptr = NULL; + int cp = 0; + int min_dset = 0; + int max_dset = 0; + MPI_Comm dummy_comm = MPI_COMM_WORLD; + MPI_Info dummy_info = MPI_INFO_NULL; + + pass = TRUE; + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the file name */ + if (pass) { + + HDassert(FILENAMES[test_file_index]); + + if (h5_fixname(FILENAMES[test_file_index], H5P_DEFAULT, filename, sizeof(filename)) == NULL) { + + pass = FALSE; + failure_mssg = "h5_fixname() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 1) Create a HDF5 file with the cache image FAPL entry. + * + * Verify that the cache is informed of the cache image FAPL entry. + * + * Set flags forcing full function of the cache image feature. + */ + + if (pass) { + + open_hdf5_file(/* create_file */ TRUE, + /* mdci_sbem_expected */ FALSE, + /* read_only */ FALSE, + /* set_mdci_fapl */ TRUE, + /* config_fsm */ TRUE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ dummy_comm, + /* info */ dummy_info, + /* l_facc_type */ 0, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ 0); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 2) Create a data set in the file. */ + + if (pass) { + + create_data_sets(file_id, min_dset++, max_dset++); + } + +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 0) { + + pass = FALSE; + failure_mssg = "metadata cache image block loaded(1)."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 3) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + while ((pass) && (max_dset < MAX_NUM_DSETS)) { + + /* 4) Open the file. + * + * Verify that the metadata cache is instructed to load the + * metadata cache image. + */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ FALSE, + /* set_mdci_fapl */ TRUE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ dummy_comm, + /* info */ dummy_info, + /* l_facc_type */ 0, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ 0); + } + + if (show_progress) + HDfprintf(stdout, "%s:L1 cp = %d, max_dset = %d, pass = %d.\n", fcn_name, cp, max_dset, pass); + + /* 5) Create a data set in the file. */ + + if (pass) { + + create_data_sets(file_id, min_dset++, max_dset++); + } + +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded == 0) { + + pass = FALSE; + failure_mssg = "metadata cache image block not loaded(1)."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s:L2 cp = %d, max_dset = %d, pass = %d.\n", fcn_name, cp + 1, max_dset, pass); + + /* 6) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s:L3 cp = %d, max_dset = %d, pass = %d.\n", fcn_name, cp + 2, max_dset, pass); + } /* end while */ + cp += 3; + + /* 7) Open the file R/O. + * + * Verify that the file contains a metadata cache image + * superblock extension message. + */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ TRUE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ dummy_comm, + /* info */ dummy_info, + /* l_facc_type */ 0, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ 0); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 8) Open and close all data sets. + * + * Verify that the cache image has been loaded. + */ + + if (pass) { + + verify_data_sets(file_id, 0, max_dset - 1); + } + +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded == 0) { + + pass = FALSE; + failure_mssg = "metadata cache image block not loaded(2)."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 9) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + return !pass; + +} /* construct_test_file() */ + +/*------------------------------------------------------------------------- + * Function: create_data_sets() + * + * Purpose: If pass is TRUE on entry, create the specified data sets + * in the indicated file. + * + * Data sets and their contents must be well know, as we + * will verify that they contain the expected data later. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 7/15/15 + * + * Modifications: + * + * Added min_dset and max_dset parameters and supporting + * code. This allows the caller to specify a range of + * datasets to create. + * JRM -- 8/20/15 + * + *------------------------------------------------------------------------- + */ + +static void +create_data_sets(hid_t file_id, int min_dset, int max_dset) +{ + const char *fcn_name = "create_data_sets()"; + char dset_name[64]; + hbool_t show_progress = FALSE; + hbool_t valid_chunk; + hbool_t verbose = FALSE; + int cp = 0; + int i, j, k, l, m; + int data_chunk[CHUNK_SIZE][CHUNK_SIZE]; + herr_t status; + hid_t dataspace_id = -1; + hid_t filespace_ids[MAX_NUM_DSETS]; + hid_t memspace_id = -1; + hid_t dataset_ids[MAX_NUM_DSETS]; + hid_t properties = -1; + hsize_t dims[2]; + hsize_t a_size[2]; + hsize_t offset[2]; + hsize_t chunk_size[2]; + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + HDassert(0 <= min_dset); + HDassert(min_dset <= max_dset); + HDassert(max_dset < MAX_NUM_DSETS); + + /* create the datasets */ + + if (pass) { + + i = min_dset; + + while ((pass) && (i <= max_dset)) { + /* create a dataspace for the chunked dataset */ + dims[0] = DSET_SIZE; + dims[1] = DSET_SIZE; + dataspace_id = H5Screate_simple(2, dims, NULL); + + if (dataspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + + /* set the dataset creation plist to specify that the raw data is + * to be partitioned into 10X10 element chunks. + */ + + if (pass) { + + chunk_size[0] = CHUNK_SIZE; + chunk_size[1] = CHUNK_SIZE; + properties = H5Pcreate(H5P_DATASET_CREATE); + + if (properties < 0) { + + pass = FALSE; + failure_mssg = "H5Pcreate() failed."; + } + } + + if (pass) { + + if (H5Pset_chunk(properties, 2, chunk_size) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_chunk() failed."; + } + } + + /* create the dataset */ + if (pass) { + + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", i); + dataset_ids[i] = H5Dcreate2(file_id, dset_name, H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, + properties, H5P_DEFAULT); + + if (dataset_ids[i] < 0) { + + pass = FALSE; + failure_mssg = "H5Dcreate() failed."; + } + } + + /* get the file space ID */ + if (pass) { + + filespace_ids[i] = H5Dget_space(dataset_ids[i]); + + if (filespace_ids[i] < 0) { + + pass = FALSE; + failure_mssg = "H5Dget_space() failed."; + } + } + + i++; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* create the mem space to be used to read and write chunks */ + if (pass) { + + dims[0] = CHUNK_SIZE; + dims[1] = CHUNK_SIZE; + memspace_id = H5Screate_simple(2, dims, NULL); + + if (memspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* select in memory hyperslab */ + if (pass) { + + offset[0] = 0; /*offset of hyperslab in memory*/ + offset[1] = 0; + a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ + a_size[1] = CHUNK_SIZE; + status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Sselect_hyperslab() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* initialize all datasets on a round robin basis */ + i = 0; + while ((pass) && (i < DSET_SIZE)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + m = min_dset; + while ((pass) && (m <= max_dset)) { + /* initialize the slab */ + for (k = 0; k < CHUNK_SIZE; k++) { + for (l = 0; l < CHUNK_SIZE; l++) { + data_chunk[k][l] = (DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l; + } + } + + /* select on disk hyperslab */ + offset[0] = (hsize_t)i; /*offset of hyperslab in file*/ + offset[1] = (hsize_t)j; + a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ + a_size[1] = CHUNK_SIZE; + status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk H5Sselect_hyperslab() failed."; + } + + /* write the chunk to file */ + status = H5Dwrite(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], H5P_DEFAULT, + data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Dwrite() failed."; + } + m++; + } + j += CHUNK_SIZE; + } + + i += CHUNK_SIZE; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* read data from data sets and validate it */ + i = 0; + while ((pass) && (i < DSET_SIZE)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + m = min_dset; + while ((pass) && (m <= max_dset)) { + + /* select on disk hyperslab */ + offset[0] = (hsize_t)i; /* offset of hyperslab in file */ + offset[1] = (hsize_t)j; + a_size[0] = CHUNK_SIZE; /* size of hyperslab */ + a_size[1] = CHUNK_SIZE; + status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + + /* read the chunk from file */ + if (pass) { + + status = H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], + H5P_DEFAULT, data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + } + + /* validate the slab */ + if (pass) { + + valid_chunk = TRUE; + for (k = 0; k < CHUNK_SIZE; k++) { + for (l = 0; l < CHUNK_SIZE; l++) { + if (data_chunk[k][l] != + ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)) { + + valid_chunk = FALSE; + + if (verbose) { + + HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", k, l, + data_chunk[k][l], + ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)); + HDfprintf(stdout, "m = %d, i = %d, j = %d, k = %d, l = %d\n", m, i, j, k, + l); + } + } + } + } + + if (!valid_chunk) { + + pass = FALSE; + failure_mssg = "slab validation failed."; + + if (verbose) { + + HDfprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", i, j, m); + } + } + } + m++; + } + j += CHUNK_SIZE; + } + i += CHUNK_SIZE; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* close the file spaces */ + i = min_dset; + while ((pass) && (i <= max_dset)) { + if (H5Sclose(filespace_ids[i]) < 0) { + + pass = FALSE; + failure_mssg = "H5Sclose() failed."; + } + i++; + } + + /* close the datasets */ + i = min_dset; + while ((pass) && (i <= max_dset)) { + if (H5Dclose(dataset_ids[i]) < 0) { + + pass = FALSE; + failure_mssg = "H5Dclose() failed."; + } + i++; + } + + /* close the mem space */ + if (pass) { + + if (H5Sclose(memspace_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Sclose(memspace_id) failed."; + } + } + + return; + +} /* create_data_sets() */ + +/*------------------------------------------------------------------------- + * Function: delete_data_sets() + * + * Purpose: If pass is TRUE on entry, verify and then delete the + * dataset(s) indicated by min_dset and max_dset in the + * indicated file. + * + * Data sets and their contents must be well know, as we + * will verify that they contain the expected data later. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 10/31/16 + * + * Modifications: + * + * None. + * JRM -- 8/20/15 + * + *------------------------------------------------------------------------- + */ +#if 0 +/* this code will be needed to test full support of cache image + * in parallel -- keep it around against that day. + * + * -- JRM + */ +static void +delete_data_sets(hid_t file_id, int min_dset, int max_dset) +{ + const char * fcn_name = "delete_data_sets()"; + char dset_name[64]; + hbool_t show_progress = FALSE; + int cp = 0; + int i; + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + HDassert(0 <= min_dset); + HDassert(min_dset <= max_dset); + HDassert(max_dset < MAX_NUM_DSETS); + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* first, verify the contents of the target dataset(s) */ + verify_data_sets(file_id, min_dset, max_dset); + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* now delete the target datasets */ + if ( pass ) { + + i = min_dset; + + while ( ( pass ) && ( i <= max_dset ) ) + { + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", i); + + if ( H5Ldelete(file_id, dset_name, H5P_DEFAULT) < 0) { + + pass = FALSE; + failure_mssg = "H5Ldelete() failed."; + } + + i++; + } + } + + if ( show_progress ) HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + return; + +} /* delete_data_sets() */ +#endif + +/*------------------------------------------------------------------------- + * Function: open_hdf5_file() + * + * Purpose: If pass is true on entry, create or open the specified HDF5 + * and test to see if it has a metadata cache image superblock + * extension message. + * + * Set pass to FALSE and issue a suitable failure + * message if either the file contains a metadata cache image + * superblock extension and mdci_sbem_expected is TRUE, or + * vice versa. + * + * If mdci_sbem_expected is TRUE, also verify that the metadata + * cache has been advised of this. + * + * If read_only is TRUE, open the file read only. Otherwise + * open the file read/write. + * + * If set_mdci_fapl is TRUE, set the metadata cache image + * FAPL entry when opening the file, and verify that the + * metadata cache is notified. + * + * If config_fsm is TRUE, setup the persistent free space + * manager. Note that this flag may only be set if + * create_file is also TRUE. + * + * Return pointers to the cache data structure and file data + * structures. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 7/14/15 + * + * Modifications: + * + * Modified function to handle parallel file creates / opens. + * + * JRM -- 2/1/17 + * + * Modified function to handle + * + *------------------------------------------------------------------------- + */ + +static void +open_hdf5_file(const hbool_t create_file, const hbool_t mdci_sbem_expected, const hbool_t read_only, + const hbool_t set_mdci_fapl, const hbool_t config_fsm, const hbool_t enable_page_buffer, + const char *hdf_file_name, const unsigned cache_image_flags, hid_t *file_id_ptr, + H5F_t **file_ptr_ptr, H5C_t **cache_ptr_ptr, MPI_Comm comm, MPI_Info info, int l_facc_type, + const hbool_t all_coll_metadata_ops, const hbool_t coll_metadata_write, + const int md_write_strat) +{ + const char *fcn_name = "open_hdf5_file()"; + hbool_t show_progress = FALSE; + hbool_t verbose = FALSE; + int cp = 0; + hid_t fapl_id = -1; + hid_t fcpl_id = -1; + hid_t file_id = -1; + herr_t result; + H5F_t *file_ptr = NULL; + H5C_t *cache_ptr = NULL; + H5C_cache_image_ctl_t image_ctl; + H5AC_cache_image_config_t cache_image_config = {H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION, TRUE, FALSE, + H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE}; + + HDassert(!create_file || config_fsm); + + if (pass) { + /* opening the file both read only and with a cache image + * requested is a contradiction. We resolve it by ignoring + * the cache image request silently. + */ + if ((create_file && mdci_sbem_expected) || (create_file && read_only) || + (config_fsm && !create_file) || (create_file && enable_page_buffer && !config_fsm) || + (hdf_file_name == NULL) || ((set_mdci_fapl) && (cache_image_flags == 0)) || + ((set_mdci_fapl) && ((cache_image_flags & ~H5C_CI__ALL_FLAGS) != 0)) || (file_id_ptr == NULL) || + (file_ptr_ptr == NULL) || (cache_ptr_ptr == NULL) || + (l_facc_type != (l_facc_type & (FACC_MPIO)))) { + + failure_mssg = "Bad param(s) on entry to open_hdf5_file().\n"; + + pass = FALSE; + } + else if (verbose) { + + HDfprintf(stdout, "%s: HDF file name = \"%s\".\n", fcn_name, hdf_file_name); + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* create a file access property list. */ + if (pass) { + + fapl_id = H5Pcreate(H5P_FILE_ACCESS); + + if (fapl_id < 0) { + + pass = FALSE; + failure_mssg = "H5Pcreate() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* call H5Pset_libver_bounds() on the fapl_id */ + if (pass) { + + if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_libver_bounds() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* get metadata cache image config -- verify that it is the default */ + if (pass) { + + result = H5Pget_mdc_image_config(fapl_id, &cache_image_config); + + if (result < 0) { + + pass = FALSE; + failure_mssg = "H5Pget_mdc_image_config() failed.\n"; + } + + if ((cache_image_config.version != H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION) || + (cache_image_config.generate_image != FALSE) || + (cache_image_config.save_resize_status != FALSE) || + (cache_image_config.entry_ageout != H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE)) { + + pass = FALSE; + failure_mssg = "Unexpected default cache image config.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* set metadata cache image fapl entry if indicated */ + if ((pass) && (set_mdci_fapl)) { + + /* set cache image config fields to taste */ + cache_image_config.generate_image = TRUE; + cache_image_config.save_resize_status = FALSE; + cache_image_config.entry_ageout = H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE; + + result = H5Pset_mdc_image_config(fapl_id, &cache_image_config); + + if (result < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_mdc_image_config() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the persistent free space manager if indicated */ + if ((pass) && (config_fsm)) { + + fcpl_id = H5Pcreate(H5P_FILE_CREATE); + + if (fcpl_id <= 0) { + + pass = FALSE; + failure_mssg = "H5Pcreate(H5P_FILE_CREATE) failed."; + } + } + + if ((pass) && (config_fsm)) { + + if (H5Pset_file_space_strategy(fcpl_id, H5F_FSPACE_STRATEGY_PAGE, TRUE, (hsize_t)1) == FAIL) { + pass = FALSE; + failure_mssg = "H5Pset_file_space_strategy() failed.\n"; + } + } + + if ((pass) && (config_fsm)) { + + if (H5Pset_file_space_page_size(fcpl_id, PAGE_SIZE) == FAIL) { + + pass = FALSE; + failure_mssg = "H5Pset_file_space_page_size() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the page buffer if indicated */ + if ((pass) && (enable_page_buffer)) { + + if (H5Pset_page_buffer_size(fapl_id, PB_SIZE, 0, 0) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_page_buffer_size() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if ((pass) && (l_facc_type == FACC_MPIO)) { + + /* set Parallel access with communicator */ + if (H5Pset_fapl_mpio(fapl_id, comm, info) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_fapl_mpio() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if ((pass) && (l_facc_type == FACC_MPIO)) { + + if (H5Pset_all_coll_metadata_ops(fapl_id, all_coll_metadata_ops) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_all_coll_metadata_ops() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if ((pass) && (l_facc_type == FACC_MPIO)) { + + if (H5Pset_coll_metadata_write(fapl_id, coll_metadata_write) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_coll_metadata_write() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if ((pass) && (l_facc_type == FACC_MPIO)) { + + /* set the desired parallel metadata write strategy */ + H5AC_cache_config_t mdc_config; + + mdc_config.version = H5C__CURR_AUTO_SIZE_CTL_VER; + + if (H5Pget_mdc_config(fapl_id, &mdc_config) < 0) { + + pass = FALSE; + failure_mssg = "H5Pget_mdc_config() failed.\n"; + } + + mdc_config.metadata_write_strategy = md_write_strat; + + if (H5Pset_mdc_config(fapl_id, &mdc_config) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_mdc_config() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* open the file */ + if (pass) { + + if (create_file) { + + if (fcpl_id != -1) + + file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC, fcpl_id, fapl_id); + else + + file_id = H5Fcreate(hdf_file_name, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_id); + } + else { + + if (read_only) + + file_id = H5Fopen(hdf_file_name, H5F_ACC_RDONLY, fapl_id); + + else + + file_id = H5Fopen(hdf_file_name, H5F_ACC_RDWR, fapl_id); + } + + if (file_id < 0) { + + pass = FALSE; + failure_mssg = "H5Fcreate() or H5Fopen() failed.\n"; + } + else { + + file_ptr = (struct H5F_t *)H5VL_object_verify(file_id, H5I_FILE); + + if (file_ptr == NULL) { + + pass = FALSE; + failure_mssg = "Can't get file_ptr."; + + if (verbose) { + HDfprintf(stdout, "%s: Can't get file_ptr.\n", fcn_name); + } + } + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* get a pointer to the files internal data structure and then + * to the cache structure + */ + if (pass) { + + if (file_ptr->shared->cache == NULL) { + + pass = FALSE; + failure_mssg = "can't get cache pointer(1).\n"; + } + else { + + cache_ptr = file_ptr->shared->cache; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* verify expected page buffer status. At present, page buffering + * must be disabled in parallel -- hopefully this will change in the + * future. + */ + if (pass) { + + if ((file_ptr->shared->page_buf) && ((!enable_page_buffer) || (l_facc_type == FACC_MPIO))) { + + pass = FALSE; + failure_mssg = "page buffer unexpectedly enabled."; + } + else if ((file_ptr->shared->page_buf != NULL) && + ((enable_page_buffer) || (l_facc_type != FACC_MPIO))) { + + pass = FALSE; + failure_mssg = "page buffer unexpectedly disabled."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* verify expected metadata cache status */ + + /* get the cache image control structure from the cache, and verify + * that it contains the expected values. + * + * Then set the flags in this structure to the specified value. + */ + if (pass) { + + if (H5C_get_cache_image_config(cache_ptr, &image_ctl) < 0) { + + pass = FALSE; + failure_mssg = "error returned by H5C_get_cache_image_config()."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if (pass) { + + if (set_mdci_fapl) { + + if (read_only) { + + if ((image_ctl.version != H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION) || + (image_ctl.generate_image != FALSE) || (image_ctl.save_resize_status != FALSE) || + (image_ctl.entry_ageout != H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE) || + (image_ctl.flags != H5C_CI__ALL_FLAGS)) { + + pass = FALSE; + failure_mssg = "Unexpected image_ctl values(1).\n"; + } + } + else { + + if ((image_ctl.version != H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION) || + (image_ctl.generate_image != TRUE) || (image_ctl.save_resize_status != FALSE) || + (image_ctl.entry_ageout != H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE) || + (image_ctl.flags != H5C_CI__ALL_FLAGS)) { + + pass = FALSE; + failure_mssg = "Unexpected image_ctl values(2).\n"; + } + } + } + else { + + if ((image_ctl.version != H5AC__CURR_CACHE_IMAGE_CONFIG_VERSION) || + (image_ctl.generate_image != FALSE) || (image_ctl.save_resize_status != FALSE) || + (image_ctl.entry_ageout != H5AC__CACHE_IMAGE__ENTRY_AGEOUT__NONE) || + (image_ctl.flags != H5C_CI__ALL_FLAGS)) { + + pass = FALSE; + failure_mssg = "Unexpected image_ctl values(3).\n"; + } + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if ((pass) && (set_mdci_fapl)) { + + image_ctl.flags = cache_image_flags; + + if (H5C_set_cache_image_config(file_ptr, cache_ptr, &image_ctl) < 0) { + + pass = FALSE; + failure_mssg = "error returned by H5C_set_cache_image_config()."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if (pass) { + + if (cache_ptr->close_warning_received == TRUE) { + + pass = FALSE; + failure_mssg = "Unexpected value of close_warning_received.\n"; + } + + if (mdci_sbem_expected) { + + if (read_only) { + + if ((cache_ptr->load_image != TRUE) || (cache_ptr->delete_image != FALSE)) { + + pass = FALSE; + failure_mssg = "mdci sb extension message not present?\n"; + } + } + else { + + if ((cache_ptr->load_image != TRUE) || (cache_ptr->delete_image != TRUE)) { + + pass = FALSE; + failure_mssg = "mdci sb extension message not present?\n"; + } + } + } + else { + + if ((cache_ptr->load_image == TRUE) || (cache_ptr->delete_image == TRUE)) { + + pass = FALSE; + failure_mssg = "mdci sb extension message present?\n"; + } + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if (pass) { + + *file_id_ptr = file_id; + *file_ptr_ptr = file_ptr; + *cache_ptr_ptr = cache_ptr; + } + + if (show_progress) { + HDfprintf(stdout, "%s: cp = %d, pass = %d -- exiting.\n", fcn_name, cp++, pass); + + if (!pass) + HDfprintf(stdout, "%s: failure_mssg = %s\n", fcn_name, failure_mssg); + } + + return; + +} /* open_hdf5_file() */ + +/*------------------------------------------------------------------------- + * Function: par_create_dataset() + * + * Purpose: Collectively create a chunked dataset, and fill it with + * known values. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 3/4/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static void +par_create_dataset(int dset_num, hid_t file_id, int mpi_rank, int mpi_size) +{ + const char *fcn_name = "par_create_dataset()"; + char dset_name[256]; + hbool_t show_progress = FALSE; + hbool_t valid_chunk; + hbool_t verbose = FALSE; + int cp = 0; + int i, j, k, l; + int data_chunk[1][CHUNK_SIZE][CHUNK_SIZE]; + hsize_t dims[3]; + hsize_t a_size[3]; + hsize_t offset[3]; + hsize_t chunk_size[3]; + hid_t status; + hid_t dataspace_id = -1; + hid_t memspace_id = -1; + hid_t dset_id = -1; + hid_t filespace_id = -1; + hid_t dcpl_id = -1; + hid_t dxpl_id = -1; + + show_progress = (show_progress && (mpi_rank == 0)); + verbose = (verbose && (mpi_rank == 0)); + + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", dset_num); + + if (show_progress) { + HDfprintf(stdout, "%s: dset name = \"%s\".\n", fcn_name, dset_name); + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + } + + if (pass) { + + /* create a dataspace for the chunked dataset */ + dims[0] = (hsize_t)mpi_size; + dims[1] = DSET_SIZE; + dims[2] = DSET_SIZE; + dataspace_id = H5Screate_simple(3, dims, NULL); + + if (dataspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* set the dataset creation plist to specify that the raw data is + * to be partitioned into 1X10X10 element chunks. + */ + + if (pass) { + + dcpl_id = H5Pcreate(H5P_DATASET_CREATE); + + if (dcpl_id < 0) { + + pass = FALSE; + failure_mssg = "H5Pcreate(H5P_DATASET_CREATE) failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if (pass) { + + chunk_size[0] = 1; + chunk_size[1] = CHUNK_SIZE; + chunk_size[2] = CHUNK_SIZE; + + if (H5Pset_chunk(dcpl_id, 3, chunk_size) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_chunk() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* create the dataset */ + if (pass) { + + dset_id = + H5Dcreate2(file_id, dset_name, H5T_STD_I32BE, dataspace_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT); + + if (dset_id < 0) { + + pass = FALSE; + failure_mssg = "H5Dcreate() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* get the file space ID */ + if (pass) { + + filespace_id = H5Dget_space(dset_id); + + if (filespace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Dget_space() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* create the mem space to be used to read and write chunks */ + if (pass) { + + dims[0] = 1; + dims[1] = CHUNK_SIZE; + dims[2] = CHUNK_SIZE; + memspace_id = H5Screate_simple(3, dims, NULL); + + if (memspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* select in memory hyperslab */ + if (pass) { + + offset[0] = 0; /* offset of hyperslab in memory */ + offset[1] = 0; + offset[2] = 0; + a_size[0] = 1; /* size of hyperslab */ + a_size[1] = CHUNK_SIZE; + a_size[2] = CHUNK_SIZE; + status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Sselect_hyperslab() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the DXPL for collective I/O */ + if (pass) { + + dxpl_id = H5Pcreate(H5P_DATASET_XFER); + + if (dxpl_id < 0) { + + pass = FALSE; + failure_mssg = "H5Pcreate(H5P_DATASET_XFER) failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if (pass) { + + if (H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_dxpl_mpio() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* initialize the dataset with collective writes */ + i = 0; + while ((pass) && (i < DSET_SIZE)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.0, pass = %d.\n", fcn_name, cp, pass); + + /* initialize the slab */ + for (k = 0; k < CHUNK_SIZE; k++) { + for (l = 0; l < CHUNK_SIZE; l++) { + data_chunk[0][k][l] = + (DSET_SIZE * DSET_SIZE * mpi_rank) + (DSET_SIZE * (i + k)) + j + l + dset_num; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.1, pass = %d.\n", fcn_name, cp, pass); + + /* select on disk hyperslab */ + offset[0] = (hsize_t)mpi_rank; /* offset of hyperslab in file */ + offset[1] = (hsize_t)i; + offset[2] = (hsize_t)j; + a_size[0] = (hsize_t)1; /* size of hyperslab */ + a_size[1] = CHUNK_SIZE; + a_size[2] = CHUNK_SIZE; + status = H5Sselect_hyperslab(filespace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk H5Sselect_hyperslab() failed."; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.2, pass = %d.\n", fcn_name, cp, pass); + + /* write the chunk to file */ + status = H5Dwrite(dset_id, H5T_NATIVE_INT, memspace_id, filespace_id, dxpl_id, data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Dwrite() failed."; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.3, pass = %d.\n", fcn_name, cp, pass); + + j += CHUNK_SIZE; + } + + i += CHUNK_SIZE; + } + + cp++; + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* read data from data sets and validate it */ + i = 0; + while ((pass) && (i < DSET_SIZE)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + /* select on disk hyperslab */ + offset[0] = (hsize_t)mpi_rank; + offset[1] = (hsize_t)i; /* offset of hyperslab in file */ + offset[2] = (hsize_t)j; + a_size[0] = (hsize_t)1; + a_size[1] = CHUNK_SIZE; /* size of hyperslab */ + a_size[2] = CHUNK_SIZE; + + status = H5Sselect_hyperslab(filespace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + + /* read the chunk from file */ + if (pass) { + + status = H5Dread(dset_id, H5T_NATIVE_INT, memspace_id, filespace_id, dxpl_id, data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "chunk read failed."; + } + } + + /* validate the slab */ + if (pass) { + + valid_chunk = TRUE; + for (k = 0; k < CHUNK_SIZE; k++) { + for (l = 0; l < CHUNK_SIZE; l++) { + if (data_chunk[0][k][l] != + ((DSET_SIZE * DSET_SIZE * mpi_rank) + (DSET_SIZE * (i + k)) + j + l + dset_num)) { + + valid_chunk = FALSE; + + if (verbose) { + + HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", k, l, + data_chunk[0][k][l], + ((DSET_SIZE * DSET_SIZE * mpi_rank) + (DSET_SIZE * (i + k)) + j + + l + dset_num)); + HDfprintf(stdout, "dset_num = %d, i = %d, j = %d, k = %d, l = %d\n", dset_num, + i, j, k, l); + } + } + } + } + + if (!valid_chunk) { + + pass = FALSE; + failure_mssg = "slab validation failed."; + + if (verbose) { + + HDfprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", i, j, dset_num); + } + } + } + j += CHUNK_SIZE; + } + i += CHUNK_SIZE; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* close the data space */ + if ((pass) && (H5Sclose(dataspace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(dataspace_id) failed."; + } + + /* close the file space */ + if ((pass) && (H5Sclose(filespace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(filespace_id) failed."; + } + + /* close the dataset */ + if ((pass) && (H5Dclose(dset_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Dclose(dset_id) failed."; + } + + /* close the mem space */ + if ((pass) && (H5Sclose(memspace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(memspace_id) failed."; + } + + /* close the dataset creation property list */ + if ((pass) && (H5Pclose(dcpl_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Pclose(dcpl) failed."; + } + + /* close the data access property list */ + if ((pass) && (H5Pclose(dxpl_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Pclose(dxpl) failed."; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + return; + +} /* par_create_dataset() */ + +/*------------------------------------------------------------------------- + * Function: par_delete_dataset() + * + * Purpose: Collectively delete the specified dataset. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 3/6/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static void +par_delete_dataset(int dset_num, hid_t file_id, int mpi_rank) +{ + const char *fcn_name = "par_delete_dataset()"; + char dset_name[256]; + hbool_t show_progress = FALSE; + int cp = 0; + + show_progress = (show_progress && (mpi_rank == 0)); + + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", dset_num); + + if (show_progress) { + HDfprintf(stdout, "%s: dset name = \"%s\".\n", fcn_name, dset_name); + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + } + + /* verify the target dataset */ + if (pass) { + + par_verify_dataset(dset_num, file_id, mpi_rank); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* delete the target dataset */ + if (pass) { + + if (H5Ldelete(file_id, dset_name, H5P_DEFAULT) < 0) { + + pass = FALSE; + failure_mssg = "H5Ldelete() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + return; + +} /* par_delete_dataset() */ + +/*------------------------------------------------------------------------- + * Function: par_insert_cache_image() + * + * Purpose: Insert a cache image in the supplied file. + * + * At present, cache image is not enabled in the parallel + * so we have to insert the cache image with a serial + * process. Do this via a fork and an execv from process 0. + * All processes wait until the child process completes, and + * then return. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 3/8/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static void +par_insert_cache_image(int file_name_idx, int mpi_rank, int mpi_size) +{ + if (pass) { + + if (mpi_rank == 0) { /* insert cache image in supplied test file */ + + if (!serial_insert_cache_image(file_name_idx, mpi_size)) { + HDfprintf(stderr, "\n\nCache image insertion failed.\n"); + HDfprintf(stderr, " failure mssg = \"%s\"\n", failure_mssg); + HDexit(EXIT_FAILURE); + } + } + } + + if (pass) { + + /* make sure insertion of the cache image is complete + * before proceeding + */ + MPI_Barrier(MPI_COMM_WORLD); + } + + return; + +} /* par_insert_cache_image() */ + +/*------------------------------------------------------------------------- + * Function: par_verify_dataset() + * + * Purpose: Collectively verify the contents of a chunked dataset. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 3/6/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static void +par_verify_dataset(int dset_num, hid_t file_id, int mpi_rank) +{ + const char *fcn_name = "par_verify_dataset()"; + char dset_name[256]; + hbool_t show_progress = FALSE; + hbool_t valid_chunk; + hbool_t verbose = FALSE; + int cp = 0; + int i, j, k, l; + int data_chunk[1][CHUNK_SIZE][CHUNK_SIZE]; + hsize_t dims[3]; + hsize_t a_size[3]; + hsize_t offset[3]; + hid_t status; + hid_t memspace_id = -1; + hid_t dset_id = -1; + hid_t filespace_id = -1; + hid_t dxpl_id = -1; + + show_progress = (show_progress && (mpi_rank == 0)); + verbose = (verbose && (mpi_rank == 0)); + + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", dset_num); + + if (show_progress) { + HDfprintf(stdout, "%s: dset name = \"%s\".\n", fcn_name, dset_name); + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + } + + if (pass) { + + /* open the dataset */ + + dset_id = H5Dopen2(file_id, dset_name, H5P_DEFAULT); + + if (dset_id < 0) { + + pass = FALSE; + failure_mssg = "H5Dopen2() failed."; + } + } + + /* get the file space ID */ + if (pass) { + + filespace_id = H5Dget_space(dset_id); + + if (filespace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Dget_space() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* create the mem space to be used to read */ + if (pass) { + + dims[0] = 1; + dims[1] = CHUNK_SIZE; + dims[2] = CHUNK_SIZE; + memspace_id = H5Screate_simple(3, dims, NULL); + + if (memspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* select in memory hyperslab */ + if (pass) { + + offset[0] = 0; /* offset of hyperslab in memory */ + offset[1] = 0; + offset[2] = 0; + a_size[0] = 1; /* size of hyperslab */ + a_size[1] = CHUNK_SIZE; + a_size[2] = CHUNK_SIZE; + status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Sselect_hyperslab() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the DXPL for collective I/O */ + if (pass) { + + dxpl_id = H5Pcreate(H5P_DATASET_XFER); + + if (dxpl_id < 0) { + + pass = FALSE; + failure_mssg = "H5Pcreate(H5P_DATASET_XFER) failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + if (pass) { + + if (H5Pset_dxpl_mpio(dxpl_id, H5FD_MPIO_COLLECTIVE) < 0) { + + pass = FALSE; + failure_mssg = "H5Pset_dxpl_mpio() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* read data from data sets and validate it */ + i = 0; + while ((pass) && (i < DSET_SIZE)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + /* select on disk hyperslab */ + offset[0] = (hsize_t)mpi_rank; + offset[1] = (hsize_t)i; /* offset of hyperslab in file */ + offset[2] = (hsize_t)j; + a_size[0] = (hsize_t)1; + a_size[1] = CHUNK_SIZE; /* size of hyperslab */ + a_size[2] = CHUNK_SIZE; + + status = H5Sselect_hyperslab(filespace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + + /* read the chunk from file */ + if (pass) { + + status = H5Dread(dset_id, H5T_NATIVE_INT, memspace_id, filespace_id, dxpl_id, data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "chunk read failed."; + } + } + + /* validate the slab */ + if (pass) { + + valid_chunk = TRUE; + for (k = 0; k < CHUNK_SIZE; k++) { + for (l = 0; l < CHUNK_SIZE; l++) { + if (data_chunk[0][k][l] != + ((DSET_SIZE * DSET_SIZE * mpi_rank) + (DSET_SIZE * (i + k)) + j + l + dset_num)) { + + valid_chunk = FALSE; + + if (verbose) { + + HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", k, l, + data_chunk[0][k][l], + ((DSET_SIZE * DSET_SIZE * mpi_rank) + (DSET_SIZE * (i + k)) + j + + l + dset_num)); + HDfprintf(stdout, "dset_num = %d, i = %d, j = %d, k = %d, l = %d\n", dset_num, + i, j, k, l); + } + } + } + } + + if (!valid_chunk) { + + pass = FALSE; + failure_mssg = "slab validation failed."; + + if (verbose) { + + HDfprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", i, j, dset_num); + } + } + } + j += CHUNK_SIZE; + } + i += CHUNK_SIZE; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* close the file space */ + if ((pass) && (H5Sclose(filespace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(filespace_id) failed."; + } + + /* close the dataset */ + if ((pass) && (H5Dclose(dset_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Dclose(dset_id) failed."; + } + + /* close the mem space */ + if ((pass) && (H5Sclose(memspace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(memspace_id) failed."; + } + + /* close the data access property list */ + if ((pass) && (H5Pclose(dxpl_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Pclose(dxpl) failed."; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + return; + +} /* par_verify_dataset() */ + +/*------------------------------------------------------------------------- + * Function: serial_insert_cache_image() + * + * Purpose: Insert a cache image in the supplied file. + * + * To populate the cache image, validate the contents + * of the file before closing. + * + * On failure, print an appropriate error message and + * return FALSE. + * + * Return: TRUE if succussful, FALSE otherwise. + * + * Programmer: John Mainzer + * 3/8/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static hbool_t +serial_insert_cache_image(int file_name_idx, int mpi_size) +{ + const char *fcn_name = "serial_insert_cache_image()"; + char filename[512]; + hbool_t show_progress = FALSE; + int cp = 0; + int i; + int num_dsets = PAR_NUM_DSETS; + hid_t file_id = -1; + H5F_t *file_ptr = NULL; + H5C_t *cache_ptr = NULL; + MPI_Comm dummy_comm = MPI_COMM_WORLD; + MPI_Info dummy_info = MPI_INFO_NULL; + + pass = TRUE; + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 1) setup the file name */ + if (pass) { + + HDassert(FILENAMES[file_name_idx]); + + if (h5_fixname(FILENAMES[file_name_idx], H5P_DEFAULT, filename, sizeof(filename)) == NULL) { + + pass = FALSE; + HDfprintf(stdout, "h5_fixname() failed.\n"); + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 2) Open the PHDF5 file with the cache image FAPL entry. + */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ FALSE, + /* read_only */ FALSE, + /* set_mdci_fapl */ TRUE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ dummy_comm, + /* info */ dummy_info, + /* l_facc_type */ 0, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ 1); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 3) Validate contents of the file */ + + i = 0; + while ((pass) && (i < num_dsets)) { + + serial_verify_dataset(i, file_id, mpi_size); + i++; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 4) Close the file */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + return pass; + +} /* serial_insert_cache_image() */ + +/*------------------------------------------------------------------------- + * Function: serial_verify_dataset() + * + * Purpose: Verify the contents of a chunked dataset. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 3/6/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static void +serial_verify_dataset(int dset_num, hid_t file_id, int mpi_size) +{ + const char *fcn_name = "serial_verify_dataset()"; + char dset_name[256]; + hbool_t show_progress = FALSE; + hbool_t valid_chunk; + hbool_t verbose = FALSE; + int cp = 0; + int i, j, k, l, m; + int data_chunk[1][CHUNK_SIZE][CHUNK_SIZE]; + hsize_t dims[3]; + hsize_t a_size[3]; + hsize_t offset[3]; + hid_t status; + hid_t memspace_id = -1; + hid_t dset_id = -1; + hid_t filespace_id = -1; + + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", dset_num); + + if (show_progress) { + HDfprintf(stdout, "%s: dset name = \"%s\".\n", fcn_name, dset_name); + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + } + + if (pass) { + + /* open the dataset */ + + dset_id = H5Dopen2(file_id, dset_name, H5P_DEFAULT); + + if (dset_id < 0) { + + pass = FALSE; + failure_mssg = "H5Dopen2() failed."; + } + } + + /* get the file space ID */ + if (pass) { + + filespace_id = H5Dget_space(dset_id); + + if (filespace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Dget_space() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* create the mem space to be used to read */ + if (pass) { + + dims[0] = 1; + dims[1] = CHUNK_SIZE; + dims[2] = CHUNK_SIZE; + memspace_id = H5Screate_simple(3, dims, NULL); + + if (memspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* select in memory hyperslab */ + if (pass) { + + offset[0] = 0; /* offset of hyperslab in memory */ + offset[1] = 0; + offset[2] = 0; + a_size[0] = 1; /* size of hyperslab */ + a_size[1] = CHUNK_SIZE; + a_size[2] = CHUNK_SIZE; + status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Sselect_hyperslab() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* read data from data sets and validate it */ + i = 0; + while ((pass) && (i < mpi_size)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + k = 0; + while ((pass) && (k < DSET_SIZE)) { + /* select on disk hyperslab */ + offset[0] = (hsize_t)i; /* offset of hyperslab in file */ + offset[1] = (hsize_t)j; /* offset of hyperslab in file */ + offset[2] = (hsize_t)k; + a_size[0] = (hsize_t)1; + a_size[1] = CHUNK_SIZE; /* size of hyperslab */ + a_size[2] = CHUNK_SIZE; + + status = H5Sselect_hyperslab(filespace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + + /* read the chunk from file */ + if (pass) { + + status = + H5Dread(dset_id, H5T_NATIVE_INT, memspace_id, filespace_id, H5P_DEFAULT, data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "chunk read failed."; + } + } + + /* validate the slab */ + if (pass) { + + valid_chunk = TRUE; + + for (l = 0; l < CHUNK_SIZE; l++) { + for (m = 0; m < CHUNK_SIZE; m++) { + if (data_chunk[0][l][m] != + ((DSET_SIZE * DSET_SIZE * i) + (DSET_SIZE * (j + l)) + k + m + dset_num)) { + + valid_chunk = FALSE; + + if (verbose) { + + HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", j, k, + data_chunk[0][j][k], + ((DSET_SIZE * DSET_SIZE * i) + (DSET_SIZE * (j + l)) + k + m + + dset_num)); + HDfprintf(stdout, + "dset_num = %d, i = %d, j = %d, k = %d, l = %d, m = %d\n", + dset_num, i, j, k, l, m); + } + } + } + } + + if (!valid_chunk) { + + pass = FALSE; + failure_mssg = "slab validation failed."; + + if (verbose) { + + HDfprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", j, k, dset_num); + } + } + } + k += CHUNK_SIZE; + } + j += CHUNK_SIZE; + } + i++; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* close the file space */ + if ((pass) && (H5Sclose(filespace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(filespace_id) failed."; + } + + /* close the dataset */ + if ((pass) && (H5Dclose(dset_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Dclose(dset_id) failed."; + } + + /* close the mem space */ + if ((pass) && (H5Sclose(memspace_id) < 0)) { + + pass = FALSE; + failure_mssg = "H5Sclose(memspace_id) failed."; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + return; + +} /* serial_verify_dataset() */ + +/*------------------------------------------------------------------------- + * Function: verify_data_sets() + * + * Purpose: If pass is TRUE on entry, verify that the data sets in the + * file exist and contain the expected data. + * + * Note that these data sets were created by + * create_data_sets() above. Thus any changes in that + * function must be reflected in this function, and + * vise-versa. + * + * On failure, set pass to FALSE, and set failure_mssg + * to point to an appropriate failure message. + * + * Do nothing if pass is FALSE on entry. + * + * Return: void + * + * Programmer: John Mainzer + * 7/15/15 + * + * Modifications: + * + * Added min_dset and max_dset parameters and supporting + * code. This allows the caller to specify a range of + * datasets to verify. + * JRM -- 8/20/15 + * + *------------------------------------------------------------------------- + */ + +static void +verify_data_sets(hid_t file_id, int min_dset, int max_dset) +{ + const char *fcn_name = "verify_data_sets()"; + char dset_name[64]; + hbool_t show_progress = FALSE; + hbool_t valid_chunk; + hbool_t verbose = FALSE; + int cp = 0; + int i, j, k, l, m; + int data_chunk[CHUNK_SIZE][CHUNK_SIZE]; + herr_t status; + hid_t filespace_ids[MAX_NUM_DSETS]; + hid_t memspace_id = -1; + hid_t dataset_ids[MAX_NUM_DSETS]; + hsize_t dims[2]; + hsize_t a_size[2]; + hsize_t offset[2]; + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + HDassert(0 <= min_dset); + HDassert(min_dset <= max_dset); + HDassert(max_dset < MAX_NUM_DSETS); + + /* open the datasets */ + + if (pass) { + + i = min_dset; + + while ((pass) && (i <= max_dset)) { + /* open the dataset */ + if (pass) { + + HDsnprintf(dset_name, sizeof(dset_name), "/dset%03d", i); + dataset_ids[i] = H5Dopen2(file_id, dset_name, H5P_DEFAULT); + + if (dataset_ids[i] < 0) { + + pass = FALSE; + failure_mssg = "H5Dopen2() failed."; + } + } + + /* get the file space ID */ + if (pass) { + + filespace_ids[i] = H5Dget_space(dataset_ids[i]); + + if (filespace_ids[i] < 0) { + + pass = FALSE; + failure_mssg = "H5Dget_space() failed."; + } + } + + i++; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* create the mem space to be used to read and write chunks */ + if (pass) { + + dims[0] = CHUNK_SIZE; + dims[1] = CHUNK_SIZE; + memspace_id = H5Screate_simple(2, dims, NULL); + + if (memspace_id < 0) { + + pass = FALSE; + failure_mssg = "H5Screate_simple() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* select in memory hyperslab */ + if (pass) { + + offset[0] = 0; /*offset of hyperslab in memory*/ + offset[1] = 0; + a_size[0] = CHUNK_SIZE; /*size of hyperslab*/ + a_size[1] = CHUNK_SIZE; + status = H5Sselect_hyperslab(memspace_id, H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "H5Sselect_hyperslab() failed."; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* read data from data sets and validate it */ + i = 0; + while ((pass) && (i < DSET_SIZE)) { + j = 0; + while ((pass) && (j < DSET_SIZE)) { + m = min_dset; + while ((pass) && (m <= max_dset)) { + + /* select on disk hyperslab */ + offset[0] = (hsize_t)i; /* offset of hyperslab in file */ + offset[1] = (hsize_t)j; + a_size[0] = CHUNK_SIZE; /* size of hyperslab */ + a_size[1] = CHUNK_SIZE; + status = H5Sselect_hyperslab(filespace_ids[m], H5S_SELECT_SET, offset, NULL, a_size, NULL); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + + /* read the chunk from file */ + if (pass) { + + status = H5Dread(dataset_ids[m], H5T_NATIVE_INT, memspace_id, filespace_ids[m], + H5P_DEFAULT, data_chunk); + + if (status < 0) { + + pass = FALSE; + failure_mssg = "disk hyperslab create failed."; + } + } + + /* validate the slab */ + if (pass) { + + valid_chunk = TRUE; + for (k = 0; k < CHUNK_SIZE; k++) { + for (l = 0; l < CHUNK_SIZE; l++) { + if (data_chunk[k][l] != + ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)) { + + valid_chunk = FALSE; + + if (verbose) { + + HDfprintf(stdout, "data_chunk[%0d][%0d] = %0d, expect %0d.\n", k, l, + data_chunk[k][l], + ((DSET_SIZE * DSET_SIZE * m) + (DSET_SIZE * (i + k)) + j + l)); + HDfprintf(stdout, "m = %d, i = %d, j = %d, k = %d, l = %d\n", m, i, j, k, + l); + } + } + } + } + + if (!valid_chunk) { + + pass = FALSE; + failure_mssg = "slab validation failed."; + + if (verbose) { + + HDfprintf(stdout, "Chunk (%0d, %0d) in /dset%03d is invalid.\n", i, j, m); + } + } + } + m++; + } + j += CHUNK_SIZE; + } + i += CHUNK_SIZE; + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d.\n", fcn_name, cp++); + + /* close the file spaces */ + i = min_dset; + while ((pass) && (i <= max_dset)) { + if (H5Sclose(filespace_ids[i]) < 0) { + + pass = FALSE; + failure_mssg = "H5Sclose() failed."; + } + i++; + } + + /* close the datasets */ + i = min_dset; + while ((pass) && (i <= max_dset)) { + if (H5Dclose(dataset_ids[i]) < 0) { + + pass = FALSE; + failure_mssg = "H5Dclose() failed."; + } + i++; + } + + /* close the mem space */ + if (pass) { + + if (H5Sclose(memspace_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Sclose(memspace_id) failed."; + } + } + + return; + +} /* verify_data_sets() */ + +/****************************************************************************/ +/******************************* Test Functions *****************************/ +/****************************************************************************/ + +/*------------------------------------------------------------------------- + * Function: verify_cache_image_RO() + * + * Purpose: Verify that a HDF5 file containing a cache image is + * opened R/O and read correctly by PHDF5 with the specified + * metadata write strategy. + * + * Basic cycle of operation is as follows: + * + * 1) Open the test file created at the beginning of this + * test read only. + * + * Verify that the file contains a cache image. + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + * + * 2) Verify that the file contains the expected data. + * + * 3) Close the file. + * + * 4) Open the file R/O, and verify that it still contains + * a cache image. + * + * 5) Verify that the file contains the expected data. + * + * 6) Close the file. + * + * Return: void + * + * Programmer: John Mainzer + * 3/11/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static unsigned +verify_cache_image_RO(int file_name_id, int md_write_strat, int mpi_rank) +{ + const char *fcn_name = "verify_cache_image_RO()"; + char filename[512]; + hbool_t show_progress = FALSE; + hid_t file_id = -1; + H5F_t *file_ptr = NULL; + H5C_t *cache_ptr = NULL; + int cp = 0; + + pass = TRUE; + + if (mpi_rank == 0) { + + switch (md_write_strat) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + TESTING("parallel CI load test -- proc0 md write -- R/O"); + break; + + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + TESTING("parallel CI load test -- dist md write -- R/O"); + break; + + default: + TESTING("parallel CI load test -- unknown md write -- R/o"); + pass = FALSE; + break; + } + } + + show_progress = ((show_progress) && (mpi_rank == 0)); + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the file name */ + if (pass) { + + if (h5_fixname(FILENAMES[file_name_id], H5P_DEFAULT, filename, sizeof(filename)) == NULL) { + + pass = FALSE; + failure_mssg = "h5_fixname() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 1) Open the test file created at the beginning of this test. + * + * Verify that the file contains a cache image. + */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ TRUE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ MPI_COMM_WORLD, + /* info */ MPI_INFO_NULL, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ md_write_strat); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 2) Verify that the file contains the expected data. + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + */ + + if (pass) { + + verify_data_sets(file_id, 0, MAX_NUM_DSETS - 1); + } + + /* Verify that only process 0 reads the cache image. */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (((mpi_rank == 0) && (cache_ptr->images_read != 1)) || + ((mpi_rank > 0) && (cache_ptr->images_read != 0))) { + + pass = FALSE; + failure_mssg = "unexpected images_read."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* Verify that all other processes receive the cache image block + * from process 0. + * + * Since we have already verified that only process 0 has read the + * image, it is sufficient to verify that the image was loaded on + * all processes. + */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 1) { + + pass = FALSE; + failure_mssg = "Image not loaded?."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 3) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 4) Open the file, and verify that it doesn't contain a cache image. */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ TRUE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ MPI_COMM_WORLD, + /* info */ MPI_INFO_NULL, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ md_write_strat); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 5) Verify that the file contains the expected data. */ + + if (pass) { + + verify_data_sets(file_id, 0, MAX_NUM_DSETS - 1); + } + +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 1) { + + pass = FALSE; + failure_mssg = "metadata cache image block not loaded(2)."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + /* 6) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* report results */ + if (mpi_rank == 0) { + + if (pass) { + + PASSED(); + } + else { + + H5_FAILED(); + + if (show_progress) { + HDfprintf(stdout, "%s: failure_mssg = \"%s\"\n", fcn_name, failure_mssg); + } + } + } + + return !pass; + +} /* verify_cache_image_RO() */ + +/*------------------------------------------------------------------------- + * Function: verify_cache_image_RW() + * + * Purpose: Verify that a HDF5 file containing a cache image is + * opened and read correctly by PHDF5 with the specified + * metadata write strategy. + * + * Basic cycle of operation is as follows: + * + * 1) Open the test file created at the beginning of this + * test. + * + * Verify that the file contains a cache image. + * + * 2) Verify that the file contains the expected data. + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + * + * + * 3) Close the file. + * + * 4) Open the file, and verify that it doesn't contain + * a cache image. + * + * 5) Verify that the file contains the expected data. + * + * 6) Close the file. + * + * 7) Delete the file. + * + * Return: void + * + * Programmer: John Mainzer + * 1/25/17 + * + * Modifications: + * + * None. + * + *------------------------------------------------------------------------- + */ + +static unsigned +verify_cache_image_RW(int file_name_id, int md_write_strat, int mpi_rank) +{ + const char *fcn_name = "verify_cache_imageRW()"; + char filename[512]; + hbool_t show_progress = FALSE; + hid_t file_id = -1; + H5F_t *file_ptr = NULL; + H5C_t *cache_ptr = NULL; + int cp = 0; + + pass = TRUE; + + if (mpi_rank == 0) { + + switch (md_write_strat) { + + case H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY: + TESTING("parallel CI load test -- proc0 md write -- R/W"); + break; + + case H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED: + TESTING("parallel CI load test -- dist md write -- R/W"); + break; + + default: + TESTING("parallel CI load test -- unknown md write -- R/W"); + pass = FALSE; + break; + } + } + + show_progress = ((show_progress) && (mpi_rank == 0)); + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the file name */ + if (pass) { + + if (h5_fixname(FILENAMES[file_name_id], H5P_DEFAULT, filename, sizeof(filename)) == NULL) { + + pass = FALSE; + failure_mssg = "h5_fixname() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 1) Open the test file created at the beginning of this test. + * + * Verify that the file contains a cache image. + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ FALSE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ MPI_COMM_WORLD, + /* info */ MPI_INFO_NULL, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ md_write_strat); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 2) Verify that the file contains the expected data. + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + */ + if (pass) { + + verify_data_sets(file_id, 0, MAX_NUM_DSETS - 1); + } + + /* Verify that only process 0 reads the cache image. */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (((mpi_rank == 0) && (cache_ptr->images_read != 1)) || + ((mpi_rank > 0) && (cache_ptr->images_read != 0))) { + + pass = FALSE; + failure_mssg = "unexpected images_read."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* Verify that all other processes receive the cache image block + * from process 0. + * + * Since we have already verified that only process 0 has read the + * image, it is sufficient to verify that the image was loaded on + * all processes. + */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 1) { + + pass = FALSE; + failure_mssg = "Image not loaded?."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 3) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 4) Open the file, and verify that it doesn't contain a cache image. */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ FALSE, + /* read_only */ FALSE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ MPI_COMM_WORLD, + /* info */ MPI_INFO_NULL, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ FALSE, + /* md_write_strat */ md_write_strat); + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 5) Verify that the file contains the expected data. */ + + if (pass) { + + verify_data_sets(file_id, 0, MAX_NUM_DSETS - 1); + } + +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 0) { + + pass = FALSE; + failure_mssg = "metadata cache image block loaded(1)."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + /* 6) Close the file. */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if (show_progress) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 7) Delete the file. */ + + if (pass) { + + /* wait for everyone to close the file */ + MPI_Barrier(MPI_COMM_WORLD); + + if ((mpi_rank == 0) && (HDremove(filename) < 0)) { + + pass = FALSE; + failure_mssg = "HDremove() failed.\n"; + } + } + + /* report results */ + if (mpi_rank == 0) { + + if (pass) { + + PASSED(); + } + else { + + H5_FAILED(); + + if (show_progress) { + HDfprintf(stdout, "%s: failure_mssg = \"%s\"\n", fcn_name, failure_mssg); + } + } + } + + return !pass; + +} /* verify_cache_imageRW() */ + +/***************************************************************************** + * + * Function: smoke_check_1() + * + * Purpose: Initial smoke check to verify correct behaviour of cache + * image in combination with parallel. + * + * As cache image is currently disabled in the parallel case, + * we construct a test file in parallel, verify it in serial + * and generate a cache image in passing, and then verify + * it again in parallel. + * + * In passing, also verify that page buffering is silently + * disabled in the parallel case. Needless to say, this part + * of the test will have to be re-worked when and if page + * buffering is supported in parallel. + * + * Return: Success: TRUE + * + * Failure: FALSE + * + * Programmer: JRM -- 3/6/17 + * + *****************************************************************************/ +static hbool_t +smoke_check_1(MPI_Comm mpi_comm, MPI_Info mpi_info, int mpi_rank, int mpi_size) +{ + const char *fcn_name = "smoke_check_1()"; + char filename[512]; + hbool_t show_progress = FALSE; + hid_t file_id = -1; + H5F_t *file_ptr = NULL; + H5C_t *cache_ptr = NULL; + int cp = 0; + int i; + int num_dsets = PAR_NUM_DSETS; + int test_file_index = 2; + h5_stat_size_t file_size; + + pass = TRUE; + + if (mpi_rank == 0) { + + TESTING("parallel cache image smoke check 1"); + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* setup the file name */ + if (pass) { + + HDassert(FILENAMES[test_file_index]); + + if (h5_fixname(FILENAMES[test_file_index], H5P_DEFAULT, filename, sizeof(filename)) == NULL) { + + pass = FALSE; + failure_mssg = "h5_fixname() failed.\n"; + } + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 1) Create a PHDF5 file without the cache image FAPL entry. + * + * Verify that a cache image is not requested + */ + + if (pass) { + + open_hdf5_file(/* create_file */ TRUE, + /* mdci_sbem_expected */ FALSE, + /* read_only */ FALSE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ TRUE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ mpi_comm, + /* info */ mpi_info, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ TRUE, + /* md_write_strat */ 1); + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 2) Create datasets in the file */ + + i = 0; + while ((pass) && (i < num_dsets)) { + + par_create_dataset(i, file_id, mpi_rank, mpi_size); + i++; + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 3) Verify the datasets in the file */ + + i = 0; + while ((pass) && (i < num_dsets)) { + + par_verify_dataset(i, file_id, mpi_rank); + i++; + } + + /* 4) Close the file */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed.\n"; + } + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 5 Insert a cache image into the file */ + + if (pass) { + + par_insert_cache_image(test_file_index, mpi_rank, mpi_size); + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 6) Open the file R/O */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ TRUE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ mpi_comm, + /* info */ mpi_info, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ TRUE, + /* md_write_strat */ 1); + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 7) Verify the datasets in the file backwards + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + */ + + i = num_dsets - 1; + while ((pass) && (i >= 0)) { + + par_verify_dataset(i, file_id, mpi_rank); + i--; + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* Verify that only process 0 reads the cache image. */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (((mpi_rank == 0) && (cache_ptr->images_read != 1)) || + ((mpi_rank > 0) && (cache_ptr->images_read != 0))) { + + pass = FALSE; + failure_mssg = "unexpected images_read."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* Verify that all other processes receive the cache image block + * from process 0. + * + * Since we have already verified that only process 0 has read the + * image, it is sufficient to verify that the image was loaded on + * all processes. + */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 1) { + + pass = FALSE; + failure_mssg = "Image not loaded?."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 8) Close the file */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed."; + } + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 9) Open the file */ + + if (pass) { + + open_hdf5_file(/* create_file */ FALSE, + /* mdci_sbem_expected */ TRUE, + /* read_only */ FALSE, + /* set_mdci_fapl */ FALSE, + /* config_fsm */ FALSE, + /* enable_page_buffer */ FALSE, + /* hdf_file_name */ filename, + /* cache_image_flags */ H5C_CI__ALL_FLAGS, + /* file_id_ptr */ &file_id, + /* file_ptr_ptr */ &file_ptr, + /* cache_ptr_ptr */ &cache_ptr, + /* comm */ mpi_comm, + /* info */ mpi_info, + /* l_facc_type */ FACC_MPIO, + /* all_coll_metadata_ops */ FALSE, + /* coll_metadata_write */ TRUE, + /* md_write_strat */ 1); + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 10) Verify the datasets in the file + * + * Verify that only process 0 reads the cache image. + * + * Verify that all other processes receive the cache + * image block from process 0. + */ + + i = 0; + while ((pass) && (i < num_dsets)) { + + par_verify_dataset(i, file_id, mpi_rank); + i++; + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* Verify that only process 0 reads the cache image. */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (((mpi_rank == 0) && (cache_ptr->images_read != 1)) || + ((mpi_rank > 0) && (cache_ptr->images_read != 0))) { + + pass = FALSE; + failure_mssg = "unexpected images_read."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* Verify that all other processes receive the cache image block + * from process 0. + * + * Since we have already verified that only process 0 has read the + * image, it is sufficient to verify that the image was loaded on + * all processes. + */ +#if H5C_COLLECT_CACHE_STATS + if (pass) { + + if (cache_ptr->images_loaded != 1) { + + pass = FALSE; + failure_mssg = "Image not loaded?."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 11) Delete the datasets in the file */ + + i = 0; + while ((pass) && (i < num_dsets)) { + + par_delete_dataset(i, file_id, mpi_rank); + i++; + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 12) Close the file */ + + if (pass) { + + if (H5Fclose(file_id) < 0) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed."; + } + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 13) Get the size of the file. Verify that it is less + * than 20 KB. Without deletions and persistent free + * space managers, size size is about 30 MB, so this + * is sufficient to verify that the persistent free + * space managers are more or less doing their job. + * + * Note that this test will have to change if we use + * a larger page size. + */ + if (pass) { + + if ((file_size = h5_get_file_size(filename, H5P_DEFAULT)) < 0) { + + pass = FALSE; + failure_mssg = "h5_get_file_size() failed."; + } + else if (file_size > 20 * 1024) { + + pass = FALSE; + failure_mssg = "unexpectedly large file size."; + } + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* 14) Delete the file */ + + if (pass) { + + /* wait for everyone to close the file */ + MPI_Barrier(MPI_COMM_WORLD); + + if ((mpi_rank == 0) && (HDremove(filename) < 0)) { + + pass = FALSE; + failure_mssg = "HDremove() failed.\n"; + } + } + + if ((mpi_rank == 0) && (show_progress)) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + /* report results */ + if (mpi_rank == 0) { + + if (pass) { + + PASSED(); + } + else { + + H5_FAILED(); + + HDfprintf(stdout, "%s: failure_mssg = \"%s\"\n", fcn_name, failure_mssg); + } + } + + return !pass; + +} /* smoke_check_1() */ + +/*------------------------------------------------------------------------- + * Function: main + * + * Purpose: Run parallel tests on the cache image feature. + * + * At present, cache image is disabled in parallel, and + * thus these tests are restricted to verifying that a + * file with a cache image can be opened in the parallel + * case, and verifying that instructions to create a + * cache image are ignored in the parallel case. + * + * WARNING: This test uses fork() and execve(), and + * therefore will not run on Windows. + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: John Mainzer + * 1/25/17 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +int +main(int argc, char **argv) +{ + unsigned nerrs = 0; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Info info = MPI_INFO_NULL; + int mpi_size; + int mpi_rank; + + MPI_Init(&argc, &argv); + MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); + MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); + + /* Attempt to turn off atexit post processing so that in case errors + * happen during the test and the process is aborted, it will not get + * hang in the atexit post processing in which it may try to make MPI + * calls. By then, MPI calls may not work. + */ + if (H5dont_atexit() < 0) + HDprintf("%d:Failed to turn off atexit processing. Continue.\n", mpi_rank); + + H5open(); + + if (mpi_rank == 0) { + HDprintf("===================================\n"); + HDprintf("Parallel metadata cache image tests\n"); + HDprintf(" mpi_size = %d\n", mpi_size); + HDprintf("===================================\n"); + } + + if (mpi_size < 2) { + if (mpi_rank == 0) + HDprintf(" Need at least 2 processes. Exiting.\n"); + goto finish; + } + + if (mpi_rank == 0) { /* create test files */ + int i; + + HDfprintf(stdout, "Constructing test files: \n"); + HDfflush(stdout); + + i = 0; + while ((FILENAMES[i] != NULL) && (i < TEST_FILES_TO_CONSTRUCT)) { + HDfprintf(stdout, " writing %s ... ", FILENAMES[i]); + HDfflush(stdout); + construct_test_file(i); + + if (pass) { + HDprintf("done.\n"); + HDfflush(stdout); + } + else { + HDprintf("failed.\n"); + HDexit(EXIT_FAILURE); + } + i++; + } + HDfprintf(stdout, "Test file construction complete.\n"); + } + + /* can't start test until test files exist */ + MPI_Barrier(MPI_COMM_WORLD); + + nerrs += verify_cache_image_RO(0, H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY, mpi_rank); + nerrs += verify_cache_image_RO(1, H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED, mpi_rank); + nerrs += verify_cache_image_RW(0, H5AC_METADATA_WRITE_STRATEGY__PROCESS_0_ONLY, mpi_rank); + nerrs += verify_cache_image_RW(1, H5AC_METADATA_WRITE_STRATEGY__DISTRIBUTED, mpi_rank); + nerrs += smoke_check_1(comm, info, mpi_rank, mpi_size); + +finish: + + /* make sure all processes are finished before final report, cleanup + * and exit. + */ + MPI_Barrier(MPI_COMM_WORLD); + + if (mpi_rank == 0) { /* only process 0 reports */ + HDprintf("===================================\n"); + if (nerrs > 0) + HDprintf("***metadata cache image tests detected %d failures***\n", nerrs); + else + HDprintf("metadata cache image tests finished with no failures\n"); + HDprintf("===================================\n"); + } + + /* close HDF5 library */ + H5close(); + + /* MPI_Finalize must be called AFTER H5close which may use MPI calls */ + MPI_Finalize(); + + /* cannot just return (nerrs) because exit code is limited to 1byte */ + return (nerrs > 0); + +} /* main() */ |
