summaryrefslogtreecommitdiffstats
path: root/src/H5Fint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Fint.c')
-rw-r--r--src/H5Fint.c257
1 files changed, 255 insertions, 2 deletions
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 39934d6..17c494f 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -81,6 +81,11 @@ static herr_t H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl,
static herr_t H5F__flush_phase1(H5F_t *f);
static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing);
+/* VFD SWMR */
+static herr_t H5F__vfd_swmr_init_info(H5F_t *f);
+static herr_t H5F__vfd_swmr_init_md(H5F_t *f);
+static herr_t H5F__vfd_swmr_close_md(H5F_t *f);
+
/*********************/
/* Package Variables */
@@ -185,6 +190,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, H5I_INVALID_HID, "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, H5I_INVALID_HID, "can't set collective metadata read flag")
@@ -1034,6 +1043,11 @@ 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")
+ f->shared->vfd_swmr_md_fd = -1;
+
/* 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.
@@ -1294,6 +1308,12 @@ H5F__dest(H5F_t *f, hbool_t flush)
/* Push error, but keep going*/
HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list")
+ /* Handle closing for the metadata file (VFD SWMR writer) */
+ if(H5F_ACC_RDWR & H5F_INTENT(f) && f->shared->vfd_swmr_md_fd >= 0) {
+ if(H5F__vfd_swmr_close_md(f) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file")
+ }
+
/* Close the file */
if(H5FD_close(f->shared->lf) < 0)
/* Push error, but keep going*/
@@ -1426,7 +1446,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)
@@ -1596,6 +1617,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.
@@ -1622,6 +1644,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. */
@@ -1636,8 +1661,36 @@ 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) {
+
+ /* Initialize globals for VFD SWMR writer and reader */
+ if(H5F__vfd_swmr_init_info(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "file open fail with initialization for VFD SWMR")
+
+ /* For VFD SWMR writer */
+ if(H5F_INTENT(file) & H5F_ACC_RDWR) {
+ HDassert(file->shared->vfd_swmr_config.vfd_swmr_writer);
+
+ /* Create the metadata file */
+ if(((file->shared->vfd_swmr_md_fd = HDopen(file->shared->vfd_swmr_config.md_file_path, O_CREAT|O_RDWR, H5_POSIX_CREATE_MODE_RW))) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create the metadata file")
+
+ /* Create header and empty index in the metadata file */
+ if(!file_create) {
+ if(H5F__vfd_swmr_init_md(file) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "fail to initialize md 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
@@ -1741,9 +1794,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() */
@@ -3465,3 +3524,197 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__format_convert() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__vfd_swmr_init_info
+ *
+ * Purpose: Initialize globals and the corresponding fields in file pointer.
+ * 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
+ * For VFD SWMR reader:
+ * --set vfd_swmr_g to TRUE
+ * --set vfd_swmr_writer_g to FALSE
+ * --set tick_num_g to the current tick read from the metadata file
+ * --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__vfd_swmr_init_info(H5F_t *f)
+{
+ struct timespec tmp_end_of_tick;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ if(f->shared->vfd_swmr_config.vfd_swmr_writer) {
+ vfd_swmr_writer_g = f->shared->vfd_swmr_writer = TRUE;
+ tick_num_g = f->shared->tick_num = 0;
+ } else {
+ HDassert(!f->shared->vfd_swmr_config.vfd_swmr_writer);
+ vfd_swmr_writer_g = f->shared->vfd_swmr_writer = FALSE;
+
+ /* Set tick_num_g to the current tick read from the metadata file */
+ if(H5FD_vfd_swmr_get_tick_and_idx(f->shared->lf, FALSE, &tick_num_g, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTLOAD, FAIL, "unable to load/decode metadata file")
+ f->shared->tick_num = tick_num_g;
+ }
+
+ /* 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_g = f->shared->vfd_swmr = TRUE;
+ vfd_swmr_file_g = f->shared;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__vfd_swmr_init_info() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__vfd_swmr_init_md
+ *
+ * Purpose: Encode the header and an empty index to the metadata file.
+ * This is used by the VFD SWMR writer when:
+ * --opening an existing HDF5 file
+ * --the HDF5 file is flushed and about to close
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__vfd_swmr_init_md(H5F_t *f)
+{
+ uint8_t *p = NULL; /* Pointer to buffer */
+ uint8_t *pp = NULL; /* Pointer to buffer for index */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ uint8_t image[H5FD_MD_HEADER_SIZE + H5FD_MD_EMPTY_INDEX_SIZE]; /* Buffer for header and empty index */
+ unsigned hdr_idx_size = H5FD_MD_HEADER_SIZE + H5FD_MD_EMPTY_INDEX_SIZE; /* Size of header and index */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /*
+ * Encode metadata file header
+ */
+ p = image;
+
+ /* Encode magic for header */
+ HDmemcpy(p, H5FD_MD_HEADER_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ /* Encode page size, tick number, index offset, index length */
+ 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));
+
+ /* Calculate checksum for header */
+ metadata_chksum = H5_checksum_metadata(image, (size_t)(p - image), 0);
+
+ /* Encode checksum for header */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Sanity checks on header */
+ HDassert((size_t)(p - image == H5FD_MD_HEADER_SIZE));
+
+ /*
+ * Encode metadata file index
+ */
+ pp = p;
+
+ /* Encode magic for index */
+ HDmemcpy(p, H5FD_MD_INDEX_MAGIC, (size_t)H5_SIZEOF_MAGIC);
+ p += H5_SIZEOF_MAGIC;
+
+ /* Encode tick number */
+ UINT64ENCODE(p, f->shared->tick_num);
+
+ /* Encode zero number of entries in index */
+ UINT32ENCODE(p, 0);
+
+ /* Calculate checksum for index */
+ metadata_chksum = H5_checksum_metadata(pp, (size_t)(p - pp), 0);
+
+ /* Encode checksum for index */
+ UINT32ENCODE(p, metadata_chksum);
+
+ /* Sanity checks on index */
+ HDassert((size_t)(p - pp == H5FD_MD_EMPTY_INDEX_SIZE));
+
+ /* Verify the md file descriptor exists */
+ HDassert(f->shared->vfd_swmr_md_fd >= 0);
+
+ /* Set to beginning of the file */
+ if(HDlseek(f->shared->vfd_swmr_md_fd, (HDoff_t)0, SEEK_SET) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file")
+
+ /* Write header and empty index to the metadata file */
+ if(HDwrite(f->shared->vfd_swmr_md_fd, image, hdr_idx_size) != hdr_idx_size)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing header and index to metadata file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__vfd_swmr_init_md() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__vfd_swmr_close_md
+ *
+ * Purpose: This is used by the VFD SWMR writer when the HDF5 file is
+ * flushed and about to close:
+ * --increment the tick
+ * --write header and an empty index to the metadata file
+ * --close and unlink the metadata file
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__vfd_swmr_close_md(H5F_t *f)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert(f->shared->vfd_swmr_md_fd >= 0);
+
+ /* Increment tick_num */
+ tick_num_g = ++f->shared->tick_num;
+
+ /* Write an empty header and index to the md file */
+ if(H5F__vfd_swmr_init_md(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to encode and write to the metadata file")
+
+ /* Close the md file */
+ if(HDclose(f->shared->vfd_swmr_md_fd) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file")
+ f->shared->vfd_swmr_md_fd = -1;
+
+ /* Unlink the md file */
+ if(HDunlink(f->shared->vfd_swmr_config.md_file_path) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTREMOVE, FAIL, "unable to unlink the metadata file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__vfd_swmr_close_md() */