/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Flexible Parallel HDF5 test: Create a file using the FPHDF5 file * driver. Populate it with groups and datasets to make sure that FPHDF5 * can handle it. * * Author: * Bill Wendling (wendling@ncsa.uiuc.edu) * 20. February 2003 */ #include #include #include #include #include #include "testphdf5.h" #ifdef H5_HAVE_FPHDF5 /*===----------------------------------------------------------------------=== * Local Functions *===----------------------------------------------------------------------=== */ static hid_t create_file(const char *filename); static hid_t create_group(hid_t loc, const char *grp_name, size_t size_hint); static hid_t create_dset(hid_t loc, const char *dset_name); static void access_dset(hid_t loc, const char *dset_name); static void slab_set(hsize_t start[], hsize_t count[], hsize_t stride[], hsize_t block[]); static void fill_data(void); static void write_data(hid_t loc, const char *dset_name, hsize_t start[], hsize_t count[], hsize_t stride[], hsize_t block[]); static void verify_complete_dataset(hid_t loc, const char *dset_name); static void verify_partial_dataset(hid_t loc, const char *dset_name, hsize_t start[], hsize_t count[], hsize_t stride[], hsize_t block[], int * buf, hsize_t buf_len); static void test_group_creation(hid_t loc); static void test_dataset_creation(hid_t loc); static void test_dataset_access(hid_t loc); static void test_dataset_write(hid_t loc); static void usage(const char *prog); /*===----------------------------------------------------------------------=== * Filenames *===----------------------------------------------------------------------=== * The names of the test files for */ static const char *FILENAME[2] = { /* List of files we want to create */ "FPHDF5Test", NULL }; static char filenames[2][PATH_MAX]; /* "Fixed" filenames */ /*===----------------------------------------------------------------------=== * Global Variables *===----------------------------------------------------------------------=== */ #ifdef RANK #undef RANK #endif /* RANK */ #ifdef DIM0 #undef DIM0 #endif /* !DIM0 */ #ifdef DIM1 #undef DIM1 #endif /* !DIM1 */ enum { SAP_RANK = 1, /* The rank acting as the SAP */ RANK = 2, DIM0 = 6, DIM1 = 12 }; int nerrors = 0; /* Errors count */ int verbose = 0; /* Verbose, default is no */ static MPI_Comm SAP_Comm = MPI_COMM_NULL; /* COMM for FPHDF5 */ static MPI_Comm SAP_Barrier_Comm = MPI_COMM_NULL; /* COMM used in barriers*/ static hid_t fapl = -1; /* FPHDF5 file access property list */ static int mpi_rank; /* Rank of this process */ static int mpi_size; /* Size of the COMM passed to FPHDF5 */ static int *orig_data = NULL; /* Data that's written to datasets */ static int *local_orig_data = NULL; /* data that's written to datasets */ /* by this process. */ /* dimensions of file data space -- initialized in slab_set() */ static hsize_t dims[RANK] = {0, 0}; /* Hyperslab settings */ static hsize_t start[RANK]; static hsize_t count[RANK]; static hsize_t stride[RANK]; static hsize_t block[RANK]; static const char *progname = "t_fphdf5"; /* Dataset Name Template */ static const char *dset_tmpl = "Dataset %d"; static char dset_name[128]; /* Group Name Template */ static const char *grp_tmpl = "Process %d's Datasets"; static char grp_name[128]; #if 0 /* A useful debugging function, but no need to compile it unless * we are going to use it. JRM - 4/13/4 */ /*------------------------------------------------------------------------- * Function: check_globals * Purpose: Debugging Function. Check the current values of some * globals, and generate a message when they change. * Return: void * Programmer: John Mainzer - 3/3/04 * Modifications: *------------------------------------------------------------------------- */ static void check_globals(char * location_name) { static hsize_t local_dims[RANK] = {0,0}; static hsize_t local_start[RANK] = {0,0}; static hsize_t local_count[RANK] = {0,0}; static hsize_t local_stride[RANK] = {0,0}; static hsize_t local_block[RANK] = {0,0}; if ( ( dims[0] != local_dims[0] ) || ( dims[1] != local_dims[1] ) || ( start[0] != local_start[0] ) || ( start[1] != local_start[1] ) || ( count[0] != local_count[0] ) || ( count[1] != local_count[1] ) || ( stride[0] != local_stride[0] ) || ( stride[1] != local_stride[1] ) || ( block[0] != local_block[0] ) || ( block[1] != local_block[1] ) ) { printf("%d: globals have changed at %s.\n old: dims=[%d,%d], start=[%d,%d], count=[%d, %d], stride=[%d,%d], block=[%d,%d]\n new: dims=[%d,%d], start=[%d,%d], count=[%d, %d], stride=[%d,%d], block=[%d,%d]\n", mpi_rank, location_name, (int)(local_dims[0]), (int)(local_dims[1]), (int)(local_start[0]), (int)(local_start[1]), (int)(local_count[0]), (int)(local_count[1]), (int)(local_stride[0]), (int)(local_stride[1]), (int)(local_block[0]), (int)(local_block[1]), (int)(dims[0]), (int)(dims[1]), (int)(start[0]), (int)(start[1]), (int)(count[0]), (int)(count[1]), (int)(stride[0]), (int)(stride[1]), (int)(block[0]), (int)(block[1])); local_dims[0] = dims[0]; local_dims[1] = dims[1]; local_start[0] = start[0]; local_start[1] = start[1]; local_count[0] = count[0]; local_count[1] = count[1]; local_stride[0] = stride[0]; local_stride[1] = stride[1]; local_block[0] = block[0]; local_block[1] = block[1]; } return; } /* check_globals() */ #endif #if 0 /* Another useful debugging function, again no need to compile it unless * we are going to use it. JRM - 4/13/04 */ /*------------------------------------------------------------------------- * Function: print_globals * Purpose: Debugging Function. Display the current values of some * globals. * Return: void * Programmer: John Mainzer - 3/9/04 * Modifications: *------------------------------------------------------------------------- */ static void print_globals(void) { printf("%d: dims=[%d,%d], start=[%d,%d], count=[%d, %d], stride=[%d,%d], block=[%d,%d]\n", (int)mpi_rank, (int)(dims[0]), (int)(dims[1]), (int)(start[0]), (int)(start[1]), (int)(count[0]), (int)(count[1]), (int)(stride[0]), (int)(stride[1]), (int)(block[0]), (int)(block[1])); return; } /* print_globals() */ #endif /*------------------------------------------------------------------------- * Function: create_file * Purpose: Create a new file with the given filename. * Return: Success: Valid file ID * Failure: -1 * Programmer: Bill Wendling * 29. October 2003 * Modifications: *------------------------------------------------------------------------- */ static hid_t create_file(const char *filename) { hid_t fid = -1; fid = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); VRFY((fid >= 0), "H5Fcreate"); printf("%d: Created file %s\n", mpi_rank, filename); return fid; } /*------------------------------------------------------------------------- * Function: create_group * Purpose: Helper function that creates a group at the given * location with the given name and size_hint. * Return: Success: The handle to the new group * Failure: Aborts * Programmer: Bill Wendling * 29. October 2003 * Modifications: *------------------------------------------------------------------------- */ static hid_t create_group(hid_t loc, const char *group_name, size_t size_hint) { hid_t group; VRFY(((group = H5Gcreate(loc, group_name, size_hint)) >= 0), "H5Gcreate"); printf("%d: Created group \"%s\"\n", mpi_rank, group_name); return group; } /*------------------------------------------------------------------------- * Function: create_dset * Purpose: Helper function that creates a dataset at the given * location with the given name and dimensions * Return: Success: The handle to the new dataset * Failure: Aborts * Programmer: Bill Wendling * 29. October 2003 * Modifications: * Altered function to use the global dims array, instead * of a locally declared and initialized version. * JRM - 3/3/04 *------------------------------------------------------------------------- */ static hid_t create_dset(hid_t loc, const char *dataset_name) { hid_t dset, sid; VRFY((dims[0] != 0), "dims array initialized."); VRFY(((sid = H5Screate_simple(RANK, dims, NULL)) >= 0), "H5Screate_simple"); printf("%d: Created simple dataspace\n", mpi_rank); dset = H5Dcreate(loc, dataset_name, H5T_NATIVE_INT, sid, H5P_DEFAULT); VRFY((dset >= 0), "H5Dcreate"); printf("%d: Created dataset \"%s\"\n", mpi_rank, dataset_name); VRFY((H5Sclose(sid) >= 0), "H5Sclose"); return dset; } /*------------------------------------------------------------------------- * Function: access_dset * Purpose: Quickly check to see if we can access this dataset. * Return: Nothing, but aborts if an error occurs. * Programmer: Bill Wendling * 03. November 2003 * Modifications: *------------------------------------------------------------------------- */ static void access_dset(hid_t loc, const char *dataset_name) { hid_t dataset; VRFY(((dataset = H5Dopen(loc, dataset_name)) >= 0), "H5Dopen"); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); } /*------------------------------------------------------------------------- * Function: slab_set * Purpose: Setup the dimensions of the hyperslab. * Return: Nothing * Programmer: Bill Wendling * 05. November 2003 * Modifications: * Modified function to initialize the dims array. Also * altered the initialization of block[0] so that the * the test program will run with mpi_size > 6. * JRM - 3/3/04 *------------------------------------------------------------------------- */ static void slab_set(hsize_t my_start[], hsize_t my_count[], hsize_t my_stride[], hsize_t my_block[]) { /* initialize dims according to the number of processes: */ dims[0] = DIM0 * mpi_size; dims[1] = DIM1; /* Each process takes a slab of rows. */ my_block[0] = DIM0; my_block[1] = DIM1; my_stride[0] = my_block[0]; my_stride[1] = my_block[1]; my_count[0] = 1; my_count[1] = 1; my_start[0] = mpi_rank * my_block[0]; my_start[1] = 0; } /*------------------------------------------------------------------------- * Function: fill_data * Purpose: Fill data buffer with some data. * Return: Nothing * Programmer: Bill Wendling * 13. November 2003 * Modifications: * Complete re-write of function. The orig_data array is * now allocated (in main) with size equal the size of the * array on file, and is loaded with the data we expect to * find there. * * The new local_orig_data array is allocated to match the * size of this processes contribution to the on file data * set, and is loaded with this processes data. * * Note how mpi_rank, row, and column are encoded in each * cell of the arrays. * JRM - 3/8/04 *------------------------------------------------------------------------- */ static void fill_data(void) { int col; int row; int offset = 0; int local_offset = 0; int proc_num = -1; for ( proc_num = 0; proc_num < mpi_size; proc_num++ ) { for ( row = 0 ; row < DIM0; row++ ) { if ( proc_num == SAP_RANK ) { for ( col = 0; col < DIM1; col++ ) { /* The SAP doesn't write to file, so its section */ /* of the matrix will be filled with zeros. */ orig_data[offset++] = 0; } } else if ( proc_num == mpi_rank ) { for ( col = 0; col < DIM1; col++ ) { local_orig_data[local_offset++] = orig_data[offset++] = (proc_num * 1000) + (row * 100) + col; } } else { for ( col = 0; col < DIM1; col++ ) { orig_data[offset++] = (proc_num * 1000) + (row * 100) + col; } } } } VRFY((offset == (mpi_size * DIM0 * DIM1)), "offset OK"); VRFY((local_offset == (DIM0 * DIM1)), "local_offset OK"); return; } /* fill_data() */ /*------------------------------------------------------------------------- * Function: write_data * Purpose: Writes data to a dataset. * Return: Nothing, but aborts if an error occurs. * Programmer: Bill Wendling * 29. October 2003 * Modifications: * Modified to use local_orig_data, instead of initializing * a portion of orig_data. Also removed some orphan code. * JRM - 3/8/04 *------------------------------------------------------------------------- */ static void write_data(hid_t loc, const char *dataset_name, hsize_t my_start[], hsize_t my_count[], hsize_t my_stride[], hsize_t my_block[]) { herr_t hrc; hid_t file_dataspace, mem_dataspace; hid_t dataset; /* See if dataset is there */ VRFY(((dataset = H5Dopen(loc, dataset_name)) >= 0), "H5Dopen"); file_dataspace = H5Dget_space(dataset); VRFY((file_dataspace >= 0), "H5Dget_space"); hrc = H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, my_start, my_stride, my_count, my_block); #if 0 /* some debugging code we may want to keep for a time. JRM - 4/13/04 */ if ( hrc < 0 ) { /* dump the parameters */ printf("%d: start=[%d,%d], count=[%d, %d], stride=[%d,%d], block=[%d,%d]\n", mpi_rank, (int)(my_start[0]), (int)(my_start[1]), (int)(my_count[0]), (int)(my_count[1]), (int)(my_stride[0]), (int)(my_stride[1]), (int)(my_block[0]), (int)(my_block[1])); } #endif VRFY((hrc >= 0), "H5Sselect_hyperslab in write_data"); /* create a memory dataspace independently */ mem_dataspace = H5Screate_simple(RANK, my_block, NULL); VRFY((mem_dataspace >= 0), "H5Screate_simple"); hrc = H5Dwrite(dataset, H5T_NATIVE_INT, mem_dataspace, file_dataspace, H5P_DEFAULT, local_orig_data); VRFY((hrc >= 0), "H5Dwrite"); VRFY((H5Sclose(mem_dataspace) >= 0), "H5Sclose"); VRFY((H5Sclose(file_dataspace) >= 0), "H5Sclose"); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); } /* write_data() */ /*------------------------------------------------------------------------- * Function: verify_complete_dataset * Purpose: Verify that all the data in the dataset is correct -- * including that written by other processes. * Return: Nothing * Programmer: John Mainzer * 3/8/04 * Modifications: * None. *------------------------------------------------------------------------- */ static void verify_complete_dataset(hid_t loc, const char *dataset_name) { hid_t dataset; int *data_array = NULL; size_t data_array_len = 0; unsigned col; unsigned row; int offset = 0; int vrfyerrs = 0; /* Open the dataset */ VRFY(((dataset = H5Dopen(loc, dataset_name)) >= 0), "H5Dopen"); /* allocate a buffer to receive the contents of the file dataset */ VRFY((dims[0] != 0), "dims array initialized."); data_array_len = ((size_t)dims[0]) * ((size_t)dims[1]) * sizeof(int); data_array = (int *)malloc(data_array_len); VRFY((data_array != NULL), "data_array allocated."); /* Read the dataset */ VRFY((H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data_array) >= 0), "H5Dread"); /* Verify the contents of the dataset */ for ( row = 0; row < dims[0]; row++ ) { for ( col = 0; col < DIM1; col++ ) { if ( data_array[offset] != orig_data[offset] ) { if ( vrfyerrs++ < MAX_ERR_REPORT ) { fprintf(stdout, "%d: Dataset Verify failed at " "row %u, col %u: expect %d, got %d\n", mpi_rank, row, col, orig_data[offset], data_array[offset]); } } offset++; } } VRFY((offset == (mpi_size * DIM0 * DIM1)), "offset OK"); if (vrfyerrs) { fprintf(stdout, "%d: %d errors found in verify_complete_dataset\n", mpi_rank, vrfyerrs); ++nerrors; } VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); if ( data_array != NULL ) { free(data_array); } return; } /* verify_complete_dataset() */ /*------------------------------------------------------------------------- * Function: verify_partial_dataset * Purpose: Verify that the data in the specified section of the * dataset matches the contents of the provided buffer. * Return: Nothing * Programmer: John Mainzer * 3/8/04 * Modifications: * None. *------------------------------------------------------------------------- */ static void verify_partial_dataset(hid_t loc, const char *dataset_name, hsize_t my_start[], hsize_t my_count[], hsize_t my_stride[], hsize_t my_block[], int * buf, hsize_t buf_len) { hid_t dataset, file_dataspace, mem_dataspace; int *data_array; unsigned col; unsigned row; hsize_t offset = 0; int vrfyerrs = 0; /* Open the dataset */ VRFY(((dataset = H5Dopen(loc, dataset_name)) >= 0), "H5Dopen"); /* Create a file dataspace */ file_dataspace = H5Dget_space(dataset); VRFY((file_dataspace >= 0), "H5Dget_space"); VRFY((H5Sselect_hyperslab(file_dataspace, H5S_SELECT_SET, my_start, my_stride, my_count, my_block) >= 0), "H5Sselect_hyperslab in verify_partial_dataset"); /* Create a memory dataspace */ mem_dataspace = H5Screate_simple(RANK, my_block, NULL); VRFY((mem_dataspace >= 0), "H5Screate_simple"); VRFY(((block[0] * block[1]) == buf_len), "buf_len matches."); /* Read the dataset */ VRFY((dims[0] != 0), "dims array initialized."); data_array = (int *)malloc(((size_t)block[0]) * ((size_t)block[1]) * sizeof(int)); VRFY((H5Dread(dataset, H5T_NATIVE_INT, mem_dataspace, file_dataspace, H5P_DEFAULT, data_array) >= 0), "H5Dread"); /* Verify the contents of the dataset */ for ( row = 0; row < block[0]; row++ ) { for ( col = 0; col < block[1]; col++ ) { if ( data_array[offset] != buf[offset] ) { if ( vrfyerrs++ < MAX_ERR_REPORT ) { fprintf(stdout, "%d: Dataset Verify failed at " "row %u, col %u: expected %d, got %d\n", mpi_rank, row, col, buf[offset], data_array[offset]); } } offset++; } } VRFY((offset == buf_len), "offset OK"); if (vrfyerrs) { fprintf(stdout, "%d: %d errors found in verify_partial_dataset\n", mpi_rank, vrfyerrs); ++nerrors; } VRFY((H5Sclose(mem_dataspace) >= 0), "H5Sclose"); VRFY((H5Sclose(file_dataspace) >= 0), "H5Sclose"); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); if ( data_array != NULL ) { free(data_array); } return; } /* verify_partial_dataset() */ /*------------------------------------------------------------------------- * Function: test_group_creation * Purpose: Test creation of multiple groups in the file. * Return: Nothing * Programmer: Bill Wendling * 11. November 2003 * Modifications: *------------------------------------------------------------------------- */ static void test_group_creation(hid_t loc) { if (mpi_rank == 0) { int i; for (i = 0; i < mpi_size; ++i) if (i != SAP_RANK) { hid_t group; sprintf(grp_name, grp_tmpl, i); group = create_group(loc, grp_name, 4); VRFY((H5Gclose(group) >= 0), "H5Gclose"); } } SYNC(SAP_Barrier_Comm); } /* test_group_creation() */ /*------------------------------------------------------------------------- * Function: test_dataset_creation * Purpose: Test simultaneous creation of multiple datasets in a * non-root group. * Return: Nothing * Programmer: Bill Wendling * 11. November 2003 * Modifications: *------------------------------------------------------------------------- */ static void test_dataset_creation(hid_t loc) { hid_t dataset, group; sprintf(grp_name, grp_tmpl, mpi_rank); group = H5Gopen(loc, grp_name); VRFY((group >= 0), "H5Gopen"); sprintf(dset_name, dset_tmpl, 0); dataset = create_dset(group, dset_name); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); /* Create 3x5x(mpi_size) dataset */ sprintf(dset_name, dset_tmpl, 1); dataset = create_dset(group, dset_name); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); /* Create 2x4x(mpi_size) dataset */ sprintf(dset_name, dset_tmpl, 2); dataset = create_dset(group, dset_name); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); /* Create 5x7x(mpi_size) dataset */ sprintf(dset_name, dset_tmpl, 3); dataset = create_dset(group, dset_name); VRFY((H5Dclose(dataset) >= 0), "H5Dclose"); VRFY((H5Gclose(group) >= 0), "H5Gclose"); SYNC(SAP_Barrier_Comm); } /* test_dataset_creation() */ /*------------------------------------------------------------------------- * Function: test_dataset_access * Purpose: Test that we can access the datasets in the file from all * processes. * Return: Nothing * Programmer: Bill Wendling * 11. November 2003 * Modifications: *------------------------------------------------------------------------- */ static void test_dataset_access(hid_t loc) { int i; for (i = 0; i < mpi_size; ++i) if (i != SAP_RANK) { hid_t group; sprintf(grp_name, grp_tmpl, i); VRFY(((group = H5Gopen(loc, grp_name)) >= 0), "H5Gopen"); sprintf(dset_name, dset_tmpl, 0); printf("%d: Accessing dataset \"%s/%s\"\n", mpi_rank, grp_name, dset_name); access_dset(group, dset_name); sprintf(dset_name, dset_tmpl, 1); printf("%d: Accessing dataset \"%s/%s\"\n", mpi_rank, grp_name, dset_name); access_dset(group, dset_name); sprintf(dset_name, dset_tmpl, 2); printf("%d: Accessing dataset \"%s/%s\"\n", mpi_rank, grp_name, dset_name); access_dset(group, dset_name); sprintf(dset_name, dset_tmpl, 3); printf("%d: Accessing dataset \"%s/%s\"\n", mpi_rank, grp_name, dset_name); access_dset(group, dset_name); VRFY((H5Gclose(group) >= 0), "H5Gclose"); } SYNC(SAP_Barrier_Comm); } /* test_dataset_access() */ /*------------------------------------------------------------------------- * Function: test_dataset_write * Purpose: Test that we can write to the datasets in the file from * all processes simultaneously. * Return: Nothing * Programmer: Bill Wendling * 11. November 2003 * Modifications: * Replaced calls to verify_dataset() with calls to * verify_partial_dataset(). In the absence of a barrier, * we don't know that the other processes have done their * writes to the datasets as well. Thus we only check the * data we have written for now. * * Also re-formatted code in passing. JRM - 3/8/04 *------------------------------------------------------------------------- */ static void test_dataset_write(hid_t loc) { int i; /*===-------------------------------------------------------------------=== * All processes write to each dataset. *===-------------------------------------------------------------------=== */ for (i = 0; i < mpi_size; ++i) { if (i != SAP_RANK) { hid_t group; sprintf(grp_name, grp_tmpl, i); VRFY(((group = H5Gopen(loc, grp_name)) >= 0), "H5Gopen"); /* Write to this dataset */ sprintf(dset_name, dset_tmpl, 0); printf("%d: Writing to \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); write_data(group, dset_name, start, count, stride, block); printf("%d: Verifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_partial_dataset(group, dset_name, start, count, stride, block, local_orig_data, (block[0] * block[1])); sprintf(dset_name, dset_tmpl, 1); printf("%d: Writing to \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); write_data(group, dset_name, start, count, stride, block); printf("%d: Verifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_partial_dataset(group, dset_name, start, count, stride, block, local_orig_data, (block[0] * block[1])); sprintf(dset_name, dset_tmpl, 2); printf("%d: Writing to \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); write_data(group, dset_name, start, count, stride, block); printf("%d: Verifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_partial_dataset(group, dset_name, start, count, stride, block, local_orig_data, (block[0] * block[1])); sprintf(dset_name, dset_tmpl, 3); printf("%d: Writing to \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); write_data(group, dset_name, start, count, stride, block); printf("%d: Verifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_partial_dataset(group, dset_name, start, count, stride, block, local_orig_data, (block[0] * block[1])); /* Close the group */ VRFY((H5Gclose(group) >= 0), "H5Gclose"); } } } /* test_dataset_write() */ /*------------------------------------------------------------------------- * Function: usage * Purpose: Print a usage message. * Return: Nothing * Programmer: Bill Wendling * 11. November 2003 * Modifications: *------------------------------------------------------------------------- */ static void usage(const char *prog) { if (mpi_rank == 0) { fprintf(stderr, "usage: %s [OPTIONS]\n", prog); fprintf(stderr, " OPTIONS\n"); fprintf(stderr, " -h, --help Print a usage message and exit\n"); fprintf(stderr, " -v, --verbose Verbose output [default: no]\n"); fprintf(stderr, "\n"); fflush(stdout); } } /*------------------------------------------------------------------------- * Function: main * Purpose: Parse the command line variables and run the test * program. * Return: Success: 0 * Failure: >0 * Programmer: Bill Wendling * 11. November 2003 * Modifications: * Moved the malloc of orig_data to just after the call to * slab_set(), and modified the call to use the global dims * array instead of the DIM0 and DIM1 constants. * JRM - 3/3/04 * * Added the allocation and deletion of local_orig_data. * This array is used to store the data written by this * process. JRM - 3/5/04 * * Replaced calls to verify_dataset() with calls to * verify_complete_dataset(). JRM - 3/8/04 *------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { hid_t fid; herr_t hrc; int nargs; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); H5open(); for (nargs = argc; nargs > 1; --nargs) if (strcmp(argv[nargs - 1], "-v") == 0 || strcmp(argv[nargs - 1], "--verbose") == 0 || strcmp(argv[nargs - 1], "--verbos") == 0 || strcmp(argv[nargs - 1], "--verbo") == 0 || strcmp(argv[nargs - 1], "--verb") == 0 || strcmp(argv[nargs - 1], "--ver") == 0 || strcmp(argv[nargs - 1], "--ve") == 0) { verbose = 1; } else if (strcmp(argv[nargs - 1], "-h") == 0 || strcmp(argv[nargs - 1], "--help") == 0 || strcmp(argv[nargs - 1], "--hel") == 0 || strcmp(argv[nargs - 1], "--he") == 0) { usage(progname); return 0; } else { fprintf(stderr, "Unknown option: %s\n", argv[nargs - 1]); usage(progname); return 1; } h5_show_hostname(); if (MAINPROCESS) { printf("===================================\n"); printf("FPHDF5 functionality tests\n"); printf("===================================\n"); } hrc = H5FPinit(MPI_COMM_WORLD, SAP_RANK, &SAP_Comm, &SAP_Barrier_Comm); VRFY((hrc == MPI_SUCCESS), "H5FP_init"); printf("%d: Initialized FPHDF5\n", mpi_rank); if (mpi_rank != SAP_RANK) { /* * Setup the file access property list that's used to create the * file. */ unsigned i; fapl = H5Pcreate(H5P_FILE_ACCESS); VRFY((fapl >= 0), "H5Pcreate"); printf("%d: Created access property list\n", mpi_rank); hrc = H5Pset_fapl_fphdf5(fapl, SAP_Comm, SAP_Barrier_Comm, MPI_INFO_NULL, (unsigned)SAP_RANK); VRFY((fapl >= 0), "H5Pset_fapl_fphdf5"); printf("%d: Set access property list\n", mpi_rank); slab_set(start, count, stride, block); VRFY((dims[0] != 0), "dims array initialized."); orig_data = (int *)malloc(((size_t)dims[0]) * ((size_t)dims[1]) * sizeof(int)); VRFY((orig_data != NULL), "orig_data malloc succeeded"); VRFY((block[0] != 0), "block array initialized."); local_orig_data = (int *)malloc(((size_t)block[0]) * ((size_t)block[1]) * sizeof(int)); VRFY((orig_data != NULL), "local_orig_data malloc succeeded"); fill_data(); for (i = 0; i < sizeof(FILENAME) / sizeof(FILENAME[0]) - 1; ++i) { if (h5_fixname(FILENAME[i], fapl, filenames[i], sizeof(filenames[i])) == NULL) { fprintf(stderr, "h5_fixname failed\n"); ++nerrors; break; } fid = create_file(filenames[i]); if (fid < 0) break; test_group_creation(fid); test_dataset_creation(fid); test_dataset_access(fid); test_dataset_write(fid); VRFY((H5Fclose(fid) >= 0), "H5Fclose"); SYNC(SAP_Barrier_Comm); printf("%d: Closed file\n", mpi_rank); fid = H5Fopen(filenames[i], H5F_ACC_RDONLY, fapl); VRFY((fid >= 0), "H5Fopen"); SYNC(SAP_Barrier_Comm); /*===------------------------------------------------------------=== * Reverify that the data is still "correct" *===------------------------------------------------------------=== */ for (i = 0; i < (unsigned)mpi_size; ++i) if (i != SAP_RANK) { hid_t group; sprintf(grp_name, grp_tmpl, i); VRFY(((group = H5Gopen(fid, grp_name)) >= 0), "H5Gopen"); /* Write to this dataset */ sprintf(dset_name, dset_tmpl, 0); printf("%d: Reverifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_complete_dataset(group, dset_name); sprintf(dset_name, dset_tmpl, 1); printf("%d: Reverifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_complete_dataset(group, dset_name); sprintf(dset_name, dset_tmpl, 2); printf("%d: Reverifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_complete_dataset(group, dset_name); sprintf(dset_name, dset_tmpl, 3); printf("%d: Reverifying dataset \"/%s/%s\"\n", mpi_rank, grp_name, dset_name); verify_complete_dataset(group, dset_name); /* Close the group */ printf("%d: Closing group.", mpi_rank); VRFY((H5Gclose(group) >= 0), "H5Gclose"); } SYNC(SAP_Barrier_Comm); VRFY((H5Fclose(fid) >= 0), "H5Fclose"); } if ( orig_data != NULL ) { free(orig_data); } if ( local_orig_data != NULL ) { free(local_orig_data); } #if 1 /* It is useful to keep the hdf file created by this test for * debugging purposes. However, this code should always be * turned on for checkin. JRM - 4/13/04 */ if (fapl > -1) h5_cleanup(FILENAME, fapl); #endif } VRFY((H5FPfinalize() >= 0), "H5FPfinalize"); printf("%d: H5FP finalized\n", mpi_rank); if (MAINPROCESS) { /* only process 0 reports */ fprintf(stderr, "===================================\n"); if (nerrors) fprintf(stderr, "***FPHDF5 test detected %d errors***\n", nerrors); else fprintf(stderr, "FPHDF5 test finished with no errors\n"); fprintf(stderr, "===================================\n"); } H5close(); MPI_Finalize(); return nerrors; } #else /* Dummy program since FPHDF5 is not configured in */ int main(int argc, char *argv[]) { int mpi_rank; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank); if (mpi_rank == 0) printf("No t_fphdf5 test because FPHDF5 is not configured in\n"); MPI_Finalize(); return 0; } #endif /* H5_HAVE_FPHDF5 */