Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ IF(ENABLE_HDF4)
ENDIF()
ENDIF()

OPTION(ENABLE_HDF5_SWMR "Support SWMR in HDF5. This requires HDF version 1.10 or later" OFF)

# Option to Build DLL
IF(WIN32)
OPTION(ENABLE_DLL "Build a Windows DLL." ${BUILD_SHARED_LIBS})
Expand Down Expand Up @@ -693,6 +695,15 @@ IF(USE_HDF5)
##

# Some versions of HDF5 set HDF5_VERSION_STRING instead of HDF5_VERSION
##
# Assert HDF5 version meets minimum required version.
##
SET(HDF5_VERSION_REQUIRED 1.8.10)
IF(ENABLE_HDF5_SWMR_SUPPORT)
SET(HDF5_VERSION_REQUIRED 1.10)
MESSAGE(STATUS "HDF5 SWMR is enabled. This implies that HDF5 version at least ${HDF5_VERSION_REQUIRED} is required.")
ENDIF()

IF(HDF5_VERSION_STRING AND NOT HDF5_VERSION)
SET(HDF5_VERSION ${HDF5_VERSION_STRING})
ENDIF()
Expand All @@ -711,6 +722,9 @@ IF(USE_HDF5)
unset(_hdf5_version)
unset(_hdf5_version_lines)
MESSAGE(STATUS "Found HDF5 libraries version ${HDF5_VERSION}")
IF(ENABLE_HDF5_SWMR_SUPPORT)
ADD_DEFINITIONS(-DHDF5_HAS_SWMR)
ENDIF()
ENDIF()
ELSE()
SET(HDF5_VERSION ${HDF5_VERSION} CACHE STRING "")
Expand Down
1 change: 1 addition & 0 deletions include/netcdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ Use this in mode flags for both nc_create() and nc_open(). */

#define NC_PERSIST 0x4000 /**< Save diskless contents to disk. Mode flag for nc_open() or nc_create() */
#define NC_INMEMORY 0x8000 /**< Read from memory. Mode flag for nc_open() or nc_create() */
#define NC_HDF5_SWMR 0x2000 /** Reuse deprecated MPIIO flag for SWMR **/

/* Upper 16 bits */
#define NC_NOATTCREORD 0x20000 /**< Disable the netcdf-4 (hdf5) attribute creation order tracking */
Expand Down
36 changes: 36 additions & 0 deletions libhdf5/hdf5create.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
NC_HDF5_FILE_INFO_T *hdf5_info;
NC_HDF5_GRP_INFO_T *hdf5_grp;

#ifdef HAVE_H5PSET_LIBVER_BOUNDS
H5F_libver_t low, high;
#endif

#ifdef USE_PARALLEL4
NC_MPI_INFO *mpiinfo = NULL;
MPI_Comm comm;
Expand Down Expand Up @@ -103,6 +107,13 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
else
flags = H5F_ACC_TRUNC;

#ifdef HDF5_HAS_SWMR
#ifndef HAVE_H5PSET_LIBVER_BOUNDS
if (cmode & NC_HDF5_SWMR)
flags |= H5F_ACC_SWMR_WRITE;
#endif
#endif

/* If this file already exists, and NC_NOCLOBBER is specified,
return an error (unless diskless|inmemory) */
if (!nc4_info->mem.diskless && !nc4_info->mem.inmemory) {
Expand Down Expand Up @@ -160,6 +171,23 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
__func__, gs->chunkcache.size, gs->chunkcache.nelems,
gs->chunkcache.preemption));
}
#ifdef HAVE_H5PSET_LIBVER_BOUNDS
#if H5_VERSION_GE(1,10,2)
low = H5F_LIBVER_EARLIEST;
high = H5F_LIBVER_V18;
#ifdef HDF5_HAS_SWMR
if ((cmode & NC_HDF5_SWMR)) {
low = H5F_LIBVER_LATEST;
high = H5F_LIBVER_LATEST;
}
#endif /* HDF5_HAS_SWMR */
#else
low = H5F_LIBVER_EARLIEST;
high = H5F_LIBVER_LATEST;
#endif
if (H5Pset_libver_bounds(fapl_id, low, high) < 0)
BAIL(NC_EHDFERR);
#endif

