diff options
author | Vailin Choi <vchoi@jam.ad.hdfgroup.org> | 2018-09-28 16:29:02 (GMT) |
---|---|---|
committer | Vailin Choi <vchoi@jam.ad.hdfgroup.org> | 2018-09-28 16:29:02 (GMT) |
commit | 5c7ca8afff0e635f12652c35dbe9818235ac34c4 (patch) | |
tree | 1245d78ca4b0aaeb40ecab6b2615ddad886042c3 /src | |
parent | 06fa8a94558939400dc43e99c08a784e26dfa01d (diff) | |
download | hdf5-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.c | 7 | ||||
-rw-r--r-- | src/H5F.c | 1 | ||||
-rw-r--r-- | src/H5FDprivate.h | 66 | ||||
-rw-r--r-- | src/H5FDvfd_swmr.c | 315 | ||||
-rw-r--r-- | src/H5FDvfd_swmr.h | 1 | ||||
-rw-r--r-- | src/H5FSprivate.h | 1 | ||||
-rw-r--r-- | src/H5Fint.c | 579 | ||||
-rw-r--r-- | src/H5Fpkg.h | 46 | ||||
-rw-r--r-- | src/H5Fprivate.h | 20 | ||||
-rw-r--r-- | src/H5Fquery.c | 24 | ||||
-rw-r--r-- | src/H5Fspace.c | 160 | ||||
-rw-r--r-- | src/H5MV.c | 518 | ||||
-rw-r--r-- | src/H5MVmodule.h | 33 | ||||
-rw-r--r-- | src/H5MVpkg.h | 83 | ||||
-rw-r--r-- | src/H5MVprivate.h | 58 | ||||
-rw-r--r-- | src/H5MVsection.c | 361 | ||||
-rw-r--r-- | src/H5Pfapl.c | 4 | ||||
-rw-r--r-- | src/H5private.h | 27 | ||||
-rw-r--r-- | src/Makefile.am | 1 |
19 files changed, 1994 insertions, 311 deletions
@@ -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 */ /*******************/ @@ -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 \ |