summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVailin Choi <vchoi@jam.ad.hdfgroup.org>2018-08-14 18:21:00 (GMT)
committerVailin Choi <vchoi@jam.ad.hdfgroup.org>2018-08-14 18:21:00 (GMT)
commit45be06a387c1294fa3c95cc71106afcc023ddb91 (patch)
tree3043133c78a523d02f2671710318046afe29d8b7 /src
parentce1e8162959b14b97d79b53ebf4bea77e2e871b2 (diff)
downloadhdf5-45be06a387c1294fa3c95cc71106afcc023ddb91.zip
hdf5-45be06a387c1294fa3c95cc71106afcc023ddb91.tar.gz
hdf5-45be06a387c1294fa3c95cc71106afcc023ddb91.tar.bz2
Preliminary checkins for implementation done so far:
1) Public routines: H5Pget/set_vfd_swmr_config 2) Public routine: H5Fvfd_swmr_end_tick 3) Initialization when opening a file with VFD SWMR writer 4) Tests in test/vfd_swmr.c for VFD SWMR 5) Fix a bug in src/H5Fint.c: when error is encountered after the root group is created Note the following: --This is WORK IN PROGRESS and will subject to change as implementation goes. --There is test failure form enc_dec_plist.c: I will fix this when changes to the property list are settled. --The branch is updated with the latest from develop as of 8/14/2018
Diffstat (limited to 'src')
-rw-r--r--src/H5.c6
-rw-r--r--src/H5AC.c4
-rw-r--r--src/H5ACprivate.h2
-rw-r--r--src/H5Cprivate.h2
-rw-r--r--src/H5Ctag.c6
-rw-r--r--src/H5Dint.c2
-rw-r--r--src/H5F.c32
-rw-r--r--src/H5FDint.c108
-rw-r--r--src/H5FDprivate.h43
-rw-r--r--src/H5Fint.c207
-rw-r--r--src/H5Fpkg.h9
-rw-r--r--src/H5Fprivate.h22
-rw-r--r--src/H5Fpublic.h16
-rw-r--r--src/H5Fquery.c23
-rw-r--r--src/H5Pfapl.c213
-rw-r--r--src/H5Ppublic.h4
-rw-r--r--src/H5private.h30
17 files changed, 720 insertions, 9 deletions
diff --git a/src/H5.c b/src/H5.c
index 1b13fea..8ff8bdc 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -85,6 +85,12 @@ char H5_lib_vers_info_g[] = H5_VERS_INFO;
static hbool_t H5_dont_atexit_g = FALSE;
H5_debug_t H5_debug_g; /* debugging info */
+hbool_t vfd_swmr_g = FALSE;
+hbool_t vfd_swmr_writer_g = FALSE;
+uint64_t tick_num_g = 0;
+struct timespec end_of_tick_g;
+H5F_file_t *vfd_swmr_file_g;
+
/*******************/
/* Local Variables */
diff --git a/src/H5AC.c b/src/H5AC.c
index 989ee10..e6b1928 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -2760,7 +2760,7 @@ done:
*------------------------------------------------------------------------------
*/
herr_t
-H5AC_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags)
+H5AC_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags, hbool_t type_match)
{
/* Variable Declarations */
herr_t ret_value = SUCCEED;
@@ -2773,7 +2773,7 @@ H5AC_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flag
HDassert(f->shared);
/* Call cache level function to expunge entries with specified tag and type id */
- if(H5C_expunge_tag_type_metadata(f, tag, type_id, flags)<0)
+ if(H5C_expunge_tag_type_metadata(f, tag, type_id, flags, type_match)<0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "Cannot expunge tagged type entries")
done:
diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h
index 99cc0e9..36872c4 100644
--- a/src/H5ACprivate.h
+++ b/src/H5ACprivate.h
@@ -444,7 +444,7 @@ H5_DLL void H5AC_set_ring(H5AC_ring_t ring, H5AC_ring_t *orig_ring);
H5_DLL herr_t H5AC_unsettle_entry_ring(void *entry);
H5_DLL herr_t H5AC_unsettle_ring(H5F_t * f, H5AC_ring_t ring);
H5_DLL herr_t H5AC_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id,
- unsigned flags);
+ unsigned flags, hbool_t type_match);
H5_DLL herr_t H5AC_get_tag(const void *thing, /*OUT*/ haddr_t *tag);
/* Virtual entry routines */
diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h
index 38a86ee..a3e46db 100644
--- a/src/H5Cprivate.h
+++ b/src/H5Cprivate.h
@@ -2246,7 +2246,7 @@ H5_DLL herr_t H5C_flush_cache(H5F_t *f, unsigned flags);
H5_DLL herr_t H5C_flush_tagged_entries(H5F_t *f, haddr_t tag);
H5_DLL herr_t H5C_force_cache_image_load(H5F_t * f);
H5_DLL herr_t H5C_evict_tagged_entries(H5F_t *f, haddr_t tag, hbool_t match_global);
-H5_DLL herr_t H5C_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags);
+H5_DLL herr_t H5C_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags, hbool_t type_match);
H5_DLL herr_t H5C_get_tag(const void *thing, /*OUT*/ haddr_t *tag);
#if H5C_DO_TAGGING_SANITY_CHECKS
herr_t H5C_verify_tag(int id, haddr_t tag);
diff --git a/src/H5Ctag.c b/src/H5Ctag.c
index 66aedd9..16baac3 100644
--- a/src/H5Ctag.c
+++ b/src/H5Ctag.c
@@ -75,6 +75,7 @@ typedef struct {
H5F_t *f; /* File pointer for evicting entry */
int type_id; /* Cache entry type to expunge */
unsigned flags; /* Flags for expunging entry */
+ hbool_t type_match;
} H5C_tag_iter_ettm_ctx_t;
/* Typedef for tagged entry iterator callback context - mark corked */
@@ -811,7 +812,7 @@ H5C__expunge_tag_type_metadata_cb(H5C_cache_entry_t *entry, void *_ctx)
HDassert(ctx);
/* Found one with the same tag and type id */
- if(entry->type->id == ctx->type_id)
+ if(entry->type->id == ctx->type_id || !ctx->type_match)
if(H5C_expunge_entry(ctx->f, entry->type, entry->addr, ctx->flags) < 0)
HGOTO_ERROR(H5E_CACHE, H5E_CANTEXPUNGE, H5_ITER_ERROR, "can't expunge entry")
@@ -835,7 +836,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5C_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags)
+H5C_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags, hbool_t type_match)
{
H5C_t *cache; /* Pointer to cache structure */
H5C_tag_iter_ettm_ctx_t ctx; /* Context for iterator callback */
@@ -855,6 +856,7 @@ H5C_expunge_tag_type_metadata(H5F_t *f, haddr_t tag, int type_id, unsigned flags
ctx.f = f;
ctx.type_id = type_id;
ctx.flags = flags;
+ ctx.type_match = type_match;
/* Iterate through hash table entries, expunge those with specified tag and type id */
if(H5C__iter_tagged_entries(cache, tag, FALSE, H5C__expunge_tag_type_metadata_cb, &ctx) < 0)
diff --git a/src/H5Dint.c b/src/H5Dint.c
index e8874a2..21594c6 100644
--- a/src/H5Dint.c
+++ b/src/H5Dint.c
@@ -2986,7 +2986,7 @@ done:
HDONE_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "address undefined")
/* Expunge from cache all v1 B-tree type entries associated with tag */
- if(H5AC_expunge_tag_type_metadata(dataset->oloc.file, dataset->oloc.addr, H5AC_BT_ID, H5AC__NO_FLAGS_SET))
+ if(H5AC_expunge_tag_type_metadata(dataset->oloc.file, dataset->oloc.addr, H5AC_BT_ID, H5AC__NO_FLAGS_SET, TRUE))
HDONE_ERROR(H5E_DATASET, H5E_CANTEXPUNGE, FAIL, "unable to expunge index metadata")
} /* end if */
diff --git a/src/H5F.c b/src/H5F.c
index 01fd7db..079af75 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1713,3 +1713,35 @@ H5Fincrement_filesize(hid_t file_id, hsize_t increment)
done:
FUNC_LEAVE_API(ret_value)
} /* H5Fincrement_filesize() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Fvfd_swmr_end_tick()
+ *
+ * Purpose: To allow user to trigger end of tick processing
+ *
+ * Return: Non-negative on success/Negative on errors
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Fvfd_swmr_end_tick(hid_t file_id)
+{
+ H5F_t *file; /* File object for file ID */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE1("e", "i", file_id);
+
+ /* Check args */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID")
+
+ /* This will work only if the file is opened with VFD SWMR configured.*/
+ if(!(H5F_USE_VFD_SWMR(file)))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "must have VFD SWMR configured for this public routine")
+
+ /* ??Trigger end of tick processing later */
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Fvfd_swmr_end_tick() */
diff --git a/src/H5FDint.c b/src/H5FDint.c
index 023ff57..a26815e 100644
--- a/src/H5FDint.c
+++ b/src/H5FDint.c
@@ -418,3 +418,111 @@ H5FD_driver_query(const H5FD_class_t *driver, unsigned long *flags/*out*/)
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_driver_query() */
+
+/*-------------------------------------------------------------------------
+* Function: H5FD_writer_end_of_tick
+*
+* Purpose:
+*
+* Return: SUCCEED/FAIL
+*
+* Programmer:
+*
+*-------------------------------------------------------------------------
+*/
+herr_t
+H5FD_writer_end_of_tick(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_writer_end_of_tick() */
+
+
+/*-------------------------------------------------------------------------
+* Function: H5FD_reader_end_of_tick
+*
+* Purpose:
+*
+* Return: SUCCEED/FAIL
+*
+* Programmer:
+*
+*-------------------------------------------------------------------------
+*/
+herr_t
+H5FD_reader_end_of_tick(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FD_reader_end_of_tick() */
+
+#ifdef OUT
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_vfd_swmr_md_read
+ *
+ * Purpose: ??
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ * Programmer:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD_vfd_swmr_md_read(int md_fd, haddr_t addr, size_t size, const void *buf)
+{
+
+ HDlseek(fd, (HDoff_t)addr, SEEK_SET);
+ bytes_read = HDread(md_fd, buf, size);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_vfd_swmr_read() */
+
+herr_t
+H5FD_vfd_swmr_hdr_deserialize(int md_fd, size_t len)
+{
+ uint8_t image[H5FD_MD_HEADER_SIZE]; /* Buffer for element data */
+ uint8_t *p = NULL;
+ uint32_t fs_page_size;
+ uint64_t tick_num;
+ uint64_t index_offset;
+ uint64_t index_length;
+ uint32_t stored_chksum; /* Stored metadata checksum value */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ p = &image[0];
+
+ HDlseek(md_fd, (HDoff_t)0, SEEK_SET);
+ HDread(md_fd, image, H5FD_MD_HEADER_SIZE);
+
+ /* Magic number */
+ if(HDmemcmp(p, H5FD_MD_HEADER_MAGIC, (size_t)H5_SIZEOF_MAGIC))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, NULL, "wrong metadata file header signature")
+ p += H5_SIZEOF_MAGIC;
+
+ UINT32DECODE(p, fs_page_size);
+ UINT64DECODE(p, tick_num);
+ UINT64DECODE(p, index_offset);
+ UINT64DECODE(p, index_length);
+
+ /* NEED to verify checksum/retry ?? */
+ /* Metadata checksum */
+ UINT32DECODE(p, stored_chksum);
+
+ /* Sanity check */
+ HDassert((size_t)(p - (const uint8_t *)&image[0]) <= len);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FD_vfd_swmr_hdr_deserialize() */
+#endif
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 0430064..1698d96 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -38,6 +38,45 @@
/* Length of filename buffer */
#define H5FD_MAX_FILENAME_LEN 1024
+/*
+ * VFD SWMR
+ */
+/* Metadata file header */
+#define H5FD_MD_HEADER_MAGIC "VHDR" /* Header magic */
+#define H5FD_SIZEOF_CHKSUM 4 /* Size of checksum */
+
+/* Size of the header in the metadata file */
+#define H5FD_MD_HEADER_SIZE \
+ ( \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ + 4 /* Page size */ \
+ + 8 /* Tick number */ \
+ + 8 /* Index offset */ \
+ + 8 /* Index length number */ \
+ + H5FD_SIZEOF_CHKSUM /* Metadata header checksum */ \
+ )
+
+/* Size of an index entry in the metadata file */
+#define H5FD_MD_INDEX_ENTRY_SIZE \
+ ( \
+ 4 /* HDF5 file page offset */ \
+ + 4 /* Metadata file page offset */ \
+ + 4 /* Length */ \
+ )
+
+/* Metadata file index magic */
+#define H5FD_MD_INDEX_MAGIC "VIDX" /* Index magic */
+
+/* Size of the metadata file index */
+#define H5FD_MD_INDEX_SIZE(N) /* N is number of entries in index */ \
+ ( \
+ H5_SIZEOF_MAGIC /* Signature */ \
+ + 8 /* Tick num */ \
+ + 4 /* Number of entries */ \
+ + (N * H5FD_MD_INDEX_ENTRY_SIZE) /* Index entries */ \
+ + H5FD_SIZEOF_CHKSUM /* Metadata header checksum */ \
+ )
+
#ifdef H5_HAVE_PARALLEL
/* ======== Temporary data transfer properties ======== */
/* Definitions for memory MPI type property */
@@ -157,6 +196,10 @@ H5_DLL herr_t H5FD_set_base_addr(H5FD_t *file, haddr_t base_addr);
H5_DLL haddr_t H5FD_get_base_addr(const H5FD_t *file);
H5_DLL herr_t H5FD_set_paged_aggr(H5FD_t *file, hbool_t paged);
+/* Function prototypes for VFD SWMR */
+H5_DLL herr_t H5FD_writer_end_of_tick();
+H5_DLL herr_t H5FD_reader_end_of_tick();
+
/* Function prototypes for MPI based VFDs*/
#ifdef H5_HAVE_PARALLEL
/* General routines */
diff --git a/src/H5Fint.c b/src/H5Fint.c
index abc638a..6448027 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -79,6 +79,9 @@ static char *H5F__getenv_prefix_name(char **env_prefix/*in,out*/);
static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name);
static herr_t H5F__flush_phase1(H5F_t *f);
static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing);
+static herr_t H5F__init_vfd_swmr(H5F_t *f, hbool_t file_create);
+static herr_t H5F__init_vfd_swmr_info(H5F_t *f);
+static herr_t H5F__init_vfd_swmr_md(H5F_t *f, hbool_t file_create);
/*********************/
@@ -184,6 +187,10 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
if(H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME, &(f->shared->page_buf->min_raw_perc)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set minimum raw data fraction of page buffer")
} /* end if */
+
+ if(H5P_set(new_plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, &(f->shared->vfd_swmr_config)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.")
+
#ifdef H5_HAVE_PARALLEL
if(H5P_set(new_plist, H5_COLL_MD_READ_FLAG_NAME, &(f->coll_md_read)) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't set collective metadata read flag")
@@ -1033,6 +1040,10 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
if(H5P_get(plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get object flush cb info")
+ /* Get VFD SWMR configuration */
+ if(H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, &(f->shared->vfd_swmr_config)) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get VFD SWMR config info")
+
/* Create a metadata cache with the specified number of elements.
* The cache might be created with a different number of elements and
* the access property list should be updated to reflect that.
@@ -1497,7 +1508,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
hbool_t use_file_locking; /*read from env var */
hbool_t ci_load = FALSE; /* whether MDC ci load requested */
hbool_t ci_write = FALSE; /* whether MDC CI write requested */
- H5F_t *ret_value = NULL; /*actual return value */
+ hbool_t file_create = FALSE; /* creating a new file or not */
+ H5F_t *ret_value = NULL; /*actual return value */
FUNC_ENTER_NOAPI(NULL)
@@ -1667,6 +1679,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get minimum raw data fraction of page buffer")
} /* end if */
+
/*
* Read or write the file superblock, depending on whether the file is
* empty or not.
@@ -1693,6 +1706,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
*/
if(H5G_mkroot(file, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
+
+ file_create = TRUE;
+
} /* end if */
else if (1 == shared->nrefs) {
/* Read the superblock if it hasn't been read before. */
@@ -1707,8 +1723,19 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* Open the root group */
if(H5G_mkroot(file, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
+
} /* end if */
+ if(H5F_VFD_SWMR_CONFIG(file)) {
+ /* Page buffering and page allocation strategy have to be enabled */
+ if(!page_buf_size || !H5F_PAGED_AGGR(file))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "file open fail with VFD SWMR writer")
+ if(1 == shared->nrefs && H5F_INTENT(file) & H5F_ACC_RDWR) {
+ if(H5F__init_vfd_swmr(file, file_create) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "file open fail with initialization for VFD SWMR writer")
+ }
+ }
+
/*
* Decide the file close degree. If it's the first time to open the
* file, set the degree to access property list value; if it's the
@@ -1812,9 +1839,15 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
ret_value = file;
done:
- if((NULL == ret_value) && file)
+ if((NULL == ret_value) && file) {
+ if(file->shared->root_grp && file->shared->nrefs == 1) {
+ if(H5AC_expunge_tag_type_metadata(file, H5G_oloc(file->shared->root_grp)->addr, H5AC_OHDR_ID, H5AC__NO_FLAGS_SET, FALSE) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, NULL, "unable to expunge root group tagged entries")
+ }
+
if(H5F__dest(file, FALSE) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
+ }
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_open() */
@@ -3685,3 +3718,173 @@ done:
FUNC_LEAVE_NOAPI_VOL(ret_value)
} /* H5F__format_convert() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__init_vfd_swmr
+ *
+ * Purpose: Intitialize info and the metadata file for VFD SWMR writer.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__init_vfd_swmr(H5F_t *f, hbool_t file_create)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Initialize info */
+ if(H5F__init_vfd_swmr_info(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "error in initializing info for VFD SWMR writer")
+
+ /* Initialize the metadata file */
+ if(H5F__init_vfd_swmr_md(f, file_create) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "error in creating metadata file for VFD SWMR writer")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__init_vfd_swmr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__init_vfd_swmr_info
+ *
+ * Purpose: Initialize globals and the corresponding fields in f
+ * for VFD SWMR writer:
+ * --set vfd_swmr_g to TRUE
+ * --set vfd_swmr_writer_g to TRUE
+ * --set tick_num_g to 0
+ * --set end_of_tick_g to the current time + tick length
+ * --set vfd_swmr_file_g to f->shared
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__init_vfd_swmr_info(H5F_t *f)
+{
+ struct timespec tmp_end_of_tick;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert(f->shared->vfd_swmr_config.vfd_swmr_writer);
+
+ vfd_swmr_g = f->shared->vfd_swmr = TRUE;
+ vfd_swmr_writer_g = f->shared->vfd_swmr_writer = TRUE;
+ tick_num_g = f->shared->tick_num = 0;
+
+ /* Get current time */
+ if(HDclock_gettime(CLOCK_MONOTONIC, &tmp_end_of_tick) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get time via clock_gettime")
+
+ /* Increment by tick length */
+ tmp_end_of_tick.tv_nsec += f->shared->vfd_swmr_config.tick_len * 100000000;
+ tmp_end_of_tick.tv_sec += tmp_end_of_tick.tv_nsec / 1000000000;
+ tmp_end_of_tick.tv_nsec = tmp_end_of_tick.tv_nsec % 1000000000;
+ HDmemcpy(&end_of_tick_g, &tmp_end_of_tick, sizeof(struct timespec));
+ HDmemcpy(&f->shared->end_of_tick, &tmp_end_of_tick, sizeof(struct timespec));
+
+ vfd_swmr_file_g = f->shared;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__init_vfd_swmr_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__init_vfd_swmr_md
+ *
+ * Purpose: Open the metadata file for VFD SMWR and allocate md_pages_reserved
+ * in the file.
+ * If not creating a new file, write header and an empty index
+ * to the file.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__init_vfd_swmr_md(H5F_t *f, hbool_t file_create)
+{
+ uint8_t image[H5FD_MD_HEADER_SIZE]; /* Buffer for element data */
+ uint8_t image_empty_idx[H5FD_MD_INDEX_SIZE(0)]; /* Buffer for element data */
+ uint8_t *p = NULL; /* Pointer to buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ int fd; /* File descriptor */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Open the metadata file */
+ if((fd = HDopen(f->shared->vfd_swmr_config.md_file_path, O_CREAT|O_RDWR, H5_POSIX_CREATE_MODE_RW)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open metadata file")
+
+ /* Set the file to md_pages_reserved */
+ if(HDftruncate(fd, (HDoff_t)f->shared->vfd_swmr_config.md_pages_reserved * f->shared->fs_page_size) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_SEEKERROR, FAIL, "unable to extend file properly")
+
+ if(!file_create) {
+ /*
+ * Encode metadata file header
+ */
+ p = &image[0];
+
+ /* Magic for header */
+ HDmemcpy(p, H5FD_MD_HEADER_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ UINT32ENCODE(p, f->shared->fs_page_size);
+ UINT64ENCODE(p, f->shared->tick_num);
+ UINT64ENCODE(p, H5FD_MD_HEADER_SIZE);
+ UINT64ENCODE(p, H5FD_MD_INDEX_SIZE(0));
+
+ metadata_chksum = H5_checksum_metadata((uint8_t *)p, (size_t)(p - &image[0]), 0);
+
+ /* Checksum for header */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Sanity checks */
+ HDassert((size_t)(p - &image[0] == H5FD_MD_HEADER_SIZE));
+
+ /* Write header to the metadata file */
+ if(HDwrite(fd, &image[0], H5FD_MD_HEADER_SIZE) != H5FD_MD_HEADER_SIZE)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing header to metadata file")
+
+ /*
+ * Encode metadata file index
+ */
+ p = &image_empty_idx[0];
+
+ /* Magic for index */
+ HDmemcpy(p, H5FD_MD_INDEX_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ UINT64ENCODE(p, f->shared->tick_num);
+
+ /* No entry in index */
+ UINT32ENCODE(p, 0);
+
+ metadata_chksum = H5_checksum_metadata((uint8_t *)p, (size_t)(p - &image_empty_idx[0]), 0);
+
+ /* Checksum for index */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* sanity checks */
+ HDassert((size_t)(p - &image_empty_idx[0] == H5FD_MD_INDEX_SIZE(0)));
+
+ /* Write index to the metadata file */
+ if(HDwrite(fd, &image_empty_idx[0], H5FD_MD_INDEX_SIZE(0)) != H5FD_MD_INDEX_SIZE(0))
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing index to metadata file")
+ }
+ f->shared->vfd_swmr_md_fd = fd;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__init_vfd_swmr_md() */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 2ab41de..19c49fb 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -353,6 +353,15 @@ struct H5F_file_t {
/* Object flush info */
H5F_object_flush_t object_flush; /* Information for object flush callback */
+
+ /* VFD SWMR configuration info */
+ H5F_vfd_swmr_config_t vfd_swmr_config; /* Copy of the VFD SWMR configuration from the
+ FAPL used to open the file */
+ hbool_t vfd_swmr; /* The file is opened with VFD SWMR configured or not*/
+ hbool_t vfd_swmr_writer; /* This is the VFD SWMR writer or not */
+ uint64_t tick_num; /* Number of the current tick */
+ struct timespec end_of_tick; /* End time of the current tick */
+ int vfd_swmr_md_fd; /* POSIX: file descriptor of the metadata file */
};
/*
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 979ba7d..9c7ea9e 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -331,6 +331,7 @@ typedef struct H5F_t H5F_t;
#define H5F_POINT_OF_NO_RETURN(F) ((F)->shared->fs.point_of_no_return)
#define H5F_FIRST_ALLOC_DEALLOC(F) ((F)->shared->first_alloc_dealloc)
#define H5F_EOA_PRE_FSM_FSALLOC(F) ((F)->shared->eoa_pre_fsm_fsalloc)
+#define H5F_USE_VFD_SWMR(F) ((F)->shared->vfd_swmr)
#else /* H5F_MODULE */
#define H5F_LOW_BOUND(F) (H5F_get_low_bound(F))
#define H5F_HIGH_BOUND(F) (H5F_get_high_bound(F))
@@ -388,6 +389,7 @@ typedef struct H5F_t H5F_t;
#define H5F_POINT_OF_NO_RETURN(F) (H5F_get_point_of_no_return(F))
#define H5F_FIRST_ALLOC_DEALLOC(F) (H5F_get_first_alloc_dealloc(F))
#define H5F_EOA_PRE_FSM_FSALLOC(F) (H5F_get_eoa_pre_fsm_fsalloc(F))
+#define H5F_USE_VFD_SWMR(F) (H5F_use_vfd_swmr(F))
#endif /* H5F_MODULE */
@@ -508,6 +510,20 @@ typedef struct H5F_t H5F_t;
#define H5F_ACS_PAGE_BUFFER_MIN_META_PERC_NAME "page_buffer_min_meta_perc" /* the min metadata percentage for the page buffer cache */
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME "page_buffer_min_raw_perc" /* the min raw data percentage for the page buffer cache */
+/* Default configuration for VFD SWMR: not configured */
+#define H5F_ACS_VFD_SWMR_CONFIG_NAME "vfd_swmr_config" /* VFD SWMR configuration */
+#define H5F__DEFAULT_VFD_SWMR_CONFIG \
+{ \
+ /* int32_t version = */ 0, \
+ /* int32_t tick_len = */ 0, \
+ /* int32_t max_lag = */ 0, \
+ /* hbool_t vfd_swmr_writer = */ FALSE, \
+ /* hbool_t flush_raw_data = */ FALSE, \
+ /* int32_t md_pages_reserved = */ 0, \
+ /* char md_file_path[] = */ "", \
+ /* char log_file_path[] = */ "" \
+}
+
/* ======================== File Mount properties ====================*/
#define H5F_MNT_SYM_LOCAL_NAME "local" /* Whether absolute symlinks local to file. */
@@ -575,6 +591,9 @@ typedef struct H5F_t H5F_t;
/* Check for file using paged aggregation */
#define H5F_PAGED_AGGR(F) (F->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE && F->shared->fs_page_size)
+/* Check for file configured with VFD SWMR */
+#define H5F_VFD_SWMR_CONFIG(F) (F->shared->vfd_swmr_config.version >= H5F__CURR_VFD_SWMR_CONFIG_VERSION)
+
/* Metadata read attempt values */
#define H5F_METADATA_READ_ATTEMPTS 1 /* Default # of read attempts for non-SWMR access */
#define H5F_SWMR_METADATA_READ_ATTEMPTS 100 /* Default # of read attempts for SWMR access */
@@ -651,6 +670,8 @@ struct H5P_genplist_t;
/* Main file structures */
typedef struct H5F_file_t H5F_file_t;
+extern H5F_file_t *vfd_swmr_file_g;
+
/* Block aggregation structure */
typedef struct H5F_blk_aggr_t H5F_blk_aggr_t;
@@ -741,6 +762,7 @@ H5_DLL hsize_t H5F_get_pgend_meta_thres(const H5F_t *f);
H5_DLL hbool_t H5F_get_point_of_no_return(const H5F_t *f);
H5_DLL hbool_t H5F_get_first_alloc_dealloc(const H5F_t *f);
H5_DLL haddr_t H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f);
+H5_DLL hbool_t H5F_use_vfd_swmr(const H5F_t *f);
/* Functions than retrieve values set/cached from the superblock/FCPL */
H5_DLL haddr_t H5F_get_base_addr(const H5F_t *f);
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 73c59f5..a685d25 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -217,6 +217,19 @@ typedef struct H5F_retry_info_t {
/* Callback for H5Pset_object_flush_cb() in a file access property list */
typedef herr_t (*H5F_flush_cb_t)(hid_t object_id, void *udata);
+/* VFD SWMR configuration data used by H5Pset/get_vfd_swmr_config */
+#define H5F__CURR_VFD_SWMR_CONFIG_VERSION 1
+#define H5F__MAX_VFD_SWMR_FILE_NAME_LEN 1024
+typedef struct H5F_vfd_swmr_config_t {
+ int32_t version;
+ int32_t tick_len;
+ int32_t max_lag;
+ hbool_t vfd_swmr_writer;
+ hbool_t flush_raw_data;
+ int32_t md_pages_reserved;
+ char md_file_path[H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1];
+ char log_file_path[H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1];
+} H5F_vfd_swmr_config_t;
#ifdef __cplusplus
extern "C" {
@@ -274,6 +287,9 @@ H5_DLL herr_t H5Fget_page_buffering_stats(hid_t file_id, unsigned accesses[2],
unsigned hits[2], unsigned misses[2], unsigned evictions[2], unsigned bypasses[2]);
H5_DLL herr_t H5Fget_mdc_image_info(hid_t file_id, haddr_t *image_addr, hsize_t *image_size);
+/* VFD SWMR */
+H5_DLL herr_t H5Fvfd_swmr_end_tick(hid_t file_id);
+
#ifdef H5_HAVE_PARALLEL
H5_DLL herr_t H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag);
H5_DLL herr_t H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag);
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
index be24072..41d885a 100644
--- a/src/H5Fquery.c
+++ b/src/H5Fquery.c
@@ -1215,3 +1215,26 @@ H5F_get_eoa_pre_fsm_fsalloc(const H5F_t *f)
FUNC_LEAVE_NOAPI(f->shared->eoa_pre_fsm_fsalloc)
} /* end H5F_get_eoa_pre_fsm_fsalloc() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_use_vfd_swmr
+ *
+ * Purpose: Quick and dirty routine to determine if VFD SWMR is
+ * enabled for this file.
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: TRUE/FALSE on success/abort on failure (shouldn't fail)
+ *-------------------------------------------------------------------------
+ */
+hbool_t
+H5F_use_vfd_swmr(const H5F_t *f)
+{
+ /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ HDassert(f);
+ HDassert(f->shared);
+
+ FUNC_LEAVE_NOAPI(f->shared->vfd_swmr)
+} /* end H5F_use_vfd_swmr() */
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index 7ba9c11..a0291e6 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -259,6 +259,11 @@
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_ENC H5P__encode_unsigned
#define H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEC H5P__decode_unsigned
+/* Definitions for the VFD SWMR configuration */
+#define H5F_ACS_VFD_SWMR_CONFIG_SIZE sizeof(H5F_vfd_swmr_config_t)
+#define H5F_ACS_VFD_SWMR_CONFIG_DEF H5F__DEFAULT_VFD_SWMR_CONFIG
+#define H5F_ACS_VFD_SWMR_CONFIG_ENC H5P__facc_vfd_swmr_config_enc
+#define H5F_ACS_VFD_SWMR_CONFIG_DEC H5P__facc_vfd_swmr_config_dec
/******************/
/* Local Typedefs */
@@ -306,6 +311,8 @@ static herr_t H5P__facc_multi_type_enc(const void *value, void **_pp, size_t *si
static herr_t H5P__facc_multi_type_dec(const void **_pp, void *value);
static herr_t H5P__facc_libver_type_enc(const void *value, void **_pp, size_t *size);
static herr_t H5P__facc_libver_type_dec(const void **_pp, void *value);
+static herr_t H5P__facc_vfd_swmr_config_enc(const void *value, void **_pp, size_t *size);
+static herr_t H5P__facc_vfd_swmr_config_dec(const void **_pp, void *value);
/* Metadata cache log location property callbacks */
static herr_t H5P_facc_mdc_log_location_enc(const void *value, void **_pp, size_t *size);
@@ -398,6 +405,8 @@ static const size_t H5F_def_page_buf_size_g = H5F_ACS_PAGE_BUFFER_SIZE_DEF;
static const unsigned H5F_def_page_buf_min_meta_perc_g = H5F_ACS_PAGE_BUFFER_MIN_META_PERC_DEF; /* Default page buffer minimum metadata size */
static const unsigned H5F_def_page_buf_min_raw_perc_g = H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_DEF; /* Default page buffer mininum raw data size */
+static const H5F_vfd_swmr_config_t *H5F_def_vfd_swmr_config_g = H5F_ACS_VFD_SWMR_CONFIG_DEF; /* Default vfd swmr configuration */
+
/*-------------------------------------------------------------------------
* Function: H5P__facc_reg_prop
@@ -644,6 +653,12 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+ /* Register the default VFD SWMR configuration */
+ if(H5P_register_real(pclass, H5F_ACS_VFD_SWMR_CONFIG_NAME, H5F_ACS_VFD_SWMR_CONFIG_SIZE, &H5F_def_vfd_swmr_config_g,
+ NULL, NULL, NULL, H5F_ACS_VFD_SWMR_CONFIG_ENC, H5F_ACS_VFD_SWMR_CONFIG_DEC,
+ NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5P__facc_reg_prop() */
@@ -3643,6 +3658,7 @@ H5P__facc_cache_config_dec(const void **_pp, void *_value)
enc_size = *(*pp)++;
HDassert(enc_size < 256);
UINT64DECODE_VAR(*pp, enc_value, enc_size);
+
config->max_size = (size_t)enc_value;
enc_size = *(*pp)++;
@@ -3927,6 +3943,105 @@ H5P__facc_libver_type_dec(const void **_pp, void *_value)
/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vfd_swmr_config_enc
+ *
+ * Purpose: Callback routine which is called whenever the VFD SWMR config
+ * property in the file access property list is encoded.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; July 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vfd_swmr_config_enc(const void *value, void **_pp, size_t *size)
+{
+ const H5F_vfd_swmr_config_t *config = (const H5F_vfd_swmr_config_t *)value; /* Create local aliases for values */
+ uint8_t **pp = (uint8_t **)_pp;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity check */
+ HDassert(value);
+ HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t));
+
+ if(NULL != *pp) {
+
+ /* int */
+ INT32ENCODE(*pp, (int32_t)config->version);
+ INT32ENCODE(*pp, (int32_t)config->tick_len);
+ INT32ENCODE(*pp, (int32_t)config->max_lag);
+ H5_ENCODE_UNSIGNED(*pp, config->vfd_swmr_writer);
+ H5_ENCODE_UNSIGNED(*pp, config->flush_raw_data);
+ INT32ENCODE(*pp, (int32_t)config->md_pages_reserved);
+ HDmemcpy(*pp, (const uint8_t *)(config->md_file_path), (size_t)(H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1));
+ *pp += H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1;
+ HDmemcpy(*pp, (const uint8_t *)(config->log_file_path), (size_t)(H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1));
+ *pp += H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1;
+
+ } /* end if */
+
+ /* Compute encoded size */
+ *size += ( (4 * sizeof(int32_t)) + sizeof(unsigned) +
+ (2 * (H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1)) );
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5P__facc_vfd_swmr_config_enc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5P__facc_vfd_swmr_config_dec
+ *
+ * Purpose: Callback routine which is called whenever the VFD SWMR
+ * config property in the file access property list is decoded.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Vailin Choi; July 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5P__facc_vfd_swmr_config_dec(const void **_pp, void *_value)
+{
+ H5F_vfd_swmr_config_t *config = (H5F_vfd_swmr_config_t *)_value;
+ const uint8_t **pp = (const uint8_t **)_pp;
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(pp);
+ HDassert(*pp);
+ HDassert(config);
+ HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t));
+
+ /* Set property to default value */
+ HDmemcpy(config, &H5F_def_vfd_swmr_config_g, sizeof(H5F_vfd_swmr_config_t));
+
+ /* int */
+ INT32DECODE(*pp, config->version);
+ INT32DECODE(*pp, config->tick_len);
+ INT32DECODE(*pp, config->max_lag);
+
+ H5_DECODE_UNSIGNED(*pp, config->vfd_swmr_writer);
+ H5_DECODE_UNSIGNED(*pp, config->flush_raw_data);
+
+ /* int */
+ INT32DECODE(*pp, config->md_pages_reserved);
+
+ HDstrcpy(config->md_file_path, (const char *)(*pp));
+ *pp += H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1;
+
+ HDstrcpy(config->log_file_path, (const char *)(*pp));
+ *pp += H5F__MAX_VFD_SWMR_FILE_NAME_LEN + 1;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5P__facc_vfd_swmr_config_dec() */
+
+/*-------------------------------------------------------------------------
* Function: H5Pset_core_write_tracking
*
* Purpose: Enables/disables core VFD write tracking and page
@@ -4939,3 +5054,101 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_page_buffer_size() */
+/*-------------------------------------------------------------------------
+ * Function: H5Pset_vfd_swmr_config
+ *
+ * Purpose: Set VFD SWMR configuration in the target FAPL.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; July 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pset_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ size_t name_len;
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", plist_id, config_ptr);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id,H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Validate the input configuration */
+
+ /* Check args */
+ if(config_ptr == NULL)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "NULL config_ptr on entry")
+
+ /* This field must always be set to a known version */
+ if(config_ptr->version != H5F__CURR_VFD_SWMR_CONFIG_VERSION)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "Unknown config version")
+
+ /* This field must be >= 0 */
+ if(config_ptr->tick_len < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "tick_len must be greater than 0")
+
+ /* This field must be at least 3 */
+ if(config_ptr->max_lag < 3 )
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "max_lag must be at least 3")
+
+ /* This field must be >= 1 */
+ if(config_ptr->md_pages_reserved < 1 )
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "md_pages_reserved must be at least 1")
+
+ /* Must provide the path for the metadata file */
+ name_len = HDstrlen(config_ptr->md_file_path);
+ if(name_len == 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "md_file_path is empty")
+ else if(name_len > H5F__MAX_VFD_SWMR_FILE_NAME_LEN)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "md_file_path is too long")
+
+ /* Set the modified config */
+ if(H5P_set(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config_ptr) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set metadata cache initial config")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pset_vfd_swmr_config() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Pget_vfd_swmr_config
+ *
+ * Purpose: Retrieve the VFD SWMR configuration from the target FAPL.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; July 2018
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Pget_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE2("e", "i*x", plist_id, config_ptr);
+
+ /* Get the plist structure */
+ if(NULL == (plist = H5P_object_verify(plist_id,H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID")
+
+ /* Validate the config_ptr */
+ if(config_ptr == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL config_ptr on entry.")
+
+ /* Get the current VFD SWMR configuration */
+ if(H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, config_ptr) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get VFD SWMR config")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* H5Pget_vfd_swmr_config() */
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index c5596e5..3abb3fd 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -370,6 +370,10 @@ H5_DLL herr_t H5Pset_mdc_image_config(hid_t plist_id, H5AC_cache_image_config_t
H5_DLL herr_t H5Pget_mdc_image_config(hid_t plist_id, H5AC_cache_image_config_t *config_ptr /*out*/);
H5_DLL herr_t H5Pset_page_buffer_size(hid_t plist_id, size_t buf_size, unsigned min_meta_per, unsigned min_raw_per);
H5_DLL herr_t H5Pget_page_buffer_size(hid_t plist_id, size_t *buf_size, unsigned *min_meta_per, unsigned *min_raw_per);
+/* VFD SWMR configuration */
+H5_DLL herr_t H5Pset_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr);
+H5_DLL herr_t H5Pget_vfd_swmr_config(hid_t plist_id, H5F_vfd_swmr_config_t *config_ptr);
+
/* Dataset creation property list (DCPL) routines */
H5_DLL herr_t H5Pset_layout(hid_t plist_id, H5D_layout_t layout);
diff --git a/src/H5private.h b/src/H5private.h
index 8974e46..6fa81a0 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -982,6 +982,9 @@ typedef off_t h5_stat_size_t;
#ifndef HDgettimeofday
#define HDgettimeofday(S,P) gettimeofday(S,P)
#endif /* HDgettimeofday */
+#ifndef HDclock_gettime
+ #define HDclock_gettime(C,T) clock_gettime(C,T)
+#endif /* HDclock_gettime */
#ifndef HDgetuid
#define HDgetuid() getuid()
#endif /* HDgetuid */
@@ -1942,6 +1945,12 @@ extern hbool_t H5_libterm_g; /* Is the library being shutdown? */
#define H5_INIT_GLOBAL (H5_libinit_g)
#define H5_TERM_GLOBAL (H5_libterm_g)
+/* Temporary Gobals for VFD SWMR */
+extern hbool_t vfd_swmr_g;
+extern hbool_t vfd_swmr_writer_g;
+extern uint64_t tick_num_g;
+extern struct timespec end_of_tick_g;
+
#endif /* H5_HAVE_THREADSAFE */
#ifdef H5_HAVE_CODESTACK
@@ -2058,12 +2067,32 @@ H5_DLL herr_t H5CX_pop(void);
\
BEGIN_MPE_LOG
+#define VFD_SWMR_TEST_FOR_END_OF_TICK(swmr_reader_exit, err) \
+ /* Initialize the library */ \
+ if(vfd_swmr_g) { \
+ struct timespec curr_time; \
+ if(HDclock_gettime(CLOCK_MONOTONIC, &curr_time) < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTGET, err, "can't get time via clock_gettime") \
+ if( (curr_time.tv_sec >= end_of_tick_g.tv_sec) && \
+ (curr_time.tv_nsec >= end_of_tick_g.tv_nsec) ) { \
+ if(vfd_swmr_writer_g) { \
+ if(H5FD_writer_end_of_tick() < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, "end of tick error for VFD SWMR writer") \
+ } \
+ else if(!swmr_reader_exit) { \
+ if(H5FD_reader_end_of_tick() < 0) \
+ HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, "end of tick error for VFD SWMR reader") \
+ } \
+ } \
+ }
+
/* Use this macro for all "normal" API functions */
#define FUNC_ENTER_API(err) {{ \
FUNC_ENTER_API_COMMON \
FUNC_ENTER_API_INIT(err); \
/* Clear thread error stack entering public functions */ \
H5E_clear_stack(NULL); \
+ VFD_SWMR_TEST_FOR_END_OF_TICK(FALSE, err); \
{
/*
@@ -2298,6 +2327,7 @@ H5_DLL herr_t H5CX_pop(void);
H5TRACE_RETURN(ret_value);
#define FUNC_LEAVE_API(ret_value) \
+ VFD_SWMR_TEST_FOR_END_OF_TICK(!vfd_swmr_writer_g, ret_value); \
FUNC_LEAVE_API_COMMON(ret_value); \
(void)H5CX_pop(); \
H5_POP_FUNC \