{
NCglobalstate* gs = NC_getglobalstate();
Expand Down Expand Up @@ -253,6 +281,14 @@ nc4_create_file(const char *path, int cmode, size_t initialsz,
if ((retval = NC4_new_provenance(nc4_info)))
BAIL(retval);

#ifdef HDF5_HAS_SWMR
if ((cmode & NC_HDF5_SWMR)) {
/* Prepare for single writer multiple readers */
if ((retval = H5Fstart_swmr_write(hdf5_info->hdfid)))
BAIL(retval);
}
#endif

return NC_NOERR;

exit: /*failure exit*/
Expand Down
20 changes: 19 additions & 1 deletion libhdf5/hdf5open.c
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,16 @@ nc4_open_file(const char *path, int mode, void* parameters, int ncid)
assert(nc);

/* Determine the HDF5 open flag to use. */
flags = (mode & NC_WRITE) ? H5F_ACC_RDWR : H5F_ACC_RDONLY;
if((mode & NC_WRITE)) {
flags = H5F_ACC_RDWR;
} else {
flags = H5F_ACC_RDONLY;
#ifdef HDF5_HAS_SWMR
if((mode & NC_HDF5_SWMR)) {
flags |= H5F_ACC_SWMR_READ;
}
#endif
}

/* Add necessary structs to hold netcdf-4 file data. */
if ((retval = nc4_nc4f_list_add(nc, path, mode)))
Expand Down Expand Up @@ -975,6 +984,15 @@ nc4_open_file(const char *path, int mode, void* parameters, int ncid)
if (H5Pclose(fapl_id) < 0)
BAIL(NC_EHDFERR);

#ifdef HDF5_HAS_SWMR
/* Prepare for single writer multiple reader. */
if (mode & NC_WRITE && mode & NC_HDF5_SWMR) {
if ((retval = H5Fstart_swmr_write(h5->hdfid))) {
BAIL(retval);
}
}
#endif

return NC_NOERR;

exit:
Expand Down
7 changes: 7 additions & 0 deletions libhdf5/hdf5var.c
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,12 @@ NC4_put_vars(int ncid, int varid, const size_t *startp, const size_t *countp,
mem_spaceid, file_spaceid, xfer_plistid, bufr) < 0)
BAIL(NC_EHDFERR);

#ifdef HDF5_HAS_SWMR
/* Flush data for SWMR */
if (H5Dflush(hdf5_var->hdf_datasetid) < 0)
BAIL(NC_EHDFERR);
#endif

/* Remember that we have written to this var so that Fill Value
* can't be set for it. */
if (!var->written_to)
Expand Down Expand Up @@ -1794,6 +1800,7 @@ NC4_put_vars(int ncid, int varid, const size_t *startp, const size_t *countp,
return retval;
if (range_error)
return NC_ERANGE;

return NC_NOERR;
}

Expand Down
73 changes: 73 additions & 0 deletions nc_test4/tst_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,79 @@ main(int argc, char **argv)
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
#ifdef HDF5_HAS_SWMR
printf("*** testing HDF5 SWMR...");
{
#define DATA_LEN 3

int ncid, ncid2, varid, dimids[2];
size_t time_len, beam_len;
int i;
int values[DATA_LEN];
size_t start[2] = {0,0}, count[2] = {1, DATA_LEN};

/* Initialize some phony data. */
for (i = 0; i < DATA_LEN; i++)
values[i] = DATA_LEN*2 - i;

/* Create a file in SWMR mode for writing, create structure and close. */
if (nc_create(FILE_NAME, NC_NETCDF4|NC_HDF5_SWMR, &ncid)) ERR;
if (nc_def_dim(ncid, "time", NC_UNLIMITED, &dimids[0])) ERR;
if (nc_def_dim(ncid, "beam", NC_UNLIMITED, &dimids[1])) ERR;
if (nc_def_var(ncid, "depth", NC_INT, 2, dimids, &varid)) ERR;
if (nc_close(ncid)) ERR;

/* Open the file for SWMR reading and close. */
if (nc_open(FILE_NAME, NC_HDF5_SWMR, &ncid)) ERR;
if (nc_close(ncid)) ERR;

/* Open the file for SWMR writing, append data, and close. */
if (nc_open(FILE_NAME, NC_WRITE|NC_HDF5_SWMR, &ncid)) ERR;
if (nc_inq_varid(ncid, "depth", &varid)) ERR;
if (nc_put_vara_int(ncid, varid, start, count, values)) ERR;
if (nc_inq_dimlen(ncid, dimids[0], &time_len)) ERR;
if (time_len != 1) ERR;
if (nc_inq_dimlen(ncid, dimids[1], &beam_len)) ERR;
if (beam_len != DATA_LEN) ERR;
if (nc_close(ncid)) ERR;

/* Open the file for SWMR reading, verify data, and close. */
if (nc_open(FILE_NAME, NC_HDF5_SWMR, &ncid)) ERR;
if (nc_inq_varid(ncid, "depth", &varid)) ERR;
if (nc_put_vara_int(ncid, varid, start, count, values) == 0) ERR; // Writing should fail
if (nc_inq_dimlen(ncid, dimids[0], &time_len)) ERR;
if (time_len != 1) ERR;
if (nc_inq_dimlen(ncid, dimids[1], &beam_len)) ERR;
if (beam_len != DATA_LEN) ERR;
if (nc_close(ncid)) ERR;

/* Append data to the file from one writer (ncid1) and verify from a reader (ncid2) */
if (nc_open(FILE_NAME, NC_WRITE|NC_HDF5_SWMR, &ncid)) ERR;
if (nc_open(FILE_NAME, NC_HDF5_SWMR, &ncid2)) ERR;

// Verify length of time dimension == 1 in both reader and writer
if (nc_inq_dimlen(ncid, dimids[0], &time_len)) ERR;
if (time_len != 1) ERR;
if (nc_inq_dimlen(ncid2, dimids[0], &time_len)) ERR;
if (time_len != 1) ERR;

// Append data
start[0] = 1; start[1] = 0;
if (nc_inq_varid(ncid, "depth", &varid)) ERR;
if (nc_put_vara_int(ncid, varid, start, count, values)) ERR;

// Verify length of time dimension == 2 in both reader and writer
if (nc_inq_dimlen(ncid, dimids[0], &time_len)) ERR;
if (time_len != 2) ERR;
if (nc_inq_dimlen(ncid2, dimids[0], &time_len)) ERR;
if (time_len != 2) ERR;

if (nc_close(ncid)) ERR;
if (nc_close(ncid2)) ERR;

}
SUMMARIZE_ERR;
#endif /* HDF_HAS_SWMR */
printf("*** testing CLASSIC_MODEL flag with classic formats...");
{
int ncid;
Expand Down