diff options
42 files changed, 4674 insertions, 1332 deletions
@@ -1420,6 +1420,7 @@ ./test/vfd_swmr_common.h ./test/vfd_swmr_generator.c ./test/vfd_swmr_group_writer.c +./test/vfd_swmr_gperf_writer.c ./test/vfd_swmr_reader.c ./test/vfd_swmr_remove_reader.c ./test/vfd_swmr_remove_writer.c diff --git a/doc/vfd-swmr-user-guide.md b/doc/vfd-swmr-user-guide.md index 6a14487..a4375b3 100644 --- a/doc/vfd-swmr-user-guide.md +++ b/doc/vfd-swmr-user-guide.md @@ -35,7 +35,7 @@ with results that become visible to the VFD SWMR readers. In particular, VFD SWMR allows the writer to create and delete both groups and datasets, and to create and delete attributes on both groups and datasets while operating in VFD SWMR mode -- -which is not possible in the original SWMR. +which is not possible using the original SWMR implementation. We say that VFD SWMR is almost "full SWMR" because there are a few limitations -- most notably: @@ -69,68 +69,44 @@ the writer makes HDF5 library API calls with sufficient regularity, and that both reader and writer avoid long running HDF5 API calls. For further details on VFD SWMR design and implementation, see -VFD_SWMR_RFC_200916.pdf or VFD_SWMR_RFC_200916.docx in the -doc directory. +`VFD_SWMR_RFC_200916.pdf` in the doc directory. # Quick start Follow these instructions to download, configure, and build the -VFD SWMR project in a jiffy. Then install the HDF5 library and +VFD SWMR project, then install the HDF5 library and utilities built by the VFD SWMR project. ## Download Clone the HDF5 repository in a new directory, then switch to the -features/vfd_swmr_alpa_1 branch as follows: +`feature/vfd_swmr_beta_1` branch as follows: ``` -% git clone https://@bitbucket.hdfgroup.org/scm/hdffv/hdf5.git swmr +% git clone https://github.com/HDFGroup/hdf5 swmr % cd swmr -% git checkout feature/vfd_swmr_alpha_1 +% git checkout feature/vfd_swmr_beta_1 ``` ## Build -Create a build directory, change to that directory, and run the -configure script: +There are no special instructions for building VFD SWMR. Simply follow +the usual build procedure for CMake or the Autotools using the guides +in the `release_docs` directory. -``` -% mkdir -p ../build/swmr -% cd ../build/swmr -% ../../swmr/configure -``` - -Build the project: - -``` -% make -``` - -## Test - -We recommend that you run the full HDF5 test suite to make sure that VFD -SWMR works correctly on your system. To test the library, utilities, run - -``` -% make check -``` +IMPORTANT: -If the tests don't pass, please let the developers know! +The VFD SWMR branches are maintenance branches and will default to a debug +build. They also do not come with generated files, so Perl will be required +when building with CMake and Perl and the Autotools (autoconf, etc.) will +be required when building with the Autotools. -Note that due to reader and writer process drifting out of sync, you -are likely to see several messages such as: +Some notes: -``` - vfd_swmr_zoo_reader: tend_zoo: vrfy_ns_grp_c: H5Gopen2() failed -``` -or -``` - vfd_swmr_zoo_reader: tend_zoo: H5Lexists unexpectedly true. -``` - -These are expected transient failues. In addition, there will be -expected errors in the variable length data tests until we are able -to re-implement variable length data storage in HDF5. +- The mirror VFD tests require some rework, so enabling that feature will cause the build step to fail. This will be fixed in a future beta release. +- The VFD SWMR tests can take some time to run. +- The VFD SWMR acceptance tests will typically emit some output about "expected errors" that you can ignore. Real errors are clearly flagged. +- If the tests do not pass on your system, please let the developers know via the email address given at the end of this document. # Sample programs @@ -170,48 +146,51 @@ and in the other window, run the reader: % ./vfd_swmr_bigset_reader -n 50 -d 2 -W ``` -The writer will wait for a signal before it quits. You may tap -Control-C to make it quit. +The writer will wait for a signal before it quits. You can tap CTRL-C to make +it quit. The reader and writer programs support several command-line options: -* `-h`: show program usage - -* `-W`: stop the program from waiting for a signal before it quits. - -* `-q`: suppress the progress messages that the programs write to the - standard error stream. - -* `-V`: create a virtual dataset with content in three source datasets - in the same HDF5 file---only available when the writer creates a - dataset extensible in one dimension (`-d 1`) - -* `-M`: like `-V`, the writer creates the virtual dataset on three - source datasets, but each source dataset is in a different HDF5 file. +``` +usage: vfd_swmr_bigset_writer [-F] [-M] [-S] [-V] [-W] [-a steps] [-b] [-c cols] + [-d dims] + [-n iterations] [-r rows] [-s datasets] + [-u milliseconds] + +-F: fixed maximal dimension for the chunked datasets +-M: use virtual datasets and many source files +-S: do not use VFD SWMR +-V: use virtual datasets and a single source file +-W: do not wait for a signal before exiting +-a steps: `steps` between adding attributes +-b: write data in big-endian byte order +-c cols: `cols` columns per chunk +-d 1|one|2|two|both: select dataset expansion in one or + both dimensions +-n iterations: how many times to expand each dataset +-r rows: `rows` rows per chunk +-s datasets: number of datasets to create +-u ms: milliseconds interval between updates + to vfd_swmr_bigset_writer.h5 +``` ## The VFD SWMR demos -The VFD SWMR demos are in a [separate -repository](https://bitbucket.hdfgroup.org/scm/~dyoung/swmr-demo.git). - -Before you build the demos, you will need to install the HDF5 library -and utilities built from the VFD SWMR branch in your home directory -somewhere. In the ./configure step, use the command-line option -`--prefix=$HOME/path/for/library` to set the directory you prefer. -In the demo Makefiles, update the `H5CC` variable with the path to -the `h5cc` installed from the VFD SWMR branch. Then you should be -able to `make` and `make clean` the demos. +The VFD SWMR demos are located in the `examples` directory of this source +tree. Instructions for building the example programs are given in the README +file in that directory. These programs are NOT installed via `make install` +and have to built by hand with h5cc as described in the README. -Under `gaussians/`, two programs are built, `wgaussians` and -`rgaussians`. If you start both from the same directory in different -terminals, you should see the "bouncing 2-D Gaussian distributions" -in the `rgaussians` terminal. This demo uses curses, so you may need -to install the curses developers library to build. +Two Gaussian programs are built, `wgaussians` and `rgaussians`. If you start +both from the same directory in different terminals, you should see the +"bouncing 2-D Gaussian distributions" in the `rgaussians` terminal. This demo +uses curses, so you may need to install the curses developers library to build +(and this is probably not going to be easy to build on Windows). The creation-deletion (`credel`) demo is also run in two terminals. -The two command lines are given in `credel/README.md`. You need -to use the `h5ls` installed from the VFD SWMR branch, since only -that version has the `--poll` option. +The two command lines are given in the README. You need to use the `h5ls` +installed from the VFD SWMR branch, since only that version has the `--poll` +option. Be careful to not use a non-VFD-SWMR system h5ls here. # Developer tips @@ -219,7 +198,7 @@ that version has the `--poll` option. ### File-creation properties -To use VFD SWMR, creating your HDF5 file with paged allocation strategy +To use VFD SWMR, creating your HDF5 file with a paged allocation strategy is mandatory. This call enables the paged allocation strategy: ``` @@ -233,74 +212,40 @@ allocation strategy. ### File-access properties -In this section we dissect `vfd_swmr_create_fapl()`, a helper routine in -the VFD SWMR tests, to show how to configure your application to use VFD +In this section we show how to configure your application to use VFD SWMR. -``` -hid_t -vfd_swmr_create_fapl(bool writer, bool only_meta_pages, bool use_vfd_swmr) -{ - H5F_vfd_swmr_config_t config; - hid_t fapl; - -``` - -`h5_fileaccess()` is also a helper routine for the tests. In your -program, you can replace the `h5_fileaccess()` call with a call to -`H5Pcreate(H5P_FILE_ACCESS)`. - -``` - /* Create file access property list */ - if((fapl = h5_fileaccess()) < 0) { - warnx("h5_fileaccess"); - return badhid; - } -``` - - -VFD SWMR has only been tested with the latest file format. It may -malfunction with older formats, we just don't know. We force the -latest version here. - -``` - /* FOR NOW: set to use latest format, the "old" parameter is not used */ - if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) { - warnx("H5Pset_libver_bounds"); - return badhid; - } - - /* - * Set up to open the file with VFD SWMR configured. - */ -``` +1. Create a file access property list using `H5Pcreate(H5P_FILE_ACCESS)`. +2. Set the latest file format using `H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST)`. +3. Enable page buffering using `H5Pset_page_buffer_size()`. +4. Set any VFD SWMR configuration properties using `H5Pset_vfd_swmr_config()`. The struct is documented in H5Fpublic.h, with some additional documentation below. (In the near future, this struct will be documented in the library's Doxygen documentation.) VFD SWMR relies on metadata reads and writes to go through the -page buffer. Note that the default page size is 4096 bytes. This -call sets the total page buffer size to 4096 bytes. So we have -effectively created a one-page page buffer! That is adequate for -testing, but it may not be best for your application. - -If `only_meta_pages` is true, then the entire page buffer is -dedicated to metadata. That's fine for VFD SWMR. +page buffer. Note that the default page size is 4096 bytes. Finding good +values for `buf_size` may take some experimentation. We use 4096 (giving a +single page buffer) for `buf_size` in our test code. *Note well*: when VFD SWMR is enabled, the meta-/raw-data pages proportion set by `H5Pset_page_buffer_size()` does not actually control the pages reserved for raw data. *All* pages are dedicated to buffering metadata. +### `H5F_vfd_swmr_config_t` fields discussion + +Example code: ``` - /* Enable page buffering */ - if(H5Pset_page_buffer_size(fapl, 4096, only_meta_pages ? 100 : 0, 0) < 0) { - warnx("H5Pset_page_buffer_size"); - return badhid; - } -``` + memset(&config, 0, sizeof(config)); + config.version = H5F__CURR_VFD_SWMR_CONFIG_VERSION; + config.tick_len = 4; + config.max_lag = 7; + config.writer = true; + config.md_pages_reserved = 128; + strcpy(config.md_file_path, "./my_md_file"); -Add VFD SWMR-specific configuration to the file-access property list -(`fapl`) using an `H5Pset_vfd_swmr_config()` call. + H5Pset_vfd_swmr_config(fapl, &config); +``` When VFD SWMR is enabled, changes to the HDF5 metadata accumulate in RAM until a configurable unit of time known as a *tick* has passed. @@ -308,11 +253,11 @@ At the end of each tick, a snapshot of the metadata at the end of the tick is "published"---that is, made visible to the readers. The length of a *tick* is configurable in units of 100 milliseconds -using the `tick_len` parameter. Below, `tick_len` is set to `4` to +using the `tick_len` parameter. Here, `tick_len` is set to `4` to select a tick length of 400ms. A snapshot does not persist forever, but it expires after a number -of ticks, given by the *maximum lag*, has passed. Below, `max_lag` +of ticks, given by the *maximum lag*, has passed. Here, `max_lag` is set to `7` to select a maximum lag of 7 ticks. After a snapshot has expired, the writer may overwrite it. @@ -352,25 +297,6 @@ The `version` parameter tells what version of VFD SWMR configuration the parameter struct `config` contains. For now, it should be initialized to `H5F__CURR_VFD_SWMR_CONFIG_VERSION`. -``` - memset(&config, 0, sizeof(config)); - - config.version = H5F__CURR_VFD_SWMR_CONFIG_VERSION; - config.tick_len = 4; - config.max_lag = 7; - config.writer = writer; - config.md_pages_reserved = 128; - HDstrcpy(config.md_file_path, "./my_md_file"); - - /* Enable VFD SWMR configuration */ - if(use_vfd_swmr && H5Pset_vfd_swmr_config(fapl, &config) < 0) { - warnx("H5Pset_vfd_swmr_config"); - return badhid; - } - return fapl; -} -``` - ## Using virtual datasets (VDS) An application may want to use VFD SWMR to create, read, or write @@ -412,14 +338,14 @@ user configurable in the first production release. With the currently hard coded flush of raw data at the end of each tick, it should not be necessary to call H5Fflush(). In fact, when VFD SWMR is -active, H5Fflush() may require up to 'max_lag' ticks to complete due to +active, H5Fflush() may require up to `max_lag` ticks to complete due to metadata consistency issues. Instead, a writer can make its last changes to HDF5 file visible to all readers immediately using the new call, `H5Fvfd_swmr_end_tick()`. Note that this call should be used sparingly, as it terminates the current -tick early, thus effectively reducing 'max_lag'. Repeated calls in -quick succession can force a reader to overrun 'max_lag', and +tick early, thus effectively reducing `max_lag`. Repeated calls in +quick succession can force a reader to overrun `max_lag`, and read stale metadata. When the flush of raw data at end of tick is disabled (not possible at present), @@ -527,14 +453,6 @@ object---while the writer deletes it, then reading content through the handle may yield corrupted data or the data from some other object, or the library may crash. -## Microsoft Windows - -VFD SWMR is not officially supported on Microsoft Windows at this time. The -feature should in theory work on Windows and NTFS, however it has not been -tested as the existing VFD SWMR tests rely on shell scripts. Note that Windows -file shares are not supported as there is no write ordering guarantee (as with -NFS, et al.). - ## Supported filesystems A VFD SWMR writer and readers share a couple of files, the HDF5 (`.h5`) @@ -547,12 +465,20 @@ ordering should take effect, regardless of the underlying filesystem. If the VFD SWMR reader and the writer run on *different* hosts, then the write-ordering rules depend on the shared filesystem. VFD SWMR is -not generally expected to work with NFS at this time. GPFS is reputed -to order writes according to POSIX convention, so we expect VFD SWMR -to work with GPFS. (Caveat: we are still looking for an authoritative -description of GPFS I/O semantics.) +not generally expected to work with NFS at this time. Parallel file systems +like GPFS and Lustre should order writes according to POSIX convention, so we +expect VFD SWMR to work on those file systems but we have not tested this. -The HDF Group plans to add support for NFS to VFD SWMR in the future. +The HDF Group plans to add support for networked file systems like NFS and +Windows SMB to VFD SWMR in the future. + +## Microsoft Windows + +VFD SWMR is not officially supported on Microsoft Windows at this time. The +feature should in theory work on Windows and NTFS, however it has not been +tested as the existing VFD SWMR tests rely on shell scripts. Note that Windows +file shares are not supported as there is no write ordering guarantee (as with +NFS, et al.). ## File-opening order @@ -564,7 +490,7 @@ seconds. # Reporting bugs -VFD SWMR is still under development, so we expect that you will encounter +VFD SWMR is still under development, so it is possible that you will encounter bugs. Please report them, along with any performance or design issues you encounter. @@ -60,7 +60,7 @@ typedef struct H5FD_wrap_t { /********************/ /* Local Prototypes */ /********************/ -static herr_t H5FD__free_cls(H5FD_class_t *cls); +static herr_t H5FD__free_cls(H5FD_class_t *cls, void **request); static herr_t H5FD__query(const H5FD_t *f, unsigned long *flags /*out*/); /*********************/ @@ -180,7 +180,7 @@ H5FD_term_package(void) *------------------------------------------------------------------------- */ static herr_t -H5FD__free_cls(H5FD_class_t *cls) +H5FD__free_cls(H5FD_class_t *cls, void H5_ATTR_UNUSED **request) { herr_t ret_value = SUCCEED; @@ -668,68 +668,81 @@ done: FUNC_LEAVE_API(ret_value) } -/* Helper routine for H5FD_deduplicate(): compare `self` and `other` using - * the deduplication method of `self`, if it has one; otherwise compare using - * `H5FDcmp()`. +/*------------------------------------------------------------------------- + * Function: H5FD__dedup + * + * Purpose: Helper routine for H5FD_deduplicate + * + * Compares `self` and `other` using the dedup callback of + * `self` (if it has one); otherwise compares using `H5FDcmp()`. + * + * No `dedup' callback: + * + * If `self` has no de-duplication method, compare `self` and + * `other` using `H5FDcmp()` and return `self` if they're equal + * and `other` if unequal. + * + * `dedup' callback present: + * + * If `self` does have a de-duplication callback, invoke it and + * return the method's result: `other` if it duplicates `self`, + * `self` if `other` does NOT duplicate it, NULL if `other` + * conflicts with `self` or if there is an error. * - * If `self` has no de-duplication method, compare `self` and `other` - * using `H5FDcmp()` and return `self` if they're equal and `other` if - * unequal. + * Return: Success: `self' or `other', as described above * - * If `self` does have a de-duplication method, call it and return the - * method's result: `other` if it duplicates `self`, `self` if `other` - * does NOT duplicate it, NULL if `other` conflicts with `self` or if - * there is an error. + * Failure: NULL + * + * Note: Unlike H5FD_deduplicate(), this routine does not free `self` + * under any circumstances. + * + *------------------------------------------------------------------------- * - * Unlike H5FD_deduplicate(), this routine does not free `self` under any - * circumstances. */ -static H5FD_t * -H5FD_dedup(H5FD_t *self, H5FD_t *other, hid_t fapl) -{ - H5FD_t *(*dedup)(H5FD_t *, H5FD_t *, hid_t); - - if ((dedup = self->cls->dedup) != NULL) - return (*dedup)(self, other, fapl); - - if (H5FDcmp(self, other) == 0) - return self; - return other; -} - -/* Search the already-opened VFD instances for an instance similar to the - * instance `file` newly-opened using file-access properties given by `fapl`. +/*------------------------------------------------------------------------- + * Function: H5FD_deduplicate + * + * Purpose: Search the already-opened VFD instances for an instance + * similar to the instance `file` newly-opened using file access + * properties given by `fapl_id`. * - * If there is an already-open instance that is functionally - * identical to `file`, close `file` and return the already-open instance. + * Return: It's complicated... * - * If there is an already-open instance that conflicts with `file` because, - * for example, its file-access properties are incompatible with `fapl`'s - * or, for another example, it is under exclusive control by a third VFD - * instance, then close `file` and return `NULL`. + * If there is an already-open instance that is functionally + * identical to `file`, close `file` and return the already + * open instance. * - * Otherwise, return `file` to indicate that there are no identical or - * conflicting VFD instances already open. + * If there is an already open instance that conflicts with + * `file` because, for example, its file-access properties are + * incompatible with `fapl_id`'s or, for another example, it is + * under exclusive control by a third VFD instance, then close + * `file` and return `NULL`. + * + * Otherwise, return `file` to indicate that there are no + * identical or conflicting VFD instances already open. + *------------------------------------------------------------------------- */ H5FD_t * -H5FD_deduplicate(H5FD_t *file, hid_t fapl) +H5FD_deduplicate(H5FD_t *file, hid_t fapl_id) { - H5FD_t * deduped = file; H5FD_wrap_t *item; + H5FD_t * ret_value = file; + + FUNC_ENTER_NOAPI(NULL) TAILQ_FOREACH(item, &all_vfds, link) { - /* skip "self" */ + /* Skip "self" */ if (item->file == file) continue; - /* skip files with exclusive owners, for now */ + /* Skip files with exclusive owners, for now */ if (item->file->exc_owner != NULL) continue; - if ((deduped = H5FD_dedup(item->file, file, fapl)) != file) - goto finish; + if ((ret_value = H5FD_vfd_swmr_dedup(item->file, file, fapl_id)) != file) + goto done; } /* If we reach this stage, then we identified neither a conflict nor a @@ -741,19 +754,17 @@ H5FD_deduplicate(H5FD_t *file, hid_t fapl) if (item->file == file || item->file->exc_owner == NULL) continue; - if (H5FDcmp(file, item->file) == 0) { - deduped = NULL; - break; - } + if (H5FD_cmp(file, item->file) == 0) + HGOTO_ERROR(H5E_VFL, H5E_FILEOPEN, NULL, + "found a conflicting open file when searching for duplicates") } -finish: - if (deduped != file && H5FD_close(file) < 0) { - HERROR(H5E_FILE, H5E_CANTOPENFILE, "could not close file"); - return NULL; - } - return deduped; -} +done: + if (ret_value != file && H5FD_close(file) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL, "could not close file") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FD_deduplicate() */ /*------------------------------------------------------------------------- * Function: H5FD_open diff --git a/src/H5FDcore.c b/src/H5FDcore.c index f405200..50288c4 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -183,7 +183,6 @@ static const H5FD_class_t H5FD_core_g = { H5FD__core_lock, /* lock */ H5FD__core_unlock, /* unlock */ H5FD__core_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDdevelop.h b/src/H5FDdevelop.h index 5cf30ff..a723a1d 100644 --- a/src/H5FDdevelop.h +++ b/src/H5FDdevelop.h @@ -192,7 +192,6 @@ typedef struct H5FD_class_t { herr_t (*lock)(H5FD_t *file, hbool_t rw); herr_t (*unlock)(H5FD_t *file); herr_t (*del)(const char *name, hid_t fapl); - H5FD_t *(*dedup)(H5FD_t *, H5FD_t *, hid_t); H5FD_mem_t fl_map[H5FD_MEM_NTYPES]; } H5FD_class_t; diff --git a/src/H5FDdirect.c b/src/H5FDdirect.c index 2a51883..a1b7b7e 100644 --- a/src/H5FDdirect.c +++ b/src/H5FDdirect.c @@ -172,7 +172,6 @@ static const H5FD_class_t H5FD_direct_g = { H5FD__direct_lock, /* lock */ H5FD__direct_unlock, /* unlock */ H5FD__direct_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 2356309..b265e1d 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -137,7 +137,6 @@ static const H5FD_class_t H5FD_family_g = { H5FD__family_lock, /* lock */ H5FD__family_unlock, /* unlock */ H5FD__family_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDhdfs.c b/src/H5FDhdfs.c index b308f17..102a3ab 100644 --- a/src/H5FDhdfs.c +++ b/src/H5FDhdfs.c @@ -310,7 +310,6 @@ static const H5FD_class_t H5FD_hdfs_g = { NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 4fd5e27..707c97b 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -212,7 +212,6 @@ static const H5FD_class_t H5FD_log_g = { H5FD__log_lock, /* lock */ H5FD__log_unlock, /* unlock */ H5FD__log_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDmirror.c b/src/H5FDmirror.c index 1886714..cf14c90 100644 --- a/src/H5FDmirror.c +++ b/src/H5FDmirror.c @@ -192,7 +192,6 @@ static const H5FD_class_t H5FD_mirror_g = { H5FD__mirror_lock, /* lock */ H5FD__mirror_unlock, /* unlock */ NULL, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index 2d86eed..dd40399 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -127,7 +127,6 @@ static const H5FD_class_mpi_t H5FD_mpio_g = { NULL, /* lock */ NULL, /* unlock */ H5FD__mpio_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }, /* End of superclass information */ H5FD__mpio_mpi_rank, /* get_rank */ diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index 1b5815a..86f7664 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -201,7 +201,6 @@ static const H5FD_class_t H5FD_multi_g = { H5FD_multi_lock, /* lock */ H5FD_multi_unlock, /* unlock */ H5FD_multi_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DEFAULT /* fl_map */ }; diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 2e3d270..0a8850f 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -367,6 +367,7 @@ H5_DLL H5FD_vfd_swmr_idx_entry_t *vfd_swmr_enlarge_shadow_index(struct H5F_t *); H5_DLL void H5FD_vfd_swmr_dump_status(H5FD_t *, uint64_t); H5_DLL void H5FD_vfd_swmr_set_pb_configured(H5FD_t *_file); H5_DLL void H5FD_vfd_swmr_record_elapsed_ticks(H5FD_t *, uint64_t); +H5_DLL H5FD_t *H5FD_vfd_swmr_dedup(H5FD_t *_self, H5FD_t *_other, hid_t fapl_id); /* Function prototypes for MPI based VFDs*/ #ifdef H5_HAVE_PARALLEL diff --git a/src/H5FDros3.c b/src/H5FDros3.c index 0303b50..6e116ee 100644 --- a/src/H5FDros3.c +++ b/src/H5FDros3.c @@ -267,7 +267,6 @@ static const H5FD_class_t H5FD_ros3_g = { NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index c694190..d823e3c 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -173,7 +173,6 @@ static const H5FD_class_t H5FD_sec2_g = { H5FD__sec2_lock, /* lock */ H5FD__sec2_unlock, /* unlock */ H5FD__sec2_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDsplitter.c b/src/H5FDsplitter.c index 91a8e84..c27cd1b 100644 --- a/src/H5FDsplitter.c +++ b/src/H5FDsplitter.c @@ -163,7 +163,6 @@ static const H5FD_class_t H5FD_splitter_g = { H5FD__splitter_lock, /* lock */ H5FD__splitter_unlock, /* unlock */ NULL, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index f9faf53..6631325 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -215,7 +215,6 @@ static const H5FD_class_t H5FD_stdio_g = { H5FD_stdio_lock, /* lock */ H5FD_stdio_unlock, /* unlock */ H5FD_stdio_delete, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/src/H5FDvfd_swmr.c b/src/H5FDvfd_swmr.c index 316ca6d..568f5d9 100644 --- a/src/H5FDvfd_swmr.c +++ b/src/H5FDvfd_swmr.c @@ -24,71 +24,64 @@ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ -#include "H5retry_private.h" /* Retry loops. */ +#include "H5retry_private.h" /* Retry loops. */ /* The driver identification number, initialized at runtime */ static hid_t H5FD_VFD_SWMR_g = 0; +/* The description of a file belonging to this driver */ typedef struct H5FD_vfd_swmr_t { - H5FD_t pub; /* public stuff, must be */ - /* first */ + H5FD_t pub; /* public stuff, must be first */ /* HDF5 file */ - char hdf5_filename[H5FD_MAX_FILENAME_LEN]; /* Name of the HDF5 file from */ - /* open */ - H5FD_t *hdf5_file_lf; /* Driver info for the HDF5 */ - /* file */ + char hdf5_filename[H5FD_MAX_FILENAME_LEN]; /* Name of the HDF5 file from open */ + H5FD_t *hdf5_file_lf; /* Driver info for the HDF5 file */ /* Metadata file */ - int md_fd; /* File descriptor for the */ - /* metadata file */ - uint32_t md_pages_reserved; /* # of pages reserved at the */ - /* head of the metadata file */ - char md_file_path[H5FD_MAX_FILENAME_LEN]; /* Name of the metadate file */ - H5FD_vfd_swmr_md_header md_header; /* Metadata file header */ - H5FD_vfd_swmr_md_index md_index; /* Metadata file index */ - - uint64_t *api_elapsed_ticks; /* Histogram of ticks elapsed - * inside the API (reader only). - * api_elapsed_ticks[elapsed] is - * the number of times `elapsed` - * ticks passed in an API call - * during the program lifetime. - */ - uint32_t api_elapsed_nbuckets; /* Number of histogram buckets. */ - - hbool_t pb_configured; /* boolean flag set to TRUE */ - /* when the page buffer is */ - /* and to FALSE otherwise. */ - /* Used for sanity checking. */ - H5F_vfd_swmr_config_t config; - hbool_t writer; /* True iff configured to write. - * All methods on a write-mode - * SWMR VFD instance are passed - * to the lower VFD instance. - */ + int md_fd; /* File descriptor for the metadata file */ + uint32_t md_pages_reserved; /* # of pages reserved at the head of the metadata file */ + char md_file_path[H5FD_MAX_FILENAME_LEN]; /* Name of the metadate file */ + H5FD_vfd_swmr_md_header md_header; /* Metadata file header */ + H5FD_vfd_swmr_md_index md_index; /* Metadata file index */ + + /* Histogram of ticks elapsed inside the API (reader only). + * api_elapsed_ticks[elapsed] is the number of times + * `elapsed' ticks passed during an API call in the + * program's lifetime. + */ + uint64_t *api_elapsed_ticks; /* Array of histogram buckets */ + uint32_t api_elapsed_nbuckets; /* Number of histogram buckets. */ + + hbool_t pb_configured; /* Sanity-checking flag set when page buffer is configured */ + H5F_vfd_swmr_config_t config; /* VFD SWMR configuration */ + + /* Flag set if the file is a SWMR writer. + * All methods on a write-mode SWMR VFD instance are passed + * to the lower VFD instance. + */ + hbool_t writer; + } H5FD_vfd_swmr_t; #define MAXADDR (((haddr_t)1 << (8 * sizeof(HDoff_t) - 1)) - 1) /* Prototypes */ -static herr_t H5FD_vfd_swmr_term(void); -static H5FD_t *H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); -static herr_t H5FD_vfd_swmr_close(H5FD_t *_file); -static int H5FD_vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2); -static H5FD_t *H5FD_vfd_swmr_dedup(H5FD_t *, H5FD_t *, hid_t); -static herr_t H5FD_vfd_swmr_query(const H5FD_t *_f1, unsigned long *flags); -static haddr_t H5FD_vfd_swmr_get_eoa(const H5FD_t *_file, H5FD_mem_t type); -static herr_t H5FD_vfd_swmr_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr); -static haddr_t H5FD_vfd_swmr_get_eof(const H5FD_t *_file, H5FD_mem_t type); -static herr_t H5FD_vfd_swmr_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle); -static herr_t H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, - void *buf); -static herr_t H5FD_vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, - const void *buf); -static herr_t H5FD_vfd_swmr_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); -static herr_t H5FD_vfd_swmr_lock(H5FD_t *_file, hbool_t rw); -static herr_t H5FD_vfd_swmr_unlock(H5FD_t *_file); +static herr_t H5FD__vfd_swmr_term(void); +static H5FD_t *H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr); +static herr_t H5FD__vfd_swmr_close(H5FD_t *_file); +static int H5FD__vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2); +static herr_t H5FD__vfd_swmr_query(const H5FD_t *_f1, unsigned long *flags); +static haddr_t H5FD__vfd_swmr_get_eoa(const H5FD_t *_file, H5FD_mem_t type); +static herr_t H5FD__vfd_swmr_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr); +static haddr_t H5FD__vfd_swmr_get_eof(const H5FD_t *_file, H5FD_mem_t type); +static herr_t H5FD__vfd_swmr_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle); +static herr_t H5FD__vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, + void *buf); +static herr_t H5FD__vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr, size_t size, + const void *buf); +static herr_t H5FD__vfd_swmr_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing); +static herr_t H5FD__vfd_swmr_lock(H5FD_t *_file, hbool_t rw); +static herr_t H5FD__vfd_swmr_unlock(H5FD_t *_file); /* VFD SWMR */ static htri_t H5FD__vfd_swmr_header_deserialize(H5FD_vfd_swmr_t *, H5FD_vfd_swmr_md_header *); @@ -97,40 +90,39 @@ static htri_t H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD static herr_t H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *, hbool_t); static const H5FD_class_t H5FD_vfd_swmr_g = { - "vfd_swmr", /* name */ - MAXADDR, /* maxaddr */ - H5F_CLOSE_WEAK, /* fc_degree */ - H5FD_vfd_swmr_term, /* terminate */ - NULL, /* sb_size */ - NULL, /* sb_encode */ - NULL, /* sb_decode */ - 0, /* fapl_size */ - NULL, /* fapl_get */ - NULL, /* fapl_copy */ - NULL, /* fapl_free */ - 0, /* dxpl_size */ - NULL, /* dxpl_copy */ - NULL, /* dxpl_free */ - H5FD_vfd_swmr_open, /* open */ - H5FD_vfd_swmr_close, /* close */ - H5FD_vfd_swmr_cmp, /* cmp */ - H5FD_vfd_swmr_query, /* query */ - NULL, /* get_type_map */ - NULL, /* alloc */ - NULL, /* free */ - H5FD_vfd_swmr_get_eoa, /* get_eoa */ - H5FD_vfd_swmr_set_eoa, /* set_eoa */ - H5FD_vfd_swmr_get_eof, /* get_eof */ - H5FD_vfd_swmr_get_handle, /* get_handle */ - H5FD_vfd_swmr_read, /* read */ - H5FD_vfd_swmr_write, /* write */ - NULL, /* flush */ - H5FD_vfd_swmr_truncate, /* truncate */ - H5FD_vfd_swmr_lock, /* lock */ - H5FD_vfd_swmr_unlock, /* unlock */ - NULL, /* del */ - H5FD_vfd_swmr_dedup, /* dedup */ - H5FD_FLMAP_DICHOTOMY /* fl_map */ + "vfd_swmr", /* name */ + MAXADDR, /* maxaddr */ + H5F_CLOSE_WEAK, /* fc_degree */ + H5FD__vfd_swmr_term, /* terminate */ + NULL, /* sb_size */ + NULL, /* sb_encode */ + NULL, /* sb_decode */ + 0, /* fapl_size */ + NULL, /* fapl_get */ + NULL, /* fapl_copy */ + NULL, /* fapl_free */ + 0, /* dxpl_size */ + NULL, /* dxpl_copy */ + NULL, /* dxpl_free */ + H5FD__vfd_swmr_open, /* open */ + H5FD__vfd_swmr_close, /* close */ + H5FD__vfd_swmr_cmp, /* cmp */ + H5FD__vfd_swmr_query, /* query */ + NULL, /* get_type_map */ + NULL, /* alloc */ + NULL, /* free */ + H5FD__vfd_swmr_get_eoa, /* get_eoa */ + H5FD__vfd_swmr_set_eoa, /* set_eoa */ + H5FD__vfd_swmr_get_eof, /* get_eof */ + H5FD__vfd_swmr_get_handle, /* get_handle */ + H5FD__vfd_swmr_read, /* read */ + H5FD__vfd_swmr_write, /* write */ + NULL, /* flush */ + H5FD__vfd_swmr_truncate, /* truncate */ + H5FD__vfd_swmr_lock, /* lock */ + H5FD__vfd_swmr_unlock, /* unlock */ + NULL, /* del */ + H5FD_FLMAP_DICHOTOMY /* fl_map */ }; /* Declare a free list to manage the H5FD_vfd_swmr_t struct */ @@ -195,7 +187,7 @@ done: } /* end H5FD_vfd_swmr_init() */ /*--------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_term + * Function: H5FD__vfd_swmr_term * * Purpose: Shut down the VFD * @@ -207,15 +199,15 @@ done: *--------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_term(void) +H5FD__vfd_swmr_term(void) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Reset VFL ID */ H5FD_VFD_SWMR_g = 0; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_vfd_swmr_term() */ +} /* end H5FD__vfd_swmr_term() */ /*------------------------------------------------------------------------- * Function: H5Pset_fapl_vfd_swmr (Not yet) @@ -255,15 +247,15 @@ H5FD__swmr_reader_open(H5FD_vfd_swmr_t *file) h5_retry_t retry; hbool_t do_try; /* more tries remain */ herr_t ret_value = SUCCEED; + FUNC_ENTER_STATIC file->api_elapsed_nbuckets = file->config.max_lag + 1; file->api_elapsed_ticks = H5MM_calloc(file->api_elapsed_nbuckets * sizeof(*file->api_elapsed_ticks)); - if (file->api_elapsed_ticks == NULL) { - HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "could not allocate API elapsed ticks"); - } + if (file->api_elapsed_ticks == NULL) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "could not allocate API elapsed ticks") /* Retry on opening the metadata file */ for (do_try = h5_retry_init(&retry, H5FD_VFD_SWMR_MD_FILE_RETRY_MAX, H5_RETRY_DEFAULT_MINIVAL, @@ -286,10 +278,10 @@ H5FD__swmr_reader_open(H5FD_vfd_swmr_t *file) done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5FD__swmr_reader_open() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_open + * Function: H5FD__vfd_swmr_open * * Purpose: Open the metadata file and the underlying HDF5 file * @@ -301,7 +293,7 @@ done: *------------------------------------------------------------------------- */ static H5FD_t * -H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) +H5FD__vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) { H5FD_vfd_swmr_t * file = NULL; size_t page_buf_size; @@ -309,35 +301,31 @@ H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxa H5F_vfd_swmr_config_t *vfd_swmr_config; H5FD_t * ret_value = NULL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* Get file access property list */ - if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) { - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list"); - } + if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list") if (H5P_get(plist, H5F_ACS_PAGE_BUFFER_SIZE_NAME, &page_buf_size) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get page buffer size"); + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get page buffer size"); /* Paged allocation, too, has to be enabled, but the page buffer * initialization (H5PB_create) will detect a conflicting configuration * and return an error. */ - if (page_buf_size == 0) { - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "page buffering must be enabled"); - } + if (page_buf_size == 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "page buffering must be enabled") /* Create the new driver struct */ - if (NULL == (file = H5FL_CALLOC(H5FD_vfd_swmr_t))) { - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct"); - } + if (NULL == (file = H5FL_CALLOC(H5FD_vfd_swmr_t))) + HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, NULL, "unable to allocate file struct") vfd_swmr_config = &file->config; /* Get VFD SWMR configuration */ - if (H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, vfd_swmr_config) < 0) { - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get VFD SWMR config info"); - } + if (H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, vfd_swmr_config) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get VFD SWMR config info") file->md_fd = -1; file->hdf5_file_lf = NULL; @@ -354,9 +342,8 @@ H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxa file->writer = vfd_swmr_config->writer; /* Ensure that this is the reader */ - if (!vfd_swmr_config->writer && H5FD__swmr_reader_open(file) < 0) { - HGOTO_ERROR(H5E_VFL, H5E_OPENERROR, NULL, "perform reader-specific opening steps failed"); - } + if (!vfd_swmr_config->writer && H5FD__swmr_reader_open(file) < 0) + HGOTO_ERROR(H5E_VFL, H5E_OPENERROR, NULL, "perform reader-specific opening steps failed") /* Hard-wired to open the underlying HDF5 file with SEC2 */ if ((file->hdf5_file_lf = H5FD_open(name, flags, H5P_FILE_ACCESS_DEFAULT, maxaddr)) == NULL) @@ -380,23 +367,19 @@ H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxa done: /* Handle closing if error */ - if (NULL == ret_value && file) { - - if (H5FD_vfd_swmr_close(&file->pub) < 0) - - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "error from closing") - - } /* end if */ + if (NULL == ret_value && file) + if (H5FD__vfd_swmr_close(&file->pub) < 0) + HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, NULL, "error from closing") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_open() */ +} /* end H5FD__vfd_swmr_open() */ /* Perform the reader-only aspects of closing in VFD SWMR mode: optionally * log and always release the histogram of ticks spent in API calls, * close the shadow file, release the shadow index. */ static void -swmr_reader_close(H5FD_vfd_swmr_t *file) +H5FD__swmr_reader_close(H5FD_vfd_swmr_t *file) { vfd_swmr_reader_did_increase_tick_to(0); @@ -404,18 +387,17 @@ swmr_reader_close(H5FD_vfd_swmr_t *file) H5MM_xfree(file->api_elapsed_ticks); /* Close the metadata file */ - if (file->md_fd >= 0 && HDclose(file->md_fd) < 0) { + if (file->md_fd >= 0 && HDclose(file->md_fd) < 0) /* Push error, but keep going */ - HERROR(H5E_FILE, H5E_CANTCLOSEFILE, "unable to close the metadata file"); - } + HERROR(H5E_VFL, H5E_CANTCLOSEFILE, "unable to close the metadata file"); /* Free the index entries */ if (file->md_index.num_entries && file->md_index.entries) file->md_index.entries = H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t, file->md_index.entries); -} +} /* end H5FD__swmr_reader_close() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_close + * Function: H5FD__vfd_swmr_close * * Purpose: Handle closing for VFD SWMR driver * --close the underlying HDF5 file @@ -428,12 +410,12 @@ swmr_reader_close(H5FD_vfd_swmr_t *file) *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_close(H5FD_t *_file) +H5FD__vfd_swmr_close(H5FD_t *_file) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC if (file->hdf5_file_lf != NULL) { if (file->hdf5_file_lf->exc_owner != NULL) { @@ -444,21 +426,21 @@ H5FD_vfd_swmr_close(H5FD_t *_file) /* Close the underlying file */ if (H5FD_close(file->hdf5_file_lf) < 0) /* Push error, but keep going */ - HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close the HDF5 file") + HDONE_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close the HDF5 file") } if (!file->writer) - (void)swmr_reader_close(file); + H5FD__swmr_reader_close(file); /* Release the driver info */ file = H5FL_FREE(H5FD_vfd_swmr_t, file); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_close() */ +} /* end H5FD__vfd_swmr_close() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_cmp + * Function: H5FD__vfd_swmr_cmp * * Purpose: Compares two files belonging to this driver using an * arbitrary (but consistent) ordering. @@ -470,58 +452,78 @@ H5FD_vfd_swmr_close(H5FD_t *_file) *------------------------------------------------------------------------- */ static int -H5FD_vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2) +H5FD__vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2) { const H5FD_vfd_swmr_t *f1 = (const H5FD_vfd_swmr_t *)_f1; const H5FD_vfd_swmr_t *f2 = (const H5FD_vfd_swmr_t *)_f2; int ret_value = 0; - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR ret_value = H5FD_cmp(f1->hdf5_file_lf, f2->hdf5_file_lf); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_cmp() */ +} /* end H5FD_vfd__swmr_cmp() */ -/* Compare the already-opened VFD instance `_self` with the - * VFD instance `_other` newly-opened with file-access properties `fapl` - * and indicate whether the instances duplicate each other, if they conflict - * with each other, or if they are dissimilar. +/*------------------------------------------------------------------------- + * Function: H5FD_vfd_swmr_dedup + * + * Purpose: Compare the already-opened VFD instance `_self` with the + * VFD instance `_other` newly-opened with file-access properties + * `fapl_id` and indicate whether the instances duplicate each + * other, if they conflict with each other, or if they are + * dissimilar. * - * If `_self` duplicates `_other`, return `_self`. + * If `_self` duplicates `_other`, return `_self`. * - * Return NULL on error, or if `_other` and `_self` refer to the same file - * but the file-access properties, `fapl`, conflict with the properties of - * `_self`. + * Return NULL on error, or if `_other` and `_self` refer to the + * same file but the file-access properties, `fapl_id`, conflict + * with the properties of `_self`. * - * If `_other` neither duplicates nor conflicts with `_self`, then return - * `_other`. + * If `_other` neither duplicates nor conflicts with `_self`, + * then return `_other`. * - * # Judging duplicate/conflicting/dissimilar VFD instances + * NOTE: Judging duplicate/conflicting/dissimilar VFD instances * - * `_self` duplicates `_other` if `_other` is also an instance of SWMR - * class, the instances' lower files are equal under `H5FD_cmp()`, and - * the file-access properties of `_self` match `fapl`. - * The wildcard `fapl` value, `H5P_FILE_ACCESS_ANY_VFD`, matches all. + * `_self` DUPLICATES `_other` if `_other` is also an instance + * of SWMR class, the instances' lower files are equal under + * `H5FD_cmp()`, and the file-access properties of `_self` match + * `fapl_id`. The wildcard `fapl_id` value, + * `H5P_FILE_ACCESS_ANY_VFD`, matches all. * - * `_self` also duplicates `_other` if `_other` is not a SWMR instance, but - * it equals the lower file of `_self` under `H5FD_cmp()`, and `fapl` is - * `H5P_FILE_ACCESS_ANY_VFD`. + * `_self` also DUPLICATES `_other` if `_other` is not a SWMR + * instance, but it equals the lower file of `_self` under + * `H5FD_cmp()`, and `fapl_id` is `H5P_FILE_ACCESS_ANY_VFD`. * - * `_self` and `_other` conflict if both are SWMR instances referring to - * the same lower file, and their file-access properties differ. + * `_self` and `_other` CONFLICT if both are SWMR instances + * referring to the same lower file, and their file-access + * properties differ. * - * `_self` and `_other` conflict if `_other` is not a SWMR instance, it - * equals the lower file of `_self`, and `fapl` is not equal to - * `H5P_FILE_ACCESS_ANY_VFD`. + * `_self` and `_other` CONFLICT if `_other` is not a SWMR + * instance, it equals the lower file of `_self`, and `fapl_id` + * is not equal to `H5P_FILE_ACCESS_ANY_VFD`. + * + * Return: Success: `_self' or `_other', as described above + * Failure: NULL + *------------------------------------------------------------------------- */ -static H5FD_t * -H5FD_vfd_swmr_dedup(H5FD_t *_self, H5FD_t *_other, hid_t fapl) +H5FD_t * +H5FD_vfd_swmr_dedup(H5FD_t *_self, H5FD_t *_other, hid_t fapl_id) { - H5FD_vfd_swmr_t *self = (H5FD_vfd_swmr_t *)_self; + H5FD_vfd_swmr_t *self = (H5FD_vfd_swmr_t *)_self; + H5FD_t * ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL); - HDassert(_self->driver_id == H5FD_VFD_SWMR_g); + /* Not VFD SWMR */ + if (_self->driver_id != H5FD_VFD_SWMR_g) { + if (H5FD_cmp(_self, _other) == 0) + HGOTO_DONE(_self) + else + HGOTO_DONE(_other) + } + /* VFD SWMR */ if (_self->cls == _other->cls) { H5FD_vfd_swmr_t * other = (H5FD_vfd_swmr_t *)_other; H5P_genplist_t * plist; @@ -529,53 +531,47 @@ H5FD_vfd_swmr_dedup(H5FD_t *_self, H5FD_t *_other, hid_t fapl) hbool_t equal_configs; if (H5FD_cmp(self->hdf5_file_lf, other->hdf5_file_lf) != 0) - return _other; + HGOTO_DONE(_other) - /* If fapl == _ANY_VFD, then the match between lower files is + /* If fapl_id == _ANY_VFD, then the match between lower files is * sufficient. */ - if (fapl == H5P_FILE_ACCESS_ANY_VFD) - return _self; + if (fapl_id == H5P_FILE_ACCESS_ANY_VFD) + HGOTO_DONE(_self) - /* If fapl != _ANY_VFD, then we have either a duplicate or + /* If fapl_id != _ANY_VFD, then we have either a duplicate or * a conflict. If the VFD SWMR parameters match, then * return `self` to indicate a duplicate. Otherwise, return * NULL to indicate a mismatch. */ - if (NULL == (plist = H5I_object(fapl))) { - HERROR(H5E_ARGS, H5E_BADTYPE, "could not get fapl"); - return NULL; - } + if (NULL == (plist = H5I_object(fapl_id))) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "could not get fapl") - if ((config = H5MM_malloc(sizeof(*config))) == NULL) { - HERROR(H5E_ARGS, H5E_BADTYPE, "could not allocate config"); - return NULL; - } - if (H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config) < 0) { - HERROR(H5E_PLIST, H5E_CANTGET, "cannot get VFD SWMR config"); - return NULL; - } + if ((config = H5MM_malloc(sizeof(*config))) == NULL) + HGOTO_ERROR(H5E_VFL, H5E_BADTYPE, NULL, "could not allocate config") + if (H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "cannot get VFD SWMR config") equal_configs = HDmemcmp(&self->config, config, sizeof(*config)) == 0; H5MM_xfree(config); if (equal_configs) - return _self; + HGOTO_DONE(_self) - HERROR(H5E_PLIST, H5E_CANTGET, "inconsistent VFD SWMR config"); - return NULL; + HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "inconsistent VFD SWMR config") } - else if (H5FD_cmp(self->hdf5_file_lf, _other) == 0) { - return (fapl == H5P_FILE_ACCESS_ANY_VFD) ? _self : NULL; - } - else { - return _other; - } -} + else if (H5FD_cmp(self->hdf5_file_lf, _other) == 0) + ret_value = (fapl_id == H5P_FILE_ACCESS_ANY_VFD) ? _self : NULL; + else + ret_value = _other; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5FD_vfd_swmr_dedup() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_query + * Function: H5FD__vfd_swmr_query * * Purpose: Set the flags that this VFL driver is capable of supporting. * (listed in H5FDpublic.h) @@ -585,49 +581,45 @@ H5FD_vfd_swmr_dedup(H5FD_t *_self, H5FD_t *_other, hid_t fapl) *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* out */) +H5FD__vfd_swmr_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* out */) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_STATIC_NOERR /* Set the VFL feature flags that this driver supports */ if (flags) { *flags = 0; - *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate */ - /* metadata allocations */ - *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate */ - /* metadata for faster */ - /* writes */ + /* OK to aggregate metadata allocations */ + *flags |= H5FD_FEAT_AGGREGATE_METADATA; - *flags |= H5FD_FEAT_DATA_SIEVE; /* OK to perform data */ - /* sieving for faster */ - /* raw data reads & */ - /* writes */ + /* OK to accumulate metadata for faster writes */ + *flags |= H5FD_FEAT_ACCUMULATE_METADATA; - *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate */ - /* "small" raw data */ - /* allocations */ + /* OK to perform data sieving for faster raw data reads & writes */ + *flags |= H5FD_FEAT_DATA_SIEVE; - *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* get_handle callback */ - /* returns a POSIX file */ - /* descriptor */ + /* OK to aggregate "small" raw data allocations */ + *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; - *flags |= H5FD_FEAT_SUPPORTS_SWMR_IO; /* VFD supports the */ - /* single-writer/ */ - /* multiple-readers */ - /* (SWMR) pattern */ + /* get_handle callback returns a POSIX file descriptor */ + *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; - *flags |= H5FD_FEAT_DEFAULT_VFD_COMPATIBLE; /* VFD creates a file */ - /* which can be opened */ - /* with the default VFD */ + /* VFD supports the single-writer / multiple readers (SWMR) pattern */ + *flags |= H5FD_FEAT_SUPPORTS_SWMR_IO; - } /* end if */ + /* VFD creates a file that can be opened with the default VFD + * + * NOTE: When this VFD becomes a true passthrough, this flag will + * probably need to go away. + */ + *flags |= H5FD_FEAT_DEFAULT_VFD_COMPATIBLE; + } FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5FD_vfd_swmr_query() */ +} /* end H5FD__vfd_swmr_query() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_get_eoa + * Function: H5FD__vfd_swmr_get_eoa * * Purpose: Gets the end-of-address marker for the file for the * underlying HDF5 file. The EOA marker is the first address @@ -638,51 +630,49 @@ H5FD_vfd_swmr_query(const H5FD_t H5_ATTR_UNUSED *_file, unsigned long *flags /* *------------------------------------------------------------------------- */ static haddr_t -H5FD_vfd_swmr_get_eoa(const H5FD_t *_file, H5FD_mem_t type) +H5FD__vfd_swmr_get_eoa(const H5FD_t *_file, H5FD_mem_t type) { const H5FD_vfd_swmr_t *file = (const H5FD_vfd_swmr_t *)_file; haddr_t ret_value = HADDR_UNDEF; - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC if ((ret_value = H5FD_get_eoa(file->hdf5_file_lf, type)) == HADDR_UNDEF) - - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, HADDR_UNDEF, "unable to get HDF5 file eoa") + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "unable to get HDF5 file eoa") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_get_eoa() */ +} /* end H5FD__vfd_swmr_get_eoa() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_set_eoa + * Function: H5FD__vfd_swmr_set_eoa * * Purpose: Set the end-of-address marker for the underlying HDF5 file. * This function is called shortly after an existing HDF5 file * is opened in order to tell the driver where the end of the * HDF5 data is located. * - * Return: SUCCEED (Can't fail) + * Return: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr) +H5FD__vfd_swmr_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC if (H5FD_set_eoa(file->hdf5_file_lf, type, addr) < 0) - - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to set HDF5 file eoa") + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "unable to set HDF5 file eoa") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_set_eoa() */ +} /* end H5FD__vfd_swmr_set_eoa() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_get_eof + * Function: H5FD__vfd_swmr_get_eof * * Purpose: Returns the end-of-file marker, which is the greater of * either the filesystem end-of-file or the HDF5 end-of-address @@ -694,38 +684,37 @@ done: *------------------------------------------------------------------------- */ static haddr_t -H5FD_vfd_swmr_get_eof(const H5FD_t *_file, H5FD_mem_t type) +H5FD__vfd_swmr_get_eof(const H5FD_t *_file, H5FD_mem_t type) { const H5FD_vfd_swmr_t *file = (const H5FD_vfd_swmr_t *)_file; haddr_t ret_value = HADDR_UNDEF; - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC /* LATER: need to determine the metadata file or underlying HDF5 file ? */ if ((ret_value = H5FD_get_eof(file->hdf5_file_lf, type)) == HADDR_UNDEF) - - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, HADDR_UNDEF, "unable to set file eoa") + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, HADDR_UNDEF, "unable to set file eoa") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_get_eof() */ +} /* end H5FD__vfd_swmr_get_eof() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_get_handle + * Function: H5FD__vfd_swmr_get_handle * - * Purpose: Returns the file handle for the underling HDF5 file + * Purpose: Returns the file handle for the underling HDF5 file * - * Returns: SUCCEED/FAIL + * Returns: SUCCEED/FAIL * *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle) +H5FD__vfd_swmr_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; herr_t ret_value = SUCCEED; - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC if (!file_handle) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid") @@ -738,10 +727,10 @@ H5FD_vfd_swmr_get_handle(H5FD_t *_file, hid_t fapl, void **file_handle) done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_get_handle() */ +} /* end H5FD__vfd_swmr_get_handle() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_read + * Function: H5FD__vfd_swmr_read * * Purpose: If the target page or multi-page metadata entry is * defined in the current metadata file index, satisfy @@ -776,8 +765,8 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, const haddr_t addr, - size_t size, void *const buf /*out*/) +H5FD__vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, const haddr_t addr, + size_t size, void *const buf /*out*/) { const size_t init_size = size; haddr_t target_page; @@ -792,7 +781,7 @@ H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, if (file->writer) return H5FD_read(file->hdf5_file_lf, type, addr, size, buf); - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC HDassert(file && file->pub.cls); HDassert(buf); @@ -808,9 +797,9 @@ H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, if (entry == NULL) { /* Cannot find addr in index, read from the underlying hdf5 file */ - if (H5FD_read(file->hdf5_file_lf, type, addr, size, buf) < 0) { - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed"); - } + if (H5FD_read(file->hdf5_file_lf, type, addr, size, buf) < 0) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed") + HGOTO_DONE(SUCCEED); } @@ -848,7 +837,7 @@ H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, } while (-1 == bytes_read && EINTR == errno); if (-1 == bytes_read) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "error reading the page/multi-page entry from the md file") HDassert(0 <= bytes_read && (size_t)bytes_read <= size); @@ -871,30 +860,30 @@ H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, H5_checksum_metadata(buf, entry->length, 0) != entry->chksum) { H5FD_vfd_swmr_md_header tmp_header; - if (H5FD__vfd_swmr_header_deserialize(file, &tmp_header) != TRUE) { + if (H5FD__vfd_swmr_header_deserialize(file, &tmp_header) != TRUE) HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, - "checksum error in shadow file entry; could not load header"); - } + "checksum error in shadow file entry; could not load header") - HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "checksum error in shadow file entry"); + HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "checksum error in shadow file entry") } done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_read() */ +} /* end H5FD__vfd_swmr_read() */ -/* - * Function: H5FD_vfd_swmr_write +/*------------------------------------------------------------------------- + * Function: H5FD__vfd_swmr_write * * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR * from buffer BUF according to data transfer properties in * DXPL_ID. * * Return: SUCCEED/FAIL + *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size, - const void *buf) +H5FD__vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, haddr_t addr, size_t size, + const void *buf) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; @@ -904,7 +893,7 @@ H5FD_vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id HDassert(file->writer); return H5FD_write(file->hdf5_file_lf, type, addr, size, buf); -} +} /* end H5FD__vfd_swmr_write() */ /*------------------------------------------------------------------------- * Function: H5FD_vfd_swmr_truncate @@ -917,20 +906,22 @@ H5FD_vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing) +H5FD__vfd_swmr_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t closing) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */ + FUNC_ENTER_STATIC_NOERR + /* This routine should only be called if the VFD instance is opened * for writing. */ HDassert(file->writer); - return H5FD_truncate(file->hdf5_file_lf, closing); + FUNC_LEAVE_NOAPI(H5FD_truncate(file->hdf5_file_lf, closing)) } /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_lock + * Function: H5FD__vfd_swmr_lock * * Purpose: To place an advisory lock on the underlying HDF5 file. * @@ -939,25 +930,24 @@ H5FD_vfd_swmr_truncate(H5FD_t *_file, hid_t H5_ATTR_UNUSED dxpl_id, hbool_t clos *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_lock(H5FD_t *_file, hbool_t rw) +H5FD__vfd_swmr_lock(H5FD_t *_file, hbool_t rw) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC HDassert(file); if (H5FD_lock(file->hdf5_file_lf, rw) < 0) - - HGOTO_ERROR(H5E_IO, H5E_CANTLOCK, FAIL, "unable to lock the HDF5 file") + HGOTO_ERROR(H5E_VFL, H5E_CANTLOCK, FAIL, "unable to lock the HDF5 file") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_lock() */ +} /* end H5FD__vfd_swmr_lock() */ /*------------------------------------------------------------------------- - * Function: H5FD_vfd_swmr_unlock + * Function: H5FD__vfd_swmr_unlock * * Purpose: To remove the existing lock on the underlying HDF5 file * @@ -966,26 +956,25 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5FD_vfd_swmr_unlock(H5FD_t *_file) +H5FD__vfd_swmr_unlock(H5FD_t *_file) { H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_STATIC HDassert(file); if (H5FD_unlock(file->hdf5_file_lf) < 0) - - HGOTO_ERROR(H5E_IO, H5E_CANTUNLOCK, FAIL, "unable to unlock the HDF5 file") + HGOTO_ERROR(H5E_VFL, H5E_CANTUNLOCK, FAIL, "unable to unlock the HDF5 file") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5FD_vfd_swmr_unlock() */ +} /* end H5FD__vfd_swmr_unlock() */ -/* +/*------------------------------------------------------------------------- * Function: H5FD__vfd_swmr_load_hdr_and_idx() * * Purpose: Load and decode the header and index in the metadata file @@ -1029,18 +1018,19 @@ done: * Return: Success: SUCCEED * Failure: FAIL * + *------------------------------------------------------------------------- */ static herr_t H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *file, hbool_t open) { hbool_t do_try; h5_retry_t retry; - H5FD_vfd_swmr_md_header md_header; /* Metadata file header, take 1 */ - H5FD_vfd_swmr_md_header md_header_two; /* Metadata file header, take 2 */ - H5FD_vfd_swmr_md_index md_index; /* Metadata file index */ - herr_t ret_value = SUCCEED; /* Return value */ + H5FD_vfd_swmr_md_header md_header; /* Metadata file header, take 1 */ + H5FD_vfd_swmr_md_header md_header_two; /* Metadata file header, take 2 */ + H5FD_vfd_swmr_md_index md_index; /* Metadata file index */ htri_t rc; static uint64_t last_index_offset = 0; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -1058,7 +1048,7 @@ H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *file, hbool_t open) continue; if (rc != TRUE) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "could not read header"); + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "could not read header") if (md_header.index_offset != last_index_offset) last_index_offset = md_header.index_offset; @@ -1070,12 +1060,11 @@ H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *file, hbool_t open) * time, then there is not a complete new index to read, so * get out. */ - HGOTO_DONE(SUCCEED); + HGOTO_DONE(SUCCEED) } - else if (md_header.tick_num < file->md_header.tick_num) { + else if (md_header.tick_num < file->md_header.tick_num) /* The tick number must not move backward. */ - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "tick number in header moved backwards"); - } + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "tick number in header moved backwards") HDassert(md_header.tick_num > file->md_header.tick_num || open); @@ -1088,7 +1077,7 @@ H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *file, hbool_t open) continue; if (rc != TRUE) - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "could not read index"); + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "could not read index") /* If the tick_num is the same in both header and index, * and the header reads the same the second time as the first time, @@ -1108,18 +1097,16 @@ H5FD__vfd_swmr_load_hdr_and_idx(H5FD_vfd_swmr_t *file, hbool_t open) (H5FD_vfd_swmr_idx_entry_t *)H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t, md_index.entries); } - if (rc == FAIL) { - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "could not re-read header"); - } + if (rc == FAIL) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "could not re-read header") } /* Exhaust all retries for loading and decoding the md file header * and index */ - if (!do_try) { + if (!do_try) HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "error in loading/decoding the metadata file header and index") - } /* Free VFD local entries */ if (file->md_index.entries != NULL) { @@ -1170,30 +1157,28 @@ H5FD__vfd_swmr_header_deserialize(H5FD_vfd_swmr_t *file, H5FD_vfd_swmr_md_header FUNC_ENTER_STATIC /* Set file pointer to the beginning the file */ - if (HDlseek(file->md_fd, H5FD_MD_HEADER_OFF, SEEK_SET) < 0) { - HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file"); - } + if (HDlseek(file->md_fd, H5FD_MD_HEADER_OFF, SEEK_SET) < 0) + HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file") /* Read the header */ nread = HDread(file->md_fd, image, H5FD_MD_HEADER_SIZE); /* Try again if a signal interrupted the read. */ if (nread == -1 && errno == EINTR) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* We cannot recover from any other error by trying again, * so bail out. */ - if (nread == -1) { - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "error in reading the shadow header"); - } + if (nread == -1) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "error in reading the shadow header") if ((uint64_t)nread < H5FD_MD_HEADER_SIZE) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* Verify magic number */ if (HDmemcmp(image, H5FD_MD_HEADER_MAGIC, H5_SIZEOF_MAGIC) != 0) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* Verify stored and computed checksums are equal */ H5F_get_checksums(image, H5FD_MD_HEADER_SIZE, &stored_chksum, &computed_chksum); @@ -1208,9 +1193,8 @@ H5FD__vfd_swmr_header_deserialize(H5FD_vfd_swmr_t *file, H5FD_vfd_swmr_md_header UINT32DECODE(p, md_header->fs_page_size); UINT64DECODE(p, md_header->tick_num); UINT64DECODE(p, md_header->index_offset); - if ((index_length = uint64_decode(&p)) > SIZE_MAX) { - HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "index is too large to hold in core"); - } + if ((index_length = uint64_decode(&p)) > SIZE_MAX) + HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "index is too large to hold in core") md_header->index_length = (size_t)index_length; @@ -1266,28 +1250,24 @@ H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD_vfd_swmr_md_i FUNC_ENTER_STATIC /* Allocate buffer for reading index */ - if (NULL == (image = H5MM_malloc(md_header->index_length))) { - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, - "memory allocation failed for index's on disk image buffer"); - } + if (NULL == (image = H5MM_malloc(md_header->index_length))) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "memory allocation failed for index's on disk image buffer") /* We may seek past EOF. That's ok, the read(2) will catch that. */ - if (HDlseek(file->md_fd, (HDoff_t)md_header->index_offset, SEEK_SET) < 0) { - HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file"); - } + if (HDlseek(file->md_fd, (HDoff_t)md_header->index_offset, SEEK_SET) < 0) + HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file") nread = HDread(file->md_fd, image, md_header->index_length); /* Try again if a signal interrupted the read. */ if (nread == -1 && errno == EINTR) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* We cannot recover from any other error by trying again, * so bail out. */ - if (nread == -1) { - HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "error in reading the header in metadata file"); - } + if (nread == -1) + HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "error in reading the header in metadata file") /* Try again if the read was not full. * @@ -1302,7 +1282,7 @@ H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD_vfd_swmr_md_i * like an unrecoverable error instead of retrying. */ if ((size_t)nread < md_header->index_length) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* If the index magic is incorrect, then assume that is a * temporary error and try again. @@ -1323,7 +1303,7 @@ H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD_vfd_swmr_md_i * re-reading the header. */ if (HDmemcmp(image, H5FD_MD_INDEX_MAGIC, H5_SIZEOF_MAGIC) != 0) - HGOTO_DONE(FALSE); + HGOTO_DONE(FALSE) /* Verify stored and computed checksums are equal */ H5F_get_checksums(image, md_header->index_length, &stored_chksum, &computed_chksum); @@ -1343,9 +1323,8 @@ H5FD__vfd_swmr_index_deserialize(const H5FD_vfd_swmr_t *file, H5FD_vfd_swmr_md_i if (md_index->num_entries) { /* Allocate memory for index entries */ md_index->entries = H5FL_SEQ_CALLOC(H5FD_vfd_swmr_idx_entry_t, md_index->num_entries); - if (NULL == md_index->entries) { - HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "memory allocation failed for index entries"); - } + if (NULL == md_index->entries) + HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "memory allocation failed for index entries") /* Decode index entries */ for (i = 0; i < md_index->num_entries; i++) { @@ -1419,9 +1398,8 @@ H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t reload_hdr_and_index, uint FUNC_ENTER_NOAPI(FAIL) /* Load and decode the header and index as indicated */ - if (reload_hdr_and_index && H5FD__vfd_swmr_load_hdr_and_idx(file, FALSE) < 0) { + if (reload_hdr_and_index && H5FD__vfd_swmr_load_hdr_and_idx(file, FALSE) < 0) HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "unable to load/decode md header and index") - } /* Return tick_num */ if (tick_ptr != NULL) @@ -1429,9 +1407,8 @@ H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t reload_hdr_and_index, uint if (index != NULL) { - if (*num_entries_ptr < file->md_index.num_entries) { - HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "not enough space to copy index"); - } + if (*num_entries_ptr < file->md_index.num_entries) + HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "not enough space to copy index") HDmemcpy(index, file->md_index.entries, (file->md_index.num_entries * sizeof(file->md_index.entries[0]))); @@ -1475,10 +1452,8 @@ H5FD_vfd_swmr_dump_status(H5FD_t *_file, uint64_t page) while ((!in_index) && (i < (int)num_entries)) { - if (index[i].hdf5_page_offset == page) { - + if (index[i].hdf5_page_offset == page) in_index = TRUE; - } HDassert((i == 0) || (index[i - 1].hdf5_page_offset < index[i].hdf5_page_offset)); @@ -1527,15 +1502,29 @@ H5FD_vfd_swmr_set_pb_configured(H5FD_t *_file) } /* H5FD_vfd_swmr_set_pb_configured() */ -/* In the histogram of ticks spent in API calls, increase the bucket - * for `elapsed` ticks by one. +/*------------------------------------------------------------------------- + * Function: H5FD_vfd_swmr_record_elapsed_ticks + * + * Purpose: In the histogram of ticks spent in API calls, increase + * the bucket for `elapsed` ticks by one. + * + * Return: VOID + * + * Programmer: JRM -- 1/29/19 + * + *------------------------------------------------------------------------- + * */ void H5FD_vfd_swmr_record_elapsed_ticks(H5FD_t *_file, uint64_t elapsed) { + FUNC_ENTER_NOAPI_NOINIT_NOERR + H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; uint32_t elapsed_idx = MIN(elapsed, file->api_elapsed_nbuckets); file->api_elapsed_ticks[elapsed_idx]++; -} + + FUNC_LEAVE_NOAPI_VOID +} /* end H5FD_vfd_swmr_record_elapsed_ticks() */ diff --git a/src/H5FDvfd_swmr.h b/src/H5FDvfd_swmr.h index d85cc95..096d5fb 100644 --- a/src/H5FDvfd_swmr.h +++ b/src/H5FDvfd_swmr.h @@ -16,10 +16,6 @@ #ifndef H5FDvfd_swmr_H #define H5FDvfd_swmr_H -#include "H5api_adpt.h" /* H5_DLL */ -#include "H5public.h" /* uint64_t *ahem* */ -#include "H5Ipublic.h" /* hid_t */ - #define H5FD_VFD_SWMR (H5FD_vfd_swmr_init()) #ifdef __cplusplus @@ -33,4 +29,4 @@ H5_DLL herr_t H5Pset_fapl_vfd_swmr(hid_t fapl_id); } #endif -#endif /* H5FDvfd_swmr_H */ +#endif diff --git a/src/H5Fint.c b/src/H5Fint.c index 44506b6..247a047 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -1575,12 +1575,6 @@ H5F__dest(H5F_t *f, hbool_t flush) /* Push error, but keep going*/ HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "vfd swmr prep for flush or close failed") - if ((f->shared->vfd_swmr) && (!f->shared->vfd_swmr_writer)) - HDfprintf(stdout, - "The maximum jump in ticks is %" PRIu64 - "; The maximum expected lag configured is %" PRIu32 "\n", - f->shared->max_jump_ticks, f->shared->vfd_swmr_config.max_lag); - /* Shutdown the page buffer cache */ if (H5PB_dest(f->shared) < 0) /* Push error, but keep going*/ @@ -1932,9 +1926,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) /* Avoid reusing a virtual file opened exclusively by a second virtual * file, or opening the same file twice with different parameters. */ - if ((lf = H5FD_deduplicate(lf, fapl_id)) == NULL) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "an already-open file conflicts with '%s'", name); - } + if ((lf = H5FD_deduplicate(lf, fapl_id)) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "an already-open file conflicts with '%s'", name) /* Is the file already open? */ if ((shared = H5F__sfile_search(lf)) != NULL) { diff --git a/src/H5Fvfd_swmr.c b/src/H5Fvfd_swmr.c index 13170af..d7cb830 100644 --- a/src/H5Fvfd_swmr.c +++ b/src/H5Fvfd_swmr.c @@ -768,26 +768,26 @@ H5F_vfd_swmr_writer_end_of_tick(H5F_t *f, hbool_t wait_for_reader) /* 1) If requested, flush all raw data to the HDF5 file. * - * (Not for first cut.) - */ - HDassert(!shared->vfd_swmr_config.flush_raw_data); - -#if 1 - /* Test to see if b-tree corruption seen in VFD SWMR tests - * is caused by client hiding data from the metadata cache. Do - * this by calling H5D_flush_all(), which flushes any cached - * dataset storage. Eventually, we will do this regardless - * when the above flush_raw_data flag is set. */ + if (shared->vfd_swmr_config.flush_raw_data) { + + /* Test to see if b-tree corruption seen in VFD SWMR tests + * is caused by client hiding data from the metadata cache. Do + * this by calling H5D_flush_all(), which flushes any cached + * dataset storage. Eventually, we will do this regardless + * when the above flush_raw_data flag is set. + */ - if (H5D_flush_all(f) < 0) + if (H5D_flush_all(f) < 0) - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") - if (H5MF_free_aggrs(f) < 0) + if (H5MF_free_aggrs(f) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") + } + /* 2) If it exists, flush the metadata cache to the page buffer. */ if (shared->cache) { if (H5AC_prep_for_file_flush(f) < 0) @@ -806,23 +806,6 @@ H5F_vfd_swmr_writer_end_of_tick(H5F_t *f, hbool_t wait_for_reader) if (H5FD_truncate(shared->lf, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") -#endif - - /* 2) If it exists, flush the metadata cache to the page buffer. */ - if (shared->cache) { - - if (H5AC_prep_for_file_flush(f) < 0) - - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "prep for MDC flush failed") - - if (H5AC_flush(f) < 0) - - HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Can't flush metadata cache to the page buffer") - - if (H5AC_secure_from_file_flush(f) < 0) - - HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "secure from MDC flush failed") - } /* 3) If this is the first tick (i.e. tick == 1), create the * in memory version of the metadata file index. @@ -1756,7 +1739,7 @@ vfd_swmr_enlarge_shadow_index(H5F_t *f) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "shadow-file allocation failed for index") } - new_mdf_idx = HDmalloc(new_mdf_idx_len * sizeof(new_mdf_idx[0])); + new_mdf_idx = H5MM_calloc(new_mdf_idx_len * sizeof(new_mdf_idx[0])); if (new_mdf_idx == NULL) { (void)H5MV_free(f, idx_addr, idx_size); @@ -1774,6 +1757,11 @@ vfd_swmr_enlarge_shadow_index(H5F_t *f) ret_value = shared->mdf_idx = new_mdf_idx; shared->mdf_idx_len = new_mdf_idx_len; + H5MM_xfree(f->shared->old_mdf_idx); + + shared->old_mdf_idx = old_mdf_idx; + f->shared->old_mdf_idx_len = old_mdf_idx_len; + /* Postpone reclamation of the old index until max_lag ticks from now. * It's only necessary to wait until after the new index is in place, * so it's possible that some disused shadow storage will build up diff --git a/test/Makefile.am b/test/Makefile.am index ee35664..3ae26bd 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -54,6 +54,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \ vfd_swmr_group_reader$(EXEEXT) vfd_swmr_group_writer$(EXEEXT) \ vfd_swmr_vlstr_reader$(EXEEXT) vfd_swmr_vlstr_writer$(EXEEXT) \ vfd_swmr_zoo_reader$(EXEEXT) vfd_swmr_zoo_writer$(EXEEXT) \ + vfd_swmr_gperf_reader$(EXEEXT) vfd_swmr_gperf_writer$(EXEEXT) \ vds_env$(EXEEXT) \ vds_swmr_gen$(EXEEXT) vds_swmr_reader$(EXEEXT) vds_swmr_writer$(EXEEXT) if HAVE_SHARED_CONDITIONAL @@ -111,6 +112,7 @@ check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \ vfd_swmr_vlstr_reader vfd_swmr_vlstr_writer \ vfd_swmr_zoo_reader vfd_swmr_zoo_writer \ vfd_swmr_attrdset_reader vfd_swmr_attrdset_writer \ + vfd_swmr_gperf_reader vfd_swmr_gperf_writer \ vfd_swmr_check_compat \ vfd_swmr_dsetchks_reader vfd_swmr_dsetchks_writer \ swmr_check_compat_vfd vds_env vds_swmr_gen vds_swmr_reader vds_swmr_writer \ @@ -178,6 +180,7 @@ vfd_swmr_zoo_reader_SOURCES=vfd_swmr_zoo_writer.c genall5.c vfd_swmr_bigset_reader_SOURCES=vfd_swmr_bigset_writer.c vfd_swmr_group_reader_SOURCES=vfd_swmr_group_writer.c +vfd_swmr_gperf_reader_SOURCES=vfd_swmr_gperf_writer.c vfd_swmr_dsetops_reader_SOURCES=vfd_swmr_dsetops_writer.c vfd_swmr_attrdset_writer_SOURCES=vfd_swmr_attrdset_writer.c diff --git a/test/h5test.c b/test/h5test.c index 9ec29ed..755ae93 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -1925,7 +1925,6 @@ static const H5FD_class_t H5FD_dummy_g = { NULL, /* lock */ NULL, /* unlock */ NULL, /* del */ - NULL, /* dedup */ H5FD_FLMAP_DICHOTOMY /* fl_map */ }; diff --git a/test/testvfdswmr.sh.in b/test/testvfdswmr.sh.in index 6095c03..ac54968 100644 --- a/test/testvfdswmr.sh.in +++ b/test/testvfdswmr.sh.in @@ -145,9 +145,9 @@ all_tests="generator expand shrink expand_shrink sparse vlstr_null vlstr_oob zoo all_tests="${all_tests} groups groups_attrs groups_ops few_big many_small attrdset" tests=${all_tests} -# For exhaustive run, add: os_groups_attrs, os_groups_ops, dsetops, dsetchks +# For exhaustive run, add: os_groups_attrs, os_groups_ops, os_groups_seg, dsetops, dsetchks if [[ "$HDF5TestExpress" -eq 0 ]] ; then # exhaustive run - all_tests="${all_tests} os_groups_attrs os_groups_ops dsetops dsetchks" + all_tests="${all_tests} os_groups_attrs os_groups_ops os_groups_seg dsetops dsetchks" fi if [ $# -gt 0 ]; then @@ -1008,6 +1008,36 @@ done ############################################################################### # +# Setting for "os_groups_seg" test +# +# Only for exhaustive run +# +# Verify the segmentation fault is fixed when running with: +# --1,000,000 groups +# --as writer only +# +############################################################################### +# +# +GROUP_seg_n=1000000 # Number of groups when segmentation fault occurs +# +if [ ${do_os_groups_seg:-no} != no ]; then + echo launch vfd_swmr_group operations with old-style group: $GROUP_seg_n groups ......may take some time...... + catch_out_err_and_rc vfd_swmr_group_writer \ + ../vfd_swmr_group_writer -q -N -G -n $GROUP_seg_n -a $GROUP_seg_n + + # Collect exit code of the writer + if [ $(cat vfd_swmr_group_writer.rc) -ne 0 ]; then + echo writer had error + nerrors=$((nerrors + 1)) + fi + + # Clean up output files + rm -f vfd_swmr_group_writer.{out,rc} +fi + +############################################################################### +# # Setting for bigset (few_big and many_small) tests # ############################################################################### @@ -1209,51 +1239,55 @@ done ############################################################################### # # -for options in "-p -e 20 -t -q" "-g -m 5 -n 2 -s 10 -w 7 -q" "-k -m 10 -n 5 -r 5 -l 10 -q"; do - # - # - if [ ${do_dsetops:-no} = no ]; then - continue - fi - # Clean up any existing fifo files from previous runs - if [ -e ./$DSETOPS_FIFO_WRITER_TO_READER ]; then # If writer fifo file is found - rm -f ./$DSETOPS_FIFO_WRITER_TO_READER - fi - if [ -e ./$DSETOPS_FIFO_READER_TO_WRITER ]; then # If reader fifo file is found - rm -f ./$DSETOPS_FIFO_READER_TO_WRITER - fi - # - echo launch vfd_swmr_dsetops_writer dsetops, options $options ......may take some time...... - catch_out_err_and_rc vfd_swmr_dsetops_writer \ - ../vfd_swmr_dsetops_writer $options & - pid_writer=$! - - catch_out_err_and_rc vfd_swmr_dsetops_reader \ - ../vfd_swmr_dsetops_reader $options & - pid_reader=$! - - # Wait for the reader to finish before signaling the - # writer to quit: the writer holds the file open so that the - # reader will find the shadow file when it opens - # the .h5 file. - wait $pid_reader - wait $pid_writer - - # Collect exit code of the reader - if [ $(cat vfd_swmr_dsetops_reader.rc) -ne 0 ]; then - echo reader had error - nerrors=$((nerrors + 1)) - fi +# Loop with flushing of raw data and then without +for flush in "" "-U"; do + # Loop with different operations + for options in "-p -e 20 -t -q" "-g -m 5 -n 2 -s 10 -w 7 -q" "-k -m 10 -n 5 -r 5 -l 10 -q"; do + # + # + if [ ${do_dsetops:-no} = no ]; then + continue + fi + # Clean up any existing fifo files from previous runs + if [ -e ./$DSETOPS_FIFO_WRITER_TO_READER ]; then # If writer fifo file is found + rm -f ./$DSETOPS_FIFO_WRITER_TO_READER + fi + if [ -e ./$DSETOPS_FIFO_READER_TO_WRITER ]; then # If reader fifo file is found + rm -f ./$DSETOPS_FIFO_READER_TO_WRITER + fi + # + echo launch vfd_swmr_dsetops_writer dsetops, options $options $flush......may take some time...... + catch_out_err_and_rc vfd_swmr_dsetops_writer \ + ../vfd_swmr_dsetops_writer $options $flush & + pid_writer=$! + + catch_out_err_and_rc vfd_swmr_dsetops_reader \ + ../vfd_swmr_dsetops_reader $options $flush & + pid_reader=$! + + # Wait for the reader to finish before signaling the + # writer to quit: the writer holds the file open so that the + # reader will find the shadow file when it opens + # the .h5 file. + wait $pid_reader + wait $pid_writer + + # Collect exit code of the reader + if [ $(cat vfd_swmr_dsetops_reader.rc) -ne 0 ]; then + echo reader had error + nerrors=$((nerrors + 1)) + fi - # Collect exit code of the writer - if [ $(cat vfd_swmr_dsetops_writer.rc) -ne 0 ]; then - echo writer had error - nerrors=$((nerrors + 1)) - fi + # Collect exit code of the writer + if [ $(cat vfd_swmr_dsetops_writer.rc) -ne 0 ]; then + echo writer had error + nerrors=$((nerrors + 1)) + fi - # Clean up output files - rm -f vfd_swmr_dsetops_writer.{out,rc} - rm -f vfd_swmr_dsetops_reader.*.{out,rc} + # Clean up output files + rm -f vfd_swmr_dsetops_writer.{out,rc} + rm -f vfd_swmr_dsetops_reader.*.{out,rc} + done done ############################################################################### @@ -1273,51 +1307,56 @@ dsetchks_list=( "-r -m 11 -n 5 -l 7 -q" "-f -x 5 -y 2 -q" ) -for options in "${dsetchks_list[@]}"; do - # - # - if [ ${do_dsetchks:-no} = no ]; then - continue - fi - # Clean up any existing fifo files from previous runs - if [ -e ./$DSETCHKS_FIFO_WRITER_TO_READER ]; then # If writer fifo file is found - rm -f ./$DSETCHKS_FIFO_WRITER_TO_READER - fi - if [ -e ./$DSETCHKS_FIFO_READER_TO_WRITER ]; then # If reader fifo file is found - rm -f ./$DSETCHKS_FIFO_READER_TO_WRITER - fi - # - echo launch vfd_swmr_dsetchks_writer dsetchks, options $options ......may take some time...... - catch_out_err_and_rc vfd_swmr_dsetchks_writer \ - ../vfd_swmr_dsetchks_writer $options & - pid_writer=$! - - catch_out_err_and_rc vfd_swmr_dsetchks_reader \ - ../vfd_swmr_dsetchks_reader $options & - pid_reader=$! - - # Wait for the reader to finish before signaling the - # writer to quit: the writer holds the file open so that the - # reader will find the shadow file when it opens - # the .h5 file. - wait $pid_reader - wait $pid_writer - - # Collect exit code of the reader - if [ $(cat vfd_swmr_dsetchks_reader.rc) -ne 0 ]; then - echo reader had error - nerrors=$((nerrors + 1)) - fi +# +# +# Loop with flushing of raw data and then without +for flush in "" "-U"; do + for options in "${dsetchks_list[@]}"; do + # + # + if [ ${do_dsetchks:-no} = no ]; then + continue + fi + # Clean up any existing fifo files from previous runs + if [ -e ./$DSETCHKS_FIFO_WRITER_TO_READER ]; then # If writer fifo file is found + rm -f ./$DSETCHKS_FIFO_WRITER_TO_READER + fi + if [ -e ./$DSETCHKS_FIFO_READER_TO_WRITER ]; then # If reader fifo file is found + rm -f ./$DSETCHKS_FIFO_READER_TO_WRITER + fi + # + echo launch vfd_swmr_dsetchks_writer dsetchks, options $options $flush ......may take some time...... + catch_out_err_and_rc vfd_swmr_dsetchks_writer \ + ../vfd_swmr_dsetchks_writer $options $flush & + pid_writer=$! + + catch_out_err_and_rc vfd_swmr_dsetchks_reader \ + ../vfd_swmr_dsetchks_reader $options $flush & + pid_reader=$! + + # Wait for the reader to finish before signaling the + # writer to quit: the writer holds the file open so that the + # reader will find the shadow file when it opens + # the .h5 file. + wait $pid_reader + wait $pid_writer + + # Collect exit code of the reader + if [ $(cat vfd_swmr_dsetchks_reader.rc) -ne 0 ]; then + echo reader had error + nerrors=$((nerrors + 1)) + fi - # Collect exit code of the writer - if [ $(cat vfd_swmr_dsetchks_writer.rc) -ne 0 ]; then - echo writer had error - nerrors=$((nerrors + 1)) - fi + # Collect exit code of the writer + if [ $(cat vfd_swmr_dsetchks_writer.rc) -ne 0 ]; then + echo writer had error + nerrors=$((nerrors + 1)) + fi - # Clean up output files - rm -f vfd_swmr_dsetchks_writer.{out,rc} - rm -f vfd_swmr_dsetchks_reader.*.{out,rc} + # Clean up output files + rm -f vfd_swmr_dsetchks_writer.{out,rc} + rm -f vfd_swmr_dsetchks_reader.*.{out,rc} + done done ############################################################################### diff --git a/test/vfd_swmr.c b/test/vfd_swmr.c index 09dee38..3ed73c1 100644 --- a/test/vfd_swmr.c +++ b/test/vfd_swmr.c @@ -884,7 +884,7 @@ test_writer_md(void) hid_t sid = -1; /* Dataspace ID */ hid_t did = -1; /* Dataset ID */ int * rwbuf = NULL; /* Data buffer for writing */ - H5O_info_t oinfo; /* Object metadata information */ + H5O_info2_t oinfo; /* Object metadata information */ char dname[100]; /* Name of dataset */ hsize_t dims[2] = {50, 20}; /* Dataset dimension sizes */ hsize_t max_dims[2] = {H5S_UNLIMITED, H5S_UNLIMITED}; /* Dataset maximum dimension sizes */ @@ -961,7 +961,7 @@ test_writer_md(void) FAIL_STACK_ERROR /* Get dataset object header address */ - if (H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0) + if (H5Oget_info3(did, &oinfo, H5O_INFO_BASIC) < 0) FAIL_STACK_ERROR /* Close the dataset */ @@ -998,7 +998,7 @@ test_writer_md(void) FAIL_STACK_ERROR /* Get dataset object info */ - if (H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0) + if (H5Oget_info3(did, &oinfo, H5O_INFO_BASIC) < 0) FAIL_STACK_ERROR /* Close the dataset */ @@ -1032,7 +1032,7 @@ test_writer_md(void) FAIL_STACK_ERROR /* Get dataset object info */ - if (H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0) + if (H5Oget_info3(did, &oinfo, H5O_INFO_BASIC) < 0) FAIL_STACK_ERROR /* Close the dataset */ @@ -1166,16 +1166,16 @@ test_file_end_tick_concur(void) static unsigned test_reader_md_concur(void) { - unsigned i = 0; /* Local index variables */ - uint8_t * buf = NULL; /* Data page from the page buffer */ - hid_t dcpl = -1; /* Dataset creation property list */ - hid_t sid = -1; /* Dataspace ID */ - hid_t did = -1; /* Dataset ID */ - int * rwbuf = NULL; /* Data buffer for writing */ - H5O_info_t oinfo; /* Object metadata information */ - char dname[100]; /* Name of dataset */ - hsize_t dims[2] = {50, 20}; /* Dataset dimension sizes */ - hsize_t max_dims[2] = /* Dataset maximum dimension sizes */ + unsigned i = 0; /* Local index variables */ + uint8_t * buf = NULL; /* Data page from the page buffer */ + hid_t dcpl = -1; /* Dataset creation property list */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1; /* Dataset ID */ + int * rwbuf = NULL; /* Data buffer for writing */ + H5O_info2_t oinfo; /* Object metadata information */ + char dname[100]; /* Name of dataset */ + hsize_t dims[2] = {50, 20}; /* Dataset dimension sizes */ + hsize_t max_dims[2] = /* Dataset maximum dimension sizes */ {H5S_UNLIMITED, H5S_UNLIMITED}; hsize_t chunk_dims[2] = {2, 5}; /* Dataset chunked dimension sizes */ unsigned num_entries = 0; /* Number of entries in the index */ @@ -1519,7 +1519,7 @@ test_reader_md_concur(void) FAIL_STACK_ERROR /* Get dataset object header address */ - if (H5Oget_info(did, &oinfo, H5O_INFO_BASIC) < 0) + if (H5Oget_info3(did, &oinfo, H5O_INFO_BASIC) < 0) FAIL_STACK_ERROR /* Close the dataset */ diff --git a/test/vfd_swmr_addrem_writer.c b/test/vfd_swmr_addrem_writer.c index 7f13cec..f115d2e 100644 --- a/test/vfd_swmr_addrem_writer.c +++ b/test/vfd_swmr_addrem_writer.c @@ -95,7 +95,7 @@ open_skeleton(const char *filename, unsigned verbose) goto error; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, TRUE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, TRUE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(TRUE, TRUE, FALSE, 4096, config)) < 0) diff --git a/test/vfd_swmr_attrdset_writer.c b/test/vfd_swmr_attrdset_writer.c index 27a23e6..f445321 100644 --- a/test/vfd_swmr_attrdset_writer.c +++ b/test/vfd_swmr_attrdset_writer.c @@ -150,12 +150,16 @@ static bool open_dset_real(hid_t fid, hid_t *did, const char *name, unsigned *ma unsigned *min_dense); static bool close_dsets(const dsets_state_t *ds); +static bool perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, + np_state_t *np); static bool attr_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which); static bool attr_action(unsigned action, const state_t *s, hid_t did, unsigned which); static bool add_attr(const state_t *s, hid_t did, unsigned int which); static bool modify_attr(const state_t *s, hid_t did, unsigned int which); static bool delete_attr(hid_t did, unsigned int which); +static bool verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, + np_state_t *np); static bool verify_attr_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which); static bool verify_attr_action(unsigned action, hid_t did, unsigned which); @@ -222,13 +226,23 @@ state_init(state_t *s, int argc, char **argv) { unsigned long tmp; int ch; - const hsize_t dims = 1; - char tfile[PATH_MAX]; + const hsize_t dims = 1; + char * tfile = NULL; char * end; *s = ALL_HID_INITIALIZER; - esnprintf(tfile, sizeof(tfile), "%s", argv[0]); - esnprintf(s->progname, sizeof(s->progname), "%s", basename(tfile)); + + if (H5_basename(argv[0], &tfile) < 0) { + HDprintf("H5_basename failed\n"); + TEST_ERROR; + } + + esnprintf(s->progname, sizeof(s->progname), "%s", tfile); + + if (tfile) { + HDfree(tfile); + tfile = NULL; + } while ((ch = getopt(argc, argv, "pgkvmbqSNa:d:u:c:")) != -1) { switch (ch) { @@ -340,6 +354,9 @@ state_init(state_t *s, int argc, char **argv) return true; error: + if (tfile) + HDfree(tfile); + return false; } /* state_init() */ @@ -892,16 +909,89 @@ error: } /* close_dsets() */ /* - * Attribute handling by the writer + * Writer */ /* - * Perform the "action" for each of the datasets specified on the command line. + * Perform the attribute operations specified on the command line. * ADD_ATTR : -a <nattrs> option * MODIFY_ATTR : -m option * DELETE_ATTR : -d <dattrs> option */ static bool +perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +{ + unsigned step; + bool result; + unsigned dd; + + for (step = 0; step < s->asteps; step++) { + dbgf(2, "Adding attribute %d\n", step); + + result = attr_dsets_action(ADD_ATTR, s, ds, step); + + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for addition failed\n"); + TEST_ERROR; + } + } + + if (s->mod_attr) { + + /* Need to sync up writer/reader before moving onto the next phase */ + if (s->use_np && !np_writer(true, 0, s, np, config)) { + HDprintf("np_writer() for modification failed\n"); + TEST_ERROR; + } + + /* Start modification */ + for (step = 0; step < s->asteps; step++) { + dbgf(2, "Modifying attribute %d\n", step); + + result = attr_dsets_action(MODIFY_ATTR, s, ds, step); + + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for modification failed\n"); + TEST_ERROR; + } + } + } + + if (s->dattrs) { + + /* Need to sync up writer/reader before moving onto the next phase */ + if (s->use_np && !np_writer(true, 0, s, np, config)) { + HDprintf("np_writer() for deletion failed\n"); + TEST_ERROR; + } + + /* Start deletion */ + for (dd = 0, step = s->asteps - 1; dd < s->dattrs; dd++, --step) { + dbgf(2, "Deleting attribute %d\n", step); + + result = attr_dsets_action(DELETE_ATTR, s, ds, step); + + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for deletion failed\n"); + TEST_ERROR; + } + } + } + + return true; + +error: + return false; + +} /* perform_dsets_operations() */ + +/* + * Perform the "action" for each of the datasets specified on the command line. + * -p: compact dataset + * -g: contiguous dataset + * -k: 5 chunked datasets with 5 indexing types + */ +static bool attr_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which) { int nerrors = 0; @@ -1181,14 +1271,111 @@ error: */ /* - * Verify the action on each of the datasets specified: + * Verify the attribute operations specified on the command line: * ADD_ATTR : -a <nattrs> option * MODIFY_ATTR : -m option * DELETE_ATTR : -d <dattrs> option * * Also verify continuation block and compact<->dense storage if: * --[-c <csteps>] is 1 - * --not -m option + * --not appliable for -m option + */ +static bool +verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +{ + unsigned step; + bool result; + unsigned dd; + + /* Start verifying addition */ + for (step = 0; step < s->asteps; step++) { + dbgf(2, "Verifying...attribute %d\n", step); + + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Wait for a few ticks for the update to happen */ + decisleep(config->tick_len * s->update_interval); + + result = verify_attr_dsets_action(ADD_ATTR, s, ds, step); + + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying addition failed\n"); + TEST_ERROR; + } + } + + if (s->mod_attr) { + /* Need to sync up writer/reader before moving onto the next phase */ + if (!np_reader_no_verification(s, np, config)) { + HDprintf("np_reader_no_verification() for verifying modification failed\n"); + TEST_ERROR; + } + + /* Start verifying modification */ + for (step = 0; step < s->asteps; step++) { + dbgf(2, "Verifying...modify attribute %d\n", step); + + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Wait for a few ticks for the update to happen */ + decisleep(config->tick_len * s->update_interval); + + result = verify_attr_dsets_action(MODIFY_ATTR, s, ds, step); + + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying modification failed\n"); + TEST_ERROR; + } + } + } + + if (s->dattrs) { + + /* Need to sync up writer/reader before moving onto the next phase */ + if (!np_reader_no_verification(s, np, config)) { + HDprintf("np_reader_no_verification() for verifying modification failed\n"); + TEST_ERROR; + } + + /* Start verifying deletion */ + for (dd = 0, step = s->asteps - 1; dd < s->dattrs; dd++, --step) { + dbgf(2, "Verifying...delete attribute %d\n", step); + + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Wait for a few ticks for the update to happen */ + decisleep(config->tick_len * s->update_interval); + + result = verify_attr_dsets_action(DELETE_ATTR, s, ds, step); + + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying deletion failed\n"); + TEST_ERROR; + } + } + } + + return true; + +error: + + return false; +} /* verify_dsets_operations() */ + +/* + * Verify the "action" for each of the datasets specified on the command line. + * -p: compact dataset + * -g: contiguous dataset + * -k: 5 chunked datasets with 5 indexing types */ static bool verify_attr_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which) @@ -1317,12 +1504,13 @@ static bool verify_add_or_modify_attr(unsigned action, hid_t did, char *attr_name, unsigned int which) { unsigned int read_which; - char vl_which[sizeof("attr-9999999999")]; - char * read_vl_which = NULL; - bool is_vl = false; - hid_t aid = H5I_INVALID_HID; - hid_t atid = H5I_INVALID_HID; - bool ret = FALSE; + unsigned int tmp_val; + char tmp_vl_val[sizeof("attr-9999999999")]; + char * read_vl_which; + bool is_vl = false; + hid_t aid = H5I_INVALID_HID; + hid_t atid = H5I_INVALID_HID; + bool ret = FALSE; HDassert(did != badhid); HDassert(action == ADD_ATTR || action == MODIFY_ATTR); @@ -1339,17 +1527,18 @@ verify_add_or_modify_attr(unsigned action, hid_t did, char *attr_name, unsigned if ((is_vl = H5Tis_variable_str(atid))) { if (action == ADD_ATTR) - HDsprintf(vl_which, "%u", which); + HDsprintf(tmp_vl_val, "%u", which); else - HDsprintf(vl_which, "%u %c", which, 'M'); - - if ((read_vl_which = HDmalloc(sizeof("9999999999"))) == NULL) { - HDprintf("HDmalloc failed\n"); - TEST_ERROR; - } + HDsprintf(tmp_vl_val, "%u %c", which, 'M'); + } + else { + if (action == MODIFY_ATTR) + tmp_val = which + 1; + else + tmp_val = which; } - if (H5Aread(aid, atid, is_vl ? (void *)&read_vl_which : (void *)&read_which) < 0) { + if (H5Aread(aid, atid, is_vl ? &read_vl_which : (void *)&read_which) < 0) { HDprintf("H5Aread failed\n"); TEST_ERROR; } @@ -1365,14 +1554,17 @@ verify_add_or_modify_attr(unsigned action, hid_t did, char *attr_name, unsigned } if (is_vl) { - if (!HDstrcmp(vl_which, read_vl_which)) + dbgf(2, "read_vl_which = %s, tmp_vl_val= %s\n", read_vl_which, tmp_vl_val); + if (!HDstrcmp(read_vl_which, tmp_vl_val)) ret = true; } - else - ret = (read_which == which); + else { + dbgf(2, "read_which = %u, tmp_val = %u\n", read_which, tmp_val); + ret = (read_which == tmp_val); + } - if (read_vl_which) - HDfree(read_vl_which); + if (is_vl) + H5free_memory(read_vl_which); return ret; @@ -1384,8 +1576,8 @@ error: } H5E_END_TRY; - if (read_vl_which) - HDfree(read_vl_which); + if (is_vl) + H5free_memory(read_vl_which); return false; @@ -1452,9 +1644,8 @@ verify_storage_cont(unsigned action, hid_t did, unsigned int which, unsigned max /* Verify dense storage & no cont */ else if (which == max_compact) ret = verify_storage_cont_real(did, which, max_compact); - - /* For deletion */ } + /* For deletion */ else if (action == DELETE_ATTR) { /* Verify compact storage & cont */ @@ -1763,17 +1954,14 @@ error: int main(int argc, char **argv) { - hid_t fapl = H5I_INVALID_HID; - hid_t fcpl = H5I_INVALID_HID; - unsigned step; + hid_t fapl = H5I_INVALID_HID; + hid_t fcpl = H5I_INVALID_HID; bool writer = FALSE; state_t s; const char * personality; H5F_vfd_swmr_config_t config; np_state_t np; dsets_state_t ds; - unsigned dd; - bool result; if (!state_init(&s, argc, argv)) { HDprintf("state_init() failed\n"); @@ -1792,7 +1980,7 @@ main(int argc, char **argv) } /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 7, writer, FALSE, 128, "./attrdset-shadow"); + init_vfd_swmr_config(&config, 4, 7, writer, true, 128, "./attrdset-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(true, s.use_vfd_swmr, true, 4096, &config)) < 0) { @@ -1835,136 +2023,15 @@ main(int argc, char **argv) } if (writer) { - for (step = 0; step < s.asteps; step++) { - dbgf(2, "Adding attribute %d\n", step); - - result = attr_dsets_action(ADD_ATTR, &s, &ds, step); - - if (s.use_np && !np_writer(result, step, &s, &np, &config)) { - HDprintf("np_writer() for addition failed\n"); - TEST_ERROR; - } - } - - if (s.mod_attr) { - - /* Need to sync up writer/reader before moving onto the next phase */ - if (s.use_np && !np_writer(true, 0, &s, &np, &config)) { - HDprintf("np_writer() for modification failed\n"); - TEST_ERROR; - } - - /* Start modification */ - for (step = 0; step < s.asteps; step++) { - dbgf(2, "Modifying attribute %d\n", step); - - result = attr_dsets_action(MODIFY_ATTR, &s, &ds, step); - - if (s.use_np && !np_writer(result, step, &s, &np, &config)) { - HDprintf("np_writer() for modification failed\n"); - TEST_ERROR; - } - } - } - - if (s.dattrs) { - - /* Need to sync up writer/reader before moving onto the next phase */ - if (s.use_np && !np_writer(true, 0, &s, &np, &config)) { - HDprintf("np_writer() for deletion failed\n"); - TEST_ERROR; - } - - /* Start deletion */ - for (dd = 0, step = s.asteps - 1; dd < s.dattrs; dd++, --step) { - dbgf(2, "Deleting attribute %d\n", step); - - result = attr_dsets_action(DELETE_ATTR, &s, &ds, step); - - if (s.use_np && !np_writer(result, step, &s, &np, &config)) { - HDprintf("np_writer() for deletion failed\n"); - TEST_ERROR; - } - } + if (!perform_dsets_operations(&s, &ds, &config, &np)) { + HDprintf("perform_dsets_operations() failed\n"); + TEST_ERROR; } } else { - - /* Start verifying addition */ - for (step = 0; step < s.asteps; step++) { - dbgf(2, "Verifying...attribute %d\n", step); - - if (s.use_np && !np_confirm_verify_notify(np.fd_writer_to_reader, step, &s, &np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; - } - - /* Wait for a few ticks for the update to happen */ - decisleep(config.tick_len * s.update_interval); - - result = verify_attr_dsets_action(ADD_ATTR, &s, &ds, step); - - if (s.use_np && !np_reader(result, step, &s, &np)) { - HDprintf("np_reader() for verifying addition failed\n"); - TEST_ERROR; - } - } - - if (s.mod_attr) { - /* Need to sync up writer/reader before moving onto the next phase */ - if (!np_reader_no_verification(&s, &np, &config)) { - HDprintf("np_reader_no_verification() for verifying modification failed\n"); - TEST_ERROR; - } - - /* Start verifying modification */ - for (step = 0; step < s.asteps; step++) { - dbgf(2, "Verifying...modify attribute %d\n", step); - - if (s.use_np && !np_confirm_verify_notify(np.fd_writer_to_reader, step, &s, &np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; - } - - /* Wait for a few ticks for the update to happen */ - decisleep(config.tick_len * s.update_interval); - - result = verify_attr_dsets_action(MODIFY_ATTR, &s, &ds, step); - - if (s.use_np && !np_reader(result, step, &s, &np)) { - HDprintf("np_reader() for verifying modification failed\n"); - TEST_ERROR; - } - } - } - - if (s.dattrs) { - - /* Need to sync up writer/reader before moving onto the next phase */ - if (!np_reader_no_verification(&s, &np, &config)) { - HDprintf("np_reader_no_verification() for verifying modification failed\n"); - TEST_ERROR; - } - - /* Start verifying deletion */ - for (dd = 0, step = s.asteps - 1; dd < s.dattrs; dd++, --step) { - dbgf(2, "Verifying...delete attribute %d\n", step); - - if (s.use_np && !np_confirm_verify_notify(np.fd_writer_to_reader, step, &s, &np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; - } - - /* Wait for a few ticks for the update to happen */ - decisleep(config.tick_len * s.update_interval); - - result = verify_attr_dsets_action(DELETE_ATTR, &s, &ds, step); - - if (s.use_np && !np_reader(result, step, &s, &np)) { - HDprintf("np_reader() for verifying deletion failed\n"); - TEST_ERROR; - } - } + if (!verify_dsets_operations(&s, &ds, &config, &np)) { + HDprintf("verify_dsets_operations() failed\n"); + TEST_ERROR; } } diff --git a/test/vfd_swmr_bigset_writer.c b/test/vfd_swmr_bigset_writer.c index 9c05fa6..61d552e 100644 --- a/test/vfd_swmr_bigset_writer.c +++ b/test/vfd_swmr_bigset_writer.c @@ -2259,6 +2259,11 @@ main(int argc, char **argv) HDfree(mat); + if (s.dataset) + HDfree(s.dataset); + if (s.sources) + HDfree(s.sources); + return EXIT_SUCCESS; error: diff --git a/test/vfd_swmr_dsetchks_writer.c b/test/vfd_swmr_dsetchks_writer.c index 1d9bc4c..d264ca9 100644 --- a/test/vfd_swmr_dsetchks_writer.c +++ b/test/vfd_swmr_dsetchks_writer.c @@ -74,6 +74,7 @@ typedef struct { bool use_np; /* For -N option */ bool use_vfd_swmr; /* For -S option */ bool use_filter; /* For -o option */ + bool flush_raw_data; /* For -U option */ bool single_index; /* -s option: create a chunked dataset with single chunk index */ bool implicit_index; /* -i option: create a chunked datasets with implicit chunk index */ @@ -99,9 +100,9 @@ typedef struct { { \ .filename = "", .file = H5I_INVALID_HID, .filetype = H5T_NATIVE_UINT32, \ .update_interval = READER_WAIT_TICKS, .csteps = 1, .use_np = true, .use_vfd_swmr = true, \ - .use_filter = false, .single_index = false, .implicit_index = false, .fa_index = false, \ - .ea_index = false, .bt2_index = false, .rows = 10, .cols = 5, .gwrites = 0, .pwrites = 0, \ - .twrites = 0, .lwrites = 0, .xincrs = 0, .ydecrs = 0 \ + .use_filter = false, .flush_raw_data = true, .single_index = false, .implicit_index = false, \ + .fa_index = false, .ea_index = false, .bt2_index = false, .rows = 10, .cols = 5, .gwrites = 0, \ + .pwrites = 0, .twrites = 0, .lwrites = 0, .xincrs = 0, .ydecrs = 0 \ } /* Structure to hold info for different dataset types */ @@ -166,20 +167,21 @@ static void setup_selection(unsigned action, unsigned which, const state_t *s, c static void check_set_edge_block(const state_t *s, const dsets_state_t *ds, unsigned i, unsigned j, hsize_t *block); static void check_set_partial_block(unsigned action, const hsize_t *dims, hsize_t *block, hsize_t *start); -static bool write_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, hsize_t *count, - hsize_t *block); +static bool write_chunks(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, + hsize_t *count, hsize_t *block); static bool write_dset_single(unsigned action, const state_t *s, const dsets_state_t *ds); static bool dsets_extent(unsigned action, const state_t *s, const dsets_state_t *ds); static bool dset_extent_real(unsigned action, hid_t did, const hsize_t *chunk_dims); static bool verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, - np_state_t *np); + np_state_t *np, bool fileclosed); -static bool verify_dsets_chunks(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which); -static bool verify_read_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, - hsize_t *count, hsize_t *block); -static bool verify_read_dset_single(unsigned action, const state_t *s, const dsets_state_t *ds); +static bool verify_dsets_chunks(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which, + bool fileclosed); +static bool verify_chunks(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, + hsize_t *count, hsize_t *block, bool fileclosed, bool flush_raw_data); +static bool verify_dset_single(unsigned action, const state_t *s, const dsets_state_t *ds, bool fileclosed); static bool verify_dsets_extent(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which); static bool verify_dset_extent_real(unsigned action, hid_t did, unsigned rows, unsigned cols, unsigned which); @@ -189,16 +191,16 @@ static const hid_t badhid = H5I_INVALID_HID; static void usage(const char *progname) { - fprintf(stderr, - "usage: %s \n" - " [-s] [-i] [-f] [-e] [-r]\n" - " [-m rows] [-n cols]\n" - " [-g gwrites] [-p pwrites] [-t twrites] [-l lwrites]\n" - " [-x xincrs] [-y decrs]\n" - " [-u nticks] [-c csteps] [-S] [-N] [-q] [-b] [-o]\n", - progname); - - fprintf( + HDfprintf(stderr, + "usage: %s \n" + " [-s] [-i] [-f] [-e] [-r]\n" + " [-m rows] [-n cols]\n" + " [-g gwrites] [-p pwrites] [-t twrites] [-l lwrites]\n" + " [-x xincrs] [-y decrs]\n" + " [-u nticks] [-c csteps] [-U] [-S] [-N] [-q] [-b] [-o]\n", + progname); + + HDfprintf( stderr, "\n" "-s: create a 2-d chunked dataset with single index\n" @@ -218,6 +220,7 @@ usage(const char *progname) " (default is 4)\n" "-c csteps: `csteps` steps communication interval between reader and writer\n" " (default is 1)\n" + "-U: disable flush of raw data (default is flushing raw data)\n" "-S: do not use VFD SWMR\n" "-N: do not use named pipes for test synchronization\n" "-q: silence printouts, few messages\n" @@ -225,7 +228,7 @@ usage(const char *progname) " (default is H5T_NATIVE_UINT32)\n\n" "-o: enable compression (deflate filter) for the datasets\n"); - fprintf( + HDfprintf( stderr, "\n" "Note:\n" @@ -263,14 +266,24 @@ state_init(state_t *s, int argc, char **argv) { unsigned long tmp; int ch; - char tfile[PATH_MAX]; + char * tfile = NULL; char * end; *s = ALL_HID_INITIALIZER; - esnprintf(tfile, sizeof(tfile), "%s", argv[0]); - esnprintf(s->progname, sizeof(s->progname), "%s", basename(tfile)); - while ((ch = getopt(argc, argv, "siferom:n:x:y:g:p:t:l:bqSNu:c:")) != -1) { + if (H5_basename(argv[0], &tfile) < 0) { + HDprintf("H5_basename failed\n"); + TEST_ERROR + } + + esnprintf(s->progname, sizeof(s->progname), "%s", tfile); + + if (tfile) { + HDfree(tfile); + tfile = NULL; + } + + while ((ch = getopt(argc, argv, "siferom:n:x:y:g:p:t:l:bqSNUu:c:")) != -1) { switch (ch) { case 's': /* A chunked dataset with single index */ @@ -309,6 +322,10 @@ state_init(state_t *s, int argc, char **argv) s->use_vfd_swmr = false; break; + case 'U': /* Disable flush of raw data */ + s->flush_raw_data = false; + break; + case 'N': /* Disable named pipes synchronization */ s->use_np = false; break; @@ -326,15 +343,15 @@ state_init(state_t *s, int argc, char **argv) errno = 0; tmp = strtoul(optarg, &end, 0); if (end == optarg || *end != '\0') { - printf("couldn't parse `-%c` argument `%s`\n", ch, optarg); + HDprintf("couldn't parse `-%c` argument `%s`\n", ch, optarg); TEST_ERROR; } else if (errno != 0) { - printf("couldn't parse `-%c` argument `%s`\n", ch, optarg); + HDprintf("couldn't parse `-%c` argument `%s`\n", ch, optarg); TEST_ERROR; } else if (tmp > UINT_MAX) { - printf("`-%c` argument `%lu` too large\n", ch, tmp); + HDprintf("`-%c` argument `%lu` too large\n", ch, tmp); TEST_ERROR; } @@ -372,63 +389,63 @@ state_init(state_t *s, int argc, char **argv) /* Require to specify at least -s or -i or -f or -e or -r option */ if (!s->single_index && !s->implicit_index && !s->fa_index && !s->ea_index && !s->bt2_index) { - printf("Require to specify at least -s or -i or -f or -e or -r option\n"); + HDprintf("Require to specify at least -s or -i or -f or -e or -r option\n"); usage(s->progname); goto error; } /* -x or -y option only apply to dataset with fixed/extensible array/v2 btree index */ if ((s->single_index || s->implicit_index) && (s->xincrs || s->ydecrs)) { - printf("-x or -y option not applicable to dataset with single or implicit index\n"); + HDprintf("-x or -y option not applicable to dataset with single or implicit index\n"); usage(s->progname); goto error; } /* rows and cols cannot be zero */ if (s->rows == 0 || s->cols == 0) { - printf("-m <rows> or -n <cols> cannot be zero\n"); + HDprintf("-m <rows> or -n <cols> cannot be zero\n"); TEST_ERROR; } /* -c <csteps> cannot be zero */ if (!s->csteps) { - printf("communication interval cannot be zero\n"); + HDprintf("communication interval cannot be zero\n"); TEST_ERROR; } /* -c <csteps> and -g <gwrites> options */ if (s->gwrites && s->csteps > s->gwrites) { - printf("communication interval with -g <gwrites> is out of bounds\n"); + HDprintf("communication interval with -g <gwrites> is out of bounds\n"); TEST_ERROR; } /* -c <csteps> and -p <pwrites> options */ if (s->pwrites && s->csteps > s->pwrites) { - printf("communication interval with -p <pwrites> is out of bounds\n"); + HDprintf("communication interval with -p <pwrites> is out of bounds\n"); TEST_ERROR; } /* -c <csteps> and -t <twrites> options */ if (s->twrites && s->csteps > s->twrites) { - printf("communication interval with -t <twrites> is out of bounds\n"); + HDprintf("communication interval with -t <twrites> is out of bounds\n"); TEST_ERROR; } /* -c <csteps> and -l <lwrites> options */ if (s->lwrites && s->csteps > s->lwrites) { - printf("communication interval with -l <lwrites> is out of bounds\n"); + HDprintf("communication interval with -l <lwrites> is out of bounds\n"); TEST_ERROR; } /* -c <csteps> and -x <xincrs> options */ if (s->xincrs && s->csteps > s->xincrs) { - printf("communication interval with -x <xincrs> is out of bounds\n"); + HDprintf("communication interval with -x <xincrs> is out of bounds\n"); TEST_ERROR; } /* -c <csteps> and -y <ydecrs> options */ if (s->ydecrs && s->csteps > s->ydecrs) { - printf("communication interval with -y <ydecrs> is out of bounds\n"); + HDprintf("communication interval with -y <ydecrs> is out of bounds\n"); TEST_ERROR; } @@ -438,6 +455,8 @@ state_init(state_t *s, int argc, char **argv) return true; error: + if (tfile) + HDfree(tfile); return false; } /* state_init() */ @@ -472,26 +491,26 @@ create_dsets(const state_t *s, dsets_state_t *ds) /* Create dataset creation property list */ /* Set properties in dcpl that are common for all the datasets */ if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) { - printf("H5Pcreate failed\n"); + HDprintf("H5Pcreate failed\n"); TEST_ERROR; } /* Set to chunked layout */ if (H5Pset_layout(dcpl, H5D_CHUNKED) < 0) { - printf("H5Pset_layout failed\n"); + HDprintf("H5Pset_layout failed\n"); TEST_ERROR; } /* Set fill value to FILL_INIT */ if (H5Pset_fill_value(dcpl, s->filetype, &fillval) < 0) { - printf("H5Pset_fill_value failed\n"); + HDprintf("H5Pset_fill_value failed\n"); goto error; } /* Set to use filter as specified */ if (s->use_filter) { if (H5Pset_deflate(dcpl, 5) < 0) { - printf("H5Pset_deflate failed\n"); + HDprintf("H5Pset_deflate failed\n"); goto error; } } @@ -501,41 +520,41 @@ create_dsets(const state_t *s, dsets_state_t *ds) if (s->single_index) { if ((dcpl2 = H5Pcopy(dcpl)) < 0) { - printf("H5Tcopy failed\n"); + HDprintf("H5Tcopy failed\n"); TEST_ERROR; } if (H5Pset_chunk(dcpl2, 2, dims) < 0) { - printf("H5Pset_chunk failed\n"); + HDprintf("H5Pset_chunk failed\n"); TEST_ERROR; } if ((sid = H5Screate_simple(2, dims, dims)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Create the chunked dataset: single index */ if ((ds->single_did = H5Dcreate2(s->file, DSET_SINGLE_NAME, s->filetype, sid, H5P_DEFAULT, dcpl2, H5P_DEFAULT)) < 0) { - printf("H5Dcreate2 chunked dataset:single index failed\n"); + HDprintf("H5Dcreate2 chunked dataset:single index failed\n"); TEST_ERROR; } if (H5Pclose(dcpl2) < 0) { - printf("H5Pclose failed\n"); + HDprintf("H5Pclose failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } } /* Chunk size is common for datasets with implicit/fa/ea/bt2 index */ if (H5Pset_chunk(dcpl, 2, ds->chunk_dims) < 0) { - printf("H5Pset_chunk failed\n"); + HDprintf("H5Pset_chunk failed\n"); TEST_ERROR; } @@ -544,34 +563,34 @@ create_dsets(const state_t *s, dsets_state_t *ds) if (s->implicit_index) { if ((dcpl2 = H5Pcopy(dcpl)) < 0) { - printf("H5Pcopy failed\n"); + HDprintf("H5Pcopy failed\n"); TEST_ERROR; } if (H5Pset_alloc_time(dcpl2, H5D_ALLOC_TIME_EARLY) < 0) { - printf("H5Pset_alloc_time\n"); + HDprintf("H5Pset_alloc_time\n"); TEST_ERROR; } if ((sid = H5Screate_simple(2, dims, dims)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Create the chunked dataset: implicit index */ if ((ds->implicit_did = H5Dcreate2(s->file, DSET_IMPLICIT_NAME, s->filetype, sid, H5P_DEFAULT, dcpl2, H5P_DEFAULT)) < 0) { - printf("H5Dcreate2 chunked dataset:implicit index failed\n"); + HDprintf("H5Dcreate2 chunked dataset:implicit index failed\n"); TEST_ERROR; } if (H5Pclose(dcpl2) < 0) { - printf("H5Pclose failed\n"); + HDprintf("H5Pclose failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } } @@ -585,19 +604,19 @@ create_dsets(const state_t *s, dsets_state_t *ds) max_dims[1] = dims[1] * 2; if ((sid = H5Screate_simple(2, dims, max_dims)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Create the chunked dataset (fixed array index) with the named datatype */ if ((ds->fa_did = H5Dcreate2(s->file, DSET_FA_NAME, s->filetype, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) { - printf("H5Dcreate2 chunked dataset: fa index failed\n"); + HDprintf("H5Dcreate2 chunked dataset: fa index failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } } @@ -611,19 +630,19 @@ create_dsets(const state_t *s, dsets_state_t *ds) max_dims[1] = H5S_UNLIMITED; if ((sid = H5Screate_simple(2, dims, max_dims)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Create the chunked dataset (extensible array index) with the named datatype */ if ((ds->ea_did = H5Dcreate2(s->file, DSET_EA_NAME, s->filetype, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) { - printf("H5Dcreate2 chunked dataset: ea index failed\n"); + HDprintf("H5Dcreate2 chunked dataset: ea index failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } } @@ -636,25 +655,25 @@ create_dsets(const state_t *s, dsets_state_t *ds) max_dims[0] = max_dims[1] = H5S_UNLIMITED; if ((sid = H5Screate_simple(2, dims, max_dims)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Create the chunked dataset (btree2 index) with the named datatype */ if ((ds->bt2_did = H5Dcreate2(s->file, DSET_BT2_NAME, s->filetype, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) { - printf("H5Dcreate2 chunked dataset: bt2 index failed\n"); + HDprintf("H5Dcreate2 chunked dataset: bt2 index failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } } if (H5Pclose(dcpl) < 0) { - printf("H5Pclose failed\n"); + HDprintf("H5Pclose failed\n"); TEST_ERROR; } @@ -690,7 +709,7 @@ open_dsets(const state_t *s, dsets_state_t *ds) /* Dataset with single index */ if (s->single_index) { if ((ds->single_did = H5Dopen2(s->file, DSET_SINGLE_NAME, H5P_DEFAULT)) < 0) { - printf("H5Dopen dataset with single index failed\n"); + HDprintf("H5Dopen dataset with single index failed\n"); TEST_ERROR; } } @@ -698,7 +717,7 @@ open_dsets(const state_t *s, dsets_state_t *ds) /* Dataset with implicit index */ if (s->implicit_index) { if ((ds->implicit_did = H5Dopen2(s->file, DSET_IMPLICIT_NAME, H5P_DEFAULT)) < 0) { - printf("H5Dopen dataset with implicit index failed\n"); + HDprintf("H5Dopen dataset with implicit index failed\n"); TEST_ERROR; } } @@ -706,7 +725,7 @@ open_dsets(const state_t *s, dsets_state_t *ds) /* Dataset with fixed array index */ if (s->fa_index) { if ((ds->fa_did = H5Dopen2(s->file, DSET_FA_NAME, H5P_DEFAULT)) < 0) { - printf("H5Dopen dataset with fa index failed\n"); + HDprintf("H5Dopen dataset with fa index failed\n"); TEST_ERROR; } } @@ -714,7 +733,7 @@ open_dsets(const state_t *s, dsets_state_t *ds) /* Dataset with extensible array index */ if (s->ea_index) { if ((ds->ea_did = H5Dopen2(s->file, DSET_EA_NAME, H5P_DEFAULT)) < 0) { - printf("H5Dopen dataset with ea index failed\n"); + HDprintf("H5Dopen dataset with ea index failed\n"); TEST_ERROR; } } @@ -722,7 +741,7 @@ open_dsets(const state_t *s, dsets_state_t *ds) /* Dataset with v2 btree index */ if (s->bt2_index) { if ((ds->bt2_did = H5Dopen2(s->file, DSET_BT2_NAME, H5P_DEFAULT)) < 0) { - printf("H5Dopen dataset with ea index failed\n"); + HDprintf("H5Dopen dataset with ea index failed\n"); TEST_ERROR; } } @@ -765,31 +784,31 @@ close_dsets(const dsets_state_t *ds) { /* Close dataset with single index */ if (ds->single_did != badhid && H5Dclose(ds->single_did) < 0) { - printf("close_dset_real() dataset: single index failed\n"); + HDprintf("close_dset_real() dataset: single index failed\n"); TEST_ERROR; } /* Close dataset with implicit index */ if (ds->implicit_did != badhid && H5Dclose(ds->implicit_did) < 0) { - printf("close_dset_real() dataset: implicit index failed\n"); + HDprintf("close_dset_real() dataset: implicit index failed\n"); TEST_ERROR; } /* Close dataset with fixed array index */ if (ds->fa_did != badhid && H5Dclose(ds->fa_did) < 0) { - printf("close_dset_real() dataset: fa index failed\n"); + HDprintf("close_dset_real() dataset: fa index failed\n"); TEST_ERROR; } /* Close dataset with extensible array index */ if (ds->ea_did != badhid && H5Dclose(ds->ea_did) < 0) { - printf("close_dset_real() : ea index failed\n"); + HDprintf("close_dset_real() : ea index failed\n"); TEST_ERROR; } /* Close dataset with v2 btree index */ if (ds->bt2_did != badhid && H5Dclose(ds->bt2_did) < 0) { - printf("close_dset_real() dataset: bt2 index failed\n"); + HDprintf("close_dset_real() dataset: bt2 index failed\n"); TEST_ERROR; } @@ -848,7 +867,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = write_dset_single(GWRITES, s, ds); if (s->use_np && !np_writer(result, 0, s, np, config)) { - printf("np_writer() for addition failed\n"); + HDprintf("np_writer() for addition failed\n"); TEST_ERROR; } } @@ -863,7 +882,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = write_dset_single(PWRITES, s, ds); if (s->use_np && !np_writer(result, 0, s, np, config)) { - printf("np_writer() for addition failed\n"); + HDprintf("np_writer() for addition failed\n"); TEST_ERROR; } } @@ -884,7 +903,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = write_dsets_chunks(GWRITES, s, ds, step); if (s->use_np && !np_writer(result, step, s, np, config)) { - printf("np_writer() for single full chunk writes failed\n"); + HDprintf("np_writer() for single full chunk writes failed\n"); TEST_ERROR; } } @@ -902,7 +921,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = write_dsets_chunks(PWRITES, s, ds, step); if (s->use_np && !np_writer(result, step, s, np, config)) { - printf("np_writer() for partial single chunk writes failed\n"); + HDprintf("np_writer() for partial single chunk writes failed\n"); TEST_ERROR; } } @@ -920,7 +939,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = write_dsets_chunks(TWRITES, s, ds, step); if (s->use_np && !np_writer(result, step, s, np, config)) { - printf("np_writer() for multiple full chunk writes failed\n"); + HDprintf("np_writer() for multiple full chunk writes failed\n"); TEST_ERROR; } } @@ -939,7 +958,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = write_dsets_chunks(LWRITES, s, ds, step); if (s->use_np && !np_writer(result, step, s, np, config)) { - printf("np_writer() for multiple partial chunk writes failed\n"); + HDprintf("np_writer() for multiple partial chunk writes failed\n"); TEST_ERROR; } } @@ -954,7 +973,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = dsets_extent(INCR_EXT, s, ds); if (s->use_np && !np_writer(result, step, s, np, config)) { - printf("np_writer() for increasing dimension sizes failed\n"); + HDprintf("np_writer() for increasing dimension sizes failed\n"); TEST_ERROR; } } @@ -969,7 +988,7 @@ perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *c result = dsets_extent(DECR_EXT, s, ds); if (s->use_np && !np_writer(result, step, s, np, config)) { - printf("np_writer() for decreasing dimension sizes failed\n"); + HDprintf("np_writer() for decreasing dimension sizes failed\n"); TEST_ERROR; } } @@ -1004,29 +1023,29 @@ write_dsets_chunks(unsigned action, const state_t *s, const dsets_state_t *ds, u setup_selection(action, which, s, ds, start, stride, count, block); if (s->implicit_index) { - if (!write_dset(action, ds->implicit_did, s->filetype, start, stride, count, block)) { - printf("H5Dwrite to chunked dataset: implicit index dataset failed\n"); + if (!write_chunks(action, ds->implicit_did, s->filetype, start, stride, count, block)) { + HDprintf("H5Dwrite to chunked dataset: implicit index dataset failed\n"); TEST_ERROR; } } if (s->fa_index) { - if (!write_dset(action, ds->fa_did, s->filetype, start, stride, count, block)) { - printf("H5Dwrite to chunked dataset: fa index dataset failed\n"); + if (!write_chunks(action, ds->fa_did, s->filetype, start, stride, count, block)) { + HDprintf("H5Dwrite to chunked dataset: fa index dataset failed\n"); TEST_ERROR; } } if (s->ea_index) { - if (!write_dset(action, ds->ea_did, s->filetype, start, stride, count, block)) { - printf("H5Dwrite to chunked dataset: ea index dataset failed\n"); + if (!write_chunks(action, ds->ea_did, s->filetype, start, stride, count, block)) { + HDprintf("H5Dwrite to chunked dataset: ea index dataset failed\n"); TEST_ERROR; } } if (s->bt2_index) { - if (!write_dset(action, ds->bt2_did, s->filetype, start, stride, count, block)) { - printf("H5Dwrite to chunked dataset: bt2 index dataset failed\n"); + if (!write_chunks(action, ds->bt2_did, s->filetype, start, stride, count, block)) { + HDprintf("H5Dwrite to chunked dataset: bt2 index dataset failed\n"); TEST_ERROR; } } @@ -1163,8 +1182,8 @@ check_set_partial_block(unsigned action, const hsize_t *chunk_dims, hsize_t *blo * Make the selection and then write to the dataset. */ static bool -write_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, hsize_t *count, - hsize_t *block) +write_chunks(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, hsize_t *count, + hsize_t *block) { hid_t sid = badhid; hid_t mem_sid = badhid; @@ -1173,12 +1192,12 @@ write_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *strid unsigned i; if ((sid = H5Dget_space(did)) < 0) { - printf("H5Sget_space failed\n"); + HDprintf("H5Sget_space failed\n"); TEST_ERROR; } if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride, count, block) < 0) { - printf("H5Sselect_hyperslab failed\n"); + HDprintf("H5Sselect_hyperslab failed\n"); TEST_ERROR; } @@ -1186,13 +1205,13 @@ write_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *strid mem_dims[1] = block[1]; if ((mem_sid = H5Screate_simple(2, mem_dims, NULL)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Allocate the buffer for writing */ if ((buf = HDmalloc(block[0] * block[1] * sizeof(unsigned int))) == NULL) { - printf("HDmalloc failed\n"); + HDprintf("HDmalloc failed\n"); TEST_ERROR; } @@ -1205,12 +1224,12 @@ write_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *strid } if (H5Dwrite(did, tid, mem_sid, sid, H5P_DEFAULT, buf) < 0) { - printf("H5Dwrite failed\n"); + HDprintf("H5Dwrite failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } @@ -1232,7 +1251,7 @@ error: return false; -} /* write_dset() */ +} /* write_chunks() */ /* * Increase or decrease the dimenion sizes for the specified datasets. @@ -1284,12 +1303,12 @@ dset_extent_real(unsigned action, hid_t did, const hsize_t *chunk_dims) hid_t sid = badhid; if ((sid = H5Dget_space(did)) < 0) { - printf("H5Sget_space failed\n"); + HDprintf("H5Sget_space failed\n"); TEST_ERROR; } if (H5Sget_simple_extent_dims(sid, dims, max_dims) < 0) { - printf("H5Sget_simple_extent_dims failed\n"); + HDprintf("H5Sget_simple_extent_dims failed\n"); TEST_ERROR; } @@ -1303,7 +1322,7 @@ dset_extent_real(unsigned action, hid_t did, const hsize_t *chunk_dims) /* Cannot increase to more than maximum dimension (dim 0) for EA dataset */ if ((max_dims[0] != H5S_UNLIMITED && new[0] > max_dims[0]) || (max_dims[1] != H5S_UNLIMITED && new[1] > max_dims[1])) { - printf("Cannot exceed maximum dimension for dataset\n"); + HDprintf("Cannot exceed maximum dimension for dataset\n"); TEST_ERROR; } @@ -1314,7 +1333,7 @@ dset_extent_real(unsigned action, hid_t did, const hsize_t *chunk_dims) new[1] = dims[1] - 1; if (new[0] < chunk_dims[0] || new[1] < chunk_dims[1]) { - printf("Cannot decrease to less than chunk dimension\n"); + HDprintf("Cannot decrease to less than chunk dimension\n"); TEST_ERROR; } break; @@ -1325,12 +1344,12 @@ dset_extent_real(unsigned action, hid_t did, const hsize_t *chunk_dims) } /* end switch */ if (H5Dset_extent(did, new) < 0) { - printf("H5Dset_extent for dataset failed\n"); + HDprintf("H5Dset_extent for dataset failed\n"); TEST_ERROR; } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } @@ -1364,8 +1383,8 @@ write_dset_single(unsigned action, const state_t *s, const dsets_state_t *ds) if (action == PWRITES || action == LWRITES) check_set_partial_block(action, block, block, start); - if (!write_dset(action, ds->single_did, s->filetype, start, stride, count, block)) { - printf("H5Dwrite to dataset with single index dataset failed\n"); + if (!write_chunks(action, ds->single_did, s->filetype, start, stride, count, block)) { + HDprintf("H5Dwrite to dataset with single index dataset failed\n"); TEST_ERROR; } @@ -1397,7 +1416,8 @@ error: * --DECR_EXT: verify the decrease to dataset dimensions sizes */ static bool -verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np, + bool fileclosed) { unsigned step; unsigned allowed_writes; @@ -1412,19 +1432,22 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co dbgf(2, "Verify single full chunk write to dataset with single index; only verify 1 write\n"); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, 0, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_read_dset_single(GWRITES, s, ds); + result = verify_dset_single(GWRITES, s, ds, fileclosed); if (s->use_np && !np_reader(result, 0, s, np)) { - printf("np_reader() for verifying addition failed\n"); + HDprintf("np_reader() for verifying addition failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } /* Verify a single partial chunk write to dataset with single index */ @@ -1434,18 +1457,22 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co dbgf(2, "Verify single partial chunk write to dataset with single index; only verify 1 write\n"); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, 0, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } + /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_read_dset_single(PWRITES, s, ds); + result = verify_dset_single(PWRITES, s, ds, fileclosed); if (s->use_np && !np_reader(result, 0, s, np)) { - printf("np_reader() for verifying addition failed\n"); + HDprintf("np_reader() for verifying addition failed\n"); TEST_ERROR; } + if (!result) + TEST_ERROR; } } @@ -1462,18 +1489,22 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co step); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } + /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_dsets_chunks(GWRITES, s, ds, step); + result = verify_dsets_chunks(GWRITES, s, ds, step, fileclosed); if (s->use_np && !np_reader(result, step, s, np)) { - printf("np_reader() for verification failed\n"); + HDprintf("np_reader() for verification failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } @@ -1487,18 +1518,22 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co step); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } + /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_dsets_chunks(PWRITES, s, ds, step); + result = verify_dsets_chunks(PWRITES, s, ds, step, fileclosed); if (s->use_np && !np_reader(result, step, s, np)) { - printf("np_reader() for verification failed\n"); + HDprintf("np_reader() for verification failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } @@ -1512,18 +1547,22 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co step); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } + /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_dsets_chunks(TWRITES, s, ds, step); + result = verify_dsets_chunks(TWRITES, s, ds, step, fileclosed); if (s->use_np && !np_reader(result, step, s, np)) { - printf("np_reader() for verification failed\n"); + HDprintf("np_reader() for verification failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } @@ -1538,18 +1577,22 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co step); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } + /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_dsets_chunks(LWRITES, s, ds, step); + result = verify_dsets_chunks(LWRITES, s, ds, step, fileclosed); if (s->use_np && !np_reader(result, step, s, np)) { - printf("np_reader() for verification failed\n"); + HDprintf("np_reader() for verification failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } @@ -1560,18 +1603,21 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co step + 1); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } + /* Wait for a few ticks for the update to happen */ decisleep(config->tick_len * s->update_interval); result = verify_dsets_extent(INCR_EXT, s, ds, step + 1); if (s->use_np && !np_reader(result, step, s, np)) { - printf("np_reader() for failed\n"); + HDprintf("np_reader() for failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } @@ -1582,7 +1628,7 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co step + 1); if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } /* Wait for a few ticks for the update to happen */ @@ -1591,9 +1637,11 @@ verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *co result = verify_dsets_extent(DECR_EXT, s, ds, step + 1); if (s->use_np && !np_reader(result, step, s, np)) { - printf("np_reader() for verification failed\n"); + HDprintf("np_reader() for verification failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } } @@ -1614,7 +1662,8 @@ error: * LWRITEs: verify `which` write that covers multiple partial chunks */ static bool -verify_dsets_chunks(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which) +verify_dsets_chunks(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which, + bool fileclosed) { hsize_t start[2] = {0, 0}; hsize_t stride[2] = {0, 0}; @@ -1627,29 +1676,33 @@ verify_dsets_chunks(unsigned action, const state_t *s, const dsets_state_t *ds, setup_selection(action, which, s, ds, start, stride, count, block); if (s->implicit_index) { - if (!verify_read_dset(action, ds->implicit_did, s->filetype, start, stride, count, block)) { - printf("verify_read_dset() to dataset with implicit index failed\n"); + if (!verify_chunks(action, ds->implicit_did, s->filetype, start, stride, count, block, fileclosed, + s->flush_raw_data)) { + HDprintf("verify_chunks() to dataset with implicit index failed\n"); TEST_ERROR; } } if (s->fa_index) { - if (!verify_read_dset(action, ds->fa_did, s->filetype, start, stride, count, block)) { - printf("verify_read_dset() to dataset with fixed array index failed\n"); + if (!verify_chunks(action, ds->fa_did, s->filetype, start, stride, count, block, fileclosed, + s->flush_raw_data)) { + HDprintf("verify_chunks() to dataset with fixed array index failed\n"); TEST_ERROR; } } if (s->ea_index) { - if (!verify_read_dset(action, ds->ea_did, s->filetype, start, stride, count, block)) { - printf("verify_read_dset() to dataset with extensible array index failed\n"); + if (!verify_chunks(action, ds->ea_did, s->filetype, start, stride, count, block, fileclosed, + s->flush_raw_data)) { + HDprintf("verify_chunks() to dataset with extensible array index failed\n"); TEST_ERROR; } } if (s->bt2_index) { - if (!verify_read_dset(action, ds->bt2_did, s->filetype, start, stride, count, block)) { - printf("verify_read_dset() to dataset with bt2 index failed\n"); + if (!verify_chunks(action, ds->bt2_did, s->filetype, start, stride, count, block, fileclosed, + s->flush_raw_data)) { + HDprintf("verify_chunks() to dataset with bt2 index failed\n"); TEST_ERROR; } } @@ -1666,8 +1719,8 @@ error: * Verify the data read from the dataset is as expected. */ static bool -verify_read_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, hsize_t *count, - hsize_t *block) +verify_chunks(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t *stride, hsize_t *count, + hsize_t *block, bool fileclosed, bool flush_raw_data) { hid_t mem_sid = badhid; hid_t sid = badhid; @@ -1677,64 +1730,80 @@ verify_read_dset(unsigned action, hid_t did, hid_t tid, hsize_t *start, hsize_t /* Refresh the dataset */ if (H5Drefresh(did) < 0) { - printf("H5Drefresh dataset failed\n"); + HDprintf("H5Drefresh dataset failed\n"); TEST_ERROR; } if ((sid = H5Dget_space(did)) < 0) { - printf("H5Dget_space dataset failed\n"); + HDprintf("H5Dget_space dataset failed\n"); TEST_ERROR; } /* Make the selection the file dataspace */ if (H5Sselect_hyperslab(sid, H5S_SELECT_SET, start, stride, count, block) < 0) { - printf("H5Sselect to dataset failed\n"); + HDprintf("H5Sselect to dataset failed\n"); TEST_ERROR; } mem_dims[0] = block[0]; mem_dims[1] = block[1]; if ((mem_sid = H5Screate_simple(2, mem_dims, NULL)) < 0) { - printf("H5Screate_simple failed\n"); + HDprintf("H5Screate_simple failed\n"); TEST_ERROR; } /* Allocate the buffer for reading */ if ((rbuf = HDmalloc(block[0] * block[1] * sizeof(unsigned int))) == NULL) { - printf("HDmalloc failed\n"); + HDprintf("HDmalloc failed\n"); TEST_ERROR; } /* Read the data from the dataset into `rbuf` */ if (H5Dread(did, tid, mem_sid, sid, H5P_DEFAULT, rbuf) < 0) { - printf("H5Dread from dataset failed\n"); + HDprintf("H5Dread from dataset failed\n"); TEST_ERROR; } /* Verify the data read in `rbuf` is as the fill value expected */ for (i = 0; i < block[0] * block[1]; i++) { - if (action == GWRITES || action == TWRITES) { - if (rbuf[i] != FILL_FULL) { - printf("Invalid value for dataset for GWRITES/TWRITES\n"); - TEST_ERROR; + if (flush_raw_data || fileclosed) { + if (action == GWRITES || action == TWRITES) { + if (rbuf[i] != FILL_FULL) { + HDprintf("Invalid value for dataset for GWRITES/TWRITES: %d\n", rbuf[i]); + TEST_ERROR; + } + } + else { + HDassert(action == PWRITES || action == LWRITES); + if (rbuf[i] != FILL_PARTIAL) { + HDprintf("Invalid value for dataset for GWRITES/TWRITES: %d\n", rbuf[i]); + TEST_ERROR; + } } } - else { - HDassert(action == PWRITES || action == LWRITES); - if (rbuf[i] != FILL_PARTIAL) { - printf("Invalid value for dataset for GWRITES/TWRITES\n"); - TEST_ERROR; + else { /* No flush && not closing file */ + if (action == GWRITES || action == TWRITES) { + if (rbuf[i] != FILL_FULL && rbuf[i] != FILL_INIT) { + HDprintf("Invalid value for dataset for GWRITES/TWRITES\n"); + TEST_ERROR; + } + } + else { + if (rbuf[i] != FILL_PARTIAL && rbuf[i] != FILL_INIT) { + HDprintf("Invalid value for dataset for GWRITES/TWRITES\n"); + TEST_ERROR; + } } } } if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } if (H5Sclose(mem_sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } @@ -1756,7 +1825,7 @@ error: return false; -} /* verify_read_dset() */ +} /* verify_chunks() */ /* * Verify the increase or decrease of dimenion sizes for the specified datasets. @@ -1779,7 +1848,7 @@ verify_dsets_extent(unsigned action, const state_t *s, const dsets_state_t *ds, if (s->fa_index) { dbgf(2, "Verify dataset extent for FA dataset\n"); if (!verify_dset_extent_real(action, ds->fa_did, rows, cols, which)) { - printf("verify_read_dset() to dataset with fixed array index failed\n"); + HDprintf("verify_read_dset() to dataset with fixed array index failed\n"); TEST_ERROR; } } @@ -1787,7 +1856,7 @@ verify_dsets_extent(unsigned action, const state_t *s, const dsets_state_t *ds, if (s->ea_index) { dbgf(2, "Verify dataset extent for EA dataset\n"); if (!verify_dset_extent_real(action, ds->fa_did, rows, cols, which)) { - printf("verify_read_dset() to dataset with fixed array index failed\n"); + HDprintf("verify_read_dset() to dataset with fixed array index failed\n"); TEST_ERROR; } } @@ -1795,7 +1864,7 @@ verify_dsets_extent(unsigned action, const state_t *s, const dsets_state_t *ds, if (s->bt2_index) { dbgf(2, "Verify dataset extent for BT2 dataset\n"); if (!verify_dset_extent_real(action, ds->bt2_did, rows, cols, which)) { - printf("verify_read_dset() to dataset with fixed array index failed\n"); + HDprintf("verify_read_dset() to dataset with fixed array index failed\n"); TEST_ERROR; } } @@ -1818,17 +1887,17 @@ verify_dset_extent_real(unsigned action, hid_t did, unsigned rows, unsigned cols /* Refresh the dataset */ if (H5Drefresh(did) < 0) { - printf("H5Drefresh dataset failed\n"); + HDprintf("H5Drefresh dataset failed\n"); TEST_ERROR; } if ((sid = H5Dget_space(did)) < 0) { - printf("H5Dget_space dataset failed\n"); + HDprintf("H5Dget_space dataset failed\n"); TEST_ERROR; } if (H5Sget_simple_extent_dims(sid, dims, NULL) < 0) { - printf("H5Sget_simple_extent_dims() failed\n"); + HDprintf("H5Sget_simple_extent_dims() failed\n"); TEST_ERROR; } @@ -1851,7 +1920,7 @@ verify_dset_extent_real(unsigned action, hid_t did, unsigned rows, unsigned cols } /* end switch */ if (H5Sclose(sid) < 0) { - printf("H5Sclose failed\n"); + HDprintf("H5Sclose failed\n"); TEST_ERROR; } @@ -1871,7 +1940,7 @@ error: * Verify that the data read from the dataset with single index is as unexpected. */ static bool -verify_read_dset_single(unsigned action, const state_t *s, const dsets_state_t *ds) +verify_dset_single(unsigned action, const state_t *s, const dsets_state_t *ds, bool fileclosed) { hsize_t block[2] = {s->rows, s->cols}; hsize_t count[2] = {1, 1}; @@ -1884,8 +1953,9 @@ verify_read_dset_single(unsigned action, const state_t *s, const dsets_state_t * if (action == PWRITES) check_set_partial_block(action, block, block, start); - if (!verify_read_dset(action, ds->single_did, s->filetype, start, stride, count, block)) { - printf("verify_read_dset() to dataset with single index failed\n"); + if (!verify_chunks(action, ds->single_did, s->filetype, start, stride, count, block, fileclosed, + s->flush_raw_data)) { + HDprintf("verify_read_dset() to dataset with single index failed\n"); TEST_ERROR; } @@ -1894,7 +1964,7 @@ verify_read_dset_single(unsigned action, const state_t *s, const dsets_state_t * error: return false; -} /* verify_read_dset_single() */ +} /* verify_dset_single() */ /* * Named pipes handling @@ -1918,36 +1988,36 @@ np_init(np_state_t *np, bool writer) /* If the named pipes are present at the start of the test, remove them */ if (HDaccess(np->fifo_writer_to_reader, F_OK) == 0) if (HDremove(np->fifo_writer_to_reader) != 0) { - printf("HDremove fifo_writer_to_reader failed\n"); + HDprintf("HDremove fifo_writer_to_reader failed\n"); TEST_ERROR; } if (HDaccess(np->fifo_reader_to_writer, F_OK) == 0) if (HDremove(np->fifo_reader_to_writer) != 0) { - printf("HDremove fifo_reader_to_writer failed\n"); + HDprintf("HDremove fifo_reader_to_writer failed\n"); TEST_ERROR; } /* Writer creates two named pipes(FIFO) */ if (HDmkfifo(np->fifo_writer_to_reader, 0600) < 0) { - printf("HDmkfifo fifo_writer_to_reader failed\n"); + HDprintf("HDmkfifo fifo_writer_to_reader failed\n"); TEST_ERROR; } if (HDmkfifo(np->fifo_reader_to_writer, 0600) < 0) { - printf("HDmkfifo fifo_reader_to_writer failed\n"); + HDprintf("HDmkfifo fifo_reader_to_writer failed\n"); TEST_ERROR; } } /* Both the writer and reader open the pipes */ if ((np->fd_writer_to_reader = HDopen(np->fifo_writer_to_reader, O_RDWR)) < 0) { - printf("HDopen fifo_writer_to_reader failed\n"); + HDprintf("HDopen fifo_writer_to_reader failed\n"); TEST_ERROR; } if ((np->fd_reader_to_writer = HDopen(np->fifo_reader_to_writer, O_RDWR)) < 0) { - printf("HDopen fifo_reader_to_writer failed\n"); + HDprintf("HDopen fifo_reader_to_writer failed\n"); TEST_ERROR; } @@ -1966,24 +2036,24 @@ np_close(np_state_t *np, bool writer) { /* Both the writer and reader close the named pipes */ if (HDclose(np->fd_writer_to_reader) < 0) { - printf("HDclose fd_writer_to_reader failed\n"); + HDprintf("HDclose fd_writer_to_reader failed\n"); TEST_ERROR; } if (HDclose(np->fd_reader_to_writer) < 0) { - printf("HDclose fd_reader_to_writer failed\n"); + HDprintf("HDclose fd_reader_to_writer failed\n"); TEST_ERROR; } /* Reader finishes last and deletes the named pipes */ if (!writer) { if (HDremove(np->fifo_writer_to_reader) != 0) { - printf("HDremove fifo_writer_to_reader failed\n"); + HDprintf("HDremove fifo_writer_to_reader failed\n"); TEST_ERROR; } if (HDremove(np->fifo_reader_to_writer) != 0) { - printf("HDremove fifo_reader_to_writer failed\n"); + HDprintf("HDremove fifo_reader_to_writer failed\n"); TEST_ERROR; } } @@ -2003,7 +2073,7 @@ np_writer(bool result, unsigned step, const state_t *s, np_state_t *np, H5F_vfd_ /* The action fails */ if (!result) { - printf("action failed\n"); + HDprintf("action failed\n"); H5_FAILED(); AT(); @@ -2021,7 +2091,7 @@ np_writer(bool result, unsigned step, const state_t *s, np_state_t *np, H5F_vfd_ /* Bump up the value of notify to tell the reader to start reading */ np->notify++; if (HDwrite(np->fd_writer_to_reader, &np->notify, sizeof(int)) < 0) { - printf("HDwrite failed\n"); + HDprintf("HDwrite failed\n"); TEST_ERROR; } @@ -2038,7 +2108,7 @@ np_writer(bool result, unsigned step, const state_t *s, np_state_t *np, H5F_vfd_ /* Handshake between writer and reader */ if (!np_confirm_verify_notify(np->fd_reader_to_writer, step, s, np)) { - printf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } } @@ -2059,7 +2129,7 @@ np_reader(bool result, unsigned step, const state_t *s, np_state_t *np) { /* The verification fails */ if (!result) { - printf("verify action failed\n"); + HDprintf("verify action failed\n"); H5_FAILED(); AT(); @@ -2076,7 +2146,7 @@ np_reader(bool result, unsigned step, const state_t *s, np_state_t *np) /* Send back the same notify value for acknowledgement: * --inform the writer to move to the next step */ if (HDwrite(np->fd_reader_to_writer, &np->notify, sizeof(int)) < 0) { - printf("HDwrite failed\n"); + HDprintf("HDwrite failed\n"); TEST_ERROR; } } @@ -2098,17 +2168,17 @@ np_confirm_verify_notify(int fd, unsigned step, const state_t *s, np_state_t *np if (step % s->csteps == 0) { np->verify++; if (HDread(fd, &np->notify, sizeof(int)) < 0) { - printf("HDread failed\n"); + HDprintf("HDread failed\n"); TEST_ERROR; } if (np->notify == -1) { - printf("reader/writer failed to verify\n"); + HDprintf("reader/writer failed to verify\n"); TEST_ERROR; } if (np->notify != np->verify) { - printf("received message %d, expecting %d\n", np->notify, np->verify); + HDprintf("received message %d, expecting %d\n", np->notify, np->verify); TEST_ERROR; } } @@ -2120,6 +2190,89 @@ error: } /* np_confirm_verify_notify() */ /* + * When flush of raw data is disabled, the following is done by the writer and reader: + * Writer: + * Close the file + * Notify the reader that the file is closed + * Reader: + * Confirm the message from the writer that the file is closed + * Verify the data + */ +static bool +closing_on_noflush(bool writer, state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +{ + HDassert(s->use_np); + + if (writer) { + if (!close_dsets(ds)) { + HDprintf("close_dsets() failed\n"); + TEST_ERROR; + } + + dbgf(2, "Writer closes the file (flush of raw data is disabled)\n"); + if (H5Fclose(s->file) < 0) { + HDprintf("H5Fclose failed\n"); + TEST_ERROR; + } + + /* Bump up the value of notify to tell the reader the file is closed */ + dbgf(2, "Writer notifies reader that the file is closed (flush of raw data is disabled)\n"); + np->notify++; + if (HDwrite(np->fd_writer_to_reader, &np->notify, sizeof(int)) < 0) { + HDprintf("HDwrite failed\n"); + TEST_ERROR; + } + + if (!np_close(np, writer)) { + HDprintf("np_close() failed\n"); + TEST_ERROR; + } + } + else { + /* Wait for a few ticks for the file to close in writer */ + decisleep(config->tick_len * s->update_interval); + + dbgf(2, "Reader checks notify value from writer (flush of raw data is disabled)\n"); + if (!np_confirm_verify_notify(np->fd_writer_to_reader, 0, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Close the named pipes */ + if (!np_close(np, writer)) { + HDprintf("np_close() failed\n"); + TEST_ERROR; + } + + /* Turn off named pipes */ + s->use_np = false; + + /* Verify the dataset again without named pipes */ + dbgf(2, "Reader verifies data after writer closes the file (flush of raw data is disabled)\n"); + if (!verify_dsets_operations(s, ds, config, np, true)) { + HDprintf("verify_dsets_operations() failed\n"); + TEST_ERROR + } + + if (!close_dsets(ds)) { + HDprintf("close_dsets() failed\n"); + TEST_ERROR; + } + + dbgf(2, "Reader closes the file (flush of raw data is disabled)\n"); + if (H5Fclose(s->file) < 0) { + HDprintf("H5Fclose failed\n"); + TEST_ERROR; + } + } + + return true; + +error: + return false; + +} /* closing_on_noflush() */ +/* * Main */ int @@ -2134,7 +2287,7 @@ main(int argc, char **argv) dsets_state_t ds; if (!state_init(&s, argc, argv)) { - printf("state_init() failed\n"); + HDprintf("state_init() failed\n"); TEST_ERROR; } @@ -2145,16 +2298,16 @@ main(int argc, char **argv) else if (personality != NULL && HDstrcmp(personality, "vfd_swmr_dsetchks_reader") == 0) writer = false; else { - printf("unknown personality, expected vfd_swmr_dsetchks_{reader,writer}\n"); + HDprintf("unknown personality, expected vfd_swmr_dsetchks_{reader,writer}\n"); TEST_ERROR; } /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 7, writer, FALSE, 128, "./dsetchks-shadow"); + init_vfd_swmr_config(&config, 4, 7, writer, s.flush_raw_data, 128, "./dsetchks-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(true, s.use_vfd_swmr, true, 4096, &config)) < 0) { - printf("vfd_swmr_create_fapl() failed\n"); + HDprintf("vfd_swmr_create_fapl() failed\n"); TEST_ERROR; } @@ -2166,70 +2319,83 @@ main(int argc, char **argv) if (writer) { if ((s.file = H5Fcreate(s.filename, H5F_ACC_TRUNC, fcpl, fapl)) < 0) { - printf("H5Fcreate failed\n"); + HDprintf("H5Fcreate failed\n"); TEST_ERROR; } if (!create_dsets(&s, &ds)) { - printf("create_dsets() failed\n"); + HDprintf("create_dsets() failed\n"); TEST_ERROR; } } else { if ((s.file = H5Fopen(s.filename, H5F_ACC_RDONLY, fapl)) < 0) { - printf("H5Fopen failed\n"); + HDprintf("H5Fopen failed\n"); TEST_ERROR; } if (!open_dsets(&s, &ds)) { - printf("open_dsets() failed\n"); + HDprintf("open_dsets() failed\n"); TEST_ERROR; } } /* Initiailze named pipes */ if (s.use_np && !np_init(&np, writer)) { - printf("np_init() failed\n"); + HDprintf("np_init() failed\n"); TEST_ERROR; } if (writer) { if (!perform_dsets_operations(&s, &ds, &config, &np)) { - printf("perform_dsets_operations() failed\n"); + HDprintf("perform_dsets_operations() failed\n"); TEST_ERROR; } } else { - if (!verify_dsets_operations(&s, &ds, &config, &np)) { - printf("perform_dsets_operations() failed\n"); + if (!verify_dsets_operations(&s, &ds, &config, &np, false)) { + HDprintf("perform_dsets_operations() failed\n"); TEST_ERROR; } } - if (!close_dsets(&ds)) { - printf("close_dsets() failed\n"); - TEST_ERROR; - } - if (H5Pclose(fapl) < 0) { - printf("H5Pclose failed\n"); + HDprintf("H5Pclose failed\n"); TEST_ERROR; } if (H5Pclose(fcpl) < 0) { - printf("H5Pclose failed\n"); + HDprintf("H5Pclose failed\n"); TEST_ERROR; } - if (H5Fclose(s.file) < 0) { - printf("H5Fclose failed\n"); - TEST_ERROR; + /* When flush of raw data is disabled, special handling is performed + * via closing_on_noflush() when closing the file. + * Nothing needs to be done for -x or -y options + * (increase and decrease dataset dimension sizes). + */ + if (!s.flush_raw_data && !s.xincrs && !s.ydecrs && s.use_np) { + + if (!closing_on_noflush(writer, &s, &ds, &config, &np)) + TEST_ERROR } + else { - if (s.use_np && !np_close(&np, writer)) { - printf("np_close() failed\n"); - TEST_ERROR; + if (!close_dsets(&ds)) { + HDprintf("close_dsets() failed\n"); + TEST_ERROR; + } + + if (H5Fclose(s.file) < 0) { + HDprintf("H5Fclose failed\n"); + TEST_ERROR; + } + + if (s.use_np && !np_close(&np, writer)) { + HDprintf("np_close() failed\n"); + TEST_ERROR; + } } return EXIT_SUCCESS; diff --git a/test/vfd_swmr_dsetops_writer.c b/test/vfd_swmr_dsetops_writer.c index 26f8977..f98843d 100644 --- a/test/vfd_swmr_dsetops_writer.c +++ b/test/vfd_swmr_dsetops_writer.c @@ -46,17 +46,19 @@ typedef struct { unsigned int csteps; /* For -c <csteps> option */ bool use_np; /* For -N option */ bool use_vfd_swmr; /* For -S option */ + bool flush_raw_data; /* For -U option */ bool compact; /* -p option: create compact dataset */ - bool compact_write; /* -o option: write to the whole compact dataset */ + bool compact_write; /* -t option: write to the whole compact dataset */ unsigned int compact_elmts; /* -e <elmts> option: # of elments for the compact dataset */ bool contig; /* -g option: create contiguous dataset */ bool chunked; /* -k option: create chunked datasets with 5 indexing types */ unsigned int rows; /* -m <rows> option for contiguous and/or chunked datasets */ unsigned int cols; /* -n <cols option for contiguous and/or chunked datasets */ - unsigned int swrites; /* -s <swrites> option: sequential writes to contiguous and/or chunked datasets */ - unsigned int rwrites; /* -r <rwrites> option: random writes to contiguous and/or chunked datasets */ - unsigned int lwrites; /* -l <lwrites> option: hyperslab writes to contiguous and/or chunked datasets */ - unsigned int wwrites; /* -w <wwrites> option: modify raw data to contiguous and/or chunked datasets */ + unsigned int swrites; /* -s <swrites> option: sequential writes to contiguous and/or chunked datasets */ + unsigned int rwrites; /* -r <rwrites> option: random writes to contiguous and/or chunked datasets */ + unsigned int lwrites; /* -l <lwrites> option: hyperslab writes to contiguous and/or chunked datasets */ + unsigned int wwrites; /* -w <wwrites> option: modify raw data to contiguous and/or chunked datasets */ + unsigned int lastwrite; /* The last operation (-s, -r, -l or -w) performed. */ } state_t; /* Initializations for state_t */ @@ -65,8 +67,9 @@ typedef struct { { \ .filename = "", .file = H5I_INVALID_HID, .filetype = H5T_NATIVE_UINT32, \ .update_interval = READER_WAIT_TICKS, .csteps = 1, .use_np = true, .use_vfd_swmr = true, \ - .compact = false, .compact_write = false, .compact_elmts = MAX_COMPACT_ELMS, .contig = false, \ - .rows = 256, .cols = 512, .swrites = 0, .rwrites = 0, .lwrites = 0, .wwrites = 0 \ + .flush_raw_data = true, .compact = false, .compact_write = false, .compact_elmts = MAX_COMPACT_ELMS, \ + .contig = false, .rows = 10, .cols = 5, .swrites = 0, .rwrites = 0, .lwrites = 0, .wwrites = 0, \ + .lastwrite = 0 \ } /* Structure to hold info for different dataset types */ @@ -132,8 +135,8 @@ static bool open_dset_real(const state_t *s, hid_t *did, hid_t *sid, const char static bool close_dsets(const dsets_state_t *ds); static bool close_dset_real(hid_t did, hid_t sid); -static bool write_dset_contig_chunked(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, - np_state_t *np); +static bool perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, + np_state_t *np); static bool dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned step); static bool dset_setup(unsigned action, unsigned which, const state_t *s, hsize_t *start, hsize_t *stride, hsize_t *count, hsize_t *block, hid_t *mem_sid, unsigned int **buf); @@ -141,12 +144,18 @@ static bool write_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsiz hsize_t *count, hsize_t *block, unsigned int *buf); static bool write_dset_compact(const state_t *s, const dsets_state_t *ds); -static bool verify_write_dset_contig_chunked(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, - np_state_t *np); -static bool verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which); -static bool verify_read_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsize_t *start, - hsize_t *stride, hsize_t *count, hsize_t *block, unsigned int *vbuf); -static bool verify_read_dset_compact(const state_t *s, const dsets_state_t *ds); +static bool verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, + np_state_t *np, bool fileclosed); +static bool verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which, + bool fileclosed); +static bool verify_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsize_t *start, hsize_t *stride, + size_t *count, hsize_t *block, unsigned int *vbuf, bool fileclosed, + bool flush_raw_data); +static bool verify_dset_compact(const state_t *s, const dsets_state_t *ds, bool fileclosed, + bool flush_raw_data); + +static bool closing_on_noflush(bool writer, state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, + np_state_t *np); static const hid_t badhid = H5I_INVALID_HID; @@ -174,7 +183,7 @@ usage(const char *progname) " [-p] [-e elmts] [-o]\n" " [-g] [-k] [-m rows] [-n cols]\n" " [-s swrites] [-r rwrites] [-l lwrites] [-w writes]\n" - " [-u nticks] [-c csteps] [-S] [-N] [-q] [-b]\n" + " [-u nticks] [-c csteps] [-U] [-S] [-N] [-q] [-b]\n" "\n" "-p: create a dataset with compact layout\n" "-e elmts: # of <elmts> for the compact dataset\n" @@ -193,6 +202,7 @@ usage(const char *progname) " (default is 4)\n" "-c csteps: `csteps` steps communication interval between reader and writer\n" " (default is 1)\n" + "-U: disable flush of raw data (default is flushing raw data)\n" "-S: do not use VFD SWMR\n" "-N: do not use named pipes for test synchronization\n" "-q: silence printouts, few messages\n" @@ -215,7 +225,7 @@ state_init(state_t *s, int argc, char **argv) { unsigned long tmp; int ch; - char * tfile; + char * tfile = NULL; char * end; *s = ALL_HID_INITIALIZER; @@ -227,7 +237,12 @@ state_init(state_t *s, int argc, char **argv) esnprintf(s->progname, sizeof(s->progname), "%s", tfile); - while ((ch = getopt(argc, argv, "pte:gkm:n:s:r:l:w:bqSNu:c:")) != -1) { + if (tfile) { + HDfree(tfile); + tfile = NULL; + } + + while ((ch = getopt(argc, argv, "pte:gkm:n:s:r:l:w:bqSNUu:c:")) != -1) { switch (ch) { case 'p': /* compact dataset */ @@ -246,6 +261,10 @@ state_init(state_t *s, int argc, char **argv) s->chunked = true; break; + case 'U': /* Disable flush of raw data */ + s->flush_raw_data = false; + break; + case 'q': verbosity = 0; break; @@ -329,6 +348,21 @@ state_init(state_t *s, int argc, char **argv) TEST_ERROR; } + /* Enable compact write (-t) without compact dataset (-p) */ + if (s->compact_write && !s->compact) { + HDprintf("Enable compact write without compact dataset\n"); + usage(s->progname); + goto error; + } + + /* Enable sequential/random/hyperslab/raw data writes (-s/-r/-l/-w) without contiguous/chunked dataset + * (-g/-k) */ + if ((s->swrites || s->rwrites || s->lwrites || s->wwrites) && !(s->contig || s->chunked)) { + HDprintf("Enable sequential/random/hypuerslab/raw data writes without contiguous/chunked dataset\n"); + usage(s->progname); + goto error; + } + /* -c <csteps> cannot be zero */ if (!s->csteps) { HDprintf("communication interval cannot be zero\n"); @@ -365,6 +399,9 @@ state_init(state_t *s, int argc, char **argv) return true; error: + if (tfile) + HDfree(tfile); + return false; } /* state_init() */ @@ -818,6 +855,8 @@ error: */ /* + * Write to whole compact dataset + * * Perform writes for contiguous and chunked datasets: * --SEQ_WRITE: sequential writes * --RANDOM_WRITE: random writes @@ -825,76 +864,93 @@ error: * --MODIFY_DATA: raw data modifications */ static bool -write_dset_contig_chunked(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +perform_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) { unsigned step; bool result; - HDassert(s->contig || s->chunked); - - /* Perform sequential writes for contiguous and/or chunked datasets */ - if (s->swrites) { + /* Perform writes to the whole compact dataset */ + if (s->compact) { - for (step = 0; (step < s->swrites && step < (s->rows * s->cols)); step++) { - dbgf(2, "Sequential writes %u to dataset\n", step); + if (s->compact_write) { + dbgf(2, "Writes all to compact dataset\n"); - result = dsets_action(SEQ_WRITE, s, ds, step); + result = write_dset_compact(s, ds); - if (s->use_np && !np_writer(result, step, s, np, config)) { - HDprintf("np_writer() for sequential writes failed\n"); + if (s->use_np && !np_writer(result, 0, s, np, config)) { + HDprintf("np_writer() for addition failed\n"); TEST_ERROR; } } } - /* Perform random writes for contiguous and/or chunked datasets */ - if (s->rwrites) { - unsigned newstep; + /* Perform writes for contiguous and/or chunked datasets */ + if (s->contig || s->chunked) { - /* Set up random seed which will be the same for both writer and reader */ - HDsrandom(RANDOM_SEED); + /* Perform sequential writes */ + if (s->swrites) { - for (step = 0; (step < s->rwrites && step < (s->rows * s->cols)); step++) { - dbgf(2, "Random writes %u to dataset\n", step); + for (step = 0; (step < s->swrites && step < (s->rows * s->cols)); step++) { + dbgf(2, "Sequential writes %u to dataset\n", step); - newstep = (unsigned int)HDrandom() % (s->rows * s->cols); - HDprintf("Random step is %u\n", newstep); - result = dsets_action(RANDOM_WRITE, s, ds, newstep); + result = dsets_action(SEQ_WRITE, s, ds, step); - if (s->use_np && !np_writer(result, step, s, np, config)) { - HDprintf("np_writer() for random writes failed\n"); - TEST_ERROR; + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for sequential writes failed\n"); + TEST_ERROR; + } } } - } - /* Perform hyperslab writes for contiguous and/or chunked datasets */ - if (s->lwrites) { - unsigned k; + /* Perform random writes */ + if (s->rwrites) { + unsigned newstep; - for (step = 0, k = 0; (step < s->lwrites && k < (s->rows * s->cols)); step++, k += s->cols) { - dbgf(2, "Hyperslab writes %u to dataset\n", step); + /* Set up random seed which will be the same for both writer and reader */ + HDsrandom(RANDOM_SEED); - result = dsets_action(HYPER_WRITE, s, ds, k); + for (step = 0; (step < s->rwrites && step < (s->rows * s->cols)); step++) { + dbgf(2, "Random writes %u to dataset\n", step); - if (s->use_np && !np_writer(result, step, s, np, config)) { - HDprintf("np_writer() for hyperslab writes failed\n"); - TEST_ERROR; + newstep = (unsigned int)HDrandom() % (s->rows * s->cols); + dbgf(2, "Random step is %u\n", newstep); + result = dsets_action(RANDOM_WRITE, s, ds, newstep); + + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for random writes failed\n"); + TEST_ERROR; + } } } - } - /* Perform raw data modifications for contiguous and/or chunked datasets */ - if (s->wwrites) { + /* Perform hyperslab writes */ + if (s->lwrites) { + unsigned k; - for (step = 0; (step < s->wwrites && step < (s->rows * s->cols)); step++) { - dbgf(2, "Modify raw data %u to dataset\n", step); + for (step = 0, k = 0; (step < s->lwrites && k < (s->rows * s->cols)); step++, k += s->cols) { + dbgf(2, "Hyperslab writes %u to dataset\n", step); - result = dsets_action(MODIFY_DATA, s, ds, step); + result = dsets_action(HYPER_WRITE, s, ds, k); - if (s->use_np && !np_writer(result, step, s, np, config)) { - HDprintf("np_writer() for modify raw data failed\n"); - TEST_ERROR; + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for hyperslab writes failed\n"); + TEST_ERROR; + } + } + } + + /* Perform raw data modifications */ + if (s->wwrites) { + + for (step = 0; (step < s->wwrites && step < (s->rows * s->cols)); step++) { + dbgf(2, "Modify raw data %u to dataset\n", step); + + result = dsets_action(MODIFY_DATA, s, ds, step); + + if (s->use_np && !np_writer(result, step, s, np, config)) { + HDprintf("np_writer() for modify raw data failed\n"); + TEST_ERROR; + } } } } @@ -902,9 +958,10 @@ write_dset_contig_chunked(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t * return true; error: + return false; -} /* write_dset_contig_chunked() */ +} /* perform_dsets_operations() */ /* * Perform the "action" for each of the datasets specified on the command line: @@ -1128,6 +1185,8 @@ error: */ /* + * Verify writes to the compact dataset. + * * Verify writes for contiguous and chunked datasets: * --SEQ_WRITE: sequential writes * --RANDOM_WRITE: random writes @@ -1135,109 +1194,162 @@ error: * --MODIFY_DATA: raw data modifications */ static bool -verify_write_dset_contig_chunked(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +verify_dsets_operations(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np, + bool fileclosed) { unsigned step; bool result; - HDassert(s->contig || s->chunked); - - /* Start verifying sequential writes for contiguous and/or chunked datasets */ - if (s->swrites) { + /* Start verifying data written to the compact dataset */ + if (s->compact) { - for (step = 0; (step < s->swrites && step < (s->rows * s->cols)); step++) { - dbgf(2, "Verify sequential writes %u to dataset\n", step); + if (s->compact_write) { + dbgf(2, "Verify writes to compact dataset\n"); - if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, 0, s, np)) { HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); TEST_ERROR; } /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_dsets_action(SEQ_WRITE, s, ds, step); + result = verify_dset_compact(s, ds, fileclosed, config->flush_raw_data); - if (s->use_np && !np_reader(result, step, s, np)) { + if (s->use_np && !np_reader(result, 0, s, np)) { HDprintf("np_reader() for verifying addition failed\n"); TEST_ERROR; } + else if (!result) + TEST_ERROR; } } - /* Start verifying random writes for contiguous and/or chunked datasets */ - if (s->rwrites) { - unsigned newstep; + /* Verify writes for contiguous and/or chunked datasets */ + if (s->contig || s->chunked) { - /* Set up random seed which will be the same for both writer and reader */ - HDsrandom(RANDOM_SEED); + /* Start verifying sequential writes */ + /* When flush of raw data is disabled, only verify data for the last write operation on file close */ + if ((s->swrites && !fileclosed) || (fileclosed && s->lastwrite == SEQ_WRITE)) { - for (step = 0; (step < s->rwrites && step < (s->rows * s->cols)); step++) { - dbgf(2, "Verify random writes %u to dataset\n", step); + s->lastwrite = SEQ_WRITE; - newstep = (unsigned int)HDrandom() % (s->rows * s->cols); - HDprintf("Random step is %u\n", newstep); + for (step = 0; (step < s->swrites && step < (s->rows * s->cols)); step++) { + dbgf(2, "Verify sequential writes %u to dataset\n", step); - if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; - } + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } - /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + /* Wait for a few ticks for the update to happen */ + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); - result = verify_dsets_action(RANDOM_WRITE, s, ds, newstep); + result = verify_dsets_action(SEQ_WRITE, s, ds, step, fileclosed); - if (s->use_np && !np_reader(result, step, s, np)) { - HDprintf("np_reader() for verifying addition failed\n"); - TEST_ERROR; + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying addition failed\n"); + TEST_ERROR; + } + else if (!result) + TEST_ERROR; } } - } - /* Start verifying hyperslab writes for contiguous and/or chunked datasets */ - if (s->lwrites) { - unsigned k; + /* Start verifying random writes */ + /* When flush of raw data is disabled, only verify data for the last write operation on file close */ + if ((s->rwrites && !fileclosed) || (fileclosed && s->lastwrite == RANDOM_WRITE)) { + unsigned newstep; - for (step = 0, k = 0; (step < s->lwrites && k < (s->rows * s->cols)); step++, k += s->cols) { - dbgf(2, "Verify hyperslab writes %u to dataset\n", step); + s->lastwrite = RANDOM_WRITE; - if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; - } + /* Set up random seed which will be the same for both writer and reader */ + HDsrandom(RANDOM_SEED); - /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + for (step = 0; (step < s->rwrites && step < (s->rows * s->cols)); step++) { + dbgf(2, "Verify random writes %u to dataset\n", step); - result = verify_dsets_action(HYPER_WRITE, s, ds, k); + newstep = (unsigned int)HDrandom() % (s->rows * s->cols); + dbgf(2, "Random step is %u\n", newstep); - if (s->use_np && !np_reader(result, step, s, np)) { - HDprintf("np_reader() for verifying addition failed\n"); - TEST_ERROR; + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Wait for a few ticks for the update to happen */ + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); + + result = verify_dsets_action(RANDOM_WRITE, s, ds, newstep, fileclosed); + + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying addition failed\n"); + TEST_ERROR; + } + else if (!result) + TEST_ERROR; } } - } - /* Start verifying raw data modifications for contiguous and/or chunked datasets */ - if (s->wwrites) { + /* Start verifying hyperslab writes */ + /* When flush of raw data is disabled, only verify data for the last write operation on file close */ + if ((s->lwrites && !fileclosed) || (fileclosed && s->lastwrite == HYPER_WRITE)) { + unsigned k; - for (step = 0; (step < s->wwrites && step < (s->rows * s->cols)); step++) { - dbgf(2, "Verify raw data modification %u to dataset\n", step); + s->lastwrite = HYPER_WRITE; - if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; + for (step = 0, k = 0; (step < s->lwrites && k < (s->rows * s->cols)); step++, k += s->cols) { + dbgf(2, "Verify hyperslab writes %u to dataset\n", step); + + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Wait for a few ticks for the update to happen */ + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); + + result = verify_dsets_action(HYPER_WRITE, s, ds, k, fileclosed); + + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying addition failed\n"); + TEST_ERROR; + } + else if (!result) + TEST_ERROR; } + } - /* Wait for a few ticks for the update to happen */ - decisleep(config->tick_len * s->update_interval); + /* Start verifying raw data modifications */ + /* When flush of raw data is disabled, only verify data for the last write operation on file close */ + if ((s->wwrites && !fileclosed) || (fileclosed && s->lastwrite == MODIFY_DATA)) { - result = verify_dsets_action(MODIFY_DATA, s, ds, step); + s->lastwrite = MODIFY_DATA; - if (s->use_np && !np_reader(result, step, s, np)) { - HDprintf("np_reader() for verifying addition failed\n"); - TEST_ERROR; + for (step = 0; (step < s->wwrites && step < (s->rows * s->cols)); step++) { + dbgf(2, "Verify raw data modification %u to dataset\n", step); + + if (s->use_np && !np_confirm_verify_notify(np->fd_writer_to_reader, step, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Wait for a few ticks for the update to happen */ + if (!fileclosed) + decisleep(config->tick_len * s->update_interval); + + result = verify_dsets_action(MODIFY_DATA, s, ds, step, fileclosed); + + if (s->use_np && !np_reader(result, step, s, np)) { + HDprintf("np_reader() for verifying addition failed\n"); + TEST_ERROR; + } + else if (!result) + TEST_ERROR; } } } @@ -1247,7 +1359,7 @@ verify_write_dset_contig_chunked(state_t *s, dsets_state_t *ds, H5F_vfd_swmr_con error: return false; -} /* verify_write_dset_contig_chunked() */ +} /* Verify_dsets_operations() */ /* * Verify the data read from each of the datasets specified on the command line @@ -1258,7 +1370,8 @@ error: * MODIFY_DATA: `which` raw data modification */ static bool -verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which) +verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, unsigned which, + bool fileclosed) { hsize_t start[2]; hsize_t stride[2]; @@ -1275,9 +1388,9 @@ verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, /* Verify the data read for the contiguous dataset */ if (s->contig) { - if (!verify_read_dset(ds->contig_did, s->filetype, mem_sid, ds->contig_sid, start, stride, count, - block, vbuf)) { - HDprintf("H5Dwrite to contiguous dataset failed\n"); + if (!verify_dset(ds->contig_did, s->filetype, mem_sid, ds->contig_sid, start, stride, count, block, + vbuf, fileclosed, s->flush_raw_data)) { + HDprintf("verify_dset() to contiguous dataset failed\n"); TEST_ERROR; } } @@ -1285,33 +1398,33 @@ verify_dsets_action(unsigned action, const state_t *s, const dsets_state_t *ds, /* Verify the data read for the chunked datasets */ if (s->chunked) { - if (!verify_read_dset(ds->single_did, s->filetype, mem_sid, ds->single_sid, start, stride, count, - block, vbuf)) { - HDprintf("H5Dwrite to chunked dataset: single index dataset failed\n"); + if (!verify_dset(ds->single_did, s->filetype, mem_sid, ds->single_sid, start, stride, count, block, + vbuf, fileclosed, s->flush_raw_data)) { + HDprintf("verify_dset() to chunked dataset: single index dataset failed\n"); TEST_ERROR; } - if (!verify_read_dset(ds->implicit_did, s->filetype, mem_sid, ds->implicit_sid, start, stride, count, - block, vbuf)) { - HDprintf("H5Dwrite to chunked dataset: implicit index dataset failed\n"); + if (!verify_dset(ds->implicit_did, s->filetype, mem_sid, ds->implicit_sid, start, stride, count, + block, vbuf, fileclosed, s->flush_raw_data)) { + HDprintf("verify_dset() to chunked dataset: implicit index dataset failed\n"); TEST_ERROR; } - if (!verify_read_dset(ds->fa_did, s->filetype, mem_sid, ds->fa_sid, start, stride, count, block, - vbuf)) { - HDprintf("H5Dwrite to chunked dataset: fa index dataset failed\n"); + if (!verify_dset(ds->fa_did, s->filetype, mem_sid, ds->fa_sid, start, stride, count, block, vbuf, + fileclosed, s->flush_raw_data)) { + HDprintf("verify_dset() to chunked dataset: fa index dataset failed\n"); TEST_ERROR; } - if (!verify_read_dset(ds->ea_did, s->filetype, mem_sid, ds->ea_sid, start, stride, count, block, - vbuf)) { - HDprintf("H5Dwrite to chunked dataset: ea index dataset failed\n"); + if (!verify_dset(ds->ea_did, s->filetype, mem_sid, ds->ea_sid, start, stride, count, block, vbuf, + fileclosed, s->flush_raw_data)) { + HDprintf("verify_dset() to chunked dataset: ea index dataset failed\n"); TEST_ERROR; } - if (!verify_read_dset(ds->bt2_did, s->filetype, mem_sid, ds->bt2_sid, start, stride, count, block, - vbuf)) { - HDprintf("H5Dwrite to chunked dataset: bt2 index dataset failed\n"); + if (!verify_dset(ds->bt2_did, s->filetype, mem_sid, ds->bt2_sid, start, stride, count, block, vbuf, + fileclosed, s->flush_raw_data)) { + HDprintf("verify_dset() to chunked dataset: bt2 index dataset failed\n"); TEST_ERROR; } } @@ -1334,8 +1447,8 @@ error: * `vbuf` contains the data expected from the read. */ static bool -verify_read_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsize_t *start, hsize_t *stride, - hsize_t *count, hsize_t *block, unsigned int *vbuf) +verify_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsize_t *start, hsize_t *stride, + hsize_t *count, hsize_t *block, unsigned int *vbuf, bool fileclosed, bool flush_raw_data) { unsigned int *rbuf = NULL; unsigned i; @@ -1365,9 +1478,16 @@ verify_read_dset(hid_t did, hid_t tid, hid_t mem_sid, hid_t file_sid, hsize_t *s } /* Verify the data read in `rbuf` is as `vbuf` */ - for (i = 0; i < count[1]; i++) - if (rbuf[i] != vbuf[i]) - TEST_ERROR; + for (i = 0; i < count[1]; i++) { + if (flush_raw_data || fileclosed) { + if (rbuf[i] != vbuf[i]) + TEST_ERROR; + } + else { /* No flush && not closing file */ + if (rbuf[i] != vbuf[i] && rbuf[0] != 0) /* FILL VALUE ?? */ + TEST_ERROR; + } + } if (rbuf) HDfree(rbuf); @@ -1379,17 +1499,23 @@ error: HDfree(rbuf); return false; -} /* verify_read_dset() */ +} /* verify_dset() */ /* * Verify that the data read from the compact dataset is as unexpected. */ static bool -verify_read_dset_compact(const state_t *s, const dsets_state_t *ds) +verify_dset_compact(const state_t *s, const dsets_state_t *ds, bool fileclosed, bool flush_raw_data) { unsigned int *rbuf; unsigned i; + /* Refresh the dataset */ + if (H5Drefresh(ds->compact_did) < 0) { + HDprintf("H5Drefresh dataset failed\n"); + TEST_ERROR; + } + if ((rbuf = HDmalloc(s->compact_elmts * sizeof(unsigned int))) == NULL) { HDprintf("HDmalloc buffer for compact dataset failed\n"); goto error; @@ -1400,11 +1526,18 @@ verify_read_dset_compact(const state_t *s, const dsets_state_t *ds) TEST_ERROR; } - for (i = 0; i < s->compact_elmts; i++) - if (rbuf[i] != (i + 1)) { - HDprintf("Invalid value for compact dataset element\n"); - TEST_ERROR; + for (i = 0; i < s->compact_elmts; i++) { + if (flush_raw_data || fileclosed) { + if (rbuf[i] != (i + 1)) { + HDprintf("Invalid value for compact dataset element\n"); + TEST_ERROR; + } + } + else { /* No flush && not closing file */ + if (rbuf[i] != (i + 1) && rbuf[0] != 0) /* FILL VALUE ?? */ + TEST_ERROR; } + } if (rbuf) HDfree(rbuf); @@ -1416,7 +1549,7 @@ error: HDfree(rbuf); return false; -} /* verify_read_dset_compact() */ +} /* verify_dset_compact() */ /* * Named pipes handling @@ -1535,9 +1668,8 @@ np_writer(bool result, unsigned step, const state_t *s, np_state_t *np, H5F_vfd_ HDwrite(np->fd_writer_to_reader, &np->notify, sizeof(int)); goto error; } - /* The action succeeds */ } - else { + else { /* The action succeeds */ /* At communication interval, notify the reader and wait for its response */ if (step % s->csteps == 0) { /* Bump up the value of notify to tell the reader to start reading */ @@ -1642,6 +1774,90 @@ error: } /* np_confirm_verify_notify() */ /* + * When flush of raw data is disabled, the following is done by the writer and reader: + * Writer: + * Close the file + * Notify the reader that the file is closed + * Reader: + * Confirm the message from the writer that the file is closed + * Verify the data + */ +static bool +closing_on_noflush(bool writer, state_t *s, dsets_state_t *ds, H5F_vfd_swmr_config_t *config, np_state_t *np) +{ + HDassert(s->use_np); + + if (writer) { + if (!close_dsets(ds)) { + HDprintf("close_dsets() failed\n"); + TEST_ERROR; + } + + dbgf(2, "Writer closes the file (flush of raw data is disabled)\n"); + if (H5Fclose(s->file) < 0) { + HDprintf("H5Fclose failed\n"); + TEST_ERROR; + } + + /* Bump up the value of notify to tell the reader the file is closed */ + dbgf(2, "Writer notifies reader that the file is closed (flush of raw data is disabled)\n"); + np->notify++; + if (HDwrite(np->fd_writer_to_reader, &np->notify, sizeof(int)) < 0) { + HDprintf("HDwrite failed\n"); + TEST_ERROR; + } + + if (!np_close(np, writer)) { + HDprintf("np_close() failed\n"); + TEST_ERROR; + } + } + else { + /* Wait for a few ticks for the file to close in writer ?? need to this or not? */ + decisleep(config->tick_len * s->update_interval); + + dbgf(2, "Reader checks notify value from writer (flush of raw data is disabled)\n"); + if (!np_confirm_verify_notify(np->fd_writer_to_reader, 0, s, np)) { + HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); + TEST_ERROR; + } + + /* Close the named pipes */ + if (!np_close(np, writer)) { + HDprintf("np_close() failed\n"); + TEST_ERROR; + } + + /* Turn off named pipes */ + s->use_np = false; + + /* Verify the dataset again without named pipes */ + dbgf(2, "Reader verifies data after writer closes the file (flush of raw data is disabled)\n"); + if (!verify_dsets_operations(s, ds, config, np, true)) { + HDprintf("verify_dsets_operations() failed\n"); + TEST_ERROR + } + + if (!close_dsets(ds)) { + HDprintf("close_dsets() failed\n"); + TEST_ERROR; + } + + dbgf(2, "Reader closes the file (flush of raw data is disabled)\n"); + if (H5Fclose(s->file) < 0) { + HDprintf("H5Fclose failed\n"); + TEST_ERROR; + } + } + + return true; + +error: + return false; + +} /* closing_on_noflush() */ + +/* * Main */ int @@ -1655,7 +1871,6 @@ main(int argc, char **argv) H5F_vfd_swmr_config_t config; np_state_t np; dsets_state_t ds; - bool result; if (!state_init(&s, argc, argv)) { HDprintf("state_init() failed\n"); @@ -1674,7 +1889,7 @@ main(int argc, char **argv) } /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 7, writer, FALSE, 128, "./dsetops-shadow"); + init_vfd_swmr_config(&config, 4, 7, writer, s.flush_raw_data, 128, "./dsetops-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(true, s.use_vfd_swmr, true, 4096, &config)) < 0) { @@ -1718,62 +1933,19 @@ main(int argc, char **argv) if (writer) { - /* Perform writes to the whole compact dataset */ - if (s.compact && s.compact_write) { - dbgf(2, "Writes all to compact dataset\n"); - - result = write_dset_compact(&s, &ds); - - if (s.use_np && !np_writer(result, 0, &s, &np, &config)) { - HDprintf("np_writer() for addition failed\n"); - TEST_ERROR; - } - } - - if (s.contig || s.chunked) { - /* Perform writes for contiguous and/or chunked datasets */ - if (!write_dset_contig_chunked(&s, &ds, &config, &np)) { - HDprintf("write_dset_contig_chunked() failed\n"); - TEST_ERROR; - } + if (!perform_dsets_operations(&s, &ds, &config, &np)) { + HDprintf("perform_dsets_operations() failed\n"); + TEST_ERROR; } } else { - /* Start verifying data written to the compact dataset */ - if (s.compact && s.compact_write) { - dbgf(2, "Verify writes to compact dataset\n"); - - if (s.use_np && !np_confirm_verify_notify(np.fd_writer_to_reader, 0, &s, &np)) { - HDprintf("np_confirm_verify_notify() verify/notify not in sync failed\n"); - TEST_ERROR; - } - /* Wait for a few ticks for the update to happen */ - decisleep(config.tick_len * s.update_interval); - - result = verify_read_dset_compact(&s, &ds); - - if (s.use_np && !np_reader(result, 0, &s, &np)) { - HDprintf("np_reader() for verifying addition failed\n"); - TEST_ERROR; - } - } - - if (s.contig || s.chunked) { - - /* Verify writes for contiguous and/or chunked datasets */ - if (!verify_write_dset_contig_chunked(&s, &ds, &config, &np)) { - HDprintf("verify_write_dset_contig_chunked() failed\n"); - TEST_ERROR; - } + if (!verify_dsets_operations(&s, &ds, &config, &np, false)) { + HDprintf("perform_dsets_operations() failed\n"); + TEST_ERROR; } } - if (!close_dsets(&ds)) { - HDprintf("close_dsets() failed\n"); - TEST_ERROR; - } - if (H5Pclose(fapl) < 0) { HDprintf("H5Pclose failed\n"); TEST_ERROR; @@ -1784,14 +1956,27 @@ main(int argc, char **argv) TEST_ERROR; } - if (H5Fclose(s.file) < 0) { - HDprintf("H5Fclose failed\n"); - TEST_ERROR; + if (!s.flush_raw_data && s.use_np) { + + if (!closing_on_noflush(writer, &s, &ds, &config, &np)) + TEST_ERROR } + else { - if (s.use_np && !np_close(&np, writer)) { - HDprintf("np_close() failed\n"); - TEST_ERROR; + if (!close_dsets(&ds)) { + HDprintf("close_dsets() failed\n"); + TEST_ERROR; + } + + if (H5Fclose(s.file) < 0) { + HDprintf("H5Fclose failed\n"); + TEST_ERROR; + } + + if (s.use_np && !np_close(&np, writer)) { + HDprintf("np_close() failed\n"); + TEST_ERROR; + } } return EXIT_SUCCESS; diff --git a/test/vfd_swmr_generator.c b/test/vfd_swmr_generator.c index 4b87072..16b1d4b 100644 --- a/test/vfd_swmr_generator.c +++ b/test/vfd_swmr_generator.c @@ -126,7 +126,7 @@ gen_skeleton(const char *filename, hbool_t verbose, hbool_t vfd_swmr_write, int return -1; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 10, vfd_swmr_write, FALSE, 128, "generator-shadow"); + init_vfd_swmr_config(config, 4, 10, vfd_swmr_write, TRUE, 128, "generator-shadow"); } /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ diff --git a/test/vfd_swmr_gperf_writer.c b/test/vfd_swmr_gperf_writer.c new file mode 100644 index 0000000..e21f931 --- /dev/null +++ b/test/vfd_swmr_gperf_writer.c @@ -0,0 +1,2979 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Description of this program: + * This program checks the performance of group creations for VFD SWMR. + * Currently the group creation time, H5Fopen and H5Fclose time are measured. + * After compiling the program, + * ./vfd_swmr_gperf_writer -n 1000 -P -N 5 -q + * will generate 1000 groups, each group has 5 attributes. + * ./vfd_swmr_gperf_writer -n 1000 -P -N 0 -q + * will generate 1000 empty groups. + * ./vfd_swmr_gperf_writer -n 1000 -P -l 1 -q + * will generate 1000 groups with 1 level of nested groups,(like /g1/g2) + * each group has one attribute. + * ./vfd_swmr_gperf_writer -n 1000 -P -S -G -V -N 5 -l 1 -m 8 -t 4 -B 16384 -s 8192 + * will generate 1000 groups with 1 level of nested groups,(like /g1/g2) + * each group has 5 attributes and the attribute type is variable length string. + * The groups is created without using VFD SWMR; + * The groups are created with the earliest file format(old-styled) + * The program is run with max_lag = 8, tick_len = 4; + * The page buffer size is 16384 bytes. The page size is 8192 bytes. + * + */ +#define H5F_FRIEND /*suppress error about including H5Fpkg */ + +#include "hdf5.h" + +#include "H5Fpkg.h" +#include "H5HGprivate.h" +#include "H5VLprivate.h" + +#include "testhdf5.h" +#include "vfd_swmr_common.h" + +#ifndef H5_HAVE_WIN32_API + +#define VS_ATTR_NAME_LEN 21 + +#define TIME_PASSED(X, Y) \ + ((double)((Y.tv_sec - X.tv_sec) * 1000000000 + (Y.tv_nsec - X.tv_nsec))) / 1000000000.0 + +typedef struct { + hid_t file, filetype, one_by_one_sid; + char filename[PATH_MAX]; + char progname[PATH_MAX]; + unsigned int asteps; + unsigned int nsteps; + bool use_vfd_swmr; + bool old_style_grp; + char grp_op_pattern; + bool grp_op_test; + char at_pattern; + bool attr_test; + uint32_t max_lag; + uint32_t tick_len; + bool gperf; + double min_gc_time; + double max_gc_time; + double mean_gc_time; + double total_gc_time; + double total_time; + double mean_time; + double fo_total_time; + double fc_total_time; + unsigned int num_attrs; + bool vlstr_test; + unsigned int ps; + unsigned int pbs; + unsigned int nglevels; +} state_t; + +#define ALL_HID_INITIALIZER \ + (state_t) \ + { \ + .file = H5I_INVALID_HID, .one_by_one_sid = H5I_INVALID_HID, .filename = "", \ + .filetype = H5T_NATIVE_UINT32, .asteps = 1, .nsteps = 100, .use_vfd_swmr = true, \ + .old_style_grp = false, .grp_op_pattern = ' ', .grp_op_test = false, .at_pattern = ' ', \ + .attr_test = false, .tick_len = 4, .max_lag = 7, .gperf = false, .min_gc_time = 100., \ + .max_gc_time = 0., .mean_gc_time = 0., .total_gc_time = 0., .total_time = 0., .mean_time = 0., \ + .fo_total_time = 0., .fc_total_time = 0., .num_attrs = 1, .vlstr_test = false, .ps = 4096, \ + .pbs = 4096, .nglevels = 0 \ + } + +static void +usage(const char *progname) +{ + fprintf(stderr, + "usage: ./%s -P -n 1000 -N 5 -q (create 1000 groups, each group has 5 attributes)\n" + "Options: \n" + " [-P] [-S] [-G] [-t tick_len] [-m max_lag][-B pbs] [-s ps]\n" + " [-n ngroups] [-l ng_levels] [-O grp_op_pattern]\n" + " [-N num_attrs] [-V] [-b] [-A at_pattern] [-a steps] [-q]\n" + "\n" + "-P: carry out the performance test\n" + "-S: do not use VFD SWMR\n" + "-G: old-style type of group\n" + "-t tick_len: length of a tick in tenths of a second.\n" + "-m max_lag: maximum expected lag(in ticks) between writer and readers\n" + "-B pbs: page Buffer Size in bytes:\n" + " The default value is 4K(4096).\n" + "-s ps: page size used by page aggregation, page buffer and \n" + " the metadata file. \n" + "-n ngroups: the number of groups\n" + "-l ng_levels: the number of level of nested groups. \n" + " If all the groups are under the root group, \n" + " this number should be 0.\n" + "-N num_attrs: the number of attributes \n" + "-V use variable length string attributes for performance test\n" + "-b: write data in big-endian byte order\n" + " (For the performance test, -V overwrites -b)\n" + "-A at_pattern: `at_pattern' for different attribute tests\n" + " The value of `at_pattern` is one of the following:\n" + " `compact` - Attributes added in compact storage\n" + " `dense` - An attribute added in dense storage\n" + " `compact-del` - Attributes added and then one\n" + " attribute deleted, in compact \n" + " `dense-del` - Attributes added until the storage\n" + " is dense then an attribute deleted\n" + " the storge still in dense\n" + " `compact-add-to-dense` - Attributes added first in compact\n" + " then in dense storage\n" + " `dense-del-to-compact` - Attributes added until the storage\n" + " is dense, then several attributes \n" + " deleted, the storage changed to\n" + " compact\n" + " `modify` - An attribute added then modified\n" + " `add-vstr` - A VL string attribute added\n" + " `remove-vstr` - A VL string attribute added then\n" + " deleted\n" + " `modify-vstr` - A VL string attribute added then \n" + " modified \n" + " `add-ohr-block` - An attribute is added and this forces\n" + " the creation of object header\n" + " continuation block \n" + " `del-ohr-block` - An attribute is added and this forces\n" + " the creation of object header\n" + " continuation block and then this \n" + " attribute is deleted so the \n" + " object header continuation block is \n" + " removed. \n" + "-O grp_op_pattern: `grp_op_pattern' for different group operation tests\n" + " The value of `grp_op_pattern` is one of the following:\n" + " `grp-creation` - A group is created.\n" + " `grp-deletion` - An existing group is deleted.\n" + " `grp-move` - A group is moved to become \n" + " another group. \n" + " `grp-ins-links` - Links are inserted, including\n" + " both hard and soft links. \n" + " `grp-del-links` - Links are deleted, including\n" + " both hard ans soft links. \n" + " `grp-compact-t-dense` - Links are inserted to the group.\n" + " The link storage of this group \n" + " changed from compact to dense. \n" + " The links include both hard and\n" + " soft links. \n" + " `grp-dense-t-compact` - Links are inserted to the group\n" + " The link storage of this group \n" + " changed from compact to dense. \n" + " Then several links are deleted.\n" + " The link storage changed from \n" + " dense to compact again. \n" + " The links include both hard and\n" + " soft links. \n" + "-a steps: `steps` between adding attributes\n" + " (Don't recommend to use this option for performance test.)\n" + "-q: silence printouts, few messages\n" + "\n", + progname); + exit(EXIT_FAILURE); +} + +static bool +state_init(state_t *s, int argc, char **argv) +{ + unsigned long tmp; + int ch; + const hsize_t dims = 1; + char * tfile = NULL; + char * end; + + *s = ALL_HID_INITIALIZER; + + if (H5_basename(argv[0], &tfile) < 0) { + printf("H5_basename failed\n"); + TEST_ERROR; + } + + esnprintf(s->progname, sizeof(s->progname), "%s", tfile); + + if (tfile) { + HDfree(tfile); + tfile = NULL; + } + + if (argc == 1) + usage(s->progname); + while ((ch = getopt(argc, argv, "PSGa:bVt:m:B:s:n:qA:N:l:O:")) != -1) { + switch (ch) { + case 'P': + s->gperf = true; + break; + case 'S': + s->use_vfd_swmr = false; + break; + case 'G': + s->old_style_grp = true; + break; + case 'a': + case 'n': + case 'N': + case 'l': + case 't': + case 'm': + case 'B': + case 's': + errno = 0; + tmp = HDstrtoul(optarg, &end, 0); + if (end == optarg || *end != '\0') { + printf("couldn't parse `-%c` argument `%s`\n", ch, optarg); + TEST_ERROR; + } + else if (errno != 0) { + printf("couldn't parse `-%c` argument `%s`\n", ch, optarg); + TEST_ERROR; + } + else if (tmp > UINT_MAX) { + printf("`-%c` argument `%lu` too large\n", ch, tmp); + TEST_ERROR; + } + + if (ch == 'a') + s->asteps = (unsigned)tmp; + else if (ch == 'n') + s->nsteps = (unsigned)tmp; + else if (ch == 'N') + s->num_attrs = (unsigned)tmp; + else if (ch == 'l') + s->nglevels = (unsigned)tmp; + else if (ch == 't') + s->tick_len = (unsigned)tmp; + else if (ch == 'm') + s->max_lag = (unsigned)tmp; + else if (ch == 's') + s->ps = (unsigned)tmp; + else if (ch == 'B') + s->pbs = (unsigned)tmp; + break; + case 'b': + s->filetype = H5T_STD_U32BE; + break; + case 'V': + s->vlstr_test = true; + break; + case 'O': + if (HDstrcmp(optarg, "grp-creation") == 0) + s->grp_op_pattern = 'c'; + else if (HDstrcmp(optarg, "grp-deletion") == 0) + s->grp_op_pattern = 'd'; + else if (HDstrcmp(optarg, "grp-move") == 0) + s->grp_op_pattern = 'm'; + else if (HDstrcmp(optarg, "grp-ins-links") == 0) + s->grp_op_pattern = 'i'; + else if (HDstrcmp(optarg, "grp-del-links") == 0) + s->grp_op_pattern = 'D'; + else if (HDstrcmp(optarg, "grp-compact-t-dense") == 0) + s->grp_op_pattern = 't'; + else if (HDstrcmp(optarg, "grp-dense-t-compact") == 0) + s->grp_op_pattern = 'T'; + else { + printf("Invalid -O argument \"%s\"", optarg); + TEST_ERROR; + } + break; + case 'A': + if (HDstrcmp(optarg, "compact") == 0) + s->at_pattern = 'c'; + else if (HDstrcmp(optarg, "dense") == 0) + s->at_pattern = 'd'; + else if (HDstrcmp(optarg, "compact-add-to-dense") == 0) + s->at_pattern = 't'; + else if (HDstrcmp(optarg, "compact-del") == 0) + s->at_pattern = 'C'; + else if (HDstrcmp(optarg, "dense-del") == 0) + s->at_pattern = 'D'; + else if (HDstrcmp(optarg, "dense-del-to-compact") == 0) + s->at_pattern = 'T'; + else if (HDstrcmp(optarg, "modify") == 0) + s->at_pattern = 'M'; + else if (HDstrcmp(optarg, "add-vstr") == 0) + s->at_pattern = 'v'; + else if (HDstrcmp(optarg, "remove-vstr") == 0) + s->at_pattern = 'r'; + else if (HDstrcmp(optarg, "modify-vstr") == 0) + s->at_pattern = 'm'; + else if (HDstrcmp(optarg, "add-ohr-block") == 0) + s->at_pattern = 'a'; + else if (HDstrcmp(optarg, "del-ohr-block") == 0) + s->at_pattern = 'R'; + else { + printf("Invalid -A argument \"%s\"", optarg); + TEST_ERROR; + } + break; + case 'q': + verbosity = 0; + break; + case '?': + default: + usage(s->progname); + break; + } + } + argc -= optind; + argv += optind; + + if (s->grp_op_pattern != ' ') + s->grp_op_test = true; + if (s->at_pattern != ' ') + s->attr_test = true; + + if (!s->grp_op_test) { + if (s->asteps < 1 || s->asteps > s->nsteps) { + printf("attribute interval is out of bounds\n"); + TEST_ERROR; + } + } + + if (s->grp_op_test && s->attr_test) { + printf("Cannot test both group operation and attribute tests!\n"); + printf("Attribute tests are ignored.\n"); + } + + if (argc > 0) { + printf("unexpected command-line arguments\n"); + TEST_ERROR; + } + + /* space for attributes */ + if ((s->one_by_one_sid = H5Screate_simple(1, &dims, &dims)) < 0) { + printf("H5Screate_simple failed\n"); + TEST_ERROR; + } + + esnprintf(s->filename, sizeof(s->filename), "vfd_swmr_group.h5"); + + return true; + +error: + if (tfile) + HDfree(tfile); + return false; +} + +/*------------------------------------------------------------------------- + * Function: check_ohr_num_chunk + * + * Purpose: Check if the number of object header chunks is as expected. + * + * Parameters: hid_t oid + * HDF5 object ID (in this file: means group ID) + * + * bool one_chunk_ohr + * flag to indicate if the object header chunk is 1 or greater + * 1: true + * greater than 1: false + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- + */ + +static bool +check_ohr_num_chunk(hid_t g, bool one_chunk_ohr) +{ + + H5O_native_info_t ninfo; + + /* Get the object information */ + if (H5Oget_native_info(g, &ninfo, H5O_NATIVE_INFO_HDR) < 0) { + printf("H5Oget_native_info failed\n"); + TEST_ERROR; + } + + if (true == one_chunk_ohr) { + if (ninfo.hdr.nchunks != 1) { + printf("Object header should have only one chunk,but it is not.\n"); + TEST_ERROR; + } + } + else { + if (ninfo.hdr.nchunks <= 1) { + printf("Object header should have more than one chunk,but it is not.\n"); + TEST_ERROR; + } + } + + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_attr + * + * Purpose: Add attributes to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t oid + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * unsigned num_attrs + * The number of attributes to be created + * + * const char*aname_fmt + * The attribute name template used to create unique attribute names. + * + * unsigned int g_which + * This parameter is used to generate correct group name in a key + * debugging message. + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- + */ + +static bool +add_attr(state_t *s, hid_t oid, unsigned int which, unsigned num_attrs, const char *aname_fmt, + unsigned int g_which) +{ + + char attrname[VS_ATTR_NAME_LEN]; + unsigned u; + unsigned attr_value; + hid_t aid = H5I_INVALID_HID; + hid_t amtype = H5I_INVALID_HID; + hid_t atype = s->filetype; + hid_t sid = s->one_by_one_sid; + + /* Need to obtain native datatype for H5Aread */ + if ((amtype = H5Tget_native_type(atype, H5T_DIR_ASCEND)) < 0) { + printf("H5Tget_native_type failed\n"); + TEST_ERROR; + } + + for (u = 0; u < num_attrs; u++) { + + /* Create attribute */ + /* Construct attribute name like attr-0-0 */ + HDsprintf(attrname, aname_fmt, which, u); + if ((aid = H5Acreate2(oid, attrname, atype, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + printf("H5Acreate2 failed\n"); + TEST_ERROR; + } + + attr_value = u + which; + + dbgf(1, "setting attribute %s on group %u to %u\n", attrname, g_which, u + which); + + /* Write data into the attribute */ + if (H5Awrite(aid, amtype, &attr_value) < 0) { + printf("H5Awrite failed\n"); + TEST_ERROR; + } + + /* Close attribute */ + if (H5Aclose(aid) < 0) { + printf("H5Aclose failed\n"); + TEST_ERROR; + } + + /* If coming to an "object header continuation block" test, + * we need to check if this test behaves as expected. */ + if (s->at_pattern == 'a' || s->at_pattern == 'R') { + if (false == check_ohr_num_chunk(oid, false)) { + printf("An object header continuation block should be created. \n"); + printf("But it is not.\n"); + TEST_ERROR; + } + } + + } /* end for */ + + if (H5Tclose(amtype) < 0) { + TEST_ERROR; + } + + return true; + +error: + H5E_BEGIN_TRY + { + H5Aclose(aid); + H5Tclose(amtype); + } + H5E_END_TRY; + + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_vlstr_attr + * + * Purpose: Add a variable length string attribute to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "vstr" test. + *------------------------------------------------------------------------- + */ + +static bool +add_vlstr_attr(state_t *s, hid_t g, unsigned int which) +{ + + hid_t aid = H5I_INVALID_HID; + hid_t atype = H5I_INVALID_HID; + char name[VS_ATTR_NAME_LEN]; + char *astr_val = NULL; + hid_t sid = s->one_by_one_sid; + + /* Allocate buffer for the VL string value */ + astr_val = HDmalloc(VS_ATTR_NAME_LEN); + if (astr_val == NULL) { + printf("Allocate memory for VL string failed.\n"); + TEST_ERROR; + } + + /* Assign the VL string value and the attribute name.. */ + HDsprintf(astr_val, "%u", which); + esnprintf(name, sizeof(name), "attr-%u", which); + + dbgf(1, "setting attribute %s on group %u to %u\n", name, which, which); + + /* Create a datatype to refer to. */ + if ((atype = H5Tcopy(H5T_C_S1)) < 0) { + printf("Cannot create variable length datatype.\n"); + TEST_ERROR; + } + + if (H5Tset_size(atype, H5T_VARIABLE) < 0) { + printf("Cannot set variable length datatype.\n"); + TEST_ERROR; + } + + /* Generate the VL string attribute.*/ + if ((aid = H5Acreate2(g, name, atype, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + printf("H5Acreate2 failed.\n"); + TEST_ERROR; + } + + if (H5Awrite(aid, atype, &astr_val) < 0) { + printf("H5Awrite failed.\n"); + TEST_ERROR; + } + + if (H5Tclose(atype) < 0) { + printf("H5Tclose() failed\n"); + TEST_ERROR; + } + if (H5Aclose(aid) < 0) { + printf("H5Aclose() failed\n"); + TEST_ERROR; + } + + HDfree(astr_val); + + return true; + +error: + H5E_BEGIN_TRY + { + H5Aclose(aid); + H5Tclose(atype); + } + H5E_END_TRY; + + if (astr_val) + HDfree(astr_val); + + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_vlstr_attrs + * + * Purpose: Add variable length string attributes to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which". The attribute names + * are "attr-which","attr-which+1".... + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the performance test that has the VL string type. + *------------------------------------------------------------------------- + */ + +static bool +add_vlstr_attrs(state_t *s, hid_t g, unsigned int which, unsigned int num_attrs) +{ + unsigned u; + bool ret_value = true; + for (u = 0; u < num_attrs; u++) { + ret_value = add_vlstr_attr(s, g, u + which); + if (ret_value == false) + break; + } + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: add_default_group_attr + * + * Purpose: Add an attribute to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the "dense" storage test. + * It is also used by the group-only, "add-ohr-block" + * and "del-ohr-block" tests. + *------------------------------------------------------------------------- + */ + +static bool +add_default_group_attr(state_t *s, hid_t g, unsigned int which) +{ + + const char *aname_format = "attr-%u-%u"; + + /* Note: the number of attributes can be configurable, + * the default number of attribute is 1. + */ + /* If the vl string attribute type is chosen. */ + if (s->vlstr_test == true) + return add_vlstr_attrs(s, g, which, s->num_attrs); + else + return add_attr(s, g, which, s->num_attrs, aname_format, which); +} + +/*------------------------------------------------------------------------- + * Function: del_one_attr + * + * Purpose: delete one attribute in a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t obj_id + * HDF5 object ID (in this file: means group ID) + * + * bool is_dense + * if the deleted attribute is for checking the dense storage + * + * bool is_vl_or_ohrc + * if the deleted attribute is a VL string or for object header + * continuation check test + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute names + * according to if this attribute is a VL string or for checking + * the dense storage or the storage transition from dense to + * compact. + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- + */ + +static bool +del_one_attr(state_t *s, hid_t obj_id, bool is_dense, bool is_vl_or_ohrc, unsigned int which) +{ + + char attrname[VS_ATTR_NAME_LEN]; + + /*attribute name template for the dense storage related deletion operation */ + const char *aname_format_d = "attr-d-%u-%u"; + + /*attribute name template used for general attribute deletion operation */ + const char *aname_format = "attr-%u-%u"; + + /*attribute name template used for VL string attribute deletion + * or object header continuation check operations */ + const char *aname_format_vl = "attr-%u"; + + dbgf(2, "writer: coming to delete the attribute.\n"); + + /* Construct the attribute name */ + if (is_dense == true) + HDsprintf(attrname, aname_format_d, which, 0); + else if (is_vl_or_ohrc == true) + HDsprintf(attrname, aname_format_vl, which, 0); + else + HDsprintf(attrname, aname_format, which, 0); + + /* Delete the attribute */ + if (H5Adelete(obj_id, attrname) < 0) { + printf("H5Adelete() failed\n"); + TEST_ERROR; + } + + /* If coming to an "object header continuation block" test, + * we need to check if this test behaves as expected. */ + if (s->at_pattern == 'R') { + if (false == check_ohr_num_chunk(obj_id, true)) { + printf("The object header chunk should not continue. \n"); + TEST_ERROR; + } + } + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_del_vlstr_attr + * + * Purpose: Add a variable length string attribute + * then delete this attribute in this a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "remove-vstr" test. + *------------------------------------------------------------------------- + */ + +static bool +add_del_vlstr_attr(state_t *s, hid_t g, unsigned int which) +{ + + bool ret_value = false; + + /* Add a VL string attribute then delete it. */ + ret_value = add_vlstr_attr(s, g, which); + if (ret_value == true) + ret_value = del_one_attr(s, g, false, true, which); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: modify_attr + * + * Purpose: Modify the value of an attribute in a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * const char*aname_fmt + * The attribute name template used to create unique attribute names. + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- + */ + +static bool +modify_attr(state_t *s, hid_t g, const char *aname_fmt, unsigned int which) +{ + + char attrname[VS_ATTR_NAME_LEN]; + hid_t aid = H5I_INVALID_HID; + hid_t amtype = H5I_INVALID_HID; + unsigned int modify_value; + + HDsprintf(attrname, aname_fmt, which, 0); + if ((aid = H5Aopen(g, attrname, H5P_DEFAULT)) < 0) { + printf("H5Aopen failed\n"); + TEST_ERROR; + } + + if ((amtype = H5Tget_native_type(s->filetype, H5T_DIR_ASCEND)) < 0) { + printf("H5Tget_native_type failed\n"); + TEST_ERROR; + } + + /* Make a large number to verify the change easily */ + modify_value = which + 10000; + + if (H5Awrite(aid, amtype, &modify_value) < 0) { + printf("H5Awrite failed\n"); + TEST_ERROR; + } + if (H5Tclose(amtype) < 0) { + printf("H5Tclose failed\n"); + TEST_ERROR; + } + if (H5Aclose(aid) < 0) { + printf("H5Aclose failed\n"); + TEST_ERROR; + } + + return true; +error: + H5E_BEGIN_TRY + { + H5Aclose(aid); + H5Tclose(aid); + } + H5E_END_TRY; + + return false; +} + +/*------------------------------------------------------------------------- + * Function: modify_vlstr_attr + * + * Purpose: Modify the value of an VL string attribute in a group. + * + * Parameters: + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- + */ + +static bool +modify_vlstr_attr(hid_t g, unsigned int which) +{ + + hid_t aid = H5I_INVALID_HID; + hid_t atype = H5I_INVALID_HID; + char name[VS_ATTR_NAME_LEN]; + char *astr_val = NULL; + + astr_val = HDmalloc(VS_ATTR_NAME_LEN); + if (astr_val == NULL) { + printf("Allocate memory for VL string failed.\n"); + TEST_ERROR; + } + + /* Change the VL string value and create the attribute name. */ + HDsprintf(astr_val, "%u%c", which, 'A'); + esnprintf(name, sizeof(name), "attr-%u", which); + + dbgf(1, "setting attribute %s on group %u to %u\n", name, which, which); + + /* Create a datatype to refer to. */ + if ((atype = H5Tcopy(H5T_C_S1)) < 0) { + printf("Cannot create variable length datatype.\n"); + TEST_ERROR; + } + + if (H5Tset_size(atype, H5T_VARIABLE) < 0) { + printf("Cannot set variable length datatype.\n"); + TEST_ERROR; + } + + /* Open this attribute. */ + if ((aid = H5Aopen(g, name, H5P_DEFAULT)) < 0) { + printf("H5Aopen failed.\n"); + TEST_ERROR; + } + + dbgf(1, "The modified VL string value is %s \n", astr_val); + + if (H5Awrite(aid, atype, &astr_val) < 0) { + printf("H5Awrite failed.\n"); + TEST_ERROR; + } + + if (H5Tclose(atype) < 0) { + printf("H5Tclose() failed\n"); + TEST_ERROR; + } + + if (H5Aclose(aid) < 0) { + printf("H5Aclose() failed\n"); + TEST_ERROR; + } + + HDfree(astr_val); + + return true; + +error: + H5E_BEGIN_TRY + { + H5Aclose(aid); + H5Tclose(atype); + } + H5E_END_TRY; + + if (astr_val) + HDfree(astr_val); + + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_modify_vlstr_attr + * + * Purpose: Add a variable length string attribute + * then modify this attribute in the group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "modify-vstr" test. + *------------------------------------------------------------------------- + */ + +static bool +add_modify_vlstr_attr(state_t *s, hid_t g, unsigned int which) +{ + + bool ret_value = false; + ret_value = add_vlstr_attr(s, g, which); + if (true == ret_value) + ret_value = modify_vlstr_attr(g, which); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: add_attrs_compact + * + * Purpose: Add some attributes to the group. + * the number of attributes should be the maximal number of + * attributes that the compact storage can hold + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "modify-vstr" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- + */ + +static bool +add_attrs_compact(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + unsigned max_compact = 0; + unsigned min_dense = 0; + const char *aname_format = "attr-%u-%u"; + + if (s->old_style_grp) + max_compact = 2; + else { + /* Obtain the maximal number of attributes to be stored in compact + * storage and the minimal number of attributes to be stored in + * dense storage. */ + if (H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + printf("H5Pget_attr_phase_change() failed\n"); + TEST_ERROR; + } + } + + /* Add max_compact attributes, these attributes are stored in + * compact storage. */ + return add_attr(s, g, which, max_compact, aname_format, which); + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_attrs_compact_dense + * + * Purpose: Add some attributes to the group. + * First, the number of attributes should be the maximal number + * of attributes that the compact storage can hold. + * Then, add another atribute, the storage becomes dense. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "compact-to-dense" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- + */ + +static bool +add_attrs_compact_dense(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + unsigned max_compact = 0; + unsigned min_dense = 0; + const char *aname_format = "attr-d-%u-%u"; + bool ret_value = false; + + if (H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + printf("H5Pget_attr_phase_change failed\n"); + TEST_ERROR; + } + + /* Add attributes, until just before converting to dense storage */ + ret_value = add_attrs_compact(s, g, gcpl, which); + + /* Add another attribute, the storage becomes dense. */ + if (ret_value == true) + ret_value = add_attr(s, g, which + max_compact, 1, aname_format, which); + + return ret_value; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: del_attrs_compact_dense_compact + * + * Purpose: delete some attributes in the group. + * The number of attributes are deleted in such a way + * that the attribute storage changes from compact to + * dense then to compact again. + * + * Parameters: hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is an internal function used by the + * "dense-del-to-compact" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- + */ + +static bool +del_attrs_compact_dense_compact(hid_t obj_id, hid_t gcpl, unsigned int which) +{ + + unsigned max_compact = 0; + unsigned min_dense = 0; + unsigned u = 0; + + char attrname[VS_ATTR_NAME_LEN]; + const char *aname_format = "attr-%u-%u"; + const char *adname_format = "attr-d-%u-%u"; + + /* Obtain the maximal number of attributes to be stored in compact + * storage and the minimal number of attributes to be stored in + * dense storage. */ + if (H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + printf("H5Pget_attr_phase_change failed\n"); + TEST_ERROR; + } + u = max_compact + 1; + + /* delete a number of attributes so that the attribute storage just becomes dense.*/ + for (u--; u >= (min_dense - 1); u--) { + HDsprintf(attrname, aname_format, which, max_compact - u); + if (H5Adelete(obj_id, attrname) < 0) { + printf("H5Adelete failed\n"); + TEST_ERROR; + } + } + + /* The writer deletes another attribute, the storage is + * still dense. However, the attribute to be deleted + * doesn't follow the previous for loop. It may be + * in different location in the object header. Just add + * a litter variation to check if this operation is successful. + * The attribute name to be deleted is attr-max_compact+which-0 + */ + + HDsprintf(attrname, adname_format, max_compact + which, 0); + if (H5Adelete(obj_id, attrname) < 0) { + printf("H5Adelete failed\n"); + TEST_ERROR; + } + + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_del_attrs_compact + * + * Purpose: Add some attributes to the group and then delete one attribute. + * First, the number of attributes to be added should be the + * maximal number of attributes that the compact storage can hold. + * Then, delete one atribute, the storage is still compact. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "compact-del" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- + */ + +static bool +add_del_attrs_compact(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + bool ret_value = false; + ret_value = add_attrs_compact(s, g, gcpl, which); + if (ret_value == true) { + dbgf(2, "writer: before deleting the attribute.\n"); + ret_value = del_one_attr(s, g, false, false, which); + } + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: add_del_attrs_compact_dense + * + * Purpose: Add some attributes to the group and then delete one attribute. + * First, the number of attributes to be added exceeds + * the maximal number of attributes that the compact storage can hold. + * The storage changes from compact to dense. + * Then, delete one atribute, the storage is still dense. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "dense-del" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- + */ + +static bool +add_del_attrs_compact_dense(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + bool ret_value = false; + unsigned max_compact = 0; + unsigned min_dense = 0; + + if (H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + printf("H5Pget_attr_phase_change failed\n"); + TEST_ERROR; + } + + ret_value = add_attrs_compact_dense(s, g, gcpl, which); + if (ret_value == true) + ret_value = del_one_attr(s, g, true, false, which + max_compact); + + return ret_value; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_del_attrs_compact_dense_compact + * + * Purpose: Add attributes to the group and then delete some of them. + * First, the number of attributes to be added exceeds + * the maximal number of attributes that the compact storage can hold. + * The storage changes from compact to dense. + * Then, delete some attributes, the storage changes from + * dense to compact again. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "dense-del-to-compact" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- + */ + +static bool +add_del_attrs_compact_dense_compact(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + bool ret_value = false; + ret_value = add_attrs_compact_dense(s, g, gcpl, which); + if (ret_value == true) + ret_value = del_attrs_compact_dense_compact(g, gcpl, which); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: add_modify_default_group_attr + * + * Purpose: Add an attribute then modify the value to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the "modify" test. + *------------------------------------------------------------------------- + */ + +static bool +add_modify_default_group_attr(state_t *s, hid_t g, unsigned int which) +{ + + bool ret_value = false; + const char *aname_format = "attr-%u"; + ret_value = add_default_group_attr(s, g, which); + if (ret_value == true) + ret_value = modify_attr(s, g, aname_format, which); + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: del_ohr_block_attr + * + * Purpose: Add an attribute to force creation of object header + * continuation block and remove this attribute to delete + * the object header continuation block + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the + * "deletion of object header continuation block" test. + *------------------------------------------------------------------------- + */ + +static bool +del_ohr_block_attr(state_t *s, hid_t g, unsigned int which) +{ + + bool ret_value = false; + ret_value = add_default_group_attr(s, g, which); + if (ret_value == true) + ret_value = del_one_attr(s, g, false, true, which); + return ret_value; +} +/*------------------------------------------------------------------------- + * Function: add_group_attribute + * + * Purpose: Check the attribute test pattern and then call the + * correponding test function.. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the write_group() function. + *------------------------------------------------------------------------- + */ + +static bool +add_group_attribute(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + bool ret_value = false; + char test_pattern = s->at_pattern; + + switch (test_pattern) { + case 'c': + ret_value = add_attrs_compact(s, g, gcpl, which); + break; + case 't': + ret_value = add_attrs_compact_dense(s, g, gcpl, which); + break; + case 'C': + ret_value = add_del_attrs_compact(s, g, gcpl, which); + break; + case 'D': + ret_value = add_del_attrs_compact_dense(s, g, gcpl, which); + break; + case 'T': + ret_value = add_del_attrs_compact_dense_compact(s, g, gcpl, which); + break; + case 'M': + ret_value = add_modify_default_group_attr(s, g, which); + break; + case 'v': + ret_value = add_vlstr_attr(s, g, which); + break; + case 'r': + ret_value = add_del_vlstr_attr(s, g, which); + break; + case 'm': + ret_value = add_modify_vlstr_attr(s, g, which); + break; + case 'R': + ret_value = del_ohr_block_attr(s, g, which); + break; + case 'a': + case 'd': + case ' ': + default: + ret_value = add_default_group_attr(s, g, which); + break; + } + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: write_group + * + * Purpose: Create a group and carry out attribute operations(add,delete etc.) + * according to the attribute test pattern. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the main() function. + *------------------------------------------------------------------------- + */ + +static bool +write_group(state_t *s, unsigned int which) +{ + char name[sizeof("/group-9999999999")]; + hid_t g = H5I_INVALID_HID; + hid_t dummy_d = H5I_INVALID_HID; + hid_t gcpl = H5I_INVALID_HID; + bool result = true; + H5G_info_t group_info; + struct timespec start_time, end_time; + double temp_time; + + if (which >= s->nsteps) { + printf("Number of created groups is out of bounds\n"); + TEST_ERROR; + } + + esnprintf(name, sizeof(name), "/group-%u", which); + + if (s->old_style_grp) + gcpl = H5P_DEFAULT; + else { + gcpl = H5Pcreate(H5P_GROUP_CREATE); + if (gcpl < 0) { + printf("H5Pcreate failed\n"); + TEST_ERROR; + } + + /* If we test the dense storage, change the attribute phase. */ + if (s->at_pattern == 'd') { + if (H5Pset_attr_phase_change(gcpl, 0, 0) < 0) { + printf("H5Pset_attr_phase_change failed for the dense storage.\n"); + TEST_ERROR; + } + } + } + + if (s->gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) { + + fprintf(stderr, "HDclock_gettime failed"); + + TEST_ERROR; + } + } + + if ((g = H5Gcreate2(s->file, name, H5P_DEFAULT, gcpl, H5P_DEFAULT)) < 0) { + printf("H5Gcreate2 failed\n"); + TEST_ERROR; + } + + if (s->gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) { + + fprintf(stderr, "HDclock_gettime failed"); + + TEST_ERROR; + } + + temp_time = TIME_PASSED(start_time, end_time); + if (temp_time < s->min_gc_time) + s->min_gc_time = temp_time; + if (temp_time > s->max_gc_time) + s->max_gc_time = temp_time; + s->total_gc_time += temp_time; + } + + /* We need to create a dummy dataset for the object header continuation block test. */ + if (s->at_pattern == 'a' || s->at_pattern == 'R') { + if ((dummy_d = H5Dcreate2(g, "Dataset", H5T_NATIVE_INT, s->one_by_one_sid, H5P_DEFAULT, H5P_DEFAULT, + H5P_DEFAULT)) < 0) { + printf("H5Dcreate2 failed\n"); + TEST_ERROR; + } + } + /* We only need to check the first group */ + if (which == 0) { + if (H5Gget_info(g, &group_info) < 0) { + printf("H5Gget_info failed\n"); + TEST_ERROR; + } + + if (s->old_style_grp) { + if (group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) { + printf("Old-styled group test: but the group is not in old-style. \n"); + TEST_ERROR; + } + dbgf(2, "Writer: group is created with the old-style.\n"); + } + else { + if (group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) { + printf("The created group should NOT be in old-style . \n"); + TEST_ERROR; + } + dbgf(2, "Writer: group is created with the new-style.\n"); + } + } + + /* If coming to an "object header continuation block" test, + * we need to check if this test behaves as expected. */ + if (s->at_pattern == 'a' || s->at_pattern == 'R') { + if (false == check_ohr_num_chunk(g, true)) { + printf("An object header continuation block should NOT be created. \n"); + printf("But it is created.\n"); + TEST_ERROR; + } + } + + /* Then carry out the attribute operation. */ + if (s->asteps != 0 && which % s->asteps == 0) + result = add_group_attribute(s, g, gcpl, which); + + if (s->at_pattern == 'a' || s->at_pattern == 'R') { + if (H5Dclose(dummy_d) < 0) { + printf("H5Dclose failed\n"); + TEST_ERROR; + } + } + + if (H5Gclose(g) < 0) { + printf("H5Gclose failed\n"); + TEST_ERROR; + } + + if (!s->old_style_grp && H5Pclose(gcpl) < 0) { + printf("H5Pclose failed\n"); + TEST_ERROR; + } + + return result; + +error: + + H5E_BEGIN_TRY + { + H5Gclose(g); + if (s->at_pattern == 'a' || s->at_pattern == 'R') + H5Dclose(dummy_d); + if (!s->old_style_grp) + H5Pclose(gcpl); + } + H5E_END_TRY; + + return false; +} + +/*------------------------------------------------------------------------- + * Function: create_group_id + * + * Purpose: Create a group and return the group ID. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * This is used to generate the group name. + * + * bool dense_to_compact + * true if this function is used to test the transition from dense to + * compact, false if the test is from compact to dense. + * + * Return: Success: the group ID + * Failure: -1 + * + * Note: Only used by testing the link storage transit functions. + *------------------------------------------------------------------------- + */ + +static hid_t +create_group_id(state_t *s, unsigned int which, bool dense_to_compact) +{ + + char name[sizeof("/group-9999999999")]; + hid_t g = H5I_INVALID_HID; + hid_t gcpl = H5I_INVALID_HID; + H5G_info_t group_info; + + if (which >= s->nsteps) { + printf("Number of created groups is out of bounds\n"); + TEST_ERROR; + } + + gcpl = H5Pcreate(H5P_GROUP_CREATE); + if (gcpl < 0) { + printf("H5Pcreate failed\n"); + TEST_ERROR; + } + + if (dense_to_compact) { + if (H5Pset_link_phase_change(gcpl, 2, 2) < 0) { + printf("H5Pset_link_phase_change failed for dense to compact.\n"); + TEST_ERROR; + } + } + else { + if (H5Pset_link_phase_change(gcpl, 1, 1) < 0) { + printf("H5Pset_attr_phase_change failed for compact to dense.\n"); + TEST_ERROR; + } + } + + esnprintf(name, sizeof(name), "/group-%u", which); + if ((g = H5Gcreate2(s->file, name, H5P_DEFAULT, gcpl, H5P_DEFAULT)) < 0) { + printf("H5Gcreate2 failed\n"); + TEST_ERROR; + } + + if (H5Gget_info(g, &group_info) < 0) { + printf("H5Gget_info failed\n"); + TEST_ERROR; + } + + /* The storage type should always be compact when a group is created. */ + if (group_info.storage_type != H5G_STORAGE_TYPE_COMPACT) { + printf("New-style group link storage test:. \n"); + printf(" still be compact after group creation. \n"); + TEST_ERROR; + } + + if (H5Pclose(gcpl) < 0) { + printf("H5Pclose failed\n"); + TEST_ERROR; + } + + return g; + +error: + + H5E_BEGIN_TRY + { + H5Pclose(gcpl); + } + H5E_END_TRY; + + return -1; +} + +/*------------------------------------------------------------------------- + * Function: close_group_id + * + * Purpose: Verify is a group is closed successfully. + * + * Parameters: hid_t g + * The ID of the group to be closed. + * + * Return: Success: true + * Failure: false + * + * Note: This is used by the link storage transit functions. + *------------------------------------------------------------------------- + */ + +static bool +close_group_id(hid_t g) +{ + + if (H5Gclose(g) < 0) { + printf("H5Gclose failed\n"); + TEST_ERROR; + } + + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: create_group + * + * Purpose: Create a group + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * This is used to generate the group name. + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the main() function. + *------------------------------------------------------------------------- + */ + +static bool +create_group(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + hid_t g = H5I_INVALID_HID; + H5G_info_t group_info; + + if (which >= s->nsteps) { + printf("Number of created groups is out of bounds\n"); + TEST_ERROR; + } + + esnprintf(name, sizeof(name), "/group-%u", which); + if ((g = H5Gcreate2(s->file, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + printf("H5Gcreate2 failed\n"); + TEST_ERROR; + } + + if (H5Gget_info(g, &group_info) < 0) { + printf("H5Gget_info failed\n"); + TEST_ERROR; + } + + if (s->old_style_grp) { + if (group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) { + printf("Old-styled group test: but the group is not in old-style. \n"); + TEST_ERROR; + } + dbgf(2, "Writer: group is created with the old-style.\n"); + } + else { + if (group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) { + printf("The created group should NOT be in old-style . \n"); + TEST_ERROR; + } + dbgf(2, "Writer: group is created with the new-style.\n"); + } + + if (H5Gclose(g) < 0) { + printf("H5Gclose failed\n"); + TEST_ERROR; + } + + return true; + +error: + + H5E_BEGIN_TRY + { + H5Gclose(g); + } + H5E_END_TRY; + + return false; +} + +/*------------------------------------------------------------------------- + * Function: delete_one_link + * + * Purpose: Delete a link(either hard/soft) in group operation tests. + * according to the group test pattern. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t obj_id + * The HDF5 object ID that the deleted link is attached to. + * + * const char *name + * The name of the link to be deleted. + * + * short link_storage + * <=0: link storage is ignored. + * 1: link storage should be compact after link deletion.. + * >1: link storage should be dense after link deletion. + * + * unsigned int which + * The number of iterations for group creation + * + * + * Return: Success: true + * Failure: false + * + * Note: This is used by delete_groups() and delete_links() functions. + *------------------------------------------------------------------------- + */ + +static bool +delete_one_link(state_t *s, hid_t obj_id, const char *name, short link_storage, unsigned int which) +{ + + H5G_info_t group_info; + + if (which >= s->nsteps) { + printf("Number of created groups is out of bounds\n"); + TEST_ERROR; + } + + if (H5Ldelete(obj_id, name, H5P_DEFAULT) < 0) { + printf("H5Ldelete failed\n"); + TEST_ERROR; + } + + if (link_storage > 0) { + + if (s->old_style_grp) { + printf("Old style group doesn't support the indexed storage.\n"); + TEST_ERROR; + } + + if (H5Gget_info(obj_id, &group_info) < 0) { + printf("H5Gget_info failed\n"); + TEST_ERROR; + } + + if (link_storage == 1) { + + if (group_info.storage_type != H5G_STORAGE_TYPE_COMPACT) { + printf("The group link storage should be compact. \n"); + TEST_ERROR; + } + } + else { + + if (group_info.storage_type != H5G_STORAGE_TYPE_DENSE) { + printf("The group link storage should be dense. \n"); + TEST_ERROR; + } + } + } + + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: delete_group + * + * Purpose: Delete a group and carry out group operations(add,delete etc.) + * according to the group operation test pattern. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * This is used to generate the group name + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the group_operations() function. + *------------------------------------------------------------------------- + */ + +static bool +delete_group(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + bool ret_value = create_group(s, which); + if (ret_value == true) { + esnprintf(name, sizeof(name), "/group-%u", which); + ret_value = delete_one_link(s, s->file, name, 0, which); + } + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: move_one_group + * + * Purpose: A helper function used by the move_group operation. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t obj_id + * ID of the object this group is attached to + * + * const char *name + * The original group name + * + * const char *newname + * The new group name + * + * unsigned int which + * The number of iterations for group creation + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the move_group() function. + *------------------------------------------------------------------------- + */ + +static bool +move_one_group(state_t *s, hid_t obj_id, const char *name, const char *newname, unsigned int which) +{ + + if (which >= s->nsteps) { + printf("Number of created groups is out of bounds\n"); + TEST_ERROR; + } + + if (H5Lmove(obj_id, name, obj_id, newname, H5P_DEFAULT, H5P_DEFAULT) < 0) { + printf("H5Ldelete failed\n"); + TEST_ERROR; + } + + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: move_group + * + * Purpose: Move a group to another group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * used to generate the group name. + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the group_operations() function. + *------------------------------------------------------------------------- + */ + +static bool +move_group(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + char new_name[sizeof("/new-group-9999999999")]; + bool ret_value = create_group(s, which); + if (ret_value == true) { + esnprintf(name, sizeof(name), "/group-%u", which); + esnprintf(new_name, sizeof(new_name), "/new-group-%u", which); + ret_value = move_one_group(s, s->file, name, new_name, which); + } + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: insert_one_link + * + * Purpose: A helper function used to attach a link to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * hid_t obj_id + * ID of the object this link is attached to + * + * const char *name + * The name of the target object used by creating links + * + * const char *newname + * The name of the linked objects + * + * bool is_hard + * true if inserting a hard link + * false if inserting a soft link + * + * short link_storage + * <=0: link storage is ignored. + * 1: link storage should be compact. + * >1: link storage should be dense. + + * unsigned int which + * The number of iterations for group creation + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the insert_links and link storage transit functions. + * For link storage, we test at both the writer and the reader. + *------------------------------------------------------------------------- +*/ + +static bool +insert_one_link(state_t *s, hid_t obj_id, const char *name, const char *newname, bool is_hard, + short link_storage, unsigned int which) +{ + + H5G_info_t group_info; + + if (which >= s->nsteps) { + printf("Number of created groups is out of bounds\n"); + TEST_ERROR; + } + + /* For storage transit and insert_links cases, we + * create links in different style, just add a little + * variation of the tests.*/ + if (is_hard) { + if (link_storage > 0) { + if (H5Lcreate_hard(s->file, name, obj_id, newname, H5P_DEFAULT, H5P_DEFAULT) < 0) { + printf("H5Lcreate_hard failed\n"); + TEST_ERROR; + } + } + else { + if (H5Lcreate_hard(obj_id, name, obj_id, newname, H5P_DEFAULT, H5P_DEFAULT) < 0) { + printf("H5Lcreate_hard failed\n"); + TEST_ERROR; + } + } + } + else { + if (link_storage > 0) { + if (H5Lcreate_soft("/", obj_id, newname, H5P_DEFAULT, H5P_DEFAULT) < 0) { + printf("H5Lcreate_soft failed\n"); + TEST_ERROR; + } + } + else { + if (H5Lcreate_soft(name, obj_id, newname, H5P_DEFAULT, H5P_DEFAULT) < 0) { + printf("H5Lcreate_soft failed.\n"); + TEST_ERROR; + } + } + } + + if (link_storage > 0) { + + if (s->old_style_grp) { + printf("Old style group doesn't support dense or compact storage.\n"); + TEST_ERROR; + } + + if (H5Gget_info(obj_id, &group_info) < 0) { + printf("H5Gget_info failed\n"); + TEST_ERROR; + } + + if (link_storage == 1) { + if (group_info.storage_type != H5G_STORAGE_TYPE_COMPACT) { + printf("The group link storage should be compact. \n"); + TEST_ERROR; + } + } + else { + if (group_info.storage_type != H5G_STORAGE_TYPE_DENSE) { + printf("The group link storage should be dense. \n"); + TEST_ERROR; + } + } + } + + return true; + +error: + return false; +} + +/*------------------------------------------------------------------------- + * Function: insert_links + * + * Purpose: create links with a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations + * used to generate the group name. + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the group_operations() function. + *------------------------------------------------------------------------- + */ + +static bool +insert_links(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + char hd_name[sizeof("/hd-group-9999999999")]; + char st_name[sizeof("/st-group-9999999999")]; + + bool ret_value = create_group(s, which); + if (ret_value == true) { + esnprintf(name, sizeof(name), "/group-%u", which); + esnprintf(hd_name, sizeof(hd_name), "/hd-group-%u", which); + esnprintf(st_name, sizeof(st_name), "/st-group-%u", which); + ret_value = insert_one_link(s, s->file, name, hd_name, true, 0, which); + if (ret_value == true) + ret_value = insert_one_link(s, s->file, name, st_name, false, 0, which); + } + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: delete_links + * + * Purpose: create links with a group and then delete them successfully. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations + * used to generate the group name. + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the group_operations() function. + *------------------------------------------------------------------------- + */ + +static bool +delete_links(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + char hd_name[sizeof("/hd-group-9999999999")]; + char st_name[sizeof("/st-group-9999999999")]; + + bool ret_value = insert_links(s, which); + if (ret_value == true) { + esnprintf(name, sizeof(name), "/group-%u", which); + esnprintf(hd_name, sizeof(hd_name), "/hd-group-%u", which); + esnprintf(st_name, sizeof(st_name), "/st-group-%u", which); + ret_value = delete_one_link(s, s->file, hd_name, 0, which); + if (ret_value == true) + ret_value = delete_one_link(s, s->file, st_name, 0, which); + } + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: transit_storage_compact_to_dense + * + * Purpose: Add links so that the link storage transits from + * compact to dense. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations used to generate the group name. + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the group_operations() function. + *------------------------------------------------------------------------- + */ + +static bool +transit_storage_compact_to_dense(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + char hd_name[sizeof("/hd-group-9999999999")]; + char st_name[sizeof("/st-group-9999999999")]; + + hid_t g = create_group_id(s, which, false); + if (g < 0) { + printf("create_group_id failed\n"); + TEST_ERROR; + } + + /* First insert a hard link, compact storage. */ + esnprintf(name, sizeof(name), "/group-%u", which); + esnprintf(hd_name, sizeof(hd_name), "hd-group-%u", which); + if (insert_one_link(s, g, name, hd_name, true, 1, which) == false) { + printf("insert_one_link for compact storage failed\n"); + TEST_ERROR; + } + + /* Then insert a soft link, the storage becomes dense. */ + esnprintf(st_name, sizeof(st_name), "st-group-%u", which); + if (insert_one_link(s, g, name, st_name, false, 2, which) == false) { + printf("insert_one_link for dense storage failed\n"); + TEST_ERROR; + } + + if (close_group_id(g) == false) { + printf("insert_one_link for dense storage failed\n"); + TEST_ERROR; + } + + return true; + +error: + H5E_BEGIN_TRY + { + H5Gclose(g); + } + H5E_END_TRY; + + return false; +} + +/*------------------------------------------------------------------------- + * Function: transit_storage_dense_to_compact + * + * Purpose: Add or delete links so that the link storage transits from + * compact to dense then to compact. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations used to generate the group name. + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the group_operations() function. + *------------------------------------------------------------------------- + */ + +static bool +transit_storage_dense_to_compact(state_t *s, unsigned int which) +{ + + char name[sizeof("/group-9999999999")]; + char hd_name[sizeof("/hd-group-9999999999")]; + char st_name[sizeof("st-group-9999999999")]; + char st2_name[sizeof("st2-group-9999999999")]; + + hid_t g = create_group_id(s, which, true); + if (g < 0) { + printf("create_group_id failed\n"); + TEST_ERROR; + } + + /* Insert a link, storage is compact. */ + esnprintf(name, sizeof(name), "/group-%u", which); + esnprintf(hd_name, sizeof(hd_name), "hd-group-%u", which); + if (insert_one_link(s, g, name, hd_name, true, 1, which) == false) { + printf("insert_one_link for compact storage failed\n"); + TEST_ERROR; + } + + /* Insert a link, storage is still compact. */ + esnprintf(st_name, sizeof(st_name), "st-group-%u", which); + if (insert_one_link(s, g, name, st_name, false, 1, which) == false) { + printf("insert_one_link for compact storage failed\n"); + TEST_ERROR; + } + + /* Insert a link, storage becomes dense. */ + esnprintf(st2_name, sizeof(st2_name), "st2-group-%u", which); + if (insert_one_link(s, g, name, st2_name, false, 2, which) == false) { + printf("insert_one_link for dense storage failed\n"); + TEST_ERROR; + } + + /* Delete a link, storage is still dense */ + if (delete_one_link(s, g, st_name, 2, which) == false) { + printf("delete_one_link for dense storage failed\n"); + TEST_ERROR; + } + + /* Delete another link, storage becomes compact */ + if (delete_one_link(s, g, st2_name, 1, which) == false) { + printf("delete_one_link for compact storage failed\n"); + TEST_ERROR; + } + + if (close_group_id(g) == false) { + printf("insert_one_link for dense storage failed\n"); + TEST_ERROR; + } + + return true; + +error: + H5E_BEGIN_TRY + { + H5Gclose(g); + } + H5E_END_TRY; + + return false; +} + +/*------------------------------------------------------------------------- + * Function: group_operations + * + * Purpose: Carry out group and attribute operations(add,delete etc.) + * according to the group operation and attribute test patterns. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the main() function. The check of attribute + * operations is inside the write_group() function. + *------------------------------------------------------------------------- + */ +static bool +group_operations(state_t *s, unsigned int which) +{ + + bool ret_value = false; + char test_pattern = s->grp_op_pattern; + + switch (test_pattern) { + case 'c': + ret_value = create_group(s, which); + break; + case 'd': + ret_value = delete_group(s, which); + break; + case 'm': + ret_value = move_group(s, which); + break; + case 'i': + ret_value = insert_links(s, which); + break; + case 'D': + ret_value = delete_links(s, which); + break; + case 't': + ret_value = transit_storage_compact_to_dense(s, which); + break; + case 'T': + ret_value = transit_storage_dense_to_compact(s, which); + break; + case ' ': + default: + ret_value = write_group(s, which); + break; + } + return ret_value; +} + +static unsigned int grp_counter = 0; + +/*------------------------------------------------------------------------- + * Function: UI_Pow + * + * Purpose: Helper function to obtain the power 'n' of + * an unsigned integer 'x' + * Similar to pow(x,y) but for an unsigned integer. + * + * Parameters: unsigned int x + * unsigned int n + * + * Return: Return an unsigned integer of value of pow(x,n) + * Note: If the returned value is > 2^32-1, an overflow + * may occur. For our testing purpose, this may never happen. + * + *------------------------------------------------------------------------- + */ + +static unsigned int +UI_Pow(unsigned int x, unsigned int n) +{ + unsigned int i; /* Variable used in loop grp_counter */ + unsigned int number = 1; + + for (i = 0; i < n; ++i) + number *= x; + + return (number); +} + +/*------------------------------------------------------------------------- + * Function: obtain_tree_level_elems + * + * Purpose: Helper function to obtain the maximum number of elements + * at one level. + * + * Parameters: unsigned int total_ele + * The total number of elements of a tree(excluding the root) + * + * unsigned int level + * The number of nested levels + * (If every element of the tree is under the root, + * the level is 0.) + * + * Return: Return the maximum number of elements at one level + * + * Example: If the total number of elements is 6 and level is 1, + * the maximum number of elements is 2.The tree is + * a perfectly balanced tree. + * Such as: + * 0 + * 1 2 + * 3 4 5 6 + * + * If the total number of elements is 5 and level is 1, + * the maximum number of elements is still 2. The + * tree is not balanced, there is no element on the + * right-most leaf but the level is still 1. + * Such as: + * 0 + * 1 2 + * 3 4 5 + * + *------------------------------------------------------------------------- + */ + +static unsigned int +obtain_tree_level_elems(unsigned int total_ele, unsigned int level) +{ + + assert(level <= total_ele); + /* if every element is under the root, just return the total number of elements. */ + if (level == 0) + return total_ele; + else { + unsigned int test_elems_level = 0; + unsigned total = 0; + unsigned int i = 1; + /* Obtain the maximum number of elements for a level with the brutal force way. */ + while (total < total_ele) { + test_elems_level++; + total = 0; + for (i = 1; i <= level + 1; i++) + total += UI_Pow(test_elems_level, i); + } + if (total == total_ele) + dbgf(2, "Perfectly match: Number of elements per level is %u\n", test_elems_level); + return test_elems_level; + } +} + +/*------------------------------------------------------------------------- + * Function: gen_tree_struct + * + * Purpose: Generate the nested groups + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file + * and some VFD SWMR configuration parameters + * + * unsigned int level + * The number of nested levels +1 + * (Note: If every element of the tree is under the root, + * the level is 1 in this function.) + * unsigned num_elems_per_level + * The maximum number of element in a level + * hid_t group_id + * The ID of the parent group + * + * Return: Success: true + * Failure: false + */ +static bool +gen_tree_struct(state_t *s, unsigned int level, unsigned ne_per_level, hid_t pgrp_id) +{ + + char name[sizeof("group-9999999999")]; + unsigned int i; + hid_t grp_id; + bool result = true; + H5G_info_t group_info; + struct timespec start_time, end_time; + double temp_time; + + if (level > 0 && grp_counter < s->nsteps) { + + for (i = 0; i < ne_per_level; i++) { + + /* For each i a group is created. + Use grp_counter to generate the group name. + printf("id: %u,level: %u, index: %u\n",id,level,i); + */ + esnprintf(name, sizeof(name), "group-%u", grp_counter); + if (grp_counter == s->nsteps) + break; + + dbgf(2, "writer in nested group: step %d\n", grp_counter); + if (s->gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) { + fprintf(stderr, "HDclock_gettime failed"); + TEST_ERROR; + } + } + + if ((grp_id = H5Gcreate2(pgrp_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + printf("H5Gcreate2 failed\n"); + TEST_ERROR; + } + + if (s->gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) { + + fprintf(stderr, "HDclock_gettime failed"); + + TEST_ERROR; + } + + temp_time = TIME_PASSED(start_time, end_time); + if (temp_time < s->min_gc_time) + s->min_gc_time = temp_time; + if (temp_time > s->max_gc_time) + s->max_gc_time = temp_time; + s->total_gc_time += temp_time; + } + + /* Just check the first group information. */ + if (grp_counter == 0) { + if (H5Gget_info(grp_id, &group_info) < 0) { + printf("H5Gget_info failed\n"); + TEST_ERROR; + } + + if (s->old_style_grp) { + if (group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) { + printf("Old-styled group test: but the group is not in old-style. \n"); + TEST_ERROR; + } + dbgf(2, "Writer: group is created with the old-style.\n"); + } + else { + if (group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) { + printf("The created group should NOT be in old-style . \n"); + TEST_ERROR; + } + dbgf(2, "Writer: group is created with the new-style.\n"); + } + } + + /* Then carry out the attribute operation. */ + if (s->asteps != 0 && grp_counter % s->asteps == 0) + result = add_default_group_attr(s, grp_id, grp_counter); + + if (result == false) { + printf("Cannot create group attributes. \n"); + TEST_ERROR; + } + grp_counter++; + + /* Generate groups in the next level */ + result = gen_tree_struct(s, level - 1, ne_per_level, grp_id); + if (result == false) { + printf("Cannot create nested groups. \n"); + TEST_ERROR; + } + + /* close the group ID. No problem. */ + if (H5Gclose(grp_id) < 0) { + printf("H5Gclose failed. \n"); + TEST_ERROR; + } + } + } + + return true; + +error: + + H5E_BEGIN_TRY + { + H5Gclose(grp_id); + } + H5E_END_TRY; + + return false; +} + +int +main(int argc, char **argv) +{ + hid_t fapl = H5I_INVALID_HID, fcpl = H5I_INVALID_HID; + unsigned step; + bool writer = false; + state_t s; + const char * personality; + H5F_vfd_swmr_config_t config; + bool wg_ret = false; + struct timespec start_time, end_time; + unsigned int num_elems_per_level; + + if (!state_init(&s, argc, argv)) { + printf("state_init failed\n"); + TEST_ERROR; + } + + personality = HDstrstr(s.progname, "vfd_swmr_gperf_"); + + if (personality != NULL && HDstrcmp(personality, "vfd_swmr_gperf_writer") == 0) + writer = true; + else if (personality != NULL && HDstrcmp(personality, "vfd_swmr_gperf_reader") == 0) + writer = false; + else { + printf("unknown personality, expected vfd_swmr_gperf_{reader,writer}\n"); + TEST_ERROR; + } + + if (writer == false) { + printf("Reader is skipped for the performance tests.\n"); + return EXIT_SUCCESS; + } + + /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ + init_vfd_swmr_config(&config, s.tick_len, s.max_lag, writer, FALSE, 128, "./group-shadow"); + + /* If old-style option is chosen, use the earliest file format(H5F_LIBVER_EARLIEST) + * as the second parameter of H5Pset_libver_bound() that is called by + * vfd_swmr_create_fapl. Otherwise, the latest file format(H5F_LIBVER_LATEST) + * should be used as the second parameter of H5Pset_libver_bound(). + * Also pass the use_vfd_swmr, only_meta_page, page buffer size, config to vfd_swmr_create_fapl().*/ + if ((fapl = vfd_swmr_create_fapl(!s.old_style_grp, s.use_vfd_swmr, true, s.pbs, &config)) < 0) { + printf("vfd_swmr_create_fapl failed\n"); + TEST_ERROR; + } + + /* Set fs_strategy (file space strategy) and fs_page_size (file space page size) */ + if ((fcpl = vfd_swmr_create_fcpl(H5F_FSPACE_STRATEGY_PAGE, s.ps)) < 0) { + HDprintf("vfd_swmr_create_fcpl() failed"); + TEST_ERROR; + } + + if (s.nglevels > 0) { + if (s.grp_op_pattern != ' ' || s.at_pattern != ' ') { + printf("For nested group creation test, only the default option is supported.\n"); + printf("Please re-run the tests with the appopriate option.\n"); + TEST_ERROR; + } + } + + if (s.gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) { + fprintf(stderr, "HDclock_gettime failed"); + TEST_ERROR; + } + } + + s.file = H5Fcreate(s.filename, H5F_ACC_TRUNC, fcpl, fapl); + + if (s.gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) { + fprintf(stderr, "HDclock_gettime failed"); + TEST_ERROR; + } + + s.fo_total_time = TIME_PASSED(start_time, end_time); + } + + if (s.file < 0) { + printf("H5Fcreate failed\n"); + TEST_ERROR; + } + + /* If generating nested groups, calculate the maximum number of + elements per level. */ + if (s.nglevels > 0) + num_elems_per_level = obtain_tree_level_elems(s.nsteps, s.nglevels); + + if (s.gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) { + fprintf(stderr, "HDclock_gettime failed"); + TEST_ERROR; + } + } + + /* If generating nested groups */ + if (s.nglevels > 0) { + + /* for the recursive call, the groups under the root is treated as one level */ + wg_ret = gen_tree_struct(&s, s.nglevels + 1, num_elems_per_level, s.file); + if (wg_ret == false) { + printf("write nested group failed at group counter %u\n", grp_counter); + TEST_ERROR; + } + } + else { + for (step = 0; step < s.nsteps; step++) { + + dbgf(2, "writer: step %d\n", step); + wg_ret = group_operations(&s, step); + if (wg_ret == false) { + printf("write_group failed at step %d\n", step); + TEST_ERROR; + } + } + } + + if (s.gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) { + + fprintf(stderr, "HDclock_gettime failed"); + TEST_ERROR; + } + + s.total_time = TIME_PASSED(start_time, end_time); + s.mean_time = s.total_time / s.nsteps; + s.mean_gc_time = s.total_gc_time / s.nsteps; + } + + if (H5Pclose(fapl) < 0) { + printf("H5Pclose failed\n"); + TEST_ERROR; + } + + if (H5Pclose(fcpl) < 0) { + printf("H5Pclose failed\n"); + TEST_ERROR; + } + + if (H5Sclose(s.one_by_one_sid) < 0) { + printf("H5Sclose failed\n"); + TEST_ERROR; + } + + if (s.gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) { + + fprintf(stderr, "HDclock_gettime failed"); + + TEST_ERROR; + } + } + + if (H5Fclose(s.file) < 0) { + printf("H5Fclose failed\n"); + TEST_ERROR; + } + + if (s.gperf) { + + if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) { + + fprintf(stderr, "HDclock_gettime failed"); + + TEST_ERROR; + } + + s.fc_total_time = TIME_PASSED(start_time, end_time); + } + + /* Performance statistics summary */ + if (s.gperf) { + + if (verbosity != 0) { + + fprintf(stdout, "\nPerformance Test Configuration: "); + if (s.use_vfd_swmr) + fprintf(stdout, " Using VFD SWMR \n"); + else + fprintf(stdout, " Not using VFD SWMR \n"); + + if (s.old_style_grp) + fprintf(stdout, " Groups: Created via the earlist file format(old-style) \n"); + else + fprintf(stdout, " Groups: Created via the latest file format(new-style) \n"); + + fprintf(stdout, "\n"); + + fprintf(stdout, "The length of a tick = %u\n", s.tick_len); + fprintf(stdout, "The maximum expected lag(in ticks)= %u\n", s.max_lag); + fprintf(stdout, "The page size(in bytes) = %u\n", s.ps); + fprintf(stdout, "The page buffer size(in bytes) = %u\n", s.pbs); + fprintf(stdout, "\n"); + fprintf(stdout, "Number of groups = %u\n", s.nsteps); + fprintf(stdout, "Group Nested levels = %u\n", s.nglevels); + fprintf(stdout, "Number of attributes = %u\n", s.num_attrs); + fprintf(stdout, "Number of element per attribute = 1\n"); + if (s.vlstr_test) + fprintf(stdout, "Attribute datatype is variable length string. \n"); + else if (s.filetype == H5T_STD_U32BE) + fprintf(stdout, "Attribute datatype is big-endian unsigned 32-bit integer.\n"); + else + fprintf(stdout, "Attribute datatype is native unsigned 32-bit integer.\n"); + + fprintf(stdout, "\n"); + fprintf(stdout, + "(If the nested level is 0, all the groups are created directly under the root.)\n\n"); + fprintf(stdout, "group creation maximum time =%lf\n", s.max_gc_time); + fprintf(stdout, "group creation minimum time =%lf\n", s.min_gc_time); + } + + fprintf(stdout, "group creation total time = %lf\n", s.total_gc_time); + fprintf(stdout, "group creation mean time(per group) = %lf\n", s.mean_gc_time); + fprintf(stdout, "group creation and attributes generation total time = %lf\n", s.total_time); + fprintf(stdout, "group creation and attributes generation mean time(per group) = %lf\n", s.mean_time); + fprintf(stdout, "H5Fcreate time = %lf\n", s.fo_total_time); + fprintf(stdout, "H5Fclose time = %lf\n", s.fc_total_time); + } + + return EXIT_SUCCESS; + +error: + H5E_BEGIN_TRY + { + H5Pclose(fapl); + H5Pclose(fcpl); + H5Sclose(s.one_by_one_sid); + H5Fclose(s.file); + } + H5E_END_TRY; + + return EXIT_FAILURE; +} + +#else /* H5_HAVE_WIN32_API */ + +int +main(void) +{ + HDfprintf(stderr, "Non-POSIX platform. Skipping.\n"); + return EXIT_SUCCESS; +} /* end main() */ + +#endif /* H5_HAVE_WIN32_API */ diff --git a/test/vfd_swmr_group_writer.c b/test/vfd_swmr_group_writer.c index f491353..c240ee5 100644 --- a/test/vfd_swmr_group_writer.c +++ b/test/vfd_swmr_group_writer.c @@ -153,8 +153,10 @@ state_init(state_t *s, int argc, char **argv) esnprintf(s->progname, sizeof(s->progname), "%s", tfile); - if (tfile) + if (tfile) { HDfree(tfile); + tfile = NULL; + } while ((ch = getopt(argc, argv, "SGa:bc:n:Nqu:A:O:")) != -1) { switch (ch) { @@ -3031,8 +3033,8 @@ verify_group(state_t *s, unsigned int which) esnprintf(name, sizeof(name), "/group-%u", which); - if ((g = H5Gopen(s->file, name, H5P_DEFAULT)) < 0) { - HDprintf("H5Gopen failed\n"); + if ((g = H5Gopen2(s->file, name, H5P_DEFAULT)) < 0) { + HDprintf("H5Gopen2 failed\n"); TEST_ERROR; } @@ -4078,8 +4080,8 @@ vrfy_create_group(state_t *s, unsigned int which) esnprintf(name, sizeof(name), "/group-%u", which); - if ((g = H5Gopen(s->file, name, H5P_DEFAULT)) < 0) { - HDprintf("H5Gopen failed\n"); + if ((g = H5Gopen2(s->file, name, H5P_DEFAULT)) < 0) { + HDprintf("H5Gopen2 failed\n"); TEST_ERROR; } @@ -4195,8 +4197,8 @@ vrfy_create_group_id(state_t *s, unsigned int which, bool dense_to_compact) esnprintf(name, sizeof(name), "/group-%u", which); - if ((g = H5Gopen(s->file, name, H5P_DEFAULT)) < 0) { - HDprintf("H5Gopen failed\n"); + if ((g = H5Gopen2(s->file, name, H5P_DEFAULT)) < 0) { + HDprintf("H5Gopen2 failed\n"); TEST_ERROR; } @@ -4569,8 +4571,8 @@ vrfy_move_one_group(state_t *s, hid_t obj_id, const char *name, const char *newn TEST_ERROR; } - if ((g = H5Gopen(obj_id, newname, H5P_DEFAULT)) < 0) { - HDprintf("H5Gopen failed\n"); + if ((g = H5Gopen2(obj_id, newname, H5P_DEFAULT)) < 0) { + HDprintf("H5Gopen2 failed\n"); TEST_ERROR; } @@ -4985,7 +4987,7 @@ main(int argc, char **argv) } /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 7, writer, FALSE, 128, "./group-shadow"); + init_vfd_swmr_config(&config, 4, 7, writer, TRUE, 128, "./group-shadow"); /* If old-style option is chosen, use the earliest file format(H5F_LIBVER_EARLIEST) * as the second parameter of H5Pset_libver_bound() that is called by diff --git a/test/vfd_swmr_reader.c b/test/vfd_swmr_reader.c index cc4d918..6265cae 100644 --- a/test/vfd_swmr_reader.c +++ b/test/vfd_swmr_reader.c @@ -320,7 +320,7 @@ read_records(const char *filename, hbool_t verbose, FILE *verbose_file, unsigned } /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, FALSE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, FALSE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(FALSE, TRUE, FALSE, 4096, config)) < 0) { diff --git a/test/vfd_swmr_remove_reader.c b/test/vfd_swmr_remove_reader.c index b729ee4..4389b05 100644 --- a/test/vfd_swmr_remove_reader.c +++ b/test/vfd_swmr_remove_reader.c @@ -304,7 +304,7 @@ read_records(const char *filename, unsigned verbose, unsigned long nseconds, uns goto error; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, FALSE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, FALSE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(FALSE, TRUE, FALSE, 4096, config)) < 0) { diff --git a/test/vfd_swmr_remove_writer.c b/test/vfd_swmr_remove_writer.c index b8b1303..8df8fa8 100644 --- a/test/vfd_swmr_remove_writer.c +++ b/test/vfd_swmr_remove_writer.c @@ -87,7 +87,7 @@ open_skeleton(const char *filename, unsigned verbose, unsigned old H5_ATTR_UNUSE goto error; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, TRUE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, TRUE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(TRUE, TRUE, FALSE, 4096, config)) < 0) diff --git a/test/vfd_swmr_sparse_reader.c b/test/vfd_swmr_sparse_reader.c index a39b357..943c375 100644 --- a/test/vfd_swmr_sparse_reader.c +++ b/test/vfd_swmr_sparse_reader.c @@ -208,7 +208,7 @@ read_records(const char *filename, unsigned verbose, unsigned long nrecords, uns goto error; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, FALSE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, FALSE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(FALSE, TRUE, FALSE, 4096, config)) < 0) { diff --git a/test/vfd_swmr_sparse_writer.c b/test/vfd_swmr_sparse_writer.c index 53b6ec9..56d19f3 100644 --- a/test/vfd_swmr_sparse_writer.c +++ b/test/vfd_swmr_sparse_writer.c @@ -87,7 +87,7 @@ open_skeleton(const char *filename, unsigned verbose) goto error; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, TRUE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, TRUE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(TRUE, TRUE, FALSE, 4096, config)) < 0) diff --git a/test/vfd_swmr_vlstr_reader.c b/test/vfd_swmr_vlstr_reader.c index 5a112cd..fa9d7b4 100644 --- a/test/vfd_swmr_vlstr_reader.c +++ b/test/vfd_swmr_vlstr_reader.c @@ -116,7 +116,7 @@ main(int argc, char **argv) errx(EXIT_FAILURE, "unexpected command-line arguments"); /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 7, false, FALSE, 128, "./vlstr-shadow"); + init_vfd_swmr_config(&config, 4, 7, false, TRUE, 128, "./vlstr-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ fapl = vfd_swmr_create_fapl(true, use_vfd_swmr, sel == TEST_OOB, 4096, &config); @@ -140,7 +140,7 @@ main(int argc, char **argv) if (fid == badhid) errx(EXIT_FAILURE, "H5Fcreate"); - /* content 1 seq 1 short + /* content 0 seq 1 short * content 1 seq 1 long long long long long long long long * content 1 seq 1 medium medium medium */ @@ -178,6 +178,11 @@ main(int argc, char **argv) dbgf(2, ": read which %d seq %d tail %s\n", scanned_content.which, scanned_content.seq, scanned_content.tail); H5Dclose(dset[which]); + + if (content[which] != NULL) { + HDfree(content[which]); + content[which] = NULL; + } } if (caught_out_of_bounds) diff --git a/test/vfd_swmr_vlstr_writer.c b/test/vfd_swmr_vlstr_writer.c index f338428..4f7376e 100644 --- a/test/vfd_swmr_vlstr_writer.c +++ b/test/vfd_swmr_vlstr_writer.c @@ -185,7 +185,7 @@ main(int argc, char **argv) errx(EXIT_FAILURE, "unexpected command-line arguments"); /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&config, 4, 7, true, FALSE, 128, "./vlstr-shadow"); + init_vfd_swmr_config(&config, 4, 7, true, TRUE, 128, "./vlstr-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ fapl = vfd_swmr_create_fapl(true, use_vfd_swmr, sel == TEST_OOB, 4096, &config); diff --git a/test/vfd_swmr_writer.c b/test/vfd_swmr_writer.c index c5b62c8..4693554 100644 --- a/test/vfd_swmr_writer.c +++ b/test/vfd_swmr_writer.c @@ -89,7 +89,7 @@ open_skeleton(const char *filename, hbool_t verbose, FILE *verbose_file, unsigne return -1; /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(config, 4, 5, TRUE, FALSE, 128, "./rw-shadow"); + init_vfd_swmr_config(config, 4, 5, TRUE, TRUE, 128, "./rw-shadow"); /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ if ((fapl = vfd_swmr_create_fapl(TRUE, TRUE, FALSE, 4096, config)) < 0) diff --git a/test/vfd_swmr_zoo_writer.c b/test/vfd_swmr_zoo_writer.c index d89fd16..13794d9 100644 --- a/test/vfd_swmr_zoo_writer.c +++ b/test/vfd_swmr_zoo_writer.c @@ -474,7 +474,7 @@ main(int argc, char **argv) parse_command_line_options(argc, argv); /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ - init_vfd_swmr_config(&vfd_swmr_config, TICK_LEN, 7, writer, FALSE, 128, "./zoo-shadow"); + init_vfd_swmr_config(&vfd_swmr_config, TICK_LEN, 7, writer, TRUE, 128, "./zoo-shadow"); /* ? turn off use latest format argument via 1st argument? since later on it reset to early format */ /* use_latest_format, use_vfd_swmr, only_meta_page, page_buf_size, config */ |