summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Cheng <acheng@hdfgroup.org>2013-05-31 17:56:57 (GMT)
committerAlbert Cheng <acheng@hdfgroup.org>2013-05-31 17:56:57 (GMT)
commitd8b37d28a3cdfbf52fa904e9c25d9d18d5e6dbca (patch)
treed28bcd0b0fa2f09c42c602ff9c504c07ad3c3a00
parent3413c2e10fcf9d2283b7d1e3c4fefb69474c7c40 (diff)
downloadhdf5-d8b37d28a3cdfbf52fa904e9c25d9d18d5e6dbca.zip
hdf5-d8b37d28a3cdfbf52fa904e9c25d9d18d5e6dbca.tar.gz
hdf5-d8b37d28a3cdfbf52fa904e9c25d9d18d5e6dbca.tar.bz2
[svn-r23724] Add use case 1.7--SWRM read/write one chunk at a time.
Tested: h5committest.
-rw-r--r--MANIFEST3
-rw-r--r--test/Makefile.am8
-rw-r--r--test/Makefile.in21
-rw-r--r--test/usecase.h74
-rw-r--r--test/usecase1_7.c521
-rw-r--r--test/usecase_common.c81
6 files changed, 702 insertions, 6 deletions
diff --git a/MANIFEST b/MANIFEST
index a1b5028..40a677d 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1121,6 +1121,9 @@
./test/tvlstr.c
./test/tvltypes.c
./test/unlink.c
+./test/usecase1_7.c
+./test/usecase_common.c
+./test/usecase.h
./test/vfd.c
./test/test_filters_le.h5
./test/test_filters_be.h5
diff --git a/test/Makefile.am b/test/Makefile.am
index f1a46e5..2bb4e5a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -50,7 +50,8 @@ TEST_PROG= testhdf5 lheap ohdr stab gheap cache cache_api cache_tagging \
freespace mf farray earray btree2 fheap file_image
bin_PROGRAMS=swmr_generator swmr_reader swmr_writer swmr_remove_reader \
- swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer
+ swmr_remove_writer swmr_addrem_writer swmr_sparse_reader swmr_sparse_writer \
+ usecase1_7
# List programs to be built when testing here. error_test and err_compat are
# built at the same time as the other tests, but executed by testerror.sh.
@@ -158,7 +159,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 \
new_multi_file_v16-r.h5 new_multi_file_v16-s.h5 \
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy \
- swmr_data.h5 \
+ swmr_data.h5 usecase1_7.h5 \
flushrefresh.h5 flushrefresh_VERIFICATION_START \
flushrefresh_VERIFICATION_CHECKPOINT1 flushrefresh_VERIFICATION_CHECKPOINT2 \
flushrefresh_VERIFICATION_DONE
@@ -169,6 +170,9 @@ testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
trefer.c trefstr.c tselect.c tskiplist.c tsohm.c ttime.c ttst.c tunicode.c \
tvlstr.c tvltypes.c
+# Sources for Use Cases
+usecase1_7_SOURCES=usecase1_7.c usecase_common.c
+
# Temporary files.
DISTCLEANFILES=testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh \
testflushrefresh.sh
diff --git a/test/Makefile.in b/test/Makefile.in
index 5dbcfa4..4fb09d1 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -81,7 +81,8 @@ DIST_COMMON = $(srcdir)/H5srcdir_str.h.in $(srcdir)/Makefile.am \
bin_PROGRAMS = swmr_generator$(EXEEXT) swmr_reader$(EXEEXT) \
swmr_writer$(EXEEXT) swmr_remove_reader$(EXEEXT) \
swmr_remove_writer$(EXEEXT) swmr_addrem_writer$(EXEEXT) \
- swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT)
+ swmr_sparse_reader$(EXEEXT) swmr_sparse_writer$(EXEEXT) \
+ usecase1_7$(EXEEXT)
check_PROGRAMS = $(am__EXEEXT_1) error_test$(EXEEXT) \
err_compat$(EXEEXT) tcheck_version$(EXEEXT) testmeta$(EXEEXT) \
links_env$(EXEEXT) flushrefresh$(EXEEXT) $(am__EXEEXT_2)
@@ -531,6 +532,10 @@ unlink_SOURCES = unlink.c
unlink_OBJECTS = unlink.$(OBJEXT)
unlink_LDADD = $(LDADD)
unlink_DEPENDENCIES = libh5test.la $(LIBHDF5)
+am_usecase1_7_OBJECTS = usecase1_7.$(OBJEXT) usecase_common.$(OBJEXT)
+usecase1_7_OBJECTS = $(am_usecase1_7_OBJECTS)
+usecase1_7_LDADD = $(LDADD)
+usecase1_7_DEPENDENCIES = libh5test.la $(LIBHDF5)
vfd_SOURCES = vfd.c
vfd_OBJECTS = vfd.$(OBJEXT)
vfd_LDADD = $(LDADD)
@@ -589,7 +594,7 @@ SOURCES = $(libdynlib1_la_SOURCES) $(libdynlib2_la_SOURCES) \
swmr_generator.c swmr_reader.c swmr_remove_reader.c \
swmr_remove_writer.c swmr_sparse_reader.c swmr_sparse_writer.c \
swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) unlink.c vfd.c
+ $(ttsafe_SOURCES) unlink.c $(usecase1_7_SOURCES) vfd.c
DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
$(am__libdynlib2_la_SOURCES_DIST) \
$(am__libdynlib3_la_SOURCES_DIST) $(libh5test_la_SOURCES) \
@@ -611,7 +616,7 @@ DIST_SOURCES = $(am__libdynlib1_la_SOURCES_DIST) \
swmr_generator.c swmr_reader.c swmr_remove_reader.c \
swmr_remove_writer.c swmr_sparse_reader.c swmr_sparse_writer.c \
swmr_writer.c tcheck_version.c $(testhdf5_SOURCES) testmeta.c \
- $(ttsafe_SOURCES) unlink.c vfd.c
+ $(ttsafe_SOURCES) unlink.c $(usecase1_7_SOURCES) vfd.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -942,7 +947,7 @@ INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src
# Test script for error_test and err_compat
TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh \
testlinks_env.sh $(srcdir)/testswmr.sh testflushrefresh.sh \
- $(am__append_1)
+ $(srcdir)/test_usecases.sh $(am__append_1)
SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) \
links_env$(EXEEXT) $(am__append_2)
check_SCRIPTS = $(TEST_SCRIPT)
@@ -999,6 +1004,9 @@ testhdf5_SOURCES = testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
tvlstr.c tvltypes.c
+# Sources for Use Cases
+usecase1_7_SOURCES = usecase1_7.c usecase_common.c
+
# Temporary files.
DISTCLEANFILES = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh \
testflushrefresh.sh
@@ -1441,6 +1449,9 @@ ttsafe$(EXEEXT): $(ttsafe_OBJECTS) $(ttsafe_DEPENDENCIES) $(EXTRA_ttsafe_DEPENDE
unlink$(EXEEXT): $(unlink_OBJECTS) $(unlink_DEPENDENCIES) $(EXTRA_unlink_DEPENDENCIES)
@rm -f unlink$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(unlink_OBJECTS) $(unlink_LDADD) $(LIBS)
+usecase1_7$(EXEEXT): $(usecase1_7_OBJECTS) $(usecase1_7_DEPENDENCIES) $(EXTRA_usecase1_7_DEPENDENCIES)
+ @rm -f usecase1_7$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(usecase1_7_OBJECTS) $(usecase1_7_LDADD) $(LIBS)
vfd$(EXEEXT): $(vfd_OBJECTS) $(vfd_DEPENDENCIES) $(EXTRA_vfd_DEPENDENCIES)
@rm -f vfd$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(vfd_OBJECTS) $(vfd_LDADD) $(LIBS)
@@ -1570,6 +1581,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tvlstr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tvltypes.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unlink.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usecase1_7.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/usecase_common.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfd.Po@am__quote@
.c.o:
diff --git a/test/usecase.h b/test/usecase.h
new file mode 100644
index 0000000..858359b
--- /dev/null
+++ b/test/usecase.h
@@ -0,0 +1,74 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Use Case Header file: common definitions for use cases tests.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include "hdf5.h"
+
+/* Macro definitions */
+#define Hgoto_error(val) {ret_value=val; goto done;}
+#define Hgoto_done {goto done;}
+#define Chunksize_DFT 256 /* chunksize default */
+#define ErrorReportMax 10 /* max number of errors reported */
+/* these two definitions must match each other */
+#define UC_DATATYPE H5T_NATIVE_SHORT /* use case HDF5 data type */
+#define UC_CTYPE short /* use case C data type */
+
+/* type declarations */
+typedef struct options_t {
+ int num_dsets; /* number of datasets */
+ int use_swmr; /* use swmr open or not */
+ int compress; /* 0: no compress */
+ int h5_use_chunks; /* 0/1: Not use/use chunked dataset */
+ int chunksize; /* chunks are chunksize^2 planes */
+ int nplanes; /* number of planes, default chunksize */
+ char *filename; /* use case data filename */
+} options_t;
+
+/* global variables declarations */
+extern options_t UC_opts; /* Use Case Options */
+extern const char *progname_g; /* Program name */
+
+/* prototype declarations */
+int parse_option(int argc, char * const argv[]);
+void usage(const char *prog);
+int create_uc_file(void);
+int write_uc_file(void);
+int read_uc_file(void);
+
+/* private definitions of Standard functions */
+
+/* Standard POSIX functions */
+#define HDassert(s) assert(s)
+#define HDfree(s) free(s)
+#define HDgetenv(s) getenv(s)
+#define HDmalloc(s) malloc(s)
+#define HDmemcpy(X,C,Z) memcpy(X,C,Z)
+#define HDmemset(X,C,Z) memset(X,C,Z)
+#define HDperror(s) perror(s)
+#define HDstrcat(s1, s2) strcat(s1, s2)
+#define HDstrcmp(s1, s2) strcmp(s1, s2)
+#define HDstrcpy(s1, s2) strcpy(s1, s2)
+#define HDstrdup(s) strdup(s)
+#define HDstrlen(s) strlen(s)
+#define HDstrncpy(s1, s2, N) strncpy(s1, s2, N)
+#define HDstrrchr(s, c) strrchr(s, c)
diff --git a/test/usecase1_7.c b/test/usecase1_7.c
new file mode 100644
index 0000000..0a4bb9d
--- /dev/null
+++ b/test/usecase1_7.c
@@ -0,0 +1,521 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Use Case 1.7 Appending a single chunk
+ * Description:
+ * Appending a single chunk of raw data to a dataset along an unlimited
+ * dimension within a pre-created file and reading the new data back.
+ * Goal:
+ * Read data appended by the Writer to a pre-existing dataset in a
+ * file. The dataset has one or more unlimited dimensions. The data is
+ * appended by a hyperslab that is contained in one chunk (for example,
+ * appending 2-dim planes along the slowest changing dimension in the
+ * 3-dim dataset).
+ * Level:
+ * User Level
+ * Guarantees:
+ * o Readers will see the modified dimension sizes after the Writer
+ * finishes HDF5 metadata updates and issues H5Fflush or H5Oflush calls.
+ * o Readers will see newly appended data after the Writer finishes
+ * the flush operation.
+ *
+ * Preconditions:
+ * o Readers are not allowed to modify the file. o All datasets
+ * that are modified by the Writer exist when the Writer opens the file.
+ * o All datasets that are modified by the Writer exist when a Reader
+ * opens the file. o Data is written by a hyperslab contained in
+ * one chunk.
+ *
+ * Main Success Scenario:
+ * 1. An application creates a file with required objects (groups,
+ * datasets, and attributes).
+ * 2. The Writer application opens the file and datasets in the file
+ * and starts adding data along the unlimited dimension using a hyperslab
+ * selection that corresponds to an HDF5 chunk.
+ * 3. A Reader opens the file and a dataset in a file, and queries
+ * the sizes of the dataset; if the extent of the dataset has changed,
+ * reads the appended data back.
+ *
+ * Discussion points:
+ * 1. Since the new data is written to the file, and metadata update
+ * operation of adding pointer to the newly written chunk is atomic and
+ * happens after the chunk is on the disk, only two things may happen
+ * to the Reader:
+ * o The Reader will not see new data.
+ * o The Reader will see all new data written by Writer.
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* Created: Albert Cheng, 2013/5/28.
+ * Modified:
+ */
+
+#include "usecase.h"
+
+/* Global Variable definitions */
+options_t UC_opts; /* Use Case Options */
+const char *progname_g="usecase1_7"; /* program name */
+
+/* create the use case file for testing.
+ * It has one 3d dataset using chunked storage.
+ * The dataset is (unlimited, chunksize, chunksize).
+ * Dataset type is 2 bytes integer.
+ * It starts out "empty", i.e., first dimension is 0.
+ *
+ * Return: 0 succeed; -1 fail.
+ */
+int create_uc_file(void)
+{
+ hsize_t dims[3]; /* Dataset starting dimensions */
+ hsize_t max_dims[3]; /* Dataset maximum dimensions */
+ hsize_t chunk_dims[3]; /* Chunk dimensions */
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t dcpl; /* Dataset creation property list */
+ hid_t sid; /* Dataspace ID */
+ hid_t dsid; /* Dataset ID */
+
+ /* Create the file */
+ if((fid = H5Fcreate(UC_opts.filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ return -1;
+
+ /* Set up dimension sizes */
+ chunk_dims[0] = 1;
+ dims[0] = 0;
+ max_dims[0] = H5S_UNLIMITED;
+ max_dims[1] = max_dims[2] = dims[1] = dims[2] = chunk_dims[1] = chunk_dims[2] = UC_opts.chunksize;
+
+ /* Create dataspace for creating datasets */
+ if((sid = H5Screate_simple(3, dims, max_dims)) < 0)
+ return -1;
+
+ /* Create dataset creation property list */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ return -1;
+ if(H5Pset_chunk(dcpl, 3, chunk_dims) < 0)
+ return -1;
+
+ /* create dataset of use case name */
+ if((dsid = H5Dcreate2(fid, UC_opts.filename, UC_DATATYPE, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0)
+ return -1;
+
+ /* Close everythign */
+ if(H5Dclose(dsid) < 0)
+ return -1;
+
+ if(H5Sclose(sid) < 0)
+ return -1;
+ if(H5Fclose(fid) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+/* Write planes to the dataset in the use case file.
+ * Fill each plan with plan numbers and then write it to the nth plane.
+ * Increase the plane number and repeat till end of dataset.
+ *
+ * Return: 0 succeed; -1 fail.
+ */
+int write_uc_file(void)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t dsid; /* dataset ID */
+ char *name;
+ UC_CTYPE *buffer, *bufptr; /* data buffer */
+ int cz=UC_opts.chunksize; /* Chunk size */
+ hid_t f_sid; /* dataset file space id */
+ hid_t m_sid; /* memory space id */
+ int rank; /* rank */
+ hsize_t dims[3]; /* Dataspace dimensions */
+ hsize_t memdims[3]; /* Memory space dimensions */
+ hsize_t start[3] = {0,0,0}, count[3]; /* Hyperslab selection values */
+ int i, j, k;
+
+ name = UC_opts.filename;
+
+ /* Open the file */
+ if((fid = H5Fopen(name, H5F_ACC_RDWR | (UC_opts.use_swmr ? H5F_ACC_SWMR_WRITE : 0), H5P_DEFAULT)) < 0){
+ fprintf(stderr, "H5Fopen failed\n");
+ return -1;
+ }
+
+ /* Open the dataset of the same name */
+ if((dsid = H5Dopen2(fid, name, H5P_DEFAULT)) < 0){
+ fprintf(stderr, "H5Dopen2 failed\n");
+ return -1;
+ }
+
+ /* allocate space for data buffer chunksize X chunksize of UC_CTYPE */
+ /*cz = UC_opts.chunksize;*/
+ memdims[0]=1;
+ memdims[1] = memdims[2] = cz;
+ if ((buffer=(UC_CTYPE*)HDmalloc(cz*cz*sizeof(UC_CTYPE)))==NULL) {
+ fprintf(stderr, "malloc: failed\n");
+ return -1;
+ };
+
+ /*
+ * Get dataset rank and dimension.
+ */
+ f_sid = H5Dget_space(dsid); /* Get filespace handle first. */
+ rank = H5Sget_simple_extent_ndims(f_sid);
+ if (rank != 3){
+ fprintf(stderr, "rank(%d) of dataset does not match\n", rank);
+ return -1;
+ }
+ if (H5Sget_simple_extent_dims(f_sid, dims, NULL) < 0){
+ fprintf(stderr, "H5Sget_simple_extent_dims got error\n");
+ return -1;
+ }
+ printf("dataset rank %d, dimensions %lu x %lu x %lu\n",
+ rank, (unsigned long)(dims[0]), (unsigned long)(dims[1]), (unsigned long)(dims[2]));
+ /* verify that file space dims are as expected and are consistent with memory space dims */
+ if (dims[0] != 0 || dims[1] != memdims[1] || dims[2] != memdims[2]){
+ fprintf(stderr, "dataset is not empty. Got dims=(%ld,%ld,%ld)\n",
+ (long)dims[0], (long)dims[1], (long)dims[2]);
+ return -1;
+ }
+
+ /* setup mem-space for buffer */
+ if ((m_sid=H5Screate_simple(rank, memdims, NULL))<0){
+ fprintf(stderr, "H5Screate_simple for memory failed\n");
+ return -1;
+ };
+
+ /* write planes */
+ count[0]=1;
+ count[1]=count[2]=cz;
+ for (i=0; i<UC_opts.nplanes; i++){
+ /* fill buffer with value i+1 */
+ /* HDmemset(buffer, i+1, cz*cz*sizeof(UC_CTYPE));*/
+ bufptr = buffer;
+ for (j=0; j<cz; j++)
+ for (k=0; k<cz; k++)
+ *bufptr++ = i;
+
+ /* extend the dataset by one for new plane */
+ dims[0]=i+1;
+ if(H5Dset_extent(dsid, dims) < 0){
+ fprintf(stderr, "H5Dset_extent failed\n");
+ return -1;
+ }
+
+ /* Get the dataset's dataspace */
+ if((f_sid = H5Dget_space(dsid)) < 0){
+ fprintf(stderr, "H5Dset_extent failed\n");
+ return -1;
+ }
+
+ start[0]=i;
+ /* Choose the next plane to write */
+ if(H5Sselect_hyperslab(f_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0){
+ fprintf(stderr, "Failed H5Sselect_hyperslab\n");
+ return -1;
+ }
+
+ /* Write plane to the dataset */
+ if(H5Dwrite(dsid, UC_DATATYPE, m_sid, f_sid, H5P_DEFAULT, buffer) < 0){
+ fprintf(stderr, "Failed H5Dwrite\n");
+ return -1;
+ }
+ /* flush file to make the just written plane available. */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0){
+ fprintf(stderr, "Failed to H5Fflush file\n");
+ return -1;
+ }
+ }
+
+ /* Done writing. Free/Close all resources including data file */
+ HDfree(buffer);
+ if (H5Dclose(dsid) < 0){
+ fprintf(stderr, "Failed to close datasete\n");
+ return -1;
+ }
+ if (H5Sclose(m_sid) < 0){
+ fprintf(stderr, "Failed to close memory space\n");
+ return -1;
+ }
+ if (H5Sclose(f_sid) < 0){
+ fprintf(stderr, "Failed to close file space\n");
+ return -1;
+ }
+ if (H5Fclose(fid) < 0){
+ fprintf(stderr, "Failed to close file id\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* Read planes from the dataset in the use case file.
+ * It expects the dataset is being changed (growing).
+ * It checks the unlimited dimension (1st one). When it increases,
+ * it will try read the new plane and verify the data correctness.
+ * (The nth plan should contain all "n".)
+ * When the unlimited dimension grows to the chunksize (it becomes
+ * a cube), that is the end of data. It will then return.
+ *
+ * Return: 0 succeed; -1 fail.
+ */
+int read_uc_file(void)
+{
+ hid_t fid; /* File ID for new HDF5 file */
+ hid_t dsid; /* dataset ID */
+ char *name;
+ UC_CTYPE *buffer, *bufptr; /* read data buffer */
+ int cz=UC_opts.chunksize; /* Chunk size */
+ hid_t f_sid; /* dataset file space id */
+ hid_t m_sid; /* memory space id */
+ int rank; /* rank */
+ hsize_t dims[3]; /* Dataspace dimensions */
+ hsize_t memdims[3]; /* Memory space dimensions */
+ int nplane=0, nplane_old=0; /* nth plane, last nth plane */
+ hsize_t start[3] = {0,0,0}, count[3]; /* Hyperslab selection values */
+ int j, k;
+ int nreadererr=0;
+ int nerrs;
+
+ name = UC_opts.filename;
+
+ /* Open the file */
+ if((fid = H5Fopen(name, H5F_ACC_RDONLY | (UC_opts.use_swmr ? H5F_ACC_SWMR_READ : 0), H5P_DEFAULT)) < 0){
+ fprintf(stderr, "H5Fopen failed\n");
+ return -1;
+ }
+
+ /* Open the dataset of the same name */
+ if((dsid = H5Dopen2(fid, name, H5P_DEFAULT)) < 0){
+ fprintf(stderr, "H5Dopen2 failed\n");
+ return -1;
+ }
+
+ /* allocate space for data buffer chunksize X chunksize of UC_CTYPE */
+ /*cz = UC_opts.chunksize;*/
+ memdims[0]=1;
+ memdims[1] = memdims[2] = cz;
+ if ((buffer=(UC_CTYPE*)HDmalloc(cz*cz*sizeof(UC_CTYPE)))==NULL) {
+ fprintf(stderr, "malloc: failed\n");
+ return -1;
+ };
+
+ /*
+ * Get dataset rank and dimension.
+ * Verify dimension is as expected (unlimited,chunksize,chunksize).
+ */
+ f_sid = H5Dget_space(dsid); /* Get filespace handle first. */
+ rank = H5Sget_simple_extent_ndims(f_sid);
+ if (rank != 3){
+ fprintf(stderr, "rank(%d) of dataset does not match\n", rank);
+ return -1;
+ }
+ if (H5Sget_simple_extent_dims(f_sid, dims, NULL) < 0){
+ fprintf(stderr, "H5Sget_simple_extent_dims got error\n");
+ return -1;
+ }
+ printf("dataset rank %d, dimensions %lu x %lu x %lu\n",
+ rank, (unsigned long)(dims[0]), (unsigned long)(dims[1]), (unsigned long)(dims[2]));
+ /* verify that file space dims are as expected and are consistent with memory space dims */
+ if (dims[1] != memdims[1] || dims[2] != memdims[2]){
+ fprintf(stderr, "dataset dimension is not as expected. Got dims=(%ld,%ld,%ld)\n",
+ (long)dims[0], (long)dims[1], (long)dims[2]);
+ return -1;
+ }
+
+ /* setup mem-space for buffer */
+ if ((m_sid=H5Screate_simple(rank, memdims, NULL))<0){
+ fprintf(stderr, "H5Screate_simple for memory failed\n");
+ return -1;
+ };
+
+ /* Read 1 plane at a time whenever the dataset grows larger
+ * (along dim[0]) */
+ count[0]=1;
+ count[1]=count[2]=cz;
+ /* quit when all nplanes, default cz, have been read */
+ while (nplane_old < UC_opts.nplanes ){
+ printf("enter while with nplane_old=%d, dims[0]=%d\n", nplane_old, (int)dims[0]);
+ for (nplane=nplane_old; nplane < dims[0]; nplane++){
+ /* read planes between last old nplanes and current extent */
+ /* Get the dataset's dataspace */
+ if((f_sid = H5Dget_space(dsid)) < 0){
+ fprintf(stderr, "H5Dget_space failed\n");
+ return -1;
+ }
+
+ start[0]=nplane;
+ /* Choose the next plane to read */
+ if(H5Sselect_hyperslab(f_sid, H5S_SELECT_SET, start, NULL, count, NULL) < 0){
+ fprintf(stderr, "H5Sselect_hyperslab failed\n");
+ return -1;
+ }
+
+ /* Read the plane from the dataset */
+ if(H5Dread(dsid, UC_DATATYPE, m_sid, f_sid, H5P_DEFAULT, buffer) < 0){
+ fprintf(stderr, "H5Dread failed\n");
+ return -1;
+ }
+
+ /* compare read data with expected data value which is nplane */
+ bufptr = buffer;
+ nerrs=0;
+ for (j=0; j<cz; j++){
+ for (k=0; k<cz; k++){
+ if (*bufptr++ != nplane){
+ if (++nerrs < ErrorReportMax){
+ fprintf(stderr,
+ "found error %d plane(%d,%d), expected %d, got %d\n",
+ nplane, j, k, nplane, (int)*(bufptr-1));
+ }
+ }
+ }
+ }
+ if (nerrs){
+ nreadererr++;
+ fprintf(stderr, "found %d unexpected values in plane %d\n", nerrs, nplane);
+ }
+ }
+ /* Have read all current planes */
+ nplane_old=dims[0];
+
+ /* check if dataset has grown since last time */
+ /* close dsid and file, then reopen them */
+ if (H5Dclose(dsid) < 0){
+ fprintf(stderr, "H5Dclose failed\n");
+ return -1;
+ }
+ if (H5Fclose(fid) < 0){
+ fprintf(stderr, "H5Fclose failed\n");
+ return -1;
+ }
+ if((fid = H5Fopen(name, H5F_ACC_RDONLY | (UC_opts.use_swmr ? H5F_ACC_SWMR_READ : 0), H5P_DEFAULT)) < 0){
+ fprintf(stderr, "H5Fopen failed\n");
+ return -1;
+ }
+ if((dsid = H5Dopen2(fid, name, H5P_DEFAULT)) < 0){
+ fprintf(stderr, "H5Dopen2 failed\n");
+ return -1;
+ }
+ f_sid = H5Dget_space(dsid); /* Get filespace handle first. */
+ if (H5Sget_simple_extent_dims(f_sid, dims, NULL) < 0){
+ fprintf(stderr, "H5Sget_simple_extent_dims got error\n");
+ return -1;
+ }
+ }
+
+ if (nreadererr)
+ return -1;
+ else
+ return 0;
+}
+
+
+/* Overall Algorithm:
+ * Parse options from user;
+ * Generate/pre-created test files needed and close it;
+ * fork: child process becomes the reader process;
+ * while parent process continues as the writer process;
+ * both run till ending conditions are met.
+ */
+int
+main(int argc, char *argv[])
+{
+ pid_t childpid, mypid, tmppid;
+ int child_status;
+ int child_wait_option=0;
+ int ret_value = 0;
+ int child_ret_value;
+
+ /* initialization */
+ /* use case defaults */
+ HDmemset(&UC_opts, 0, sizeof(options_t));
+ UC_opts.h5_use_chunks = 1; /* use chunked datasets */
+ UC_opts.chunksize = Chunksize_DFT;
+ UC_opts.num_dsets = 1;
+ UC_opts.compress = 0; /* no compression */
+ UC_opts.use_swmr = 1; /* use swmr open */
+
+ /* parse options */
+ if (parse_option(argc, argv) < 0){
+ Hgoto_error(1);
+ }
+
+ /* data file name is <progname>.h5 */
+ if ((UC_opts.filename=(char*)HDmalloc(HDstrlen(progname_g)+4))==NULL) {
+ fprintf(stderr, "malloc: failed\n");
+ Hgoto_error(1);
+ };
+ HDstrcpy(UC_opts.filename, progname_g);
+ HDstrcat(UC_opts.filename, ".h5");
+
+ /* generate files */
+ printf("Creating data file for test...\n");
+ if (create_uc_file() < 0){
+ fprintf(stderr, "***encounter error\n");
+ Hgoto_error(1);
+ }else
+ printf("File created.\n");
+
+ /* fork process */
+ if((childpid = fork()) < 0) {
+ perror("fork");
+ Hgoto_error(1);
+ };
+ mypid = getpid();
+
+ /* child process becomes the reader */
+ if(0 == childpid) {
+ printf("%d: become reader process\n", mypid);
+ if (read_uc_file() < 0){
+ fprintf(stderr, "read_uc_file encountered error\n");
+ Hgoto_error(1);
+ }
+ exit(0);
+ }
+
+ /* this process continues as the writer */
+ printf("%d: child pid is %d\n", mypid, childpid);
+ printf("%d: continue as the writer process\n", mypid);
+ if (write_uc_file() < 0){
+ fprintf(stderr, "write_uc_file encountered error\n");
+ Hgoto_error(1);
+ }
+
+ /* Collect exit code of child process */
+ if ((tmppid = waitpid(childpid, &child_status, child_wait_option)) < 0){
+ perror("waitpid");
+ Hgoto_error(1);
+ }
+ if (WIFEXITED(child_status)){
+ if ((child_ret_value=WEXITSTATUS(child_status)) != 0){
+ printf("%d: child process exited with non-zero code (%d)\n",
+ mypid, child_ret_value);
+ Hgoto_error(2);
+ }
+ } else {
+ printf("%d: child process terminated abnormally\n", mypid);
+ Hgoto_error(2);
+ }
+
+done:
+ /* Print result and exit */
+ if (ret_value != 0){
+ printf("Error(s) encountered\n");
+ }else{
+ printf("All passed\n");
+ }
+
+ return(ret_value);
+}
diff --git a/test/usecase_common.c b/test/usecase_common.c
new file mode 100644
index 0000000..0230644
--- /dev/null
+++ b/test/usecase_common.c
@@ -0,0 +1,81 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "usecase.h"
+
+void
+usage(const char *prog)
+{
+ fprintf(stderr, "usage: %s [OPTIONS]\n", prog);
+ fprintf(stderr, " OPTIONS\n");
+ fprintf(stderr, " -h, --help Print a usage message and exit\n");
+ fprintf(stderr, " -z N, --chunksize=N Chunk size [default: %d]\n", Chunksize_DFT);
+ fprintf(stderr, " -s N, --swmr=N Use SWMR mode (0: no, non-0: yes) default is yes\n");
+ fprintf(stderr, "\n");
+}
+
+/* Setup Use Case parameters by parsing command line options.
+* Setup default values if not set by options. */
+int
+parse_option(int argc, char * const argv[])
+{
+ int ret_value=0;
+ int c;
+ /* command line options: See function usage for a description */
+ const char *nagg_options = "hs:z:";
+
+ /* suppress getopt from printing error */
+ opterr = 0;
+
+ while (1){
+ c = getopt (argc, argv, nagg_options);
+ if (-1 == c)
+ break;
+ switch (c) {
+ case 'h':
+ usage(progname_g);
+ break;
+ case 'z': /* size of chunk=(z,z) */
+ if ((UC_opts.chunksize = atoi(optarg)) <= 0){
+ fprintf(stderr, "bad chunksize %s, must be a positive integer\n", optarg);
+ usage(progname_g);
+ Hgoto_error(-1);
+ };
+ break;
+ case 's': /* use swmr file open mode */
+ UC_opts.use_swmr=0;
+ if ((UC_opts.use_swmr = atoi(optarg)) < 0){
+ fprintf(stderr, "use swmr value should be 0(no) or 1(yes)\n");
+ usage(progname_g);
+ Hgoto_error(-1);
+ };
+ break;
+ case '?':
+ fprintf(stderr, "getopt returned '%c'.\n", c);
+ Hgoto_error(-1);
+ default:
+ fprintf(stderr, "getopt returned unexpected value.\n");
+ fprintf(stderr, "Unexpected value is %d\n", c);
+ Hgoto_error(-1);
+ }
+ }
+
+ /* set nplanes */
+ if (UC_opts.nplanes == 0)
+ UC_opts.nplanes = UC_opts.chunksize;
+
+done:
+ /* All done. */
+ return(ret_value);
+}