/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Use Case 1.8 Appending a hyperslab of multiple chunks. * Description: * Appending a hyperslab that spans several chunks of a dataset with * unlimited dimensions 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 several chunks (for * example, appending 2-dim planes along the slowest changing dimension * in the 3-dim dataset and each plane is covered by 4 chunks). * 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. * * Main Success Scenario: * 1. An application creates a file with required objects (groups, * datasets, and attributes). * 2. The Writer opens the file and datasets in the file and starts * adding data using H5Dwrite call with a hyperslab selection that * spans several chunks. * 3. A Reader opens the file and a dataset in a file; if the size of * the unlimited dimension has changed, reads the appended data back. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* Created: Albert Cheng, 2013/6/1 */ #include "h5test.h" /* This test uses many POSIX things that are not available on * Windows. We're using a check for fork(2) here as a proxy for * all POSIX/Unix/Linux things until this test can be made * more platform-independent. */ #ifdef H5_HAVE_FORK #include "use.h" /* Global Variable definitions */ options_t UC_opts; /* Use Case Options */ const char *progname_g="use_append_mchunks"; /* program name */ /* Setup parameters for the use case. * Return: 0 succeed; -1 fail. */ int setup_parameters(int argc, char * const argv[]) { /* use case defaults */ HDmemset(&UC_opts, 0, sizeof(options_t)); UC_opts.chunksize = Chunksize_DFT; UC_opts.use_swmr = 1; /* use swmr open */ UC_opts.iterations = 1; UC_opts.chunkplanes = 1; /* parse options */ if (parse_option(argc, argv) < 0){ return(-1); } /* set chunk dims */ UC_opts.chunkdims[0] = (hsize_t)UC_opts.chunkplanes; UC_opts.chunkdims[1] = UC_opts.chunkdims[2] = (hsize_t)UC_opts.chunksize; /* set dataset initial and max dims */ UC_opts.dims[0] = 0; UC_opts.max_dims[0] = H5S_UNLIMITED; UC_opts.dims[1] = UC_opts.dims[2] = UC_opts.max_dims[1] = UC_opts.max_dims[2] = 2 * (hsize_t)UC_opts.chunksize; /* set nplanes */ if (UC_opts.nplanes == 0) UC_opts.nplanes = 2 * (hsize_t)UC_opts.chunksize; /* show parameters and return */ show_parameters(); 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=0; pid_t mypid, tmppid; int child_status; int child_wait_option=0; int ret_value = 0; int child_ret_value; hbool_t send_wait = 0; hid_t fapl = -1; /* File access property list */ hid_t fid = -1; /* File ID */ char *name; /* Test file name */ /* initialization */ if (setup_parameters(argc, argv) < 0){ Hgoto_error(1); } /* Determine the need to send/wait message file*/ if(UC_opts.launch == UC_READWRITE) { HDunlink(WRITER_MESSAGE); send_wait = 1; } /* ==============================================================*/ /* UC_READWRITE: create datafile, launch both reader and writer. */ /* UC_WRITER: create datafile, skip reader, launch writer. */ /* UC_READER: skip create, launch reader, exit. */ /* ==============================================================*/ /* ============*/ /* Create file */ /* ============*/ if (UC_opts.launch != UC_READER){ HDprintf("Creating skeleton data file for test...\n"); if (create_uc_file() < 0){ HDfprintf(stderr, "***encounter error\n"); Hgoto_error(1); }else HDprintf("File created.\n"); } if (UC_opts.launch==UC_READWRITE){ /* fork process */ if((childpid = fork()) < 0) { perror("fork"); Hgoto_error(1); }; }; mypid = getpid(); /* ============= */ /* launch reader */ /* ============= */ if (UC_opts.launch != UC_WRITER){ /* child process launch the reader */ if(0 == childpid) { HDprintf("%d: launch reader process\n", mypid); if (read_uc_file(send_wait) < 0){ HDfprintf(stderr, "read_uc_file encountered error\n"); HDexit(EXIT_FAILURE); } HDexit(EXIT_SUCCESS); } } /* ============= */ /* launch writer */ /* ============= */ /* this process continues to launch the writer */ HDprintf("%d: continue as the writer process\n", mypid); name = UC_opts.filename; /* Set the file access property list */ if((fapl = h5_fileaccess()) < 0) Hgoto_error(1); if(UC_opts.use_swmr) if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) Hgoto_error(1); /* Open the file */ if((fid = H5Fopen(name, H5F_ACC_RDWR | (UC_opts.use_swmr ? H5F_ACC_SWMR_WRITE : 0), fapl)) < 0) { HDfprintf(stderr, "H5Fopen failed\n"); Hgoto_error(1); } if(write_uc_file(send_wait, fid) < 0) { HDfprintf(stderr, "write_uc_file encountered error\n"); Hgoto_error(1); } /* ================================================ */ /* If readwrite, collect exit code of child process */ /* ================================================ */ if (UC_opts.launch == UC_READWRITE){ if ((tmppid = waitpid(childpid, &child_status, child_wait_option)) < 0){ perror("waitpid"); Hgoto_error(1); } /* Close the file */ if(H5Fclose(fid) < 0) { HDfprintf(stderr, "Failed to close file id\n"); Hgoto_error(1); } /* Close the property list */ if(H5Pclose(fapl) < 0) { HDfprintf(stderr, "Failed to close the property list\n"); Hgoto_error(1); } if (WIFEXITED(child_status)){ if ((child_ret_value=WEXITSTATUS(child_status)) != 0){ HDprintf("%d: child process exited with non-zero code (%d)\n", mypid, child_ret_value); Hgoto_error(1); } } else { HDprintf("%d: child process terminated abnormally\n", mypid); Hgoto_error(2); } } done: /* Print result and exit */ if (ret_value != 0){ HDprintf("Error(s) encountered\n"); }else{ HDprintf("All passed\n"); } return(ret_value); } #else /* H5_HAVE_FORK */ int main(void) { HDfprintf(stderr, "Non-POSIX platform. Skipping.\n"); return EXIT_SUCCESS; } /* end main() */ #endif /* H5_HAVE_FORK */