diff options
Diffstat (limited to 'src/H5Fint.c')
-rw-r--r-- | src/H5Fint.c | 579 |
1 files changed, 482 insertions, 97 deletions
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() */ |