321 lines
9.1 KiB
C
321 lines
9.1 KiB
C
/*
|
|
* Copyright by The HDF Group.
|
|
* Copyright by the Board of Trustees of the University of Illinois.
|
|
* All rights reserved.
|
|
*
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including
|
|
* terms governing use, modification, and redistribution, is contained in
|
|
* the COPYING file, which can be found at the root of the source code
|
|
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.
|
|
* If you do not have access to either file, you may request a copy from
|
|
* help@hdfgroup.org.
|
|
*/
|
|
|
|
#include <err.h>
|
|
#include <time.h> /* nanosleep(2) */
|
|
#include <unistd.h> /* getopt(3) */
|
|
|
|
#define H5C_FRIEND /*suppress error about including H5Cpkg */
|
|
#define H5F_FRIEND /*suppress error about including H5Fpkg */
|
|
|
|
#include "hdf5.h"
|
|
|
|
#include "H5Cpkg.h"
|
|
#include "H5Fpkg.h"
|
|
// #include "H5Iprivate.h"
|
|
#include "H5HGprivate.h"
|
|
#include "H5VLprivate.h"
|
|
|
|
#include "testhdf5.h"
|
|
#include "vfd_swmr_common.h"
|
|
|
|
enum _step {
|
|
CREATE = 0
|
|
, LENGTHEN
|
|
, SHORTEN
|
|
, DELETE
|
|
, NSTEPS
|
|
} step_t;
|
|
|
|
static const hid_t badhid = H5I_INVALID_HID; // abbreviate
|
|
static bool caught_out_of_bounds = false;
|
|
|
|
static void
|
|
write_vl_dset(hid_t dset, hid_t type, hid_t space, char *data)
|
|
{
|
|
if (H5Dwrite(dset, type, space, space, H5P_DEFAULT, &data) < 0)
|
|
errx(EXIT_FAILURE, "%s: H5Dwrite", __func__);
|
|
if (H5Dflush(dset) < 0)
|
|
errx(EXIT_FAILURE, "%s: H5Dflush", __func__);
|
|
}
|
|
|
|
#if 0
|
|
static hid_t
|
|
initialize_dset(hid_t file, hid_t type, hid_t space, const char *name,
|
|
void *data)
|
|
{
|
|
hid_t dset;
|
|
|
|
dset = H5Dcreate2(file, name, type, space, H5P_DEFAULT, H5P_DEFAULT,
|
|
H5P_DEFAULT);
|
|
|
|
if (dset == badhid)
|
|
errx(EXIT_FAILURE, "H5Dcreate2");
|
|
|
|
if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
|
|
errx(EXIT_FAILURE, "H5Dwrite");
|
|
|
|
if (H5Dflush(dset) < 0)
|
|
errx(EXIT_FAILURE, "%s: H5Dflush", __func__);
|
|
|
|
return dset;
|
|
}
|
|
|
|
static void
|
|
rewrite_dset(hid_t dset, hid_t type, char *data)
|
|
{
|
|
if (H5Dwrite(dset, type, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
|
|
errx(EXIT_FAILURE, "%s: H5Dwrite", __func__);
|
|
if (H5Dflush(dset) < 0)
|
|
errx(EXIT_FAILURE, "%s: H5Dflush", __func__);
|
|
}
|
|
#endif
|
|
|
|
static hid_t
|
|
create_vl_dset(hid_t file, hid_t type, hid_t space, const char *name)
|
|
{
|
|
hid_t dset;
|
|
|
|
dset = H5Dcreate2(file, name, type, space, H5P_DEFAULT, H5P_DEFAULT,
|
|
H5P_DEFAULT);
|
|
|
|
if (dset == badhid)
|
|
errx(EXIT_FAILURE, "H5Dcreate2");
|
|
|
|
return dset;
|
|
}
|
|
|
|
static void
|
|
print_cache_hits(H5C_t *cache)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < H5AC_NTYPES; i++) {
|
|
dbgf(3, "type-%d cache hits %" PRId64 "%s\n",
|
|
i, cache->hits[i], (i == H5AC_GHEAP_ID) ? " *" : "");
|
|
}
|
|
dbgf(3, "\n");
|
|
}
|
|
|
|
static void
|
|
usage(const char *progname)
|
|
{
|
|
fprintf(stderr, "usage: %s [-W] [-V]\n", progname);
|
|
fprintf(stderr, "\n -W: do not wait for SIGINT or SIGUSR1\n");
|
|
fprintf(stderr, "\n -S: do not use VFD SWMR\n");
|
|
fprintf(stderr, " -f: use fixed-length string\n");
|
|
fprintf(stderr, " (default: variable-length string)\n");
|
|
fprintf(stderr, " -n: number of test steps to perform\n");
|
|
fprintf(stderr, " -q: be quiet: few/no progress messages\n");
|
|
fprintf(stderr, " -t (oob|null): select out-of-bounds or NULL test\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
bool
|
|
H5HG_trap(const char *reason)
|
|
{
|
|
if (strcmp(reason, "out of bounds") == 0) {
|
|
caught_out_of_bounds = true;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
hid_t fapl, fcpl, fid, space, type;
|
|
hid_t dset[2];
|
|
char content[2][96];
|
|
char name[2][96];
|
|
H5F_t *f;
|
|
H5C_t *cache;
|
|
sigset_t oldsigs;
|
|
herr_t ret;
|
|
bool variable = true, wait_for_signal = true;
|
|
const hsize_t dims = 1;
|
|
int ch, i, ntimes = 100;
|
|
unsigned long tmp;
|
|
char *end;
|
|
bool use_vfd_swmr = true;
|
|
const struct timespec delay =
|
|
{.tv_sec = 0, .tv_nsec = 1000 * 1000 * 1000 / 10};
|
|
testsel_t sel = TEST_NONE;
|
|
|
|
assert(H5T_C_S1 != badhid);
|
|
|
|
while ((ch = getopt(argc, argv, "SWfn:qt:")) != -1) {
|
|
switch(ch) {
|
|
case 'S':
|
|
use_vfd_swmr = false;
|
|
break;
|
|
case 'W':
|
|
wait_for_signal = false;
|
|
break;
|
|
case 'f':
|
|
variable = false;
|
|
break;
|
|
case 'n':
|
|
errno = 0;
|
|
tmp = strtoul(optarg, &end, 0);
|
|
if (end == optarg || *end != '\0')
|
|
errx(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg);
|
|
else if (errno != 0)
|
|
err(EXIT_FAILURE, "couldn't parse `-n` argument `%s`", optarg);
|
|
else if (tmp > INT_MAX)
|
|
errx(EXIT_FAILURE, "`-n` argument `%lu` too large", tmp);
|
|
ntimes = (int)tmp;
|
|
break;
|
|
case 'q':
|
|
verbosity = 1;
|
|
break;
|
|
case 't':
|
|
if (strcmp(optarg, "oob") == 0)
|
|
sel = TEST_OOB;
|
|
else if (strcmp(optarg, "null") == 0)
|
|
sel = TEST_NULL;
|
|
else
|
|
usage(argv[0]);
|
|
break;
|
|
default:
|
|
usage(argv[0]);
|
|
break;
|
|
}
|
|
}
|
|
argv += optind;
|
|
argc -= optind;
|
|
|
|
if (argc > 0)
|
|
errx(EXIT_FAILURE, "unexpected command-line arguments");
|
|
|
|
if ((fapl = vfd_swmr_create_fapl(true, sel == TEST_OOB, use_vfd_swmr)) < 0)
|
|
errx(EXIT_FAILURE, "vfd_swmr_create_fapl");
|
|
|
|
if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0)
|
|
errx(EXIT_FAILURE, "H5Pcreate");
|
|
|
|
ret = H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1);
|
|
if (ret < 0)
|
|
errx(EXIT_FAILURE, "H5Pset_file_space_strategy");
|
|
|
|
fid = H5Fcreate("vfd_swmr_vlstr.h5", H5F_ACC_TRUNC, fcpl, fapl);
|
|
|
|
/* Create the VL string datatype and a scalar dataspace, or a
|
|
* fixed-length string datatype and a simple dataspace.
|
|
*/
|
|
if ((type = H5Tcopy(H5T_C_S1)) == badhid)
|
|
errx(EXIT_FAILURE, "H5Tcopy");
|
|
|
|
/* Create the VL string datatype and a scalar dataspace */
|
|
if ((type = H5Tcopy(H5T_C_S1)) == badhid)
|
|
errx(EXIT_FAILURE, "H5Tcopy");
|
|
|
|
if (!variable) {
|
|
if (H5Tset_size(type, 32) < 0)
|
|
errx(EXIT_FAILURE, "H5Tset_size");
|
|
space = H5Screate_simple(1, &dims, NULL);
|
|
} else {
|
|
if (H5Tset_size(type, H5T_VARIABLE) < 0)
|
|
errx(EXIT_FAILURE, "H5Tset_size");
|
|
space = H5Screate(H5S_SCALAR);
|
|
}
|
|
|
|
if (space == badhid)
|
|
errx(EXIT_FAILURE, "H5Screate");
|
|
|
|
if ((f = H5VL_object_verify(fid, H5I_FILE)) == NULL)
|
|
errx(EXIT_FAILURE, "H5VL_object_verify");
|
|
|
|
cache = f->shared->cache;
|
|
|
|
if (fid == badhid)
|
|
errx(EXIT_FAILURE, "H5Fcreate");
|
|
|
|
block_signals(&oldsigs);
|
|
|
|
print_cache_hits(cache);
|
|
|
|
/* content 1 seq 1 short
|
|
* content 1 seq 1 long long long long long long long long
|
|
* content 1 seq 1 medium medium medium
|
|
*/
|
|
for (i = 0; i < ntimes; i++) {
|
|
const int ndsets = 2;
|
|
const int step = i % NSTEPS;
|
|
const int which = (i / NSTEPS) % ndsets;
|
|
const int seq = i / (ndsets * NSTEPS);
|
|
dbgf(2, "iteration %d which %d step %d seq %d\n",
|
|
i, which, step, seq);
|
|
switch (step) {
|
|
case CREATE:
|
|
(void)snprintf(name[which], sizeof(name[which]),
|
|
"dset-%d", which);
|
|
(void)snprintf(content[which], sizeof(content[which]),
|
|
"content %d seq %d short", which, seq);
|
|
dset[which] =
|
|
create_vl_dset(fid, type, space, name[which]);
|
|
write_vl_dset(dset[which], type, space, content[which]);
|
|
break;
|
|
case LENGTHEN:
|
|
(void)snprintf(content[which], sizeof(content[which]),
|
|
"content %d seq %d long long long long long long long long",
|
|
which, seq);
|
|
write_vl_dset(dset[which], type, space, content[which]);
|
|
break;
|
|
case SHORTEN:
|
|
(void)snprintf(content[which], sizeof(content[which]),
|
|
"content %d seq %d medium medium medium",
|
|
which, seq);
|
|
write_vl_dset(dset[which], type, space, content[which]);
|
|
break;
|
|
case DELETE:
|
|
if (H5Dclose(dset[which]) < 0)
|
|
errx(EXIT_FAILURE, "H5Dclose");
|
|
if (H5Ldelete(fid, name[which], H5P_DEFAULT) < 0) {
|
|
errx(EXIT_FAILURE, "%s: H5Ldelete(, \"%s\", ) failed",
|
|
__func__, name[which]);
|
|
}
|
|
break;
|
|
default:
|
|
errx(EXIT_FAILURE, "%s: unknown step %d", __func__, step);
|
|
}
|
|
if (caught_out_of_bounds) {
|
|
fprintf(stderr, "caught out of bounds\n");
|
|
break;
|
|
}
|
|
nanosleep(&delay, NULL);
|
|
}
|
|
|
|
if (use_vfd_swmr && wait_for_signal)
|
|
await_signal(fid);
|
|
|
|
restore_signals(&oldsigs);
|
|
|
|
if (H5Pclose(fapl) < 0)
|
|
errx(EXIT_FAILURE, "H5Pclose(fapl)");
|
|
|
|
if (H5Pclose(fcpl) < 0)
|
|
errx(EXIT_FAILURE, "H5Pclose(fcpl)");
|
|
|
|
if (H5Tclose(type) < 0)
|
|
errx(EXIT_FAILURE, "H5Tclose");
|
|
|
|
if (H5Sclose(space) < 0)
|
|
errx(EXIT_FAILURE, "H5Sclose");
|
|
|
|
if (H5Fclose(fid) < 0)
|
|
errx(EXIT_FAILURE, "H5Fclose");
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|