summaryrefslogtreecommitdiffstats
path: root/testpar
diff options
context:
space:
mode:
Diffstat (limited to 'testpar')
-rw-r--r--testpar/t_chunk_alloc.c443
1 files changed, 400 insertions, 43 deletions
diff --git a/testpar/t_chunk_alloc.c b/testpar/t_chunk_alloc.c
index 0cfa328..88ab3ff 100644
--- a/testpar/t_chunk_alloc.c
+++ b/testpar/t_chunk_alloc.c
@@ -17,7 +17,7 @@
* serial and parallel modes.
*
* Created by: Christian Chilan and Albert Cheng
- * Date: 2005/07/05
+ * Date: 2006/05/25
*/
#include "testphdf5.h"
@@ -25,7 +25,9 @@ static int mpi_size, mpi_rank;
#define DATASETNAME "ExtendibleArray"
#define CHUNKSIZE 1000 /* #elements per chunk */
-#define DSETSIZE 20000*CHUNKSIZE
+#define DSETCHUNKS 20000
+#define CLOSE 1
+#define NO_CLOSE 0
static MPI_Offset
get_filesize(const char *filename)
@@ -47,25 +49,46 @@ get_filesize(const char *filename)
return(filesize);
}
+typedef enum write_ {
+ none,
+ sec_last,
+ all
+} write_type;
+
+typedef enum access_ {
+ write_all,
+ open_only,
+ extend_only
+} access_type;
+
+
/*
- * This creates a dataset serially with 20000 chunks, each of 1000
- * elements. It does not perform any writing on it. Another routine
- * will open this in parallel for extension test.
+ * This creates a dataset serially with 'nchunks' chunks, each of CHUNKSIZE
+ * elements. The allocation time is set to H5D_ALLOC_TIME_EARLY. Another
+ * routine will open this in parallel for extension test.
*/
void
-create_chunked_dataset(const char *filename)
+create_chunked_dataset(const char *filename, int nchunks, write_type write)
{
- hid_t file; /* handles */
- hid_t dataspace, dataset;
- hid_t cparms;
- hsize_t dims[1] = {DSETSIZE}; /* dataset dimensions
- at creation time */
-
+ hid_t file_id, dataset; /* handles */
+ hid_t dataspace,memspace;
+ hid_t cparms;
+ hsize_t dims[1];
hsize_t maxdims[1] = {H5S_UNLIMITED};
+
+ hsize_t chunk_dims[1] ={CHUNKSIZE};
+ hsize_t count[1];
+ hsize_t stride[1];
+ hsize_t block[1];
+ hsize_t offset[1]; /* Selection offset within dataspace */
+ /* Variables used in reading data back */
+ char buffer[CHUNKSIZE];
+ int i;
+
herr_t hrc;
- /* Variables used in reading data back */
- hsize_t chunk_dims[1] ={CHUNKSIZE};
+ MPI_Offset filesize, /* actual file size */
+ est_filesize; /* estimated file size */
/* set up MPI parameters */
MPI_Comm_size(MPI_COMM_WORLD,&mpi_size);
@@ -73,54 +96,119 @@ create_chunked_dataset(const char *filename)
/* Only MAINPROCESS should create the file. Others just wait. */
if (MAINPROCESS){
+
+ dims[0]=nchunks*CHUNKSIZE;
/* Create the data space with unlimited dimensions. */
dataspace = H5Screate_simple (1, dims, maxdims);
VRFY((dataspace >= 0), "");
+ memspace = H5Screate_simple(1, chunk_dims, NULL);
+ VRFY((memspace >= 0), "");
+
/* Create a new file. If file exists its contents will be overwritten. */
- file = H5Fcreate (filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
- VRFY((file >= 0), "");
+ file_id = H5Fcreate (filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ VRFY((file_id >= 0), "");
/* Modify dataset creation properties, i.e. enable chunking */
cparms = H5Pcreate (H5P_DATASET_CREATE);
VRFY((cparms >= 0), "");
+ hrc = H5Pset_alloc_time(cparms, H5D_ALLOC_TIME_EARLY);
+ VRFY((hrc >= 0), "");
+
hrc = H5Pset_chunk ( cparms, 1, chunk_dims);
VRFY((hrc >= 0), "");
/* Create a new dataset within the file using cparms creation properties. */
- dataset = H5Dcreate (file, DATASETNAME, H5T_NATIVE_INT, dataspace, cparms);
+ dataset = H5Dcreate (file_id, DATASETNAME, H5T_NATIVE_UCHAR, dataspace, cparms);
VRFY((dataset >= 0), "");
+ switch (write) {
+
+ /* writes only the second to last chunk */
+ case sec_last:
+
+ memset(buffer, 100, CHUNKSIZE);
+
+ count[0] = 1;
+ stride[0] = 1;
+ block[0] = chunk_dims[0];
+ offset[0] = (nchunks-2)*chunk_dims[0];
+
+ hrc = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, stride, count, block);
+ VRFY((hrc >= 0), "");
+
+ /* Write sec_last chunk */
+ hrc = H5Dwrite(dataset, H5T_NATIVE_UCHAR, memspace, dataspace, H5P_DEFAULT, buffer);
+ VRFY((hrc >= 0), "H5Dwrite");
+
+ break;
+
+
+ /* doesn't write anything */
+ case none:
+
+ break;
+ }
+
/* Close resources */
hrc = H5Dclose (dataset);
VRFY((hrc >= 0), "");
+ dataset = -1;
+
+ hrc = H5Sclose (dataspace);
+ VRFY((hrc >= 0), "");
- hrc = H5Fclose (file);
+ hrc = H5Sclose (memspace);
VRFY((hrc >= 0), "");
+
+ hrc = H5Pclose (cparms);
+ VRFY((hrc >= 0), "");
+
+ hrc = H5Fclose (file_id);
+ VRFY((hrc >= 0), "");
+ file_id = -1;
+
+ /* verify file size */
+ filesize = get_filesize(filename);
+ est_filesize = nchunks*CHUNKSIZE*sizeof(unsigned char);
+ VRFY((filesize >= est_filesize), "file size check");
+
}
/* Make sure all processes are done before exiting this routine. Otherwise,
* other tests may start and change the test data file before some processes
* of this test are still accessing the file.
*/
+
MPI_Barrier(MPI_COMM_WORLD);
}
+
/*
- * This program extends the size of a small dataset to 20000 chunks (each of
- * 1000 elements) in parallel. The dataset was initially created in a serial
- * environment. A correct extend operation should increase the file size
- * considerably.
+ * This program performs three different types of parallel access. It writes on
+ * the entire dataset, it extends the dataset to nchunks*CHUNKSIZE, and it only
+ * opens the dataset. At the end, it verifies the size of the dataset to be
+ * consistent with argument 'nchunks'.
*/
void
-extend_chunked_dataset(const char *filename)
+parallel_access_dataset(const char *filename, int nchunks, access_type action, hid_t *file_id, hid_t *dataset)
{
/* HDF5 gubbins */
- hid_t file_id, dataset; /* HDF5 file identifier */
+ hid_t memspace, dataspace; /* HDF5 file identifier */
hid_t access_plist; /* HDF5 ID for file access property list */
herr_t hrc; /* HDF5 return code */
hsize_t size[1];
+ hsize_t dim_size;
+
+ hsize_t chunk_dims[1] ={CHUNKSIZE};
+ hsize_t count[1];
+ hsize_t stride[1];
+ hsize_t block[1];
+ hsize_t offset[1]; /* Selection offset within dataspace */
+ /* Variables used in reading data back */
+ char buffer[CHUNKSIZE];
+ int i;
/* MPI Gubbins */
MPI_Offset filesize, /* actual file size */
@@ -139,32 +227,101 @@ extend_chunked_dataset(const char *filename)
VRFY((hrc >= 0), "");
/* Open the file */
- file_id = H5Fopen(filename, H5F_ACC_RDWR, access_plist);
- VRFY((file_id >= 0), "");
+ if (*file_id<0){
+ *file_id = H5Fopen(filename, H5F_ACC_RDWR, access_plist);
+ VRFY((*file_id >= 0), "");
+ }
/* Open dataset*/
- dataset = H5Dopen(file_id, DATASETNAME);
- VRFY((dataset >= 0), "");
+ if (*dataset<0){
+ *dataset = H5Dopen(*file_id, DATASETNAME);
+ VRFY((*dataset >= 0), "");
+ }
-#if 0
- size[0] = DSETSIZE;
+ memspace = H5Screate_simple(1, chunk_dims, NULL);
+ VRFY((memspace >= 0), "");
- /* Extend dataset*/
- hrc = H5Dextend(dataset, size);
- VRFY((hrc >= 0), "");
-#endif
+ dataspace = H5Dget_space(*dataset);
+ VRFY((dataspace >= 0), "");
+
+ size[0] = nchunks*CHUNKSIZE;
+
+ switch (action) {
+
+ /* all chunks are written by all the processes in an interleaved way*/
+ case write_all:
+
+ for (i=0; i<nchunks/mpi_size; i++){
+
+ memset(buffer, mpi_rank+1, CHUNKSIZE);
+
+ offset[0] = (i*mpi_size+mpi_rank)*chunk_dims[0];
+ count[0] = 1;
+ stride[0] = 1;
+ block[0] = chunk_dims[0];
+
+ hrc = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, stride, count, block);
+ VRFY((hrc >= 0), "");
+
+ /* Write the buffer out */
+ hrc = H5Dwrite(*dataset, H5T_NATIVE_UCHAR, memspace, dataspace, H5P_DEFAULT, buffer);
+ VRFY((hrc >= 0), "H5Dwrite");
+
+ }
+
+ /* remainder writing */
+ if (mpi_rank < nchunks%mpi_size){
+
+ memset(buffer, mpi_rank+1, CHUNKSIZE);
+
+ offset[0] = ((nchunks/mpi_size)*mpi_size+mpi_rank)*chunk_dims[0];
+ count[0] = 1;
+ stride[0] = 1;
+ block[0] = chunk_dims[0];
+
+ hrc = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, stride, count, block);
+ VRFY((hrc >= 0), "");
+
+ /* Write the buffer out */
+ hrc = H5Dwrite(*dataset, H5T_NATIVE_UCHAR, memspace, dataspace, H5P_DEFAULT, buffer);
+ VRFY((hrc >= 0), "H5Dwrite");
+ }
+
+ break;
+
+ /* only extends the dataset */
+ case extend_only:
+ /* Extend dataset*/
+ hrc = H5Dextend(*dataset, size);
+ VRFY((hrc >= 0), "");
+
+ break;
+
+ /* only opens the dataset */
+ case open_only:
+
+ break;
+ }
/* Close up */
- hrc = H5Dclose(dataset);
+ hrc = H5Dclose(*dataset);
VRFY((hrc >= 0), "");
+ *dataset = -1;
+
+ hrc = H5Sclose (dataspace);
+ VRFY((hrc >= 0), "");
- hrc = H5Fclose(file_id);
+ hrc = H5Sclose (memspace);
+ VRFY((hrc >= 0), "");
+
+ hrc = H5Fclose(*file_id);
VRFY((hrc >= 0), "");
+ *file_id = -1;
- /* verify file size has grown */
+ /* verify file size */
filesize = get_filesize(filename);
- est_filesize = DSETSIZE*sizeof(H5T_NATIVE_INT);
- VRFY((filesize>=est_filesize), "file size check");
+ est_filesize = nchunks*CHUNKSIZE*sizeof(unsigned char);
+ VRFY((filesize >= est_filesize), "file size check");
/* Can close some plists */
hrc = H5Pclose(access_plist);
@@ -177,17 +334,217 @@ extend_chunked_dataset(const char *filename)
MPI_Barrier(MPI_COMM_WORLD);
}
+/*
+ * This routine verifies the data written in the dataset. It does one of the
+ * three cases according to the value of parameter `write'.
+ * 1. it returns correct fill values though the dataset has not been written;
+ * 2. it still returns correct fill values though only a small part is written;
+ * 3. it returns correct values when the whole dataset has been written in an
+ * interleaved pattern.
+ */
+void verify_data(const char *filename, int nchunks, write_type write, int close, hid_t *file_id, hid_t *dataset)
+{
+ /* HDF5 gubbins */
+ hid_t dataspace, memspace; /* HDF5 file identifier */
+ hid_t access_plist; /* HDF5 ID for file access property list */
+ herr_t hrc; /* HDF5 return code */
+
+ hsize_t chunk_dims[1] ={CHUNKSIZE};
+ hsize_t count[1];
+ hsize_t stride[1];
+ hsize_t block[1];
+ hsize_t offset[1]; /* Selection offset within dataspace */
+ /* Variables used in reading data back */
+ char buffer[CHUNKSIZE];
+ int value, i;
+ int index, current;
+
+ /* MPI Gubbins */
+ MPI_Offset filesize, /* actual file size */
+ est_filesize; /* estimated file size */
+ int mpierr;
+
+ /* Initialize MPI */
+ MPI_Comm_size(MPI_COMM_WORLD,&mpi_size);
+ MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank);
+
+ /* Set up MPIO file access property lists */
+ access_plist = H5Pcreate(H5P_FILE_ACCESS);
+ VRFY((access_plist >= 0), "");
+
+ hrc = H5Pset_fapl_mpio(access_plist, MPI_COMM_WORLD, MPI_INFO_NULL);
+ VRFY((hrc >= 0), "");
+
+ /* Open the file */
+ if (*file_id<0){
+ *file_id = H5Fopen(filename, H5F_ACC_RDWR, access_plist);
+ VRFY((*file_id >= 0), "");
+ }
+
+ /* Open dataset*/
+ if (*dataset<0){
+ *dataset = H5Dopen(*file_id, DATASETNAME);
+ VRFY((*dataset >= 0), "");
+ }
+
+ memspace = H5Screate_simple(1, chunk_dims, NULL);
+ VRFY((memspace >= 0), "");
+
+ dataspace = H5Dget_space(*dataset);
+ VRFY((dataspace >= 0), "");
+
+ /* expected value in the dataset */
+ if (write == all)
+ value = mpi_rank + 1;
+ else
+ value =0;
+
+ /* checks main portion of the dataset */
+ for (i=0; i<nchunks/mpi_size; i++){
+
+ memset(buffer, -1, CHUNKSIZE);
+
+ offset[0] = (i*mpi_size+mpi_rank)*chunk_dims[0];
+ count[0] = 1;
+ stride[0] = 1;
+ block[0] = chunk_dims[0];
+
+ hrc = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, stride, count, block);
+ VRFY((hrc >= 0), "");
+
+ /* Read the chunk */
+ hrc = H5Dread(*dataset, H5T_NATIVE_UCHAR, memspace, dataspace, H5P_DEFAULT, buffer);
+ VRFY((hrc >= 0), "H5Dread");
+
+ /* adjust expected value for sec_last chunk */
+ if (i == nchunks/mpi_size-1 && !(nchunks%mpi_size) && write==sec_last){
+ if (mpi_rank == mpi_size-2)
+ value = 100;
+ else
+ value = 0;
+ }
+
+ /* verify content of the chunk */
+ for (index = 0; index < CHUNKSIZE; index++)
+ VRFY((buffer[index] == value), "data verification");
+
+ }
+
+ /* remainder checking */
+ if (mpi_rank < nchunks%mpi_size){
+
+ memset(buffer, -1, CHUNKSIZE);
+
+ offset[0] = ((nchunks/mpi_size)*mpi_size+mpi_rank)*chunk_dims[0];
+ count[0] = 1;
+ stride[0] = 1;
+ block[0] = chunk_dims[0];
+
+ hrc = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, stride, count, block);
+ VRFY((hrc >= 0), "");
+
+ /* read the buffer out */
+ hrc = H5Dread(*dataset, H5T_NATIVE_UCHAR, memspace, dataspace, H5P_DEFAULT, buffer);
+ VRFY((hrc >= 0), "H5Dread");
+
+ /* adjust expected value for sec_last chunk */
+ if (write == sec_last){
+ if (mpi_rank == nchunks%mpi_size-2)
+ value = 100;
+ else
+ value = 0;
+ }
+
+ /* verify content of the chunk */
+ for (index = 0; index < CHUNKSIZE; index++)
+ VRFY((buffer[index] == value), "data verification");
+
+ }
+
+ hrc = H5Sclose (dataspace);
+ VRFY((hrc >= 0), "");
+
+ hrc = H5Sclose (memspace);
+ VRFY((hrc >= 0), "");
+
+ /* Can close some plists */
+ hrc = H5Pclose(access_plist);
+ VRFY((hrc >= 0), "");
+
+ /* Close up */
+ if (close){
+ hrc = H5Dclose(*dataset);
+ VRFY((hrc >= 0), "");
+ *dataset = -1;
+
+ hrc = H5Fclose(*file_id);
+ VRFY((hrc >= 0), "");
+ *file_id = -1;
+ }
+
+ /* Make sure all processes are done before exiting this routine. Otherwise,
+ * other tests may start and change the test data file before some processes
+ * of this test are still accessing the file.
+ */
+ MPI_Barrier(MPI_COMM_WORLD);
+}
+
+
+
+/*
+ * Test following possible scenarios,
+ * Case 1:
+ * Sequential create a file and dataset with H5D_ALLOC_TIME_EARLY and large
+ * size, no write, close, reopen in parallel, read to verify all return
+ * the fill value.
+ * Case 2:
+ * Sequential create a file and dataset with H5D_ALLOC_TIME_EARLY but small
+ * size, no write, close, reopen in parallel, extend to large size, then close,
+ * then reopen in parallel and read to verify all return the fill value.
+ * Case 3:
+ * Sequential create a file and dataset with H5D_ALLOC_TIME_EARLY and large
+ * size, write just a small part of the dataset (second to the last), close,
+ * then reopen in parallel, read to verify all return the fill value except
+ * those small portion that has been written. Without closing it, writes
+ * all parts of the dataset in a interleave pattern, close it, and reopen
+ * it, read to verify all data are as written.
+ */
void
test_chunk_alloc(void)
{
const char *filename;
+ hid_t file_id, dataset;
+
+ file_id = dataset = -1;
filename = GetTestParameters();
if (VERBOSE_MED)
printf("Extend Chunked allocation test on file %s\n", filename);
- /* create the datafile first */
- create_chunked_dataset(filename);
- /* reopen it in parallel and extend it. */
- extend_chunked_dataset(filename);
+ /* Case 1 */
+ /* Create chunked dataset without writing anything.*/
+ create_chunked_dataset(filename, DSETCHUNKS, none);
+ /* reopen dataset in parallel and check for file size */
+ parallel_access_dataset(filename, DSETCHUNKS, open_only, &file_id, &dataset);
+ /* reopen dataset in parallel, read and verify the data */
+ verify_data(filename, DSETCHUNKS, none, CLOSE, &file_id, &dataset);
+
+ /* Case 2 */
+ /* Create chunked dataset without writing anything */
+ create_chunked_dataset(filename, 20, none);
+ /* reopen dataset in parallel and only extend it */
+ parallel_access_dataset(filename, DSETCHUNKS, extend_only, &file_id, &dataset);
+ /* reopen dataset in parallel, read and verify the data */
+ verify_data(filename, DSETCHUNKS, none, CLOSE, &file_id, &dataset);
+
+ /* Case 3 */
+ /* Create chunked dataset and write in the second to last chunk */
+ create_chunked_dataset(filename, DSETCHUNKS, sec_last);
+ /* Reopen dataset in parallel, read and verify the data. The file and dataset are not closed*/
+ verify_data(filename, DSETCHUNKS, sec_last, NO_CLOSE, &file_id, &dataset);
+ /* All processes write in all the chunks in a interleaved way */
+ parallel_access_dataset(filename, DSETCHUNKS, write_all, &file_id, &dataset);
+ /* reopen dataset in parallel, read and verify the data */
+ verify_data(filename, DSETCHUNKS, all, CLOSE, &file_id, &dataset);
+
}