diff options
author | mainzer <mainzer#hdfgroup.org> | 2017-03-16 17:42:10 (GMT) |
---|---|---|
committer | mainzer <mainzer#hdfgroup.org> | 2017-03-16 17:42:10 (GMT) |
commit | 11ce930ae94bd21b1a8d4afdde7b982439f2800b (patch) | |
tree | 581a2a020c12b4714b6d00aee2b1ef1f12c3ba61 /testpar | |
parent | cee9624b0febcb60a7b2699262104e9eaf20313d (diff) | |
download | hdf5-11ce930ae94bd21b1a8d4afdde7b982439f2800b.zip hdf5-11ce930ae94bd21b1a8d4afdde7b982439f2800b.tar.gz hdf5-11ce930ae94bd21b1a8d4afdde7b982439f2800b.tar.bz2 |
Checkin of additions to cache image parallel test code and
associated bug fixes.
Also, modifications to H5PB_dest() to flush the page buffer before
destroying the page buffer. This is necessary, as when persistant
free space managers are enabled, the page buffer will typically contain
dirty FSM data at page buffer destroy time.
Tested serial/debug, serial/production, serial/check-vfd/debug,
parallel/debug, parallel/production on Jelly.
Diffstat (limited to 'testpar')
-rw-r--r-- | testpar/t_cache_image.c | 2025 |
1 files changed, 1999 insertions, 26 deletions
diff --git a/testpar/t_cache_image.c b/testpar/t_cache_image.c index 7283fa7..9e9efea 100644 --- a/testpar/t_cache_image.c +++ b/testpar/t_cache_image.c @@ -25,10 +25,17 @@ #include "cache_common.h" #include "genall5.h" +#if 1 +#define TEST_FILES_TO_CONSTRUCT 2 +#else +#define TEST_FILES_TO_CONSTRUCT 1 +#endif #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: */ @@ -36,6 +43,7 @@ const char *FILENAMES[] = { "t_cache_image_00", "t_cache_image_01", + "t_cache_image_02", NULL }; @@ -45,28 +53,48 @@ static void create_data_sets(hid_t file_id, int min_dset, int max_dset); static void delete_data_sets(hid_t file_id, int min_dset, int max_dset); 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 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 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 hbool_t parse_flags(int argc, char * argv[], hbool_t * setup_ptr, - hbool_t display); + hbool_t * ici_ptr, int * file_idx_ptr, int * mpi_size_ptr, hbool_t display); static void usage(void); 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 ****************************/ @@ -187,6 +215,7 @@ construct_test_file(int test_file_index) /* 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, @@ -258,6 +287,7 @@ construct_test_file(int test_file_index) /* 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, @@ -331,6 +361,7 @@ construct_test_file(int test_file_index) /* 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, @@ -863,6 +894,8 @@ delete_data_sets(hid_t file_id, int min_dset, int max_dset) * * JRM -- 2/1/17 * + * Modified function to handle + * *------------------------------------------------------------------------- */ @@ -872,6 +905,7 @@ open_hdf5_file(const hbool_t create_file, 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, @@ -901,6 +935,8 @@ open_hdf5_file(const hbool_t create_file, 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 @@ -910,6 +946,7 @@ open_hdf5_file(const hbool_t create_file, 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 ) && @@ -1029,9 +1066,32 @@ open_hdf5_file(const hbool_t create_file, } } + 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 */ @@ -1162,6 +1222,31 @@ open_hdf5_file(const hbool_t create_file, 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 unexepectedly enabled."; + + } else if ( ( file_ptr->shared->page_buf != NULL ) && + ( ( enable_page_buffer ) || ( l_facc_type != FACC_MPIO ) ) ) { + + pass = FALSE; + failure_mssg = "page buffer unexepectedly 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 @@ -1181,6 +1266,7 @@ open_hdf5_file(const hbool_t create_file, if ( show_progress ) HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + if ( pass ) { if ( set_mdci_fapl ) { @@ -1308,6 +1394,1244 @@ open_hdf5_file(const hbool_t create_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)); + + sprintf(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 partioned 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 ) { + + fprintf(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)); + + sprintf(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 ) +{ + hbool_t show_progress = FALSE; + + if ( pass ) { + + if ( mpi_rank == 0 ) { /* insert cache image in supplied test file */ + + char file_name_idx_str[32]; + char mpi_size_str[32]; + int child_status; + pid_t child_pid; + + sprintf(file_name_idx_str, "%d", file_name_idx); + sprintf(mpi_size_str, "%d", mpi_size); + + child_pid = fork(); + + if ( child_pid == 0 ) { /* this is the child process */ + + /* fun and games to shutup the compiler */ + char param0[32] = "t_cache_image"; + char param1[32] = "ici"; + char * child_argv[] = {param0, + param1, + file_name_idx_str, + mpi_size_str, + NULL}; + + /* we may need to play with the path here */ + if ( execv("t_cache_image", child_argv) == -1 ) { + + HDfprintf(stdout, + "execl() of ici process failed. errno = %d(%s)\n", + errno, strerror(errno)); + exit(1); + } + + } else if ( child_pid != -1 ) { + /* this is the parent process -- wait until child is done */ + if ( -1 == waitpid(child_pid, &child_status, WUNTRACED)) { + + HDfprintf(stdout, "can't wait on ici process.\n"); + pass = FALSE; + + } else if ( ! WIFEXITED(child_status) ) { + + HDfprintf(stdout, "ici process hasn't exitied.\n"); + pass = FALSE; + + } else if ( WEXITSTATUS(child_status) != 0 ) { + + HDfprintf(stdout, "ici process reports failure.\n"); + pass = FALSE; + + } else if ( show_progress ) { + + HDfprintf(stdout, "cache image insertion complete.\n"); + } + } else { /* fork failed */ + + HDfprintf(stdout, + "can't create process to insert cache image.\n"); + pass = FALSE; + } + } + } + + 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)); + + sprintf(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 ) { + + fprintf(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; + + sprintf(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 ) { + + fprintf(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: parse_flags * * Purpose: Parse the flags passed to this program, and load the @@ -1321,50 +2645,80 @@ open_hdf5_file(const hbool_t create_file, * *------------------------------------------------------------------------- */ -hbool_t -parse_flags(int argc, char * argv[], hbool_t * setup_ptr, hbool_t display) +static hbool_t +parse_flags(int argc, char * argv[], hbool_t * setup_ptr, + hbool_t * ici_ptr, int * file_idx_ptr, int * mpi_size_ptr, hbool_t display) { const char * fcn_name = "parse_flags()"; - const char * (ops[]) = {"setup"}; + const char * (ops[]) = {"setup", "ici"}; int success = TRUE; + HDassert(setup_ptr); + HDassert(*setup_ptr == FALSE); + HDassert(ici_ptr); + HDassert(*ici_ptr == FALSE); + HDassert(file_idx_ptr); + HDassert(mpi_size_ptr); + if ( setup_ptr == NULL ) { success = FALSE; HDfprintf(stdout, "%s: bad arg(s) on entry.\n", fcn_name); } + if ( ( success ) && - ( ( argc < 1 ) || ( argc > 2 ) ) ) { + ( ( argc != 1 ) && ( argc != 2 ) && ( argc != 4 ) ) ) { success = FALSE; usage(); } - if ( success ) { - if ( argc == 2 ) { + if ( ( success ) && ( argc >= 2 ) ) { - if ( strcmp(argv[1], ops[0]) == 0 ) { + if ( strcmp(argv[1], ops[0]) == 0 ) { - *setup_ptr = TRUE; + if ( argc != 2 ) { + + success = FALSE; + usage(); } else { + *setup_ptr = TRUE; + + } + } else if ( strcmp(argv[1], ops[1]) == 0 ) { + + if ( argc != 4 ) { + success = FALSE; usage(); - } - } else { - *setup_ptr = FALSE; + } else { + + *ici_ptr = TRUE; + *file_idx_ptr = atoi(argv[2]); + *mpi_size_ptr = atoi(argv[3]); + + } } } if ( ( success ) && ( display ) ) { if ( *setup_ptr ) + HDfprintf(stdout, "t_cache_image setup\n"); + + else if ( *ici_ptr ) + + HDfprintf(stdout, "t_cache_image ici %d %d\n", + *file_idx_ptr, *mpi_size_ptr); + else + HDfprintf(stdout, "t_cache_image\n"); } @@ -1694,6 +3048,266 @@ verify_data_sets(hid_t file_id, int min_dset, int max_dset) /****************************************************************************/ /*------------------------------------------------------------------------- + * 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. + * + * 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 */ 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); + + /* Verify that only process 0 reads the cache image. */ + + 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. + */ + + if ( show_progress ) + HDfprintf(stdout, "%s: cp = %d, pass = %d.\n", fcn_name, cp++, pass); + + + /* 2) 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 not loaded(1)."; + } + } +#endif /* H5C_COLLECT_CACHE_STATS */ + + + /* 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", failure_mssg); + } + } + + + return !pass; + +} /* verify_cache_image_RO() */ + + +/*------------------------------------------------------------------------- * Function: verify_cache_image_RW() * * Purpose: Verify that a HDF5 file containing a cache image is @@ -1747,7 +3361,6 @@ verify_cache_image_RW(int file_name_id, int md_write_strat, int mpi_rank) H5F_t *file_ptr = NULL; H5C_t *cache_ptr = NULL; int cp = 0; - int i; pass = TRUE; @@ -1808,6 +3421,7 @@ verify_cache_image_RW(int file_name_id, int md_write_strat, int mpi_rank) /* 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, @@ -1880,6 +3494,7 @@ verify_cache_image_RW(int file_name_id, int md_write_strat, int mpi_rank) /* 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, @@ -1969,6 +3584,338 @@ verify_cache_image_RW(int file_name_id, int md_write_strat, int mpi_rank) } /* 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 */ + + i = num_dsets - 1; + while ( ( pass ) && ( i >= 0 ) ) { + + par_verify_dataset(i, file_id, mpi_rank); + i--; + } + + + /* 8) Close the file */ + + if ( pass ) { + + if ( H5Fclose(file_id) < 0 ) { + + pass = FALSE; + failure_mssg = "H5Fclose() failed."; + + } + } + + + /* 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 */ + + 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); + + + /* 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 persistant free + * space managers, size size is about 30 MB, so this + * is sufficient to verify that the persistant 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 * @@ -1999,22 +3946,26 @@ int main(int argc, char **argv) { hbool_t setup = FALSE; + hbool_t ici = FALSE; unsigned nerrs = 0; + MPI_Comm comm = MPI_COMM_WORLD; + MPI_Info info = MPI_INFO_NULL; + int file_idx; int i; int mpi_size; int mpi_rank; - if ( ! parse_flags(argc, argv, &setup, FALSE) ) + if ( ! parse_flags(argc, argv, &setup, &ici, &file_idx, &mpi_size, FALSE) ) exit(1); /* exit now if unable to parse flags */ - if ( setup ) { /* construct test file and exit */ + if ( setup ) { /* construct test files and exit */ H5open(); HDfprintf(stdout, "Constructing test files: \n"); HDfflush(stdout); i = 0; - while ( FILENAMES[i] != NULL ) { + while ( ( FILENAMES[i] != NULL ) && ( i < TEST_FILES_TO_CONSTRUCT ) ) { HDfprintf(stdout, " writing %s ... ", FILENAMES[i]); HDfflush(stdout); @@ -2032,11 +3983,26 @@ main(int argc, char **argv) } i++; } + HDfprintf(stdout, "Test file construction complete.\n"); exit(0); + + } else if ( ici ) { + + if ( serial_insert_cache_image(file_idx, mpi_size) ) { + + exit(0); + + } else { + + HDfprintf(stderr, "\n\nCache image insertion failed.\n"); + HDfprintf(stderr, " failure mssg = \"%s\"\n", failure_mssg); + exit(1); + } } HDassert(!setup); + HDassert(!ici); MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); @@ -2118,14 +4084,21 @@ main(int argc, char **argv) } } - /* can't start test until test file exists */ + /* 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); +#if 1 + 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); +#endif finish: /* make sure all processes are finished before final report, cleanup |