mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-11-27 02:10:55 +08:00
44a00ef876
* Strip HD prefix from string/char C API calls * HD(f)(put|get)(s|c) * HDstr* * HDv*printf * HD(s)(print|scan)f * HDperror But NOT: * HDstrcase* * HDvasprintf * HDstrtok_r * HDstrndup As those are not C99 and have portability work-around implementations. They will be handled later. * Fix th5_system.c screwup
281 lines
9.6 KiB
C
281 lines
9.6 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* 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://www.hdfgroup.org/licenses. *
|
|
* 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.
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "h5test.h"
|
|
|
|
/* This test uses many POSIX things that are not available on
|
|
* Windows.
|
|
*/
|
|
#if defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID)
|
|
|
|
#include "use.h"
|
|
|
|
#define USE_APPEND_CHUNK_PROGNAME "use_append_chunk"
|
|
|
|
static options_t UC_opts; /* Use Case Options */
|
|
|
|
/* Setup parameters for the use case.
|
|
* Return: 0 succeed; -1 fail.
|
|
*/
|
|
int
|
|
setup_parameters(int argc, char *const argv[], options_t *opts)
|
|
{
|
|
/* use case defaults */
|
|
memset(opts, 0, sizeof(options_t));
|
|
opts->chunksize = Chunksize_DFT;
|
|
opts->use_swmr = true; /* use swmr open */
|
|
opts->iterations = 1;
|
|
opts->chunkplanes = 1;
|
|
opts->progname = USE_APPEND_CHUNK_PROGNAME;
|
|
|
|
if (parse_option(argc, argv, opts) < 0)
|
|
return (-1);
|
|
|
|
opts->chunkdims[0] = opts->chunkplanes;
|
|
opts->chunkdims[1] = opts->chunkdims[2] = opts->chunksize;
|
|
|
|
opts->dims[0] = 0;
|
|
opts->max_dims[0] = H5S_UNLIMITED;
|
|
opts->dims[1] = opts->dims[2] = opts->max_dims[1] = opts->max_dims[2] = opts->chunksize;
|
|
|
|
if (opts->nplanes == 0)
|
|
opts->nplanes = (hsize_t)opts->chunksize;
|
|
|
|
show_parameters(opts);
|
|
return (0);
|
|
} /* setup_parameters() */
|
|
|
|
/* 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;
|
|
bool send_wait = false;
|
|
hid_t fapl = H5I_INVALID_HID; /* File access property list */
|
|
hid_t fid = H5I_INVALID_HID; /* File ID */
|
|
|
|
if (setup_parameters(argc, argv, &UC_opts) < 0) {
|
|
Hgoto_error(1);
|
|
}
|
|
|
|
/* Determine the need to send/wait message file*/
|
|
if (UC_opts.launch == UC_READWRITE) {
|
|
HDunlink(WRITER_MESSAGE);
|
|
send_wait = true;
|
|
}
|
|
|
|
/* ==============================================================*/
|
|
/* 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) {
|
|
printf("Creating skeleton data file for test...\n");
|
|
if ((UC_opts.fapl_id = h5_fileaccess()) < 0) {
|
|
fprintf(stderr, "can't create creation FAPL\n");
|
|
Hgoto_error(1);
|
|
}
|
|
if (H5Pset_libver_bounds(UC_opts.fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) {
|
|
fprintf(stderr, "can't set creation FAPL libver bounds\n");
|
|
Hgoto_error(1);
|
|
}
|
|
if (create_uc_file(&UC_opts) < 0) {
|
|
fprintf(stderr, "***encounter error\n");
|
|
Hgoto_error(1);
|
|
}
|
|
else {
|
|
printf("File created.\n");
|
|
}
|
|
/* Close FAPL to prevent issues with forking later */
|
|
if (H5Pclose(UC_opts.fapl_id) < 0) {
|
|
fprintf(stderr, "can't close creation FAPL\n");
|
|
Hgoto_error(1);
|
|
}
|
|
UC_opts.fapl_id = H5I_INVALID_HID;
|
|
}
|
|
|
|
/* ============ */
|
|
/* Fork process */
|
|
/* ============ */
|
|
if (UC_opts.launch == UC_READWRITE) {
|
|
if ((childpid = fork()) < 0) {
|
|
perror("fork");
|
|
Hgoto_error(1);
|
|
}
|
|
}
|
|
mypid = HDgetpid();
|
|
|
|
/* ============= */
|
|
/* launch reader */
|
|
/* ============= */
|
|
if (UC_opts.launch != UC_WRITER) {
|
|
/* child process launch the reader */
|
|
if (0 == childpid) {
|
|
printf("%d: launch reader process\n", mypid);
|
|
if ((UC_opts.fapl_id = h5_fileaccess()) < 0) {
|
|
fprintf(stderr, "can't create read FAPL\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (read_uc_file(send_wait, &UC_opts) < 0) {
|
|
fprintf(stderr, "read_uc_file encountered error\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (H5Pclose(UC_opts.fapl_id) < 0) {
|
|
fprintf(stderr, "can't close read FAPL\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
/* ============= */
|
|
/* launch writer */
|
|
/* ============= */
|
|
/* this process continues to launch the writer */
|
|
printf("%d: continue as the writer process\n", mypid);
|
|
|
|
if ((fapl = h5_fileaccess()) < 0) {
|
|
fprintf(stderr, "can't create write FAPL\n");
|
|
Hgoto_error(1);
|
|
}
|
|
|
|
if (UC_opts.use_swmr) {
|
|
if (H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) {
|
|
fprintf(stderr, "can't set write FAPL libver bounds\n");
|
|
Hgoto_error(1);
|
|
}
|
|
}
|
|
|
|
if ((fid = H5Fopen(UC_opts.filename, H5F_ACC_RDWR | (UC_opts.use_swmr ? H5F_ACC_SWMR_WRITE : 0), fapl)) <
|
|
0) {
|
|
fprintf(stderr, "H5Fopen failed\n");
|
|
Hgoto_error(1);
|
|
}
|
|
|
|
if (write_uc_file(send_wait, fid, &UC_opts) < 0) {
|
|
fprintf(stderr, "write_uc_file encountered error\n");
|
|
Hgoto_error(1);
|
|
}
|
|
|
|
if (H5Fclose(fid) < 0) {
|
|
fprintf(stderr, "Failed to close write\n");
|
|
Hgoto_error(1);
|
|
}
|
|
|
|
if (H5Pclose(fapl) < 0) {
|
|
fprintf(stderr, "can't close write FAPL\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);
|
|
}
|
|
|
|
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:
|
|
if (ret_value != 0) {
|
|
printf("Error(s) encountered\n");
|
|
}
|
|
else {
|
|
printf("All passed\n");
|
|
}
|
|
|
|
return (ret_value);
|
|
}
|
|
|
|
#else /* defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID) */
|
|
|
|
int
|
|
main(void)
|
|
{
|
|
fprintf(stderr, "Non-POSIX platform. Skipping.\n");
|
|
return EXIT_SUCCESS;
|
|
} /* end main() */
|
|
|
|
#endif /* defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID) */
|