diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5F.c | 262 | ||||
-rw-r--r-- | src/H5Fint.c | 318 | ||||
-rw-r--r-- | src/H5Fprivate.h | 2 |
3 files changed, 334 insertions, 248 deletions
@@ -1260,82 +1260,23 @@ done: herr_t H5Fget_metadata_read_retry_info(hid_t file_id, H5F_retry_info_t *info) { - H5F_t *file; /* File object for file ID */ - unsigned i, j; /* Local index variable */ - size_t tot_size; /* Size of each retries[i] */ - herr_t ret_value = SUCCEED; /* Return value */ + H5F_t *file; /* File object for file ID */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE2("e", "i*x", file_id, info); /* Check args */ - if(!info) + if (!info) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct") /* Get the file pointer */ - if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + if (NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a file ID") - /* Copy the # of bins for "retries" array */ - info->nbins = file->shared->retries_nbins; - - /* Initialize the array of "retries" */ - HDmemset(info->retries, 0, sizeof(info->retries)); - - /* Return if there are no bins -- no retries */ - if(!info->nbins) - HGOTO_DONE(SUCCEED); - - /* Calculate size for each retries[i] */ - tot_size = info->nbins * sizeof(uint32_t); - - /* Map and copy information to info's retries for metadata items with tracking for read retries */ - j = 0; - for(i = 0; i < H5AC_NTYPES; i++) { - switch(i) { - case H5AC_OHDR_ID: - case H5AC_OHDR_CHK_ID: - case H5AC_BT2_HDR_ID: - case H5AC_BT2_INT_ID: - case H5AC_BT2_LEAF_ID: - case H5AC_FHEAP_HDR_ID: - case H5AC_FHEAP_DBLOCK_ID: - case H5AC_FHEAP_IBLOCK_ID: - case H5AC_FSPACE_HDR_ID: - case H5AC_FSPACE_SINFO_ID: - case H5AC_SOHM_TABLE_ID: - case H5AC_SOHM_LIST_ID: - case H5AC_EARRAY_HDR_ID: - case H5AC_EARRAY_IBLOCK_ID: - case H5AC_EARRAY_SBLOCK_ID: - case H5AC_EARRAY_DBLOCK_ID: - case H5AC_EARRAY_DBLK_PAGE_ID: - case H5AC_FARRAY_HDR_ID: - case H5AC_FARRAY_DBLOCK_ID: - case H5AC_FARRAY_DBLK_PAGE_ID: - case H5AC_SUPERBLOCK_ID: - HDassert(j < H5F_NUM_METADATA_READ_RETRY_TYPES); - if(file->shared->retries[i] != NULL) { - /* Allocate memory for retries[i] - * - * This memory should be released by the user with - * the H5free_memory() call. - */ - if(NULL == (info->retries[j] = (uint32_t *)H5MM_malloc(tot_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - - /* Copy the information */ - HDmemcpy(info->retries[j], file->shared->retries[i], tot_size); - } /* end if */ - - /* Increment location in info->retries[] array */ - j++; - break; - - default: - break; - } /* end switch */ - } /* end for */ + /* Get the retry info */ + if (H5F_get_metadata_read_retry_info(file, info) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't get metadata read retry info") done: FUNC_LEAVE_API(ret_value) @@ -1446,196 +1387,21 @@ done: herr_t H5Fstart_swmr_write(hid_t file_id) { - hbool_t ci_load = FALSE; /* whether MDC ci load requested */ - hbool_t ci_write = FALSE; /* whether MDC CI write requested */ - H5F_t *file = NULL; /* File info */ - size_t grp_dset_count=0; /* # of open objects: groups & datasets */ - size_t nt_attr_count=0; /* # of opened named datatypes + opened attributes */ - hid_t *obj_ids=NULL; /* List of ids */ - H5G_loc_t *obj_glocs=NULL; /* Group location of the object */ - H5O_loc_t *obj_olocs=NULL; /* Object location */ - H5G_name_t *obj_paths=NULL; /* Group hierarchy path */ - size_t u; /* Local index variable */ - hbool_t setup = FALSE; /* Boolean flag to indicate whether SWMR setting is enabled */ - H5F_io_info2_t fio_info; /* I/O info for operation */ - herr_t ret_value = SUCCEED; /* Return value */ + H5F_t *file = NULL; /* File info */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("e", "i", file_id); /* check args */ - if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file") - - /* Should have write permission */ - if((H5F_INTENT(file) & H5F_ACC_RDWR) == 0) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file") - - if(file->shared->sblock->super_vers < HDF5_SUPERBLOCK_VERSION_3) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file superblock version should be at least 3") - - HDassert((file->shared->low_bound == H5F_LIBVER_V110) && (file->shared->high_bound == H5F_LIBVER_V110)); - - /* Should not be marked for SWMR writing mode already */ - if(file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file already in SWMR writing mode") - - HDassert(file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS); - - /* Check to see if cache image is enabled. Fail if so */ - if(H5C_cache_image_status(file, &ci_load, &ci_write) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MDC cache image status") - if(ci_load || ci_write ) - HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "can't have both SWMR and MDC cache image") - - /* Flush the superblock extension */ - if(H5F_flush_tagged_metadata(file, file->shared->sblock->ext_addr, H5AC_ind_read_dxpl_id) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock extension") - - /* Flush data buffers */ - if(H5F__flush(file, H5AC_ind_read_dxpl_id, H5AC_rawdata_dxpl_id, FALSE) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information") - - /* Get the # of opened named datatypes and attributes */ - if(H5F_get_obj_count(file, H5F_OBJ_DATATYPE|H5F_OBJ_ATTR, FALSE, &nt_attr_count) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed") - if(nt_attr_count) - HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "named datatypes and/or attributes opened in the file") - - /* Get the # of opened datasets and groups */ - if(H5F_get_obj_count(file, H5F_OBJ_GROUP|H5F_OBJ_DATASET, FALSE, &grp_dset_count) < 0) - HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed") - - if(grp_dset_count) { - /* Allocate space for group and object locations */ - if((obj_ids = (hid_t *) H5MM_malloc(grp_dset_count * sizeof(hid_t))) == NULL) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for hid_t") - if((obj_glocs = (H5G_loc_t *) H5MM_malloc(grp_dset_count * sizeof(H5G_loc_t))) == NULL) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_loc_t") - if((obj_olocs = (H5O_loc_t *) H5MM_malloc(grp_dset_count * sizeof(H5O_loc_t))) == NULL) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5O_loc_t") - if((obj_paths = (H5G_name_t *) H5MM_malloc(grp_dset_count * sizeof(H5G_name_t))) == NULL) - HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_name_t") - - /* Get the list of opened object ids (groups & datasets) */ - if(H5F_get_obj_ids(file, H5F_OBJ_GROUP|H5F_OBJ_DATASET, grp_dset_count, obj_ids, FALSE, &grp_dset_count) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "H5F_get_obj_ids failed") - - /* Refresh opened objects (groups, datasets) in the file */ - for(u = 0; u < grp_dset_count; u++) { - H5O_loc_t *oloc; /* object location */ - H5G_loc_t tmp_loc; - - /* Set up the id's group location */ - obj_glocs[u].oloc = &obj_olocs[u]; - obj_glocs[u].path = &obj_paths[u]; - H5G_loc_reset(&obj_glocs[u]); - - /* get the id's object location */ - if((oloc = H5O_get_loc(obj_ids[u])) == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object") - - /* Make deep local copy of object's location information */ - H5G_loc(obj_ids[u], &tmp_loc); - H5G_loc_copy(&obj_glocs[u], &tmp_loc, H5_COPY_DEEP); - - /* Close the object */ - if(H5I_dec_ref(obj_ids[u]) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "decrementing object ID failed") - } /* end for */ - } /* end if */ - - /* Set up I/O info for operation */ - fio_info.f = file; - if(NULL == (fio_info.meta_dxpl = (H5P_genplist_t *)H5I_object(H5AC_ind_read_dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - if(NULL == (fio_info.raw_dxpl = (H5P_genplist_t *)H5I_object(H5AC_rawdata_dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - - /* Flush and reset the accumulator */ - if(H5F__accum_reset(&fio_info, TRUE) < 0) - HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator") - - /* Turn on SWMR write in shared file open flags */ - file->shared->flags |= H5F_ACC_SWMR_WRITE; - - /* Mark the file in SWMR writing mode */ - file->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS; - - /* Set up metadata read attempts */ - file->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS; - - /* Initialize "retries" and "retries_nbins" */ - if(H5F_set_retries(file) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins") - - /* Turn off usage of accumulator */ - file->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA; - if(H5FD_set_feature_flags(file->shared->lf, file->shared->feature_flags) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD") - - setup = TRUE; - - /* Mark superblock as dirty */ - if(H5F_super_dirty(file) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") - - /* Flush the superblock */ - if(H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG, H5AC_ind_read_dxpl_id) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock") - - /* Evict all flushed entries in the cache except the pinned superblock */ - if(H5F__evict_cache_entries(file, H5AC_ind_read_dxpl_id) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to evict file's cached information") - - /* Refresh (reopen) the objects (groups & datasets) in the file */ - for(u = 0; u < grp_dset_count; u++) - if(H5O_refresh_metadata_reopen(obj_ids[u], &obj_glocs[u], H5AC_ind_read_dxpl_id, TRUE) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object") + if (NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hid_t identifier is not a file ID") - /* Unlock the file */ - if(H5FD_unlock(file->shared->lf) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to unlock the file") + /* start SWMR writing */ + if (H5F_start_swmr_write(file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, "unable to start SWMR writing") done: - if(ret_value < 0 && setup) { - HDassert(file); - - /* Re-enable accumulator */ - file->shared->feature_flags |= (unsigned)H5FD_FEAT_ACCUMULATE_METADATA; - if(H5FD_set_feature_flags(file->shared->lf, file->shared->feature_flags) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD") - - /* Reset the # of read attempts */ - file->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS; - if(H5F_set_retries(file) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins") - - /* Un-set H5F_ACC_SWMR_WRITE in shared open flags */ - file->shared->flags &= ~H5F_ACC_SWMR_WRITE; - - /* Unmark the file: not in SWMR writing mode */ - file->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS); - - /* Mark superblock as dirty */ - if(H5F_super_dirty(file) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") - - /* Flush the superblock */ - if(H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG, H5AC_ind_read_dxpl_id) < 0) - HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock") - } /* end if */ - - /* Free memory */ - if(obj_ids) - H5MM_xfree(obj_ids); - if(obj_glocs) - H5MM_xfree(obj_glocs); - if(obj_olocs) - H5MM_xfree(obj_olocs); - if(obj_paths) - H5MM_xfree(obj_paths); - FUNC_LEAVE_API(ret_value) } /* end H5Fstart_swmr_write() */ diff --git a/src/H5Fint.c b/src/H5Fint.c index 24844a4..1d14ec6 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -2981,3 +2981,321 @@ H5F_set_coll_md_read(H5F_t *f, H5P_coll_md_read_flag_t cmr) FUNC_LEAVE_NOAPI_VOID } /* H5F_set_coll_md_read() */ #endif /* H5_HAVE_PARALLEL */ + + +/*------------------------------------------------------------------------- + * Function: H5F_get_metadata_read_retry_info + * + * Purpose: Private function to retrieve the collection of read retries + * for metadata items with checksum. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_get_metadata_read_retry_info(H5F_t *file, H5F_retry_info_t *info) +{ + unsigned i, j; /* Local index variable */ + size_t tot_size; /* Size of each retries[i] */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* Check args */ + HDassert(file); + HDassert(info); + + /* Copy the # of bins for "retries" array */ + info->nbins = file->shared->retries_nbins; + + /* Initialize the array of "retries" */ + HDmemset(info->retries, 0, sizeof(info->retries)); + + /* Return if there are no bins -- no retries */ + if (!info->nbins) + HGOTO_DONE(SUCCEED); + + /* Calculate size for each retries[i] */ + tot_size = info->nbins * sizeof(uint32_t); + + /* Map and copy information to info's retries for metadata items with tracking for read retries */ + j = 0; + for (i = 0; i < H5AC_NTYPES; i++) { + switch (i) { + case H5AC_OHDR_ID: + case H5AC_OHDR_CHK_ID: + case H5AC_BT2_HDR_ID: + case H5AC_BT2_INT_ID: + case H5AC_BT2_LEAF_ID: + case H5AC_FHEAP_HDR_ID: + case H5AC_FHEAP_DBLOCK_ID: + case H5AC_FHEAP_IBLOCK_ID: + case H5AC_FSPACE_HDR_ID: + case H5AC_FSPACE_SINFO_ID: + case H5AC_SOHM_TABLE_ID: + case H5AC_SOHM_LIST_ID: + case H5AC_EARRAY_HDR_ID: + case H5AC_EARRAY_IBLOCK_ID: + case H5AC_EARRAY_SBLOCK_ID: + case H5AC_EARRAY_DBLOCK_ID: + case H5AC_EARRAY_DBLK_PAGE_ID: + case H5AC_FARRAY_HDR_ID: + case H5AC_FARRAY_DBLOCK_ID: + case H5AC_FARRAY_DBLK_PAGE_ID: + case H5AC_SUPERBLOCK_ID: + HDassert(j < H5F_NUM_METADATA_READ_RETRY_TYPES); + if (file->shared->retries[i] != NULL) { + /* Allocate memory for retries[i] + * + * This memory should be released by the user with + * the H5free_memory() call. + */ + if (NULL == (info->retries[j] = (uint32_t *)H5MM_malloc(tot_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Copy the information */ + HDmemcpy(info->retries[j], file->shared->retries[i], tot_size); + } + + /* Increment location in info->retries[] array */ + j++; + break; + + default: + break; + } + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_get_metadata_read_retry_info() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_start_swmr_write + * + * Purpose: To enable SWMR writing mode for the file + * + * 1) Refresh opened objects: part 1 + * 2) Flush & reset accumulator + * 3) Mark the file in SWMR writing mode + * 4) Set metadata read attempts and retries info + * 5) Disable accumulator + * 6) Evict all cache entries except the superblock + * 7) Refresh opened objects (part 2) + * 8) Unlock the file + * + * Pre-conditions: + * + * 1) The file being opened has v3 superblock + * 2) The file is opened with H5F_ACC_RDWR + * 3) The file is not already marked for SWMR writing + * 4) Current implementaion for opened objects: + * --only allow datasets and groups without attributes + * --disallow named datatype with/without attributes + * --disallow opened attributes attached to objects + * + * NOTE: Currently, only opened groups and datasets are allowed + * when enabling SWMR via H5Fstart_swmr_write(). + * Will later implement a different approach-- + * set up flush dependency/proxy even for file opened without + * SWMR to resolve issues with opened objects. + * + * Return: SUCCEED/FAIL + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_start_swmr_write(H5F_t *file) +{ + hbool_t ci_load = FALSE; /* whether MDC ci load requested */ + hbool_t ci_write = FALSE; /* whether MDC CI write requested */ + size_t grp_dset_count=0; /* # of open objects: groups & datasets */ + size_t nt_attr_count=0; /* # of opened named datatypes + opened attributes */ + hid_t *obj_ids = NULL; /* List of ids */ + H5G_loc_t *obj_glocs = NULL; /* Group location of the object */ + H5O_loc_t *obj_olocs = NULL; /* Object location */ + H5G_name_t *obj_paths = NULL; /* Group hierarchy path */ + size_t u; /* Local index variable */ + hbool_t setup = FALSE; /* Boolean flag to indicate whether SWMR setting is enabled */ + H5F_io_info2_t fio_info; /* I/O info for operation */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) + + /* check args */ + HDassert(file); + + /* Should have write permission */ + if ((H5F_INTENT(file) & H5F_ACC_RDWR) == 0) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file") + + /* Check superblock version */ + if (file->shared->sblock->super_vers < HDF5_SUPERBLOCK_VERSION_3) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file superblock version - should be at least 3") + + /* Check for correct file format version */ + if ((file->shared->low_bound != H5F_LIBVER_V110) || (file->shared->high_bound != H5F_LIBVER_V110)) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file format version does not support SWMR - needs to be 1.10 or greater") + + /* Should not be marked for SWMR writing mode already */ + if (file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file already in SWMR writing mode") + + /* Check to see if cache image is enabled. Fail if so */ + if (H5C_cache_image_status(file, &ci_load, &ci_write) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MDC cache image status") + if (ci_load || ci_write ) + HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "can't have both SWMR and MDC cache image") + + /* Flush the superblock extension */ + if (H5F_flush_tagged_metadata(file, file->shared->sblock->ext_addr, H5AC_ind_read_dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock extension") + + /* Flush data buffers */ + if (H5F__flush(file, H5AC_ind_read_dxpl_id, H5AC_rawdata_dxpl_id, FALSE) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information") + + /* Get the # of opened named datatypes and attributes */ + if (H5F_get_obj_count(file, H5F_OBJ_DATATYPE|H5F_OBJ_ATTR, FALSE, &nt_attr_count) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed") + if (nt_attr_count) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "named datatypes and/or attributes opened in the file") + + /* Get the # of opened datasets and groups */ + if (H5F_get_obj_count(file, H5F_OBJ_GROUP|H5F_OBJ_DATASET, FALSE, &grp_dset_count) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_count failed") + + if (grp_dset_count) { + /* Allocate space for group and object locations */ + if ((obj_ids = (hid_t *) H5MM_malloc(grp_dset_count * sizeof(hid_t))) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for hid_t") + if ((obj_glocs = (H5G_loc_t *) H5MM_malloc(grp_dset_count * sizeof(H5G_loc_t))) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_loc_t") + if ((obj_olocs = (H5O_loc_t *) H5MM_malloc(grp_dset_count * sizeof(H5O_loc_t))) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5O_loc_t") + if ((obj_paths = (H5G_name_t *) H5MM_malloc(grp_dset_count * sizeof(H5G_name_t))) == NULL) + HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_name_t") + + /* Get the list of opened object ids (groups & datasets) */ + if (H5F_get_obj_ids(file, H5F_OBJ_GROUP|H5F_OBJ_DATASET, grp_dset_count, obj_ids, FALSE, &grp_dset_count) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "H5F_get_obj_ids failed") + + /* Refresh opened objects (groups, datasets) in the file */ + for (u = 0; u < grp_dset_count; u++) { + H5O_loc_t *oloc; /* object location */ + H5G_loc_t tmp_loc; + + /* Set up the id's group location */ + obj_glocs[u].oloc = &obj_olocs[u]; + obj_glocs[u].path = &obj_paths[u]; + H5G_loc_reset(&obj_glocs[u]); + + /* get the id's object location */ + if ((oloc = H5O_get_loc(obj_ids[u])) == NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object") + + /* Make deep local copy of object's location information */ + H5G_loc(obj_ids[u], &tmp_loc); + H5G_loc_copy(&obj_glocs[u], &tmp_loc, H5_COPY_DEEP); + + /* Close the object */ + if (H5I_dec_ref(obj_ids[u]) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "decrementing object ID failed") + } + } + + /* Set up I/O info for operation */ + fio_info.f = file; + if (NULL == (fio_info.meta_dxpl = (H5P_genplist_t *)H5I_object(H5AC_ind_read_dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + if (NULL == (fio_info.raw_dxpl = (H5P_genplist_t *)H5I_object(H5AC_rawdata_dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") + + /* Flush and reset the accumulator */ + if (H5F__accum_reset(&fio_info, TRUE) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator") + + /* Turn on SWMR write in shared file open flags */ + file->shared->flags |= H5F_ACC_SWMR_WRITE; + + /* Mark the file in SWMR writing mode */ + file->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS; + + /* Set up metadata read attempts */ + file->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS; + + /* Initialize "retries" and "retries_nbins" */ + if (H5F_set_retries(file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins") + + /* Turn off usage of accumulator */ + file->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA; + if (H5FD_set_feature_flags(file->shared->lf, file->shared->feature_flags) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD") + + setup = TRUE; + + /* Mark superblock as dirty */ + if (H5F_super_dirty(file) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + + /* Flush the superblock */ + if (H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG, H5AC_ind_read_dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock") + + /* Evict all flushed entries in the cache except the pinned superblock */ + if (H5F__evict_cache_entries(file, H5AC_ind_read_dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to evict file's cached information") + + /* Refresh (reopen) the objects (groups & datasets) in the file */ + for (u = 0; u < grp_dset_count; u++) + if (H5O_refresh_metadata_reopen(obj_ids[u], &obj_glocs[u], H5AC_ind_read_dxpl_id, TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object") + + /* Unlock the file */ + if (H5FD_unlock(file->shared->lf) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to unlock the file") + +done: + if(ret_value < 0 && setup) { + + /* Re-enable accumulator */ + file->shared->feature_flags |= (unsigned)H5FD_FEAT_ACCUMULATE_METADATA; + if (H5FD_set_feature_flags(file->shared->lf, file->shared->feature_flags) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD") + + /* Reset the # of read attempts */ + file->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS; + if (H5F_set_retries(file) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins") + + /* Un-set H5F_ACC_SWMR_WRITE in shared open flags */ + file->shared->flags &= ~H5F_ACC_SWMR_WRITE; + + /* Unmark the file: not in SWMR writing mode */ + file->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS); + + /* Mark superblock as dirty */ + if (H5F_super_dirty(file) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + + /* Flush the superblock */ + if (H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG, H5AC_ind_read_dxpl_id) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock") + } + + /* Free memory */ + if (obj_ids) + H5MM_xfree(obj_ids); + if (obj_glocs) + H5MM_xfree(obj_glocs); + if (obj_olocs) + H5MM_xfree(obj_olocs); + if (obj_paths) + H5MM_xfree(obj_paths); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F_start_swmr_write() */ + diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 28ebbd2..a53ca24 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -723,6 +723,7 @@ typedef enum H5F_mem_page_t { H5_DLL H5F_t *H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t dxpl_id); H5_DLL herr_t H5F_try_close(H5F_t *f, hbool_t *was_closed/*out*/); +H5_DLL herr_t H5F_start_swmr_write(H5F_t *file); /* Functions that retrieve values from the file struct */ H5_DLL H5F_libver_t H5F_get_low_bound(const H5F_t *f); @@ -817,6 +818,7 @@ H5_DLL herr_t H5F_get_checksums(const uint8_t *buf, size_t chk_size, uint32_t *s /* Routine to track the # of retries */ H5_DLL herr_t H5F_track_metadata_read_retries(H5F_t *f, unsigned actype, unsigned retries); H5_DLL herr_t H5F_set_retries(H5F_t *f); +H5_DLL herr_t H5F_get_metadata_read_retry_info(H5F_t *file, H5F_retry_info_t *info); /* Routine to invoke callback function upon object flush */ H5_DLL herr_t H5F_object_flush_cb(H5F_t *f, hid_t obj_id); |