diff options
Diffstat (limited to 'src/H5Fint.c')
-rw-r--r-- | src/H5Fint.c | 257 |
1 files changed, 255 insertions, 2 deletions
diff --git a/src/H5Fint.c b/src/H5Fint.c index 39934d6..17c494f 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -81,6 +81,11 @@ static herr_t H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, static herr_t H5F__flush_phase1(H5F_t *f); static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing); +/* VFD SWMR */ +static herr_t H5F__vfd_swmr_init_info(H5F_t *f); +static herr_t H5F__vfd_swmr_init_md(H5F_t *f); +static herr_t H5F__vfd_swmr_close_md(H5F_t *f); + /*********************/ /* Package Variables */ @@ -185,6 +190,10 @@ H5F_get_access_plist(H5F_t *f, hbool_t app_ref) if(H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME, &(f->shared->page_buf->min_raw_perc)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set minimum raw data fraction of page buffer") } /* end if */ + + if(H5P_set(new_plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, &(f->shared->vfd_swmr_config)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set initial metadata cache resize config.") + #ifdef H5_HAVE_PARALLEL if(H5P_set(new_plist, H5_COLL_MD_READ_FLAG_NAME, &(f->coll_md_read)) < 0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't set collective metadata read flag") @@ -1034,6 +1043,11 @@ H5F__new(H5F_file_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_ if(H5P_get(plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get object flush cb info") + /* Get VFD SWMR configuration */ + if(H5P_get(plist, H5F_ACS_VFD_SWMR_CONFIG_NAME, &(f->shared->vfd_swmr_config)) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get VFD SWMR config info") + f->shared->vfd_swmr_md_fd = -1; + /* Create a metadata cache with the specified number of elements. * The cache might be created with a different number of elements and * the access property list should be updated to reflect that. @@ -1294,6 +1308,12 @@ H5F__dest(H5F_t *f, hbool_t flush) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list") + /* Handle closing for the metadata file (VFD SWMR writer) */ + if(H5F_ACC_RDWR & H5F_INTENT(f) && f->shared->vfd_swmr_md_fd >= 0) { + if(H5F__vfd_swmr_close_md(f) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file") + } + /* Close the file */ if(H5FD_close(f->shared->lf) < 0) /* Push error, but keep going*/ @@ -1426,7 +1446,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) hbool_t use_file_locking; /*read from env var */ hbool_t ci_load = FALSE; /* whether MDC ci load requested */ hbool_t ci_write = FALSE; /* whether MDC CI write requested */ - H5F_t *ret_value = NULL; /*actual return value */ + hbool_t file_create = FALSE; /* creating a new file or not */ + H5F_t *ret_value = NULL; /*actual return value */ FUNC_ENTER_NOAPI(NULL) @@ -1596,6 +1617,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get minimum raw data fraction of page buffer") } /* end if */ + /* * Read or write the file superblock, depending on whether the file is * empty or not. @@ -1622,6 +1644,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) */ if(H5G_mkroot(file, TRUE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group") + + file_create = TRUE; + } /* end if */ else if(1 == shared->nrefs) { /* Read the superblock if it hasn't been read before. */ @@ -1636,8 +1661,36 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) /* Open the root group */ if(H5G_mkroot(file, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group") + } /* end if */ + if(H5F_VFD_SWMR_CONFIG(file)) { + /* Page buffering and page allocation strategy have to be enabled */ + if(!page_buf_size || !H5F_PAGED_AGGR(file)) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "file open fail with VFD SWMR writer") + if(1 == shared->nrefs) { + + /* Initialize globals for VFD SWMR writer and reader */ + if(H5F__vfd_swmr_init_info(file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "file open fail with initialization for VFD SWMR") + + /* For VFD SWMR writer */ + if(H5F_INTENT(file) & H5F_ACC_RDWR) { + HDassert(file->shared->vfd_swmr_config.vfd_swmr_writer); + + /* Create the metadata file */ + if(((file->shared->vfd_swmr_md_fd = HDopen(file->shared->vfd_swmr_config.md_file_path, O_CREAT|O_RDWR, H5_POSIX_CREATE_MODE_RW))) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create the metadata file") + + /* Create header and empty index in the metadata file */ + if(!file_create) { + if(H5F__vfd_swmr_init_md(file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "fail to initialize md for VFD SWMR writer") + } + } + } + } + /* * Decide the file close degree. If it's the first time to open the * file, set the degree to access property list value; if it's the @@ -1741,9 +1794,15 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) ret_value = file; done: - if((NULL == ret_value) && file) + if((NULL == ret_value) && file) { + if(file->shared->root_grp && file->shared->nrefs == 1) { + if(H5AC_expunge_tag_type_metadata(file, H5G_oloc(file->shared->root_grp)->addr, H5AC_OHDR_ID, H5AC__NO_FLAGS_SET, FALSE) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTEXPUNGE, NULL, "unable to expunge root group tagged entries") + } + if(H5F__dest(file, FALSE) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file") + } FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_open() */ @@ -3465,3 +3524,197 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F__format_convert() */ + +/*------------------------------------------------------------------------- + * Function: H5F__vfd_swmr_init_info + * + * Purpose: Initialize globals and the corresponding fields in file pointer. + * For VFD SWMR writer: + * --set vfd_swmr_g to TRUE + * --set vfd_swmr_writer_g to TRUE + * --set tick_num_g to 0 + * --set end_of_tick_g to the current time + tick length + * --set vfd_swmr_file_g to f->shared + * For VFD SWMR reader: + * --set vfd_swmr_g to TRUE + * --set vfd_swmr_writer_g to FALSE + * --set tick_num_g to the current tick read from the metadata file + * --set end_of_tick_g to the current time + tick length + * --set vfd_swmr_file_g to f->shared + * + * Return: Success: SUCCEED + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F__vfd_swmr_init_info(H5F_t *f) +{ + struct timespec tmp_end_of_tick; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + if(f->shared->vfd_swmr_config.vfd_swmr_writer) { + vfd_swmr_writer_g = f->shared->vfd_swmr_writer = TRUE; + tick_num_g = f->shared->tick_num = 0; + } else { + HDassert(!f->shared->vfd_swmr_config.vfd_swmr_writer); + vfd_swmr_writer_g = f->shared->vfd_swmr_writer = FALSE; + + /* Set tick_num_g to the current tick read from the metadata file */ + if(H5FD_vfd_swmr_get_tick_and_idx(f->shared->lf, FALSE, &tick_num_g, NULL, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTLOAD, FAIL, "unable to load/decode metadata file") + f->shared->tick_num = tick_num_g; + } + + /* Get current time */ + if(HDclock_gettime(CLOCK_MONOTONIC, &tmp_end_of_tick) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get time via clock_gettime") + + /* Increment by tick length */ + tmp_end_of_tick.tv_nsec += f->shared->vfd_swmr_config.tick_len * 100000000; + tmp_end_of_tick.tv_sec += tmp_end_of_tick.tv_nsec / 1000000000; + tmp_end_of_tick.tv_nsec = tmp_end_of_tick.tv_nsec % 1000000000; + HDmemcpy(&end_of_tick_g, &tmp_end_of_tick, sizeof(struct timespec)); + HDmemcpy(&f->shared->end_of_tick, &tmp_end_of_tick, sizeof(struct timespec)); + + vfd_swmr_g = f->shared->vfd_swmr = TRUE; + vfd_swmr_file_g = f->shared; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F__vfd_swmr_init_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__vfd_swmr_init_md + * + * Purpose: Encode the header and an empty index to the metadata file. + * This is used by the VFD SWMR writer when: + * --opening an existing HDF5 file + * --the HDF5 file is flushed and about to close + * + * Return: Success: SUCCEED + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F__vfd_swmr_init_md(H5F_t *f) +{ + uint8_t *p = NULL; /* Pointer to buffer */ + uint8_t *pp = NULL; /* Pointer to buffer for index */ + uint32_t metadata_chksum; /* Computed metadata checksum value */ + uint8_t image[H5FD_MD_HEADER_SIZE + H5FD_MD_EMPTY_INDEX_SIZE]; /* Buffer for header and empty index */ + unsigned hdr_idx_size = H5FD_MD_HEADER_SIZE + H5FD_MD_EMPTY_INDEX_SIZE; /* Size of header and index */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* + * Encode metadata file header + */ + p = image; + + /* Encode magic for header */ + HDmemcpy(p, H5FD_MD_HEADER_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += H5_SIZEOF_MAGIC; + + /* Encode page size, tick number, index offset, index length */ + UINT32ENCODE(p, f->shared->fs_page_size); + UINT64ENCODE(p, f->shared->tick_num); + UINT64ENCODE(p, H5FD_MD_HEADER_SIZE); + UINT64ENCODE(p, H5FD_MD_INDEX_SIZE(0)); + + /* Calculate checksum for header */ + metadata_chksum = H5_checksum_metadata(image, (size_t)(p - image), 0); + + /* Encode checksum for header */ + UINT32ENCODE(p, metadata_chksum); + + /* Sanity checks on header */ + HDassert((size_t)(p - image == H5FD_MD_HEADER_SIZE)); + + /* + * Encode metadata file index + */ + pp = p; + + /* Encode magic for index */ + HDmemcpy(p, H5FD_MD_INDEX_MAGIC, (size_t)H5_SIZEOF_MAGIC); + p += H5_SIZEOF_MAGIC; + + /* Encode tick number */ + UINT64ENCODE(p, f->shared->tick_num); + + /* Encode zero number of entries in index */ + UINT32ENCODE(p, 0); + + /* Calculate checksum for index */ + metadata_chksum = H5_checksum_metadata(pp, (size_t)(p - pp), 0); + + /* Encode checksum for index */ + UINT32ENCODE(p, metadata_chksum); + + /* Sanity checks on index */ + HDassert((size_t)(p - pp == H5FD_MD_EMPTY_INDEX_SIZE)); + + /* Verify the md file descriptor exists */ + HDassert(f->shared->vfd_swmr_md_fd >= 0); + + /* Set to beginning of the file */ + if(HDlseek(f->shared->vfd_swmr_md_fd, (HDoff_t)0, SEEK_SET) < 0) + HGOTO_ERROR(H5E_VFL, H5E_SEEKERROR, FAIL, "unable to seek in metadata file") + + /* Write header and empty index to the metadata file */ + if(HDwrite(f->shared->vfd_swmr_md_fd, image, hdr_idx_size) != hdr_idx_size) + HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "error in writing header and index to metadata file") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F__vfd_swmr_init_md() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__vfd_swmr_close_md + * + * Purpose: This is used by the VFD SWMR writer when the HDF5 file is + * flushed and about to close: + * --increment the tick + * --write header and an empty index to the metadata file + * --close and unlink the metadata file + * + * Return: Success: SUCCEED + * Failure: FAIL + * + *------------------------------------------------------------------------- + */ +static herr_t +H5F__vfd_swmr_close_md(H5F_t *f) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + HDassert(f->shared->vfd_swmr_md_fd >= 0); + + /* Increment tick_num */ + tick_num_g = ++f->shared->tick_num; + + /* Write an empty header and index to the md file */ + if(H5F__vfd_swmr_init_md(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "unable to encode and write to the metadata file") + + /* Close the md file */ + if(HDclose(f->shared->vfd_swmr_md_fd) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close the metadata file") + f->shared->vfd_swmr_md_fd = -1; + + /* Unlink the md file */ + if(HDunlink(f->shared->vfd_swmr_config.md_file_path) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTREMOVE, FAIL, "unable to unlink the metadata file") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5F__vfd_swmr_close_md() */ |