summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVailin Choi <vchoi@jam.ad.hdfgroup.org>2018-09-28 16:29:02 (GMT)
committerVailin Choi <vchoi@jam.ad.hdfgroup.org>2018-09-28 16:29:02 (GMT)
commit5c7ca8afff0e635f12652c35dbe9818235ac34c4 (patch)
tree1245d78ca4b0aaeb40ecab6b2615ddad886042c3 /src
parent06fa8a94558939400dc43e99c08a784e26dfa01d (diff)
downloadhdf5-5c7ca8afff0e635f12652c35dbe9818235ac34c4.zip
hdf5-5c7ca8afff0e635f12652c35dbe9818235ac34c4.tar.gz
hdf5-5c7ca8afff0e635f12652c35dbe9818235ac34c4.tar.bz2
Third batch of checkin:
1) Free space manager for the metadata file 2) Delayed free space release linked list 3) H5F_update_vfd_swmr_metadata_file() 3) VFD SWMR driver: read callback 4) Flushing for VFD SWMR 5) Port one concurrent test from swmr test set 6) Bug fixes and refactoring
Diffstat (limited to 'src')
-rw-r--r--src/H5.c7
-rw-r--r--src/H5F.c1
-rw-r--r--src/H5FDprivate.h66
-rw-r--r--src/H5FDvfd_swmr.c315
-rw-r--r--src/H5FDvfd_swmr.h1
-rw-r--r--src/H5FSprivate.h1
-rw-r--r--src/H5Fint.c579
-rw-r--r--src/H5Fpkg.h46
-rw-r--r--src/H5Fprivate.h20
-rw-r--r--src/H5Fquery.c24
-rw-r--r--src/H5Fspace.c160
-rw-r--r--src/H5MV.c518
-rw-r--r--src/H5MVmodule.h33
-rw-r--r--src/H5MVpkg.h83
-rw-r--r--src/H5MVprivate.h58
-rw-r--r--src/H5MVsection.c361
-rw-r--r--src/H5Pfapl.c4
-rw-r--r--src/H5private.h27
-rw-r--r--src/Makefile.am1
19 files changed, 1994 insertions, 311 deletions
diff --git a/src/H5.c b/src/H5.c
index 20038fe..c401667 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -85,13 +85,6 @@ 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/H5F.c b/src/H5F.c
index c6db168..e168343 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -2016,6 +2016,7 @@ H5Fvfd_swmr_end_tick(hid_t file_id)
HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "must have VFD SWMR configured for this public routine")
/* ??Trigger end of tick processing later */
+ H5F_vfd_swmr_writer_end_of_tick();
done:
FUNC_LEAVE_API(ret_value)
diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h
index 57be23a..16bb2b7 100644
--- a/src/H5FDprivate.h
+++ b/src/H5FDprivate.h
@@ -71,23 +71,15 @@
/* Size of the metadata file index */
#define H5FD_MD_INDEX_SIZE(N) /* N is number of entries in index */ \
( \
- H5_SIZEOF_MAGIC /* Signature */ \
+ 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 */ \
)
-#define H5FD_MD_EMPTY_INDEX_SIZE \
- ( \
- H5_SIZEOF_MAGIC /* Signature */ \
- + 8 /* Tick num */ \
- + 4 /* Number of entries */ \
- + H5FD_SIZEOF_CHKSUM /* Metadata header checksum */ \
- )
-
/* Retries for metadata file */
-#define H5FD_VFD_SWMR_MD_FILE_RETRY_MAX 50 /* Maximum retries when opening the MD file */
+#define H5FD_VFD_SWMR_MD_FILE_RETRY_MAX 50 /* Maximum retries when opening the MD file */
#define H5FD_VFD_SWMR_MD_LOAD_RETRY_MAX 20 /* Maximum retries when trying to load the MD file header and index */
#define H5FD_VFD_SWMR_MD_HEADER_RETRY_MAX 40 /* Maximum retries when deserializing the MD file header */
#define H5FD_VFD_SWMR_MD_INDEX_RETRY_MAX 5 /* Maximum retries when deserializing the MD file index */
@@ -115,16 +107,48 @@ typedef struct H5FD_vfd_swmr_md_header {
* metadata page, or multi page metadata entry in the HDF5
* file IN PAGES.
* To obtain byte offset, multiply this value by the page size.
+ *
* md_file_page_offset: Unsigned 64-bit value containing the base address of the
* metadata page, or multi page metadata entry in the metadata
* file IN PAGES.
* To obtain byte offset, multiply this value by the page size.
- * length: The length of the metadata page or multi page metadata entry
+ *
+ * length: The length of the metadata page or multi- page metadata entry
* in BYTES.
- * chksum: Checksum for the metadata page or multi page metadata entry
+ *
+ * chksum: Checksum for the metadata page or multi-page metadata entry.
+ * For the VFD SWMR writer, this value is undefined until the
+ * referenced entry has been written to the metadata file.
+ *
+ * entry_ptr: Used by the VFD SWMR writer only.
+ * For the VFD SWMR reader, this field should always be NULL.
+ * If the referenced metadata page or multi-page metadata
+ * entry was modified in the current tick, this field points to
+ * a buffer in the page buffer containing its value.
+ * This field is used by the metadata file creation/update code
+ * to access the metadata pages or multi-page metadata entries
+ * so that their current values can be copied into the metadata
+ * file. After this copy, this field should be set to NULL.
+ *
* tick_of_last_change: Number of the last tick in which this index entry was changed.
- * This field is only used by the VFD SWMR writer.
- * For readers, it will always be set to 0.
+ * Used by the VFD SWMR writer only.
+ * For the VFD SWMR reader, this field will always be set to 0.
+ *
+ * clean: Used by the VFD SWMR writer only.
+ * Set to TRUE whenever the referenced metadata page or multi-page
+ * metadata entry is written to the HDF5 file.
+ * Set to FALSE whenever it is marked dirty in the page buffer.
+ *
+ * tick_of_last_flush: Number of the tick in which this entry was last written to the
+ * HDF5 file or zero if it has never been flusehd.
+ * Used by the VFD SWMR writer only.
+ * For the VFD SWMR reader, this field should always be 0.
+ *
+ * delayed_flush: If the flush of the referenced metadata page or multi-page
+ * metadata entry must be delayed, the earliest tick in which
+ * it may be flushed, or zero if there is no such constraint.
+ * Used by the VFD SWMR writer only.
+ *
* is_moved_to_hdf5_file: Set to TRUE iff the entry referenced is in the HDF5 file and
* is therefore about to be removed from the metadata file
*/
@@ -133,8 +157,12 @@ typedef struct H5FD_vfd_swmr_idx_entry_t {
uint64_t md_file_page_offset;
uint32_t length;
uint32_t chksum;
+ void *entry_ptr;
uint64_t tick_of_last_change;
- hbool_t is_moved_to_hdf5_file;
+ hbool_t clean;
+ uint64_t tick_of_last_flush;
+ uint64_t delayed_flush;
+ hbool_t moved_to_hdf5_file;
} H5FD_vfd_swmr_idx_entry_t;
/*
@@ -145,9 +173,9 @@ typedef struct H5FD_vfd_swmr_idx_entry_t {
* entries: The array of index entries
*/
typedef struct H5FD_vfd_swmr_md_index {
- uint64_t tick_num;
- uint32_t num_entries;
- H5FD_vfd_swmr_idx_entry_t *entries;
+ uint64_t tick_num;
+ uint32_t num_entries;
+ H5FD_vfd_swmr_idx_entry_t *entries;
} H5FD_vfd_swmr_md_index;
@@ -270,8 +298,6 @@ 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_vfd_swmr_writer_end_of_tick();
-H5_DLL herr_t H5FD_vfd_swmr_reader_end_of_tick();
H5_DLL herr_t H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t read_index,
uint64_t *tick_ptr, uint32_t *num_entries_ptr, H5FD_vfd_swmr_idx_entry_t index[]);
diff --git a/src/H5FDvfd_swmr.c b/src/H5FDvfd_swmr.c
index e4df4f1..9dcf8ef 100644
--- a/src/H5FDvfd_swmr.c
+++ b/src/H5FDvfd_swmr.c
@@ -12,7 +12,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
- * Purpose:
+ * Purpose: VFD SWMR driver
*/
#include "H5FDdrvr_module.h" /* This source code file is part of the H5FD driver module */
@@ -251,8 +251,8 @@ H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxa
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
/* Allocate buffer for reading the VFD SWMR configuration */
- if(NULL == (vfd_swmr_config = (uint8_t *)H5MM_malloc(sizeof(H5F_vfd_swmr_config_t))))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "memory allocation failed for H5F_vfd_swmr_config_t")
+ if(NULL == (vfd_swmr_config = (H5F_vfd_swmr_config_t *)H5MM_malloc(sizeof(H5F_vfd_swmr_config_t))))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "memory allocation failed for H5F_vfd_swmr_config_t")
/* Get VFD SWMR configuration */
if(H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, vfd_swmr_config) < 0)
@@ -290,7 +290,7 @@ H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxa
HGOTO_ERROR(H5E_VFL, H5E_OPENERROR, NULL, "unable to open the metadata file after all retry attempts")
/* Retry on loading and decoding the header and index in the metadata file */
- if(H5FD_vfd_swmr_load_hdr_and_idx(file, TRUE) < 0)
+ if(H5FD_vfd_swmr_load_hdr_and_idx((H5FD_t *)file, TRUE) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "unable to load/decode the md file header/index")
/* Hard-wired to open the underlying HDF5 file with SEC2 */
@@ -303,12 +303,12 @@ H5FD_vfd_swmr_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxa
done:
/* Free the buffer */
if(vfd_swmr_config)
- vfd_swmr_config = (uint8_t *)H5MM_xfree(vfd_swmr_config);
+ vfd_swmr_config = (H5F_vfd_swmr_config_t *)H5MM_xfree(vfd_swmr_config);
/* Handle closing if error */
if(NULL == ret_value && file) {
- if(H5FD_vfd_swmr_close(file) < 0)
- HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "error from closing")
+ if(H5FD_vfd_swmr_close((H5FD_t *)file) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "error from closing")
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -370,9 +370,6 @@ H5FD_vfd_swmr_close(H5FD_t *_file)
* Failure: never fails (arguments were checked by the
* caller).
*
- * Programmer: Robb Matzke
- * Thursday, July 29, 1999
- *
*-------------------------------------------------------------------------
*/
static int
@@ -398,13 +395,10 @@ H5FD_vfd_swmr_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
*
* Return: SUCCEED (Can't fail)
*
- * Programmer: Quincey Koziol
- * Friday, August 25, 2000
- *
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_vfd_swmr_query(const H5FD_t *_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
@@ -434,9 +428,6 @@ H5FD_vfd_swmr_query(const H5FD_t *_file, unsigned long *flags /* out */)
*
* Return: The end-of-address marker.
*
- * Programmer: Robb Matzke
- * Monday, August 2, 1999
- *
*-------------------------------------------------------------------------
*/
static haddr_t
@@ -448,7 +439,7 @@ H5FD_vfd_swmr_get_eoa(const H5FD_t *_file, H5FD_mem_t type)
FUNC_ENTER_NOAPI_NOINIT
if((ret_value = H5FD_get_eoa(file->hdf5_file_lf, type)) == HADDR_UNDEF)
- HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to get HDF5 file eoa")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, HADDR_UNDEF, "unable to get HDF5 file eoa")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -464,9 +455,6 @@ done:
*
* Return: SUCCEED (Can't fail)
*
- * Programmer: Robb Matzke
- * Thursday, July 29, 1999
- *
*-------------------------------------------------------------------------
*/
static herr_t
@@ -507,7 +495,7 @@ H5FD_vfd_swmr_get_eof(const H5FD_t *_file, H5FD_mem_t type)
/* 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, FAIL, "unable to set file eoa")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, HADDR_UNDEF, "unable to set file eoa")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -559,44 +547,112 @@ static herr_t
H5FD_vfd_swmr_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
haddr_t addr, size_t size, void *buf /*out*/)
{
- H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file;
-H5FD_vfd_swmr_idx_entry_t *index;
- herr_t ret_value = SUCCEED; /* Return value */
+ H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */
+ H5FD_vfd_swmr_idx_entry_t *index = NULL; /* Metadata file index */
+ unsigned entry_retries = H5FD_VFD_SWMR_MD_INDEX_RETRY_MAX; /* # of retries */
+ uint64_t nanosec = 1; /* # of nanoseconds to sleep between retries */
+ uint32_t num_entries = 0; /* Number of entries in index */
+ uint32_t fs_page_size; /* Page size */
+ unsigned lo = 0, hi; /* Low & high index values */
+ unsigned my_idx = 0; /* Final index value */
+ int cmp; /* Return from comparison */
+ uint32_t computed_chksum; /* Computed checksum */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
HDassert(file && file->pub.cls);
HDassert(buf);
-#ifdef TEMP
-tick_num
-num_entries
-H5FD_vfd_swmr_idx_entry_t *index;
- if(H5FD_vfd_swmr_get_tick_and_idx(file, TRUE, &tick_num, &num_entries, NULL) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FALSE, "unable to retrieve tick and entries from the md file")
+ /* Try loading and decoding the header and index in the metadata file */
+ if(H5FD_vfd_swmr_load_hdr_and_idx(_file, FALSE) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "unable to load/decode the md file header/index")
+ fs_page_size = file->md_header.fs_page_size;
+ num_entries = file->md_index.num_entries;
if(num_entries) {
-
/* Allocate memory for index entries */
if(NULL == (index = H5FL_SEQ_MALLOC(H5FD_vfd_swmr_idx_entry_t, num_entries)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FALSE, "memory allocation failed for index entries")
-
- /* Get the entries for the index */
- if(H5FD_vfd_swmr_get_tick_and_idx(file, FALSE, FALSE, &tick_num, &num_entries, index) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "unable to load/decode the md file header/index")
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "memory allocation failed for index entries")
+ HDmemcpy(index, file->md_index.entries, num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t));
}
-search for addr from the index
-if found, read the page into buf based on the offset/size found in the index and return
-otherwise read from the underlying HDF5 file
-#endif
+ /* Try finding the addr from the index */
+ cmp = -1;
+ lo = 0;
+ hi = num_entries;
+ while(lo < hi && cmp) {
+ my_idx = (lo + hi) / 2;
+ cmp = H5F_addr_cmp(index[my_idx].hdf5_page_offset * fs_page_size, addr);
+ if(cmp < 0)
+ hi = my_idx;
+ else
+ lo = my_idx + 1;
+ } /* end while */
+
+ /* Found in index, read from the metadata file */
+ if(cmp == 0) {
+ HDassert(size == index[my_idx].length);
+
+ do {
+ if(HDlseek(file->md_fd, (HDoff_t)index[my_idx].md_file_page_offset * fs_page_size, SEEK_SET) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file")
+
+ /* Coding borrowed from sec2 read */
+ while(size > 0) {
+
+ h5_posix_io_t bytes_in = 0; /* # of bytes to read */
+ h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */
+
+ /* Trying to read more bytes than the return type can handle is
+ * undefined behavior in POSIX.
+ */
+ if(size > H5_POSIX_MAX_IO_BYTES)
+ bytes_in = H5_POSIX_MAX_IO_BYTES;
+ else
+ bytes_in = (h5_posix_io_t)size;
+
+ do {
+ bytes_read = HDread(file->md_fd, buf, bytes_in);
+ } while(-1 == bytes_read && EINTR == errno);
+
+ if(-1 == bytes_read) /* error */
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "error reading the page/multi-page entry from the md file")
+
+ HDassert(bytes_read >= 0);
+ HDassert((size_t)bytes_read <= size);
+
+ size -= (size_t)bytes_read;
+ addr += (haddr_t)bytes_read;
+ buf = (char *)buf + bytes_read;
+ } /* end while size */
+
+ /* Verify stored and computed checksums are equal */
+ computed_chksum = H5_checksum_metadata(buf, index[my_idx].length, 0);
+ if(index[my_idx].chksum == computed_chksum)
+ break;
+
+ /* Double the sleep time next time */
+ H5_nanosleep(nanosec);
+ nanosec *= 2;
- if(H5FD_read(file->hdf5_file_lf, type, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "file read request failed")
+ } while(--entry_retries);
+
+ /* Exhaust all retries for reading the page/multi-page entry */
+ if(entry_retries == 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTLOAD, FAIL, "error in reading the page/multi-page entry")
+
+ } else { /* 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")
+ }
done:
if(ret_value < 0) {
- /* What needs to be cleaned up */
+ if(index) {
+ HDassert(num_entries);
+ index = H5FL_SEQ_FREE(H5FD_vfd_swmr_idx_entry_t, num_entries);
+ }
} /* end if */
FUNC_LEAVE_NOAPI(ret_value)
@@ -628,16 +684,12 @@ H5FD_vfd_swmr_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id
HDassert(file && file->pub.cls);
HDassert(buf);
-
+
+ /* SHOULDN'T come here ?? */
if(H5FD_write(file->hdf5_file_lf, type, addr, size, buf) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed")
done:
- if(ret_value < 0) {
- /* Reset last file I/O information */
- /* What needs to be cleaned up */
- } /* end if */
-
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_vfd_swmr_write() */
@@ -653,7 +705,7 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FD_vfd_swmr_truncate(H5FD_t *_file, hid_t 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 */
herr_t ret_value = SUCCEED; /* Return value */
@@ -683,7 +735,6 @@ static herr_t
H5FD_vfd_swmr_lock(H5FD_t *_file, hbool_t rw)
{
H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */
- int lock_flags; /* file locking flags */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -724,49 +775,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD_vfd_swmr_unlock() */
-
-/*-------------------------------------------------------------------------
- * Function: H5FD_vfd_swmr_get_tick_and_idx()
- *
- * Purpose: Retrieve tick_num, num_entries and index from the metadata file
- * --If the parameter "reload_hdr_and_index" is true, load and decode the header
- * and index via H5FD_vfd_swmr_load_hdr_and_idx(), which may replace the VFD's
- * local copies of header and index with the latest info read.
- * --Return tick_num, num_entries and index from the VFD's local copies.
- *
- * Return: Success: SUCCEED
- * Failure: FAIL
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t reload_hdr_and_index,
- uint64_t *tick_ptr, uint32_t *num_entries_ptr, H5FD_vfd_swmr_idx_entry_t index[])
-{
- H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */
- H5FD_t *ret_value = FALSE; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT
-
- if(reload_hdr_and_index) {
- if(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)
- *tick_ptr = file->md_header.tick_num;
-
- if(num_entries_ptr != NULL) {
- if(*num_entries_ptr >= file->md_index.num_entries && index != NULL)
- HDmemcpy(index, file->md_index.entries, (file->md_index.num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)));
-
- *num_entries_ptr = file->md_index.num_entries;
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FD_vfd_swmr_get_tick_and_idx() */
/*-------------------------------------------------------------------------
@@ -802,7 +810,7 @@ H5FD_vfd_swmr_load_hdr_and_idx(H5FD_t *_file, hbool_t open)
uint64_t nanosec = 1; /* # of nanoseconds to sleep between retries */
H5FD_vfd_swmr_md_header md_header; /* Metadata file header */
H5FD_vfd_swmr_md_index md_index; /* Metadata file index */
- H5FD_t *ret_value = FALSE; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
@@ -811,11 +819,11 @@ H5FD_vfd_swmr_load_hdr_and_idx(H5FD_t *_file, hbool_t open)
HDmemset(&md_index, 0, sizeof(H5FD_vfd_swmr_md_index));
/* Load and decode the header */
- if(H5FD_vfd_swmr_header_deserialize(file, &md_header) >= 0) {
+ if(H5FD_vfd_swmr_header_deserialize(_file, &md_header) >= 0) {
/* Error if header + index fit does not within md_pages_reserved */
if((H5FD_MD_HEADER_SIZE + md_header.index_length) >
- (file->md_pages_reserved * md_header.fs_page_size))
+ (uint64_t)((hsize_t)file->md_pages_reserved * md_header.fs_page_size))
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "header + index does not fit within md_pages_reserved")
if(!open) {
@@ -828,7 +836,7 @@ H5FD_vfd_swmr_load_hdr_and_idx(H5FD_t *_file, hbool_t open)
HDassert(md_header.tick_num > file->md_header.tick_num || open);
/* Load and decode the index */
- if(H5FD_vfd_swmr_index_deserialize(file, &md_index, &md_header) >= 0) {
+ if(H5FD_vfd_swmr_index_deserialize(_file, &md_index, &md_header) >= 0) {
/* tick_num is the same in both header and index */
if(md_header.tick_num == md_index.tick_num) {
@@ -891,7 +899,7 @@ H5FD_vfd_swmr_header_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_header *md_head
do {
/* Retrieve the metadata file size */
if(HDfstat(file->md_fd, &stat_buf))
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "unable to fstat the md file")
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "unable to fstat the md file")
/* Verify file size is at least header size */
if(stat_buf.st_size >= H5FD_MD_HEADER_SIZE)
@@ -904,7 +912,7 @@ H5FD_vfd_swmr_header_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_header *md_head
/* Exhaust all retries for "stat" the md file */
if(file_retries == 0)
- HGOTO_ERROR(H5E_VFL, H5E_OPENERROR, NULL, "unable to the metadata file after all retry attempts")
+ HGOTO_ERROR(H5E_VFL, H5E_OPENERROR, FAIL, "unable to the metadata file after all retry attempts")
/* Try to get valid magic and checksum for header */
p = image;
@@ -991,10 +999,10 @@ H5FD_vfd_swmr_index_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_index *md_index,
do {
/* Retrieve the metadata file size */
if(HDfstat(file->md_fd, &stat_buf))
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "unable to fstat the md file")
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "unable to fstat the md file")
/* Verify file size is at least header size */
- if(stat_buf.st_size >= (H5FD_MD_HEADER_SIZE + md_header->index_length))
+ if((uint64_t)stat_buf.st_size >= (H5FD_MD_HEADER_SIZE + md_header->index_length))
break;
/* Sleep and double the sleep time next time */
@@ -1011,7 +1019,7 @@ H5FD_vfd_swmr_index_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_index *md_index,
do {
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(HDread(file->md_fd, image, md_header->index_length) < md_header->index_length)
+ if(HDread(file->md_fd, image, md_header->index_length) < (int64_t)md_header->index_length)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "error in reading the header in metadata file")
/* Verify valid magic for index */
@@ -1022,8 +1030,9 @@ H5FD_vfd_swmr_index_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_index *md_index,
if(stored_chksum == computed_chksum)
break;
}
+ /* Double the sleep time next time */
H5_nanosleep(nanosec);
- nanosec *= 2; /* Double the sleep time next time */
+ nanosec *= 2;
} while(--index_retries);
/* Exhaust all retries for loading the index */
@@ -1041,7 +1050,7 @@ H5FD_vfd_swmr_index_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_index *md_index,
if(md_index->num_entries) {
/* Allocate memory for index entries */
if(NULL == (md_index->entries = H5FL_SEQ_MALLOC(H5FD_vfd_swmr_idx_entry_t, md_index->num_entries)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, NULL, "memory allocation failed for 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++) {
@@ -1051,8 +1060,6 @@ H5FD_vfd_swmr_index_deserialize(H5FD_t *_file, H5FD_vfd_swmr_md_index *md_index,
UINT32DECODE(p, md_index->entries[i].chksum);
} /* end for */
- /* MAY BE SORTED ALREADY: Sort entries in increasing hdf5_page_offset */
- //HDqsort(file->md_index.entries, num_entries, sizeof(H5FD_vfd_swmr_idx_entry_t), H5FD__idx_entry_cmp);
} /* end if */
/* Checksum is already valid */
@@ -1070,70 +1077,46 @@ done:
/*-------------------------------------------------------------------------
-* Function: H5FD_vfd_swmr_writer_end_of_tick
-*
-* Purpose: TBD
-*
-* Return: SUCCEED/FAIL
-*
-* Programmer:
-*
-*-------------------------------------------------------------------------
-*/
-herr_t
-H5FD_vfd_swmr_writer_end_of_tick(void)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_vfd_swmr_writer_end_of_tick() */
-
-
-/*-------------------------------------------------------------------------
-* Function: H5FD_vfd_swmr_reader_end_of_tick
-*
-* Purpose: TBD
-*
-* Return: SUCCEED/FAIL
-*
-*-------------------------------------------------------------------------
-*/
+ * Function: H5FD_vfd_swmr_get_tick_and_idx()
+ *
+ * Purpose: Retrieve tick_num, num_entries and index from the metadata file
+ * --If the parameter "reload_hdr_and_index" is true, load and decode
+ * the header and index via H5FD_vfd_swmr_load_hdr_and_idx(), which
+ * may replace the VFD's local copies of header and index with the
+ * latest info read.
+ * --Return tick_num, num_entries and index from the VFD's local copies.
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5FD_vfd_swmr_reader_end_of_tick(void)
+H5FD_vfd_swmr_get_tick_and_idx(H5FD_t *_file, hbool_t reload_hdr_and_index,
+ uint64_t *tick_ptr, uint32_t *num_entries_ptr, H5FD_vfd_swmr_idx_entry_t index[])
{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5FD_vfd_swmr_reader_end_of_tick() */
-
+ H5FD_vfd_swmr_t *file = (H5FD_vfd_swmr_t *)_file; /* VFD SWMR file struct */
+ herr_t ret_value = SUCCEED; /* Return value */
-/* Used by HDqsort: keep this for now */
-#ifdef TEMP
-static int
-H5FD__idx_entry_cmp(const void *_entry1, const void *_entry2)
-{
- const H5FD_vfd_swmr_idx_entry_t *entry1 = (const H5FD_vfd_swmr_idx_entry_t *)_entry1;
- const H5FD_vfd_swmr_idx_entry_t *entry2 = (const H5FD_vfd_swmr_idx_entry_t *)_entry2;
+ FUNC_ENTER_NOAPI_NOINIT
- int ret_value = 0; /* Return value */
+ /* Load and decode the header and index as indicated */
+ if(reload_hdr_and_index) {
+ if(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")
+ }
- FUNC_ENTER_STATIC_NOERR
+ /* Return tick_num */
+ if(tick_ptr != NULL)
+ *tick_ptr = file->md_header.tick_num;
- /* Sanity checks */
- HDassert(entry1);
- HDassert(entry2);
+ if(num_entries_ptr != NULL) {
+ if(*num_entries_ptr >= file->md_index.num_entries && index != NULL)
+ HDmemcpy(index, file->md_index.entries, (file->md_index.num_entries * sizeof(H5FD_vfd_swmr_idx_entry_t)));
- if(entry1->hdf5_page_offset < entry2->hdf5_page_offset)
- ret_value = -1;
- else if(entry1->hdf5_page_offset > entry2->hdf5_page_offset)
- ret_value = 1;
- else
- ret_value = 0;
+ *num_entries_ptr = file->md_index.num_entries;
+ }
+done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5FD__idx_entry_cmp() */
-#endif
+} /* H5FD_vfd_swmr_get_tick_and_idx() */
diff --git a/src/H5FDvfd_swmr.h b/src/H5FDvfd_swmr.h
index d317a18..3e4a1ce 100644
--- a/src/H5FDvfd_swmr.h
+++ b/src/H5FDvfd_swmr.h
@@ -27,6 +27,7 @@ extern "C" {
#endif
H5_DLL hid_t H5FD_vfd_swmr_init(void);
+H5_DLL herr_t H5Pset_fapl_vfd_swmr(hid_t fapl_id);
#ifdef __cplusplus
}
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index de1b4c1..374576e 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -133,6 +133,7 @@ struct H5FS_section_info_t {
typedef enum H5FS_client_t {
H5FS_CLIENT_FHEAP_ID = 0, /* Free space is used by fractal heap */
H5FS_CLIENT_FILE_ID, /* Free space is used by file */
+ H5FS_CLIENT_MD_VFD_ID, /* Free space is used by the metadata file for VFD SWMR */
H5FS_NUM_CLIENT_ID /* Number of free space client IDs (must be last) */
} H5FS_client_t;
diff --git a/src/H5Fint.c b/src/H5Fint.c
index 17c494f..248d7a4 100644
--- a/src/H5Fint.c
+++ b/src/H5Fint.c
@@ -33,6 +33,7 @@
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MVprivate.h" /* File memory management for VFD SWMR */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
@@ -43,6 +44,41 @@
/* Local Macros */
/****************/
+/* VFD SWMR */
+/* Append entry to the delayed free spaced release linked list */
+#define H5F_DC_APPEND(entry_ptr, head_ptr, tail_ptr, len) \
+{ \
+ if((head_ptr) == NULL) { \
+ (head_ptr) = (entry_ptr); \
+ (tail_ptr) = (entry_ptr); \
+ } else { \
+ (tail_ptr)->next = (entry_ptr); \
+ (entry_ptr)->prev = (tail_ptr); \
+ (tail_ptr) = (entry_ptr); \
+ } \
+ (len)++; \
+} /* H5F_DC_APPEND() */
+
+/* Remove entry from delayed free spaced release linked list */
+#define H5F_DC_REMOVE(entry_ptr, head_ptr, tail_ptr, len) \
+{ \
+ if((head_ptr) == (entry_ptr)) { \
+ (head_ptr) = (entry_ptr)->next; \
+ if((head_ptr) != NULL ) \
+ (head_ptr)->prev = NULL; \
+ } else \
+ (entry_ptr)->prev->next = (entry_ptr)->next; \
+ if((tail_ptr) == (entry_ptr)) { \
+ (tail_ptr) = (entry_ptr)->prev; \
+ if((tail_ptr) != NULL) \
+ (tail_ptr)->next = NULL; \
+ } else \
+ (entry_ptr)->next->prev = (entry_ptr)->prev; \
+ entry_ptr->next = NULL; \
+ entry_ptr->prev = NULL; \
+ (len)--; \
+} /* H5F_DC_REMOVE() */
+
/******************/
/* Local Typedefs */
/******************/
@@ -82,15 +118,25 @@ 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);
+static herr_t H5F__vfd_swmr_init(H5F_t *f, hbool_t file_create);
+static herr_t H5F__vfd_swmr_close_or_flush(H5F_t *f, hbool_t closing);
+static herr_t H5F__vfd_swmr_update_end_of_tick(H5F_t *f);
+static herr_t H5F__vfd_swmr_construct_write_md_hdr(H5F_t *f, uint32_t index_len);
+static herr_t H5F__vfd_swmr_construct_write_md_idx(H5F_t *f, uint32_t index_len, struct H5FD_vfd_swmr_idx_entry_t index[]);
+static herr_t H5F__idx_entry_cmp(const void *_entry1, const void *_entry2);
/*********************/
/* Package Variables */
/*********************/
+/* VFD SWMR globals */
+H5F_t *vfd_swmr_file_g; /* Points to the file struct */
+hbool_t vfd_swmr_g = FALSE; /* Is this a VFD SWMR configured file */
+hbool_t vfd_swmr_writer_g = FALSE; /* Is this the VFD SWMR writer */
+uint64_t tick_num_g = 0; /* The current tick_num */
+struct timespec end_of_tick_g; /* The current end_of_tick */
+
/*****************************/
/* Library Private Variables */
@@ -107,6 +153,10 @@ H5FL_DEFINE(H5F_t);
/* Declare a free list to manage the H5F_file_t struct */
H5FL_DEFINE(H5F_file_t);
+/* Declare a free list to manage the H5F_vfd_swmr_dl_entry_t struct */
+H5FL_DEFINE(H5F_vfd_swmr_dl_entry_t);
+
+
/*-------------------------------------------------------------------------
@@ -1046,7 +1096,13 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_
/* 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")
+
+ /* Initialization for VFD SWMR */
f->shared->vfd_swmr_md_fd = -1;
+ f->shared->fs_man_md = NULL;
+ f->shared->dl_head_ptr = NULL;
+ f->shared->dl_tail_ptr = NULL;
+ f->shared->dl_len = 0;
/* Create a metadata cache with the specified number of elements.
* The cache might be created with a different number of elements and
@@ -1308,9 +1364,9 @@ 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) */
+ /* VFD SWMR: closing down */
if(H5F_ACC_RDWR & H5F_INTENT(f) && f->shared->vfd_swmr_md_fd >= 0) {
- if(H5F__vfd_swmr_close_md(f) < 0)
+ if(H5F__vfd_swmr_close_or_flush(f, TRUE) < 0)
HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file")
}
@@ -1664,30 +1720,16 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
} /* end if */
+ /* Checked if configured for VFD SWMR */
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)
+ /* Initialization for VFD SWMR writer and reader */
+ if(1 == shared->nrefs) {
+ if(H5F__vfd_swmr_init(file, file_create) < 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")
- }
- }
}
}
@@ -1755,7 +1797,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
} /* version 3 superblock */
file->shared->sblock->status_flags |= H5F_SUPER_WRITE_ACCESS;
- if(H5F_INTENT(file) & H5F_ACC_SWMR_WRITE)
+ if(H5F_INTENT(file) & H5F_ACC_SWMR_WRITE || H5F_USE_VFD_SWMR(file))
file->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS;
/* Flush the superblock & superblock extension */
@@ -1767,7 +1809,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, NULL, "unable to flush superblock extension")
/* Remove the file lock for SWMR_WRITE */
- if(use_file_locking && (H5F_INTENT(file) & H5F_ACC_SWMR_WRITE)) {
+ if(use_file_locking && ((H5F_INTENT(file) & H5F_ACC_SWMR_WRITE) || H5F_USE_VFD_SWMR(file))) {
if(H5FD_unlock(file->shared->lf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to unlock the file")
} /* end if */
@@ -1775,7 +1817,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
else { /* H5F_ACC_RDONLY: check consistency of status_flags */
/* Skip check of status_flags for file with < superblock version 3 */
if(file->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_3) {
- if(H5F_INTENT(file) & H5F_ACC_SWMR_READ) {
+ if(H5F_INTENT(file) & H5F_ACC_SWMR_READ || H5F_USE_VFD_SWMR(file)) {
if((file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS &&
!(file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS))
||
@@ -1945,6 +1987,14 @@ H5F__flush(H5F_t *f)
/* Push error, but keep going*/
HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data")
+ /* VFD SWMR when flushing the HDF5 file */
+ if(f->shared->nrefs == 1 && f->shared->vfd_swmr_writer && f->shared->vfd_swmr_md_fd >= 0) {
+ HDassert(H5F_ACC_RDWR & H5F_INTENT(f));
+
+ if(H5F__vfd_swmr_close_or_flush(f, FALSE) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to encode and write to the metadata file")
+ }
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__flush() */
@@ -3524,23 +3574,27 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5F__format_convert() */
+/*
+ * VFD SWMR
+ */
+
/*-------------------------------------------------------------------------
- * Function: H5F__vfd_swmr_init_info
+ * Function: H5F__vfd_swmr_init
*
* Purpose: Initialize globals and the corresponding fields in file pointer.
- * For VFD SWMR writer:
+ * For both:
* --set vfd_swmr_g to TRUE
+ * --set vfd_swmr_file_g to f
+ * --set end_of_tick to the current time + tick length
+ * For VFD SWMR writer:
* --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
+ * --create the metadata file
+ * --when opening an existing HDF5 file, write header and empty index in the metadata file
* 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
@@ -3548,17 +3602,46 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5F__vfd_swmr_init_info(H5F_t *f)
+H5F__vfd_swmr_init(H5F_t *f, hbool_t file_create)
{
- struct timespec tmp_end_of_tick;
+ hsize_t md_size; /* Size of the metadata file */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
- if(f->shared->vfd_swmr_config.vfd_swmr_writer) {
+ HDassert(H5F_VFD_SWMR_CONFIG(f));
+
+ vfd_swmr_g = f->shared->vfd_swmr = TRUE;
+ vfd_swmr_file_g = f;
+
+ if(H5F_INTENT(f) & H5F_ACC_RDWR) {
+ HDassert(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 {
+
+ /* Create the metadata file */
+ if(((f->shared->vfd_swmr_md_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 create the metadata file")
+
+ md_size = (hsize_t)f->shared->vfd_swmr_config.md_pages_reserved * f->shared->fs_page_size;
+
+ /* Set the metadata file size to md_pages_reserved */
+ if(-1 == HDftruncate(f->shared->vfd_swmr_md_fd, (HDoff_t)md_size))
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "truncate fail for the metadata file")
+
+ /* Set eof for metadata file to md_pages_reserved */
+ f->shared->vfd_swmr_md_eoa = (haddr_t)md_size;
+
+ /* When opening an existing HDF5 file, create header and empty index in the metadata file */
+ if(!file_create) {
+ if(H5F__vfd_swmr_construct_write_md_hdr(f, 0) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "fail to create header in md")
+ if(H5F__vfd_swmr_construct_write_md_idx(f, 0, NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "fail to create index in md")
+ }
+
+ } else { /* VFD SWMR reader */
HDassert(!f->shared->vfd_swmr_config.vfd_swmr_writer);
vfd_swmr_writer_g = f->shared->vfd_swmr_writer = FALSE;
@@ -3568,32 +3651,23 @@ H5F__vfd_swmr_init_info(H5F_t *f)
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;
+ /* Update end_of_tick */
+ if(H5F__vfd_swmr_update_end_of_tick(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to update end of tick")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5F__vfd_swmr_init_info() */
+} /* H5F__vfd_swmr_init() */
-
/*-------------------------------------------------------------------------
- * Function: H5F__vfd_swmr_init_md
+ * Function: H5F__vfd_swmr_construct_write_md_hdr
*
- * 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
+ * Purpose: Encode and write header to the metadata file.
+ * This is used by the VFD SWMR writer:
+ * --when opening an existing HDF5 file
+ * --when closing the HDF5 file
+ * --after flushing an HDF5 file
+ * --when updating the metadata file
*
* Return: Success: SUCCEED
* Failure: FAIL
@@ -3601,21 +3675,20 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5F__vfd_swmr_init_md(H5F_t *f)
+H5F__vfd_swmr_construct_write_md_hdr(H5F_t *f, uint32_t index_len)
{
- 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 */
+ uint8_t image[H5FD_MD_HEADER_SIZE]; /* Buffer for header */
+ uint8_t *p = NULL; /* Pointer to buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ unsigned hdr_size = H5FD_MD_HEADER_SIZE; /* Size of header and index */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/*
* Encode metadata file header
*/
- p = image;
+ p = image;
/* Encode magic for header */
HDmemcpy(p, H5FD_MD_HEADER_MAGIC, (size_t)H5_SIZEOF_MAGIC);
@@ -3624,8 +3697,8 @@ H5F__vfd_swmr_init_md(H5F_t *f)
/* 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));
+ UINT64ENCODE(p, hdr_size);
+ UINT64ENCODE(p, H5FD_MD_INDEX_SIZE(index_len));
/* Calculate checksum for header */
metadata_chksum = H5_checksum_metadata(image, (size_t)(p - image), 0);
@@ -3634,12 +3707,57 @@ H5F__vfd_swmr_init_md(H5F_t *f)
UINT32ENCODE(p, metadata_chksum);
/* Sanity checks on header */
- HDassert((size_t)(p - image == H5FD_MD_HEADER_SIZE));
+ HDassert((size_t)(p - image == hdr_size));
+
+ /* 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 to the metadata file */
+ if(HDwrite(f->shared->vfd_swmr_md_fd, image, hdr_size) != hdr_size)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing header to metadata file")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__vfd_swmr_construct_write_md_hdr() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__vfd_swmr_construct_write_md_idx
+ *
+ * Purpose: Encode and write index to the metadata file.
+ * This is used by the VFD SWMR writer:
+ * --when opening an existing HDF5 file
+ * --when closing the HDF5 file
+ * --after flushing an HDF5 file
+ * --when updating the metadata file
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__vfd_swmr_construct_write_md_idx(H5F_t *f, uint32_t index_len, struct H5FD_vfd_swmr_idx_entry_t index[])
+{
+ uint8_t *image = NULL; /* Pointer to buffer */
+ uint8_t *p = NULL; /* Pointer to buffer */
+ uint32_t metadata_chksum; /* Computed metadata checksum value */
+ unsigned idx_size = H5FD_MD_INDEX_SIZE(index_len); /* Size of index */
+ unsigned i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ HDassert((index_len != 0 && index != NULL) || (index_len == 0 && index == NULL));
+
+ /* Allocate space for the buffer to hold the index */
+ if((image = (uint8_t *)HDmalloc(idx_size)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for md index")
/*
* Encode metadata file index
*/
- pp = p;
+ p = image;
/* Encode magic for index */
HDmemcpy(p, H5FD_MD_INDEX_MAGIC, (size_t)H5_SIZEOF_MAGIC);
@@ -3648,42 +3766,96 @@ H5F__vfd_swmr_init_md(H5F_t *f)
/* Encode tick number */
UINT64ENCODE(p, f->shared->tick_num);
- /* Encode zero number of entries in index */
- UINT32ENCODE(p, 0);
+ /* Encode number of entries in index */
+ UINT32ENCODE(p, index_len);
+
+ /* Encode the index entries */
+ for(i = 0; i < index_len; i++) {
+ UINT32ENCODE(p, index[i].hdf5_page_offset);
+ UINT32ENCODE(p, index[i].md_file_page_offset);
+ UINT32ENCODE(p, index[i].length);
+ UINT32ENCODE(p, index[i].chksum);
+ }
/* Calculate checksum for index */
- metadata_chksum = H5_checksum_metadata(pp, (size_t)(p - pp), 0);
+ metadata_chksum = H5_checksum_metadata(image, (size_t)(p - image), 0);
/* Encode checksum for index */
UINT32ENCODE(p, metadata_chksum);
/* Sanity checks on index */
- HDassert((size_t)(p - pp == H5FD_MD_EMPTY_INDEX_SIZE));
+ HDassert((size_t)(p - image == idx_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)
+ /* Set to right after the header */
+ if(HDlseek(f->shared->vfd_swmr_md_fd, (HDoff_t)H5FD_MD_HEADER_SIZE, 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")
+ /* Write index to the metadata file */
+ if(HDwrite(f->shared->vfd_swmr_md_fd, image, idx_size) != idx_size)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing index to metadata file")
done:
+ if(image)
+ HDfree(image);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5F__vfd_swmr_init_md() */
+} /* H5F__vfd_swmr_construct_write_idx() */
+
/*-------------------------------------------------------------------------
- * Function: H5F__vfd_swmr_close_md
+ * Function: H5F__vfd_swmr_update_end_of_tick
+ *
+ * Purpose: Set end_of_tick to the current time + tick length:
+ * --end_of_tick_g
+ * --f->shared->end_of_tick
+ *
+ * Return: Success: SUCCEED
+ * Failure: FAIL
*
- * 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
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__vfd_swmr_update_end_of_tick(H5F_t *f)
+{
+ struct timespec tmp_end_of_tick; /* end_of_tick */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* 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));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__vfd_swmr_update_end_of_tick() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__vfd_swmr_close_or_flush
+ *
+ * Purpose: Used by the VFD SWMR writer when the HDF5 file is closed or flushed:
+ * 1) For file close:
+ * --write header and an empty index to the metadata file
+ * --increment tick_num
+ * --close the metadata file
+ * --unlink the metadata file
+ * --close the free-space manager for the metadata file
+ * 2) For file flush:
+ * --write header and an empty index to the metadata file
+ * --increment tick_num
+ * --start a new tick (??check with JM for sure)
+ * ??update end_of_tick
*
* Return: Success: SUCCEED
* Failure: FAIL
@@ -3691,30 +3863,243 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5F__vfd_swmr_close_md(H5F_t *f)
+H5F__vfd_swmr_close_or_flush(H5F_t *f, hbool_t closing)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
+ HDassert(f->shared->vfd_swmr_writer);
HDassert(f->shared->vfd_swmr_md_fd >= 0);
+ /* Write empty index to the md file */
+ if(H5F__vfd_swmr_construct_write_md_idx(f, 0, NULL) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "fail to create index in md")
+ /* Write header to the md file */
+ if(H5F__vfd_swmr_construct_write_md_hdr(f, 0) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "fail to create header in md")
+
/* 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")
+ if(closing) { /* For file close */
+ /* 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")
+
+ /* Close the free-space manager for the metadata file */
+ if(H5MV_close(f) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to close the free-space manager for the metadata file")
+
+ vfd_swmr_file_g = NULL;
+
+ } else { /* For file flush */
+ /* Update end_of_tick */
+ if(H5F__vfd_swmr_update_end_of_tick(f) < 0)
+ HDONE_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to update end of tick")
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__vfd_swmr_close_or_flush() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__idx_entry_cmp()
+ *
+ * Purpose: Callback used by HDqsort to sort entries in the index
+ *
+ * Return: 0 if the entries are the same
+ * -1 if entry1's offset is less than that of entry2
+ * 1 if entry1's offset is greater than that of entry2
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__idx_entry_cmp(const void *_entry1, const void *_entry2)
+{
+ const H5FD_vfd_swmr_idx_entry_t *entry1 = (const H5FD_vfd_swmr_idx_entry_t *)_entry1;
+ const H5FD_vfd_swmr_idx_entry_t *entry2 = (const H5FD_vfd_swmr_idx_entry_t *)_entry2;
+
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Sanity checks */
+ HDassert(entry1);
+ HDassert(entry2);
+
+ if(entry1->hdf5_page_offset < entry2->hdf5_page_offset)
+ ret_value = -1;
+ else if(entry1->hdf5_page_offset > entry2->hdf5_page_offset)
+ ret_value = 1;
- /* 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;
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5F__idx_entry_cmp() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_update_vfd_swmr_metadata_file()
+ *
+ * Purpose: Updating the metadata file
+ * --Sort index
+ * --For each non-null entry_ptr in the index:
+ * --Insert previous image of the entry onto the delayed list
+ * --Allocate space for the entry in the metadata file
+ * --Compute checksum
+ * --Update index
+ * --Write the entry to the metadata file
+ * --Set entry_ptr to NULL
+ * --Construct on disk image of the index and write index to the metadata file
+ * --Construct on disk image of the header and write header to the metadata file
+ * --Release time out space from the delayed list to the free-space manager
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t index_len, struct H5FD_vfd_swmr_idx_entry_t index[])
+{
+ H5F_vfd_swmr_dl_entry_t *prev; /* Points to the delayed list */
+ H5F_vfd_swmr_dl_entry_t *dl_entry;
+ haddr_t md_addr;
+ unsigned i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sort index by increasing offset in the HDF5 file */
+ HDqsort(index, index_len, sizeof(H5FD_vfd_swmr_idx_entry_t), H5F__idx_entry_cmp);
- /* 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")
+ /* For each non-null entry_ptr in the index:
+ * --If exists, insert previous image of the entry to the delayed list
+ * --Allocate space for the entry in the metadata file
+ * --Compute checksum, update index, write entry to the metadata file
+ * --Set entry_ptr to NULL
+ */
+ for(i = 0; i < index_len; i++) {
+ if(index[i].entry_ptr != NULL) {
+ /* Append previous image of the entry to the delayed list */
+ if(index[i].md_file_page_offset) {
+ if(NULL == (dl_entry = H5FL_CALLOC(H5F_vfd_swmr_dl_entry_t)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate the delayed entry")
+ dl_entry->hdf5_page_offset = index[i].hdf5_page_offset;
+ dl_entry->md_file_page_offset = index[i].md_file_page_offset;
+ dl_entry->length = index[i].length;
+ dl_entry->tick_num = f->shared->tick_num;
+ H5F_DC_APPEND(dl_entry, f->shared->dl_head_ptr, f->shared->dl_tail_ptr, f->shared->dl_len);
+ }
+
+ /* Allocate space for the entry in the metadata file */
+ if((md_addr = H5MV_alloc(f, index[i].length)) == HADDR_UNDEF)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in allocating space from the metadata file")
+ /* Compute checksum and update the index */
+ index[i].md_file_page_offset = md_addr/f->shared->fs_page_size;
+ index[i].chksum = H5_checksum_metadata(index[i].entry_ptr, (size_t)(index[i].length), 0);
+
+ /* Seek and write the entry to the metadata file */
+ if(HDlseek(f->shared->vfd_swmr_md_fd, (HDoff_t)md_addr, SEEK_SET) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_SEEKERROR, FAIL, "unable to seek in the metadata file")
+ if(HDwrite(f->shared->vfd_swmr_md_fd, index[i].entry_ptr, index[i].length) != index[i].length)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing the page/multi-page entry to metadata file")
+
+ /* Set entry_ptr to NULL */
+ index[i].entry_ptr = NULL;
+ } /* end if */
+
+ } /* end for */
+
+ /* Construct and write index to the md file */
+ if(H5F__vfd_swmr_construct_write_md_idx(f, index_len, index) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "fail to construct & write index in md")
+
+ /* Construct and write header to the md file */
+ if(H5F__vfd_swmr_construct_write_md_hdr(f, index_len) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "fail to construct & write header in md")
+
+ /*
+ * Release time out entry from the delayed list:
+ * Scan the delayed list from the bottom up:
+ * --release to the metadata file free space manager all entries that have
+ * resided on the list for more than max_lag ticks
+ * --remove the associated entries from the list
+ */
+ dl_entry = f->shared->dl_tail_ptr;
+ while(dl_entry != NULL) {
+
+ prev = dl_entry->prev;
+ /* max_lag is at least 3 */
+ if((int)dl_entry->tick_num <= ((int)f->shared->tick_num - f->shared->vfd_swmr_config.max_lag)) {
+ if(H5MV_free(f, dl_entry->md_file_page_offset * f->shared->fs_page_size, dl_entry->length) < 0)
+ HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush clean entry")
+
+ /* Remove the entry from the delayed list */
+ H5F_DC_REMOVE(dl_entry, f->shared->dl_head_ptr, f->shared->dl_tail_ptr, f->shared->dl_len)
+
+ /* Free the delayed entry struct */
+ H5FL_FREE(H5F_vfd_swmr_dl_entry_t, dl_entry);
+ }
+ /* DO I break from it once it is false ?? */
+ dl_entry = prev;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_update_vfd_swmr_metadata_file() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_vfd_swmr_writer_end_of_tick
+ *
+ * Purpose: Dummy right now
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_vfd_swmr_writer_end_of_tick(void)
+{
+ H5FD_vfd_swmr_idx_entry_t *index;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* construct */
+ if(vfd_swmr_file_g) {
+ ;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_vfd_swmr_writer_end_of_tick() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_vfd_swmr_reader_end_of_tick
+ *
+ * Purpose: Dummy right now
+ *
+ * Return: SUCCEED/FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_vfd_swmr_reader_end_of_tick(void)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* construct */
+ if(vfd_swmr_file_g) {
+ ;
+ }
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5F__vfd_swmr_close_md() */
+} /* end H5F_vfd_swmr_reader_end_of_tick() */
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 7e04f35..2a5847e 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -215,6 +215,28 @@ typedef struct H5F_mtab_t {
H5F_mount_t *child; /* An array of mount records */
} H5F_mtab_t;
+/*
+ * VFD SWMR: Entry for the delayed free space release doubly linked list
+ *
+ * md_file_page_offset: Unsigned 64-bit value containing the base address of the
+ * metadata page, or multi page metadata entry in the metadata
+ * file IN PAGES.
+ * To obtain byte offset, multiply this value by the page size.
+ * length: The length of the metadata page or multi page metadata entry
+ * in BYTES.
+ * tick_num: Sequence # of the current tick
+ * next: Pointer to the next entry in the the list
+ * prev: Pointer to the previous entry in the list
+ */
+typedef struct H5F_vfd_swmr_dl_entry_t {
+ uint64_t hdf5_page_offset;
+ uint64_t md_file_page_offset;
+ uint32_t length;
+ uint64_t tick_num;
+ struct H5F_vfd_swmr_dl_entry_t *next;
+ struct H5F_vfd_swmr_dl_entry_t *prev;
+} H5F_vfd_swmr_dl_entry_t;
+
/* Structure specifically to store superblock. This was originally
* maintained entirely within H5F_file_t, but is now extracted
* here because the superblock is now handled by the cache */
@@ -354,16 +376,32 @@ struct H5F_file_t {
/* Object flush info */
H5F_object_flush_t object_flush; /* Information for object flush callback */
- /* VFD SWMR configuration info */
+ /* 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 */
+
+ /* Metadata file */
int vfd_swmr_md_fd; /* POSIX: file descriptor of the metadata file */
+ haddr_t vfd_swmr_md_eoa; /* POSIX: eoa for the metadata file */
+
+ /* Free space manager for the metadata file */
+ H5FS_t *fs_man_md; /* Free-space manager */
+ H5F_fs_state_t fs_state_md; /* State of the free space manager */
+
+ /* Delayed free space release doubly linked list */
+ uint32_t dl_len; /* # of entries in the list */
+ H5F_vfd_swmr_dl_entry_t *dl_head_ptr; /* Points to the beginning of the list */
+ H5F_vfd_swmr_dl_entry_t *dl_tail_ptr; /* Points to the end of the list */
+
};
+
/*
* This is the top-level file descriptor. One of these structures is
* allocated every time H5Fopen() is called although they may contain pointers
@@ -471,6 +509,12 @@ H5_DLL haddr_t H5F__alloc(H5F_t *f, H5F_mem_t type, hsize_t size, haddr_t *frag_
H5_DLL herr_t H5F__free(H5F_t *f, H5F_mem_t type, haddr_t addr, hsize_t size);
H5_DLL htri_t H5F__try_extend(H5F_t *f, H5FD_mem_t type, haddr_t blk_end, hsize_t extra_requested);
+/* VFD SWMR */
+/* Space allocation routines */
+H5_DLL haddr_t H5F__alloc_md(H5F_t *f, hsize_t size);
+H5_DLL herr_t H5F__free_md(H5F_t *f, haddr_t addr, hsize_t size);
+H5_DLL htri_t H5F__try_extend_md(H5F_t *f, haddr_t blk_end, hsize_t extra_requested);
+
/* Functions that get/retrieve values from VFD layer */
H5_DLL herr_t H5F__set_eoa(const H5F_t *f, H5F_mem_t type, haddr_t addr);
H5_DLL herr_t H5F__set_base_addr(const H5F_t *f, haddr_t addr);
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index 356a606..dc407c8 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -331,7 +331,8 @@ 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)
+#define H5F_USE_VFD_SWMR(F) ((F)->shared->vfd_swmr)
+#define H5F_VFD_SWMR_MD_EOA(F) ((F)->shared->vfd_swmr_md_eoa)
#else /* H5F_MODULE */
#define H5F_LOW_BOUND(F) (H5F_get_low_bound(F))
#define H5F_HIGH_BOUND(F) (H5F_get_high_bound(F))
@@ -390,6 +391,7 @@ typedef struct H5F_t H5F_t;
#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))
+#define H5F_VFD_SWMR_MD_EOA(F) (H5F_get_vfd_swmr_md_eoa(F))
#endif /* H5F_MODULE */
@@ -511,7 +513,7 @@ typedef struct H5F_t H5F_t;
#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_ACS_VFD_SWMR_CONFIG_NAME "vfd_swmr_config"
#define H5F__DEFAULT_VFD_SWMR_CONFIG \
{ \
/* int32_t version = */ 0, \
@@ -665,13 +667,15 @@ struct H5HG_heap_t;
struct H5VL_class_t;
struct H5P_genplist_t;
+/* VFD SWMR */
+/* Forward declaration */
+struct H5FD_vfd_swmr_idx_entry_t;
+
/* Forward declarations for anonymous H5F objects */
/* 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;
@@ -761,7 +765,6 @@ 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);
@@ -875,5 +878,12 @@ H5_DLL herr_t H5F_cwfs_remove_heap(H5F_file_t *shared, struct H5HG_heap_t *heap)
/* Debugging functions */
H5_DLL herr_t H5F_debug(H5F_t *f, FILE * stream, int indent, int fwidth);
+/* VFD SWMR */
+H5_DLL herr_t H5F_vfd_swmr_writer_end_of_tick(void);
+H5_DLL herr_t H5F_vfd_swmr_reader_end_of_tick(void);
+H5_DLL herr_t H5F_update_vfd_swmr_metadata_file(H5F_t *f, uint32_t index_len, struct H5FD_vfd_swmr_idx_entry_t *index);
+H5_DLL hbool_t H5F_use_vfd_swmr(const H5F_t *f);
+H5_DLL haddr_t H5F_get_vfd_swmr_md_eoa(const H5F_t *f);
+
#endif /* _H5Fprivate_H */
diff --git a/src/H5Fquery.c b/src/H5Fquery.c
index 93b50d7..1dadd15 100644
--- a/src/H5Fquery.c
+++ b/src/H5Fquery.c
@@ -1238,3 +1238,27 @@ H5F_use_vfd_swmr(const H5F_t *f)
FUNC_LEAVE_NOAPI(f->shared->vfd_swmr)
} /* end H5F_use_vfd_swmr() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_get_vfd_swmr_md_eoa
+ *
+ * Purpose: Quick and dirty routine to retrieve the EOA for the metadata file
+ * (Mainly added to stop non-file routines from poking about in the
+ * H5F_t data structure)
+ *
+ * Return: The EOA for the metadata file
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5F_get_vfd_swmr_md_eoa(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);
+ HDassert(f->shared->vfd_swmr);
+
+ FUNC_LEAVE_NOAPI(f->shared->vfd_swmr_md_eoa)
+} /* end H5F_get_vfd_swmr_md_eof() */
diff --git a/src/H5Fspace.c b/src/H5Fspace.c
index 6baf163..a35fdff 100644
--- a/src/H5Fspace.c
+++ b/src/H5Fspace.c
@@ -42,6 +42,10 @@
/* Local Macros */
/****************/
+/* Define this to display debugging information for VFD SWMR */
+/* #define H5F_VFD_SWMR_DEBUG */
+
+
/******************/
/* Local Typedefs */
@@ -56,6 +60,7 @@
/********************/
/* Local Prototypes */
/********************/
+static haddr_t H5F__extend_md(H5F_t *f, hsize_t size);
/*********************/
@@ -222,3 +227,158 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F__try_extend() */
+
+/*
+ * VFD SWMR
+ */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__free_md
+ *
+ * Purpose: Release space at the end of the metadata file's allocated space
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F__free_md(H5F_t *f, haddr_t addr, hsize_t size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(size > 0);
+
+ /* Sanity checking */
+ if(!H5F_addr_defined(addr))
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "invalid file offset")
+
+ if(addr > f->shared->maxaddr || H5F_addr_overflow(addr, size) || (addr + size) > f->shared->maxaddr)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "invalid file free space region to free")
+
+ /* Check if this free block is at the end of file allocated space.
+ * Truncate it if this is true.
+ */
+ if(f->shared->vfd_swmr_md_eoa == (addr + size))
+ f->shared->vfd_swmr_md_eoa = addr;
+ else {
+ /* leak memory */
+#ifdef H5F_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: LEAKED MEMORY!!! addr = %a, size = %Hu\n", FUNC, addr, size);
+#endif
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__free_md() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__alloc_md
+ *
+ * Purpose: Allocate space at the end of the metadata file
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5F__alloc_md(H5F_t *f, hsize_t size)
+{
+ haddr_t ret_value = HADDR_UNDEF; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(size > 0);
+
+ /* Extend the EOA space of the metadata file */
+ ret_value = H5F__extend_md(f, size);
+
+ if(!H5F_addr_defined(ret_value))
+ HGOTO_ERROR(H5E_VFL, H5E_NOSPACE, HADDR_UNDEF, "driver eoa update request failed")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5F__alloc_md() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__try_extend_md
+ *
+ * Purpose: Try to extend a block at the end of the metadata file, if possible.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5F__try_extend_md(H5F_t *f, haddr_t blk_end, hsize_t extra_requested)
+{
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* check args */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(extra_requested > 0);
+
+ /* Check if the block is exactly at the end of the file */
+ if(H5F_addr_eq(blk_end, f->shared->vfd_swmr_md_eoa)) {
+
+ /* Extend the EOA space of the metadata file */
+ if(HADDR_UNDEF == H5F__extend_md(f, extra_requested))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTEXTEND, FAIL, "driver extend request failed")
+
+ /* Indicate success */
+ ret_value = TRUE;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F__try_extend_md() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__extend_md
+ *
+ * Purpose: Extend the EOA space of the metadata file.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static haddr_t
+H5F__extend_md(H5F_t *f, hsize_t size)
+{
+ haddr_t eoa;
+ haddr_t ret_value = HADDR_UNDEF; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Get current end-of-allocated space address */
+ eoa = f->shared->vfd_swmr_md_eoa;
+
+ /* Check for overflow when extending */
+ if(H5F_addr_overflow(eoa, size) || (eoa + size) > f->shared->maxaddr)
+ HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, HADDR_UNDEF, "file allocation request failed")
+
+ /* Set the address to return */
+ ret_value = eoa;
+
+ /* Extend the end-of-allocated space address */
+ f->shared->vfd_swmr_md_eoa += size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
diff --git a/src/H5MV.c b/src/H5MV.c
new file mode 100644
index 0000000..d0cca9f
--- /dev/null
+++ b/src/H5MV.c
@@ -0,0 +1,518 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5MV.c
+ *
+ * Purpose: Free-space manager for VFD SWMR's metadata file
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5FS_FRIEND /*suppress error about including H5Fpkg */
+#include "H5MVmodule.h" /* This source code file is part of the H5MV module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5FSpkg.h" /* File free space */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MVpkg.h" /* File memory management */
+#include "H5VMprivate.h" /* Vectors and arrays */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+#define H5MV_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */
+#define H5MV_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */
+#define H5MV_FSPACE_THRHD_DEF 1 /* Default: no alignment threshold */
+#define H5MV_FSPACE_ALIGN_DEF 1 /* Default: no alignment */
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+/* User data for section info iterator callback for iterating over free space sections */
+typedef struct {
+ H5F_sect_info_t *sects; /* section info to be retrieved */
+ size_t sect_count; /* # of sections requested */
+ size_t sect_idx; /* the current count of sections */
+} H5MV_sect_iter_ud_t;
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Package initialization variable */
+hbool_t H5_PKG_INIT_VAR = FALSE;
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__create()
+ *
+ * Purpose: Create free space manager for the metadata file by creating
+ * a free-space structure
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MV__create(H5F_t *f)
+{
+ /* Free space section classes implemented for file */
+ const H5FS_section_class_t *classes[] = { H5MV_FSPACE_SECT_CLS_SIMPLE };
+ H5FS_create_t fs_create; /* Free space creation parameters */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->fs_state_md == H5F_FS_STATE_CLOSED);
+
+ /* Set the free space creation parameters */
+ fs_create.client = H5FS_CLIENT_MD_VFD_ID;
+ fs_create.shrink_percent = H5MV_FSPACE_SHRINK;
+ fs_create.expand_percent = H5MV_FSPACE_EXPAND;
+ fs_create.max_sect_addr = 1 + H5VM_log2_gen((uint64_t)f->shared->maxaddr);
+ fs_create.max_sect_size = f->shared->maxaddr;
+
+ if(NULL == (f->shared->fs_man_md = H5FS_create(f, NULL, &fs_create, NELMTS(classes), classes, f, H5MV_FSPACE_ALIGN_DEF, H5MV_FSPACE_THRHD_DEF)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space info")
+
+ /* Set the state for the free space manager to "open", if it is now */
+ if(f->shared->fs_man_md)
+ f->shared->fs_state_md = H5F_FS_STATE_OPEN;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV__create() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV_close
+ *
+ * Purpose: Close the free space manager for the metadata file
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MV_close(H5F_t *f)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(f);
+ HDassert(f->shared);
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Trying to close free space manager\n", FUNC);
+#endif
+
+ /* Close an existing free space structure for the file */
+ if(f->shared->fs_man_md) {
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Going to close free space manager\n", FUNC);
+#endif
+ HDassert(f->shared->fs_state_md != H5F_FS_STATE_CLOSED);
+
+ if(H5FS_close(f, f->shared->fs_man_md) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't release free space info")
+ }
+
+ f->shared->fs_man_md = NULL;
+ f->shared->fs_state_md = H5F_FS_STATE_CLOSED;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV_close() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__find_sect
+ *
+ * Purpose: To find a section from the specified free-space manager
+ * to fulfill the request.
+ * If found, re-add the left-over space back to the manager.
+ *
+ * Return: TRUE if a section is found to fulfill the request
+ * FALSE if not
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MV__find_sect(H5F_t *f, hsize_t size, H5FS_t *fspace, haddr_t *addr)
+{
+ H5MV_free_section_t *node; /* Free space section pointer */
+ htri_t ret_value = FAIL; /* Whether an existing free list node was found */
+
+ FUNC_ENTER_PACKAGE
+
+ HDassert(f);
+ HDassert(fspace);
+
+ /* Try to get a section from the free space manager */
+ if((ret_value = H5FS_sect_find(f, fspace, size, (H5FS_section_info_t **)&node)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "error locating free space in file")
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: section found = %t\n", FUNC, ret_value);
+#endif
+
+ /* Check for actually finding section */
+ if(ret_value) {
+ /* Sanity check */
+ HDassert(node);
+
+ /* Retrieve return value */
+ if(addr)
+ *addr = node->sect_info.addr;
+
+ /* Check for eliminating the section */
+ if(node->sect_info.size == size) {
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: freeing node\n", FUNC);
+#endif
+
+ /* Free section node */
+ if(H5MV__sect_free((H5FS_section_info_t *)node) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+ } /* end if */
+ else {
+ /* Adjust information for section */
+ node->sect_info.addr += size;
+ node->sect_info.size -= size;
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: adding node, node->sect_info.addr = %a, node->sect_info.size = %Hu\n", FUNC, node->sect_info.addr, node->sect_info.size);
+#endif
+
+ /* Re-add the section to the free-space manager */
+ if(H5FS_sect_add(f, fspace, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, f) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't re-add section to file free space")
+ } /* end else */
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV__find_sect() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV_alloc
+ *
+ * Purpose: Allocate SIZE bytes of file memory and return the relative
+ * address where that contiguous chunk of file memory exists.
+ *
+ * Return: Success: The file address of new chunk.
+ * Failure: HADDR_UNDEF
+ *
+ *-------------------------------------------------------------------------
+ */
+haddr_t
+H5MV_alloc(H5F_t *f, hsize_t size)
+{
+ haddr_t ret_value = HADDR_UNDEF; /* Return value */
+
+ FUNC_ENTER_NOAPI(HADDR_UNDEF)
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: size = %Hu\n", FUNC, size);
+#endif
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->vfd_swmr_md_fd >= 0);
+ HDassert(size > 0);
+
+ /* Search for large enough space in the free space manager */
+ if(f->shared->fs_man_md != NULL) {
+ if(H5MV__find_sect(f, size, f->shared->fs_man_md, &ret_value) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "error locating a node")
+ }
+
+ /* If no space is found from the free-space manager or no free-space manager, extend md's EOF */
+ if(!H5F_addr_defined(ret_value)) {
+ if(HADDR_UNDEF == (ret_value = H5F__alloc_md(f, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, HADDR_UNDEF, "allocation failed")
+ } /* end if */
+ HDassert(H5F_addr_defined(ret_value));
+
+done:
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Leaving: ret_value = %a, size = %Hu\n", FUNC, ret_value, size);
+#endif
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV_alloc() */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV_free
+ *
+ * Purpose: Frees part of a file, making that part of the file
+ * available for reuse.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MV_free(H5F_t *f, haddr_t addr, hsize_t size)
+{
+ H5MV_free_section_t *node = NULL; /* Free space section pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Entering - addr = %a, size = %Hu\n", FUNC, addr, size);
+#endif
+
+ /* check arguments */
+ HDassert(f);
+ if(!H5F_addr_defined(addr) || 0 == size)
+ HGOTO_DONE(SUCCEED)
+ HDassert(addr != 0);
+
+
+ /* Check if the free space manager for the file has been initialized */
+ if(f->shared->fs_man_md == NULL) {
+ /* If there's no free space manager for objects of this type,
+ * see if we can avoid creating one by checking if the freed
+ * space is at the end of the file
+ */
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: fs_addr = %a\n", FUNC, f->shared->fs_man_md);
+#endif
+ htri_t status; /* "can absorb" status for section into */
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Trying to avoid starting up free space manager\n", FUNC);
+#endif
+ /* Try to shrink the file */
+ if((status = H5MV_try_shrink(f, addr, size)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check for absorbing block")
+ else if(status > 0)
+ /* Indicate success */
+ HGOTO_DONE(SUCCEED)
+
+ /* If we are deleting the free space manager, leave now, to avoid
+ * [re-]starting it: dropping free space section on the floor.
+ */
+ if(f->shared->fs_state_md == H5F_FS_STATE_DELETING) {
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: dropping addr = %a, size = %Hu, on the floor!\n", FUNC, addr, size);
+#endif
+ HGOTO_DONE(SUCCEED)
+ } /* end if */
+
+ /* There's either already a free space manager, or the freed
+ * space isn't at the end of the file, so start up (or create)
+ * the file space manager
+ */
+ if(H5MV__create(f) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space manager")
+ } /* end if */
+
+ /* Create the free-space section for the freed section */
+ if(NULL == (node = H5MV__sect_new(addr, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+
+ HDassert(f->shared->fs_man_md);
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Before H5FS_sect_add()\n", FUNC);
+#endif
+
+ /* Add the section */
+ if(H5FS_sect_add(f, f->shared->fs_man_md, (H5FS_section_info_t *)node, H5FS_ADD_RETURNED_SPACE, f) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINSERT, FAIL, "can't re-add section to file free space")
+
+ node = NULL;
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: After H5FS_sect_add()\n", FUNC);
+#endif
+
+done:
+ /* Release section node, if allocated and not added to section list or merged */
+ if(node)
+ if(H5MV__sect_free((H5FS_section_info_t *)node) < 0)
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV_try_extend
+ *
+ * Purpose: Extend a block at EOA in the file if possible.
+ *
+ * Return: Success: TRUE(1) - Block was extended
+ * FALSE(0) - Block could not be extended
+ * Failure: FAIL
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MV_try_extend(H5F_t *f, haddr_t addr, hsize_t size, hsize_t extra_requested)
+{
+ haddr_t end; /* End of block to extend */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Entering: addr = %a, size = %Hu, extra_requested = %Hu\n", FUNC, addr, size, extra_requested);
+#endif
+
+ /* Sanity check */
+ HDassert(f);
+ HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
+
+ /* Compute end of block to extend */
+ end = addr + size;
+
+ /* Try extending the block at EOA */
+ if((ret_value = H5F__try_extend_md(f, end, extra_requested)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending file")
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: extended = %t\n", FUNC, ret_value);
+#endif
+
+ /* If no extension so far, try to extend into a free-space section */
+ if(ret_value == FALSE) {
+
+ /* Try to extend the block into a free-space section */
+ if(f->shared->fs_man_md) {
+ if((ret_value = H5FS_sect_try_extend(f, f->shared->fs_man_md, addr, size, extra_requested, H5FS_ADD_RETURNED_SPACE, NULL)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTEXTEND, FAIL, "error extending block in free space manager")
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Try to H5FS_sect_try_extend = %t\n", FUNC, ret_value);
+#endif
+ } /* end if */
+
+ } /* end if */
+
+done:
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Leaving: ret_value = %t\n", FUNC, ret_value);
+#endif
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV_try_extend() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV_try_shrink
+ *
+ * Purpose: Try to shrink the size of a file with a block
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MV_try_shrink(H5F_t *f, haddr_t addr, hsize_t size)
+{
+ H5MV_free_section_t *node = NULL; /* Free space section pointer */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI(FAIL)
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Entering - addr = %a, size = %Hu\n", FUNC, addr, size);
+#endif
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->lf);
+ HDassert(H5F_addr_defined(addr));
+ HDassert(size > 0);
+
+ /* Create free-space section for block */
+ if(NULL == (node = H5MV__sect_new(addr, size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize free space section")
+
+ /* Check if the block can shrink the container */
+ if((ret_value = H5MV__sect_can_shrink((const H5FS_section_info_t *)node, f)) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTMERGE, FAIL, "can't check if section can shrink container")
+ else if(ret_value > 0) {
+ /* Shrink or absorb the section */
+ if(H5MV__sect_shrink((H5FS_section_info_t **)&node, NULL) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSHRINK, FAIL, "can't shrink container")
+ } /* end if */
+
+done:
+ /* Free section node allocated */
+ if(node && H5MV__sect_free((H5FS_section_info_t *)node) < 0)
+ HDONE_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+#ifdef H5MV_VFD_SWMR_DEBUG
+HDfprintf(stderr, "%s: Leaving, ret_value = %d\n", FUNC, ret_value);
+#endif
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV_try_shrink() */
+
+/*
+ * If need to find out the amount of free-space in the file, port routines in H5MF.c
+ */
diff --git a/src/H5MVmodule.h b/src/H5MVmodule.h
new file mode 100644
index 0000000..5a95767
--- /dev/null
+++ b/src/H5MVmodule.h
@@ -0,0 +1,33 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Saturday, September 12, 2015
+ *
+ * Purpose: This file contains declarations which define macros for the
+ * H5MV package. Including this header means that the source file
+ * is part of the H5MV package.
+ */
+#ifndef _H5MVmodule_H
+#define _H5MVmodule_H
+
+/* Define the proper control macros for the generic FUNC_ENTER/LEAVE and error
+ * reporting macros.
+ */
+#define H5MV_MODULE
+#define H5_MY_PKG H5MV
+#define H5_MY_PKG_ERR H5E_RESOURCE
+#define H5_MY_PKG_INIT NO
+
+#endif /* _H5MVmodule_H */
+
diff --git a/src/H5MVpkg.h b/src/H5MVpkg.h
new file mode 100644
index 0000000..32b87ac
--- /dev/null
+++ b/src/H5MVpkg.h
@@ -0,0 +1,83 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: This file contains declarations which are visible only within
+ * the H5MV package. Source files outside the H5MV package should
+ * include H5MVprivate.h instead.
+ */
+#if !(defined H5MV_FRIEND || defined H5MV_MODULE)
+#error "Do not include this file outside the H5MV package!"
+#endif
+
+#ifndef _H5MVpkg_H
+#define _H5MVpkg_H
+
+/* Get package's private header */
+#include "H5MVprivate.h"
+
+/* Other private headers needed by this file */
+#include "H5FSprivate.h" /* File free space */
+
+
+/**************************/
+/* Package Private Macros */
+/**************************/
+
+/* Define this to display information about file allocations */
+/* #define H5MV_VFD_SWMR_DEBUG */
+
+/* Free-space section types for file */
+/* (values stored in free space data structures in file) */
+#define H5MV_FSPACE_SECT_SIMPLE 0 /* For non-paged aggregation: section is a range of actual bytes in file */
+
+/****************************/
+/* Package Private Typedefs */
+/****************************/
+
+/* File free space section info */
+typedef struct H5MV_free_section_t {
+ H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */
+} H5MV_free_section_t;
+
+/*****************************/
+/* Package Private Variables */
+/*****************************/
+
+/* H5MF single section inherits serializable properties from H5FS_section_class_t */
+H5_DLLVAR H5FS_section_class_t H5MV_FSPACE_SECT_CLS_SIMPLE[1];
+
+
+/******************************/
+/* Package Private Prototypes */
+/******************************/
+
+H5_DLL htri_t H5MV__find_sect(H5F_t *f, hsize_t size, H5FS_t *fspace, haddr_t *addr);
+H5_DLL herr_t H5MV__create(H5F_t *f);
+
+/* free-space section routines */
+H5_DLL H5MV_free_section_t *H5MV__sect_new(haddr_t sect_off, hsize_t sect_size);
+H5_DLL herr_t H5MV__sect_free(H5FS_section_info_t *sect);
+H5_DLL htri_t H5MV__sect_can_shrink(const H5FS_section_info_t *_sect, void *udata);
+H5_DLL herr_t H5MV__sect_shrink(H5FS_section_info_t **_sect, void *udata);
+
+
+/* Testing routines */
+#ifdef H5MF_TESTING
+#endif /* H5MF_TESTING */
+
+#endif /* _H5MFpkg_H */
+
diff --git a/src/H5MVprivate.h b/src/H5MVprivate.h
new file mode 100644
index 0000000..2c0e95a
--- /dev/null
+++ b/src/H5MVprivate.h
@@ -0,0 +1,58 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*-------------------------------------------------------------------------
+ *
+ * Created: H5MVprivate.h
+ *
+ * Purpose: Private header file for file memory management.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef _H5MVprivate_H
+#define _H5MVprivate_H
+
+/* Private headers needed by this file */
+#include "H5Fprivate.h" /* File access */
+
+/**************************/
+/* Library Private Macros */
+/**************************/
+
+
+/****************************/
+/* Library Private Typedefs */
+/****************************/
+
+
+/*****************************/
+/* Library-private Variables */
+/*****************************/
+
+
+/***************************************/
+/* Library-private Function Prototypes */
+/***************************************/
+
+/* File space manager routines */
+
+H5_DLL herr_t H5MV_close(H5F_t *f);
+
+/* File space allocation routines */
+H5_DLL haddr_t H5MV_alloc(H5F_t *f, hsize_t size);
+H5_DLL herr_t H5MV_free(H5F_t *f, haddr_t addr, hsize_t size);
+H5_DLL herr_t H5MV_try_extend(H5F_t *f, haddr_t addr, hsize_t size, hsize_t extra_requested);
+H5_DLL htri_t H5MV_try_shrink(H5F_t *f, haddr_t addr, hsize_t size);
+
+#endif /* end _H5MVprivate_H */
+
diff --git a/src/H5MVsection.c b/src/H5MVsection.c
new file mode 100644
index 0000000..e2e2007
--- /dev/null
+++ b/src/H5MVsection.c
@@ -0,0 +1,361 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Quincey Koziol <koziol@hdfgroup.org>
+ * Tuesday, January 8, 2008
+ *
+ * Purpose: Free space section callbacks for file.
+ *
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#include "H5MVmodule.h" /* This source code file is part of the H5MF module */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5MVpkg.h" /* File memory management */
+
+
+/****************/
+/* Local Macros */
+/****************/
+
+
+/******************/
+/* Local Typedefs */
+/******************/
+
+
+/********************/
+/* Package Typedefs */
+/********************/
+
+
+/********************/
+/* Local Prototypes */
+/********************/
+
+/* 'simple' section callbacks */
+static htri_t H5MV__sect_can_merge(const H5FS_section_info_t *sect1,
+ const H5FS_section_info_t *sect2, void *udata);
+static herr_t H5MV__sect_merge(H5FS_section_info_t **sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static herr_t H5MV__sect_valid(const H5FS_section_class_t *cls,
+ const H5FS_section_info_t *sect);
+
+
+
+/*********************/
+/* Package Variables */
+/*********************/
+
+/* Class info for "simple" free space sections */
+H5FS_section_class_t H5MV_FSPACE_SECT_CLS_SIMPLE[1] = {{
+ /* Class variables */
+ H5MV_FSPACE_SECT_SIMPLE, /* Section type */
+ 0, /* Extra serialized size */
+ H5FS_CLS_MERGE_SYM | H5FS_CLS_ADJUST_OK | H5FS_CLS_GHOST_OBJ, /* Class flags */
+ NULL, /* Class private info */
+
+ /* Class methods */
+ NULL, /* Initialize section class */
+ NULL, /* Terminate section class */
+
+ /* Object methods */
+ NULL, /* Add section */
+ NULL, /* Serialize section */
+ NULL, /* Deserialize section */
+ H5MV__sect_can_merge, /* Can sections merge? */
+ H5MV__sect_merge, /* Merge sections */
+ H5MV__sect_can_shrink, /* Can section shrink container?*/
+ H5MV__sect_shrink, /* Shrink container w/section */
+ H5MV__sect_free, /* Free section */
+ H5MV__sect_valid, /* Check validity of section */
+ NULL, /* Split section node for alignment */
+ NULL, /* Dump debugging for section */
+}};
+
+
+/*****************************/
+/* Library Private Variables */
+/*****************************/
+
+
+/*******************/
+/* Local Variables */
+/*******************/
+
+/* Declare a free list to manage the H5MF_free_section_t struct */
+H5FL_DEFINE(H5MV_free_section_t);
+
+/*
+ * "simple" section callbacks
+ */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_new
+ *
+ * Purpose: Create a new section and return it to the caller
+ *
+ * Return: Pointer to new section on success/NULL on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+H5MV_free_section_t *
+H5MV__sect_new(haddr_t sect_off, hsize_t sect_size)
+{
+ H5MV_free_section_t *sect; /* 'Simple' free space section to add */
+ H5MV_free_section_t *ret_value = NULL; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check arguments. */
+ HDassert(sect_size);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5FL_MALLOC(H5MV_free_section_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free section node")
+
+ /* Set the information passed in */
+ sect->sect_info.addr = sect_off;
+ sect->sect_info.size = sect_size;
+
+ /* Set the section's class & state */
+ sect->sect_info.type = H5MV_FSPACE_SECT_SIMPLE;
+ sect->sect_info.state = H5FS_SECT_LIVE;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MV__sect_new() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_free
+ *
+ * Purpose: Free a 'simple' section node
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MV__sect_free(H5FS_section_info_t *_sect)
+{
+ H5MV_free_section_t *sect = (H5MV_free_section_t *)_sect; /* File free section */
+
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Check arguments. */
+ HDassert(sect);
+
+ /* Release the section */
+ sect = H5FL_FREE(H5MV_free_section_t, sect);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MV__sect_free() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_valid
+ *
+ * Purpose: Check the validity of a section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MV__sect_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, const H5FS_section_info_t *_sect)
+{
+ const H5MV_free_section_t *sect = (const H5MV_free_section_t *)_sect; /* File free section */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments. */
+ HDassert(sect);
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* H5MV__sect_valid() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_can_merge
+ *
+ * Purpose: Can two sections of this type merge?
+ *
+ * Note: Second section must be "after" first section
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5MV__sect_can_merge(const H5FS_section_info_t *_sect1,
+ const H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata)
+{
+ const H5MV_free_section_t *sect1 = (const H5MV_free_section_t *)_sect1; /* File free section */
+ const H5MV_free_section_t *sect2 = (const H5MV_free_section_t *)_sect2; /* File free section */
+ htri_t ret_value = FAIL; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect2);
+ HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+ /* Check if second section adjoins first section */
+ ret_value = H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr);
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MV__sect_can_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_merge
+ *
+ * Purpose: Merge two sections of this type
+ *
+ * Note: Second section always merges into first node
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5MV__sect_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2,
+ void H5_ATTR_UNUSED *_udata)
+{
+ H5MV_free_section_t **sect1 = (H5MV_free_section_t **)_sect1; /* File free section */
+ H5MV_free_section_t *sect2 = (H5MV_free_section_t *)_sect2; /* File free section */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert((*sect1)->sect_info.type == H5MV_FSPACE_SECT_SIMPLE);
+ HDassert(sect2);
+ HDassert(sect2->sect_info.type == H5MV_FSPACE_SECT_SIMPLE);
+ HDassert(H5F_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr));
+
+ /* Add second section's size to first section */
+ (*sect1)->sect_info.size += sect2->sect_info.size;
+
+ /* Get rid of second section */
+ if(H5MV__sect_free((H5FS_section_info_t *)sect2) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MV__sect_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_can_shrink
+ *
+ * Purpose: Can this section shrink the container?
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+htri_t
+H5MV__sect_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
+{
+ const H5MV_free_section_t *sect = (const H5MV_free_section_t *)_sect; /* File free section */
+ H5F_t *f = (H5F_t *)_udata;
+ haddr_t eoa; /* End of address space in the file */
+ haddr_t end; /* End of section to extend */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(f);
+
+ /* Retrieve the end oa the file's address space */
+ if(HADDR_UNDEF == (eoa = H5F_VFD_SWMR_MD_EOA(f)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "get_eoa request for VFD SWMR metadata file failed")
+
+ /* Compute address of end of section to check */
+ end = sect->sect_info.addr + sect->sect_info.size;
+
+ /* Check if the section is exactly at the end of the allocated space in the file */
+ if(H5F_addr_eq(end, eoa))
+ /* Indicate shrinking can occur */
+ ret_value = TRUE;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MV__sect_can_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5MV__sect_shrink
+ *
+ * Purpose: Shrink container with section
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5MV__sect_shrink(H5FS_section_info_t **_sect, void *_udata)
+{
+ H5F_t *f = (H5F_t *)_udata;
+ H5MV_free_section_t **sect = (H5MV_free_section_t **)_sect; /* File free section */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(H5F_INTENT(f) & H5F_ACC_RDWR);
+
+ /* Release section's space at EOA */
+ if(H5F__free_md(f, (*sect)->sect_info.addr, (*sect)->sect_info.size) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "free request for VFD SWMR metadata file failed")
+
+ /* Free the section */
+ if(H5MV__sect_free((H5FS_section_info_t *)*sect) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "can't free simple section node")
+
+ /* Mark section as freed, for free space manager */
+ *sect = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5MV__sect_shrink() */
diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c
index f2e9a75..fbac84d 100644
--- a/src/H5Pfapl.c
+++ b/src/H5Pfapl.c
@@ -406,7 +406,7 @@ 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 */
+static const H5F_vfd_swmr_config_t H5F_def_vfd_swmr_config_g = H5F_ACS_VFD_SWMR_CONFIG_DEF; /* Default vfd swmr configuration */
/*-------------------------------------------------------------------------
@@ -655,7 +655,7 @@ H5P__facc_reg_prop(H5P_genclass_t *pclass)
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,
+ 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")
diff --git a/src/H5private.h b/src/H5private.h
index 45b0340..842ba87 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1945,7 +1945,7 @@ 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 */
+/* Temporary globals for VFD SWMR */
extern hbool_t vfd_swmr_g;
extern hbool_t vfd_swmr_writer_g;
extern uint64_t tick_num_g;
@@ -2075,11 +2075,11 @@ H5_DLL herr_t H5CX_pop(void);
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_vfd_swmr_writer_end_of_tick() < 0) \
+ if(H5F_vfd_swmr_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_vfd_swmr_reader_end_of_tick() < 0) \
+ if(H5F_vfd_swmr_reader_end_of_tick() < 0) \
HGOTO_ERROR(H5E_FUNC, H5E_CANTSET, err, "end of tick error for VFD SWMR reader") \
} \
} \
@@ -2089,9 +2089,9 @@ H5_DLL herr_t H5CX_pop(void);
#define FUNC_ENTER_API(err) {{ \
FUNC_ENTER_API_COMMON \
FUNC_ENTER_API_INIT(err); \
+ VFD_SWMR_TEST_FOR_END_OF_TICK(FALSE, err); \
/* Clear thread error stack entering public functions */ \
H5E_clear_stack(NULL); \
- VFD_SWMR_TEST_FOR_END_OF_TICK(FALSE, err); \
{
/*
@@ -2291,15 +2291,16 @@ H5_DLL herr_t H5CX_pop(void);
FINISH_MPE_LOG \
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 \
- if(err_occurred) \
- (void)H5E_dump_api_stack(TRUE); \
- FUNC_LEAVE_API_THREADSAFE \
- return(ret_value); \
+#define FUNC_LEAVE_API(ret_value) \
+ if(!err_occurred) \
+ 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 \
+ if(err_occurred) \
+ (void)H5E_dump_api_stack(TRUE); \
+ FUNC_LEAVE_API_THREADSAFE \
+ return(ret_value); \
}} /*end scope from beginning of FUNC_ENTER*/
/* Use this macro to match the FUNC_ENTER_API_NOINIT macro */
diff --git a/src/Makefile.am b/src/Makefile.am
index bc89990..ef4a880 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -79,6 +79,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5HL.c H5HLcache.c H5HLdbg.c H5HLint.c H5HLprfx.c H5HLdblk.c\
H5HP.c H5I.c H5Itest.c H5L.c H5Lexternal.c H5lib_settings.c \
H5MF.c H5MFaggr.c H5MFdbg.c H5MFsection.c \
+ H5MV.c H5MVsection.c \
H5MM.c H5MP.c H5MPtest.c \
H5O.c H5Odeprec.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c H5Ocache_image.c \