diff options
Diffstat (limited to 'src/H5Fint.c')
-rw-r--r-- | src/H5Fint.c | 1129 |
1 files changed, 916 insertions, 213 deletions
diff --git a/src/H5Fint.c b/src/H5Fint.c index 24844a4..e6188e6 100644 --- a/src/H5Fint.c +++ b/src/H5Fint.c @@ -24,6 +24,7 @@ #include "H5private.h" /* Generic Functions */ #include "H5Aprivate.h" /* Attributes */ #include "H5ACprivate.h" /* Metadata cache */ +#include "H5CXprivate.h" /* API Contexts */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ @@ -73,10 +74,13 @@ typedef struct H5F_olist_t { /********************/ static int H5F_get_objects_cb(void *obj_ptr, hid_t obj_id, void *key); +static herr_t H5F__build_name(const char *prefix, const char *file_name, + char **full_name/*out*/); +static char *H5F__getenv_prefix_name(char **env_prefix/*in,out*/); static herr_t H5F_build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name, char ** /*out*/ actual_name);/* Declare a free list to manage the H5F_t struct */ -static herr_t H5F__flush_phase1(H5F_t *f, hid_t meta_dxpl_id); -static herr_t H5F__flush_phase2(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t closing); +static herr_t H5F__flush_phase1(H5F_t *f); +static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing); /*********************/ @@ -100,6 +104,7 @@ H5FL_DEFINE(H5F_t); H5FL_DEFINE(H5F_file_t); + /*------------------------------------------------------------------------- * Function: H5F_get_access_plist * @@ -213,7 +218,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_access_plist() */ - + /*------------------------------------------------------------------------- * Function: H5F_get_obj_count * @@ -241,7 +246,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_obj_count() */ - + /*------------------------------------------------------------------------- * Function: H5F_get_obj_ids * @@ -268,7 +273,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_obj_ids() */ - + /*--------------------------------------------------------------------------- * Function: H5F_get_objects * @@ -370,7 +375,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_objects() */ - + /*------------------------------------------------------------------------- * Function: H5F_get_objects_cb * @@ -479,6 +484,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_objects_cb() */ + /*-------------------------------------------------------------------------- * Function: H5F__build_name * @@ -487,7 +493,7 @@ done: * Return: Non-negative on success/Negative on failure *--------------------------------------------------------------------------*/ static herr_t -H5F__build_name(char *prefix, char *file_name, char **full_name/*out*/) +H5F__build_name(const char *prefix, const char *file_name, char **full_name/*out*/) { size_t prefix_len; /* length of prefix */ size_t fname_len; /* Length of external link file name */ @@ -500,7 +506,7 @@ H5F__build_name(char *prefix, char *file_name, char **full_name/*out*/) /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */ if(NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate filename buffer") + HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate filename buffer") /* Compose the full file name */ HDsnprintf(*full_name, (prefix_len + fname_len + 2), "%s%s%s", prefix, @@ -510,9 +516,9 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F__build_name() */ - + /*-------------------------------------------------------------------------- - * Function: H5F__getenv_prefix_name -- + * Function: H5F__getenv_prefix_name * * Purpose: Get the first pathname in the list of pathnames stored in env_prefix, * which is separated by the environment delimiter. @@ -524,43 +530,49 @@ done: static char * H5F__getenv_prefix_name(char **env_prefix/*in,out*/) { - char *retptr=NULL; - char *strret=NULL; + char *strret; /* Pointer to next separator */ + char *ret_value = NULL; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_STATIC_NOERR + + /* Set return value now */ + ret_value = *env_prefix; + /* Advance to next component, if possible */ strret = HDstrchr(*env_prefix, H5_COLON_SEPC); - if (strret == NULL) { - retptr = *env_prefix; - *env_prefix = strret; - } else { - retptr = *env_prefix; + if(strret == NULL) + *env_prefix = NULL; + else { + /* Advance to next component */ *env_prefix = strret + 1; + + /* Terminate current component (pointed to by ret_value) */ *strret = '\0'; - } + } /* end else */ - FUNC_LEAVE_NOAPI(retptr) + FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__getenv_prefix_name() */ + /*------------------------------------------------------------------------- * Function: H5F_prefix_open_file * * Purpose: Attempts to open a dataset file. * - * Return: Non-negative on success/Negative on failure + * Return: Pointer to an opened file on success / NULL on failure *------------------------------------------------------------------------- */ H5F_t * -H5F_prefix_open_file(hid_t plist_id, H5F_t *primary_file, const char *prefix_type, - const char *file_name, unsigned file_intent, hid_t fapl_id, hid_t dxpl_id) +H5F_prefix_open_file(H5F_t *primary_file, H5F_prefix_open_t prefix_type, + const char *prop_prefix, const char *file_name, unsigned file_intent, + hid_t fapl_id) { H5F_t *src_file = NULL; /* Source file */ - H5F_t *ret_value = NULL; /* Actual return value */ char *full_name = NULL; /* File name with prefix */ - char *my_prefix = NULL; /* Library's copy of the prefix */ char *actual_file_name = NULL; /* File's actual name */ char *temp_file_name = NULL; /* Temporary pointer to file name */ size_t temp_file_name_len; /* Length of temporary file name */ + H5F_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -572,15 +584,19 @@ H5F_prefix_open_file(hid_t plist_id, H5F_t *primary_file, const char *prefix_typ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") temp_file_name_len = HDstrlen(temp_file_name); - /* target file_name is an absolute pathname: see RM for detailed description */ + /* Target file_name is an absolute pathname: see RM for detailed description */ if(H5_CHECK_ABSOLUTE(file_name) || H5_CHECK_ABS_PATH(file_name)) { /* Try opening file */ - if(NULL == (src_file = H5F_efc_open(primary_file, file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id))) { + src_file = H5F__efc_open(primary_file, file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); + + /* Adjust temporary file name if file not opened */ + if(NULL == src_file) { char *ptr; + /* Reset the error stack */ H5E_clear_stack(NULL); - /* get last component of file_name */ + /* Get last component of file_name */ H5_GET_LAST_DELIMITER(file_name, ptr) HDassert(ptr); @@ -594,32 +610,40 @@ H5F_prefix_open_file(hid_t plist_id, H5F_t *primary_file, const char *prefix_typ } /* end if */ else if(H5_CHECK_ABS_DRIVE(file_name)) { /* Try opening file */ - if(NULL == (src_file = H5F_efc_open(primary_file, file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id))) { + src_file = H5F__efc_open(primary_file, file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); + /* Adjust temporary file name if file not opened */ + if(NULL == src_file) { + /* Reset the error stack */ H5E_clear_stack(NULL); - /* strip "<drive-letter>:" */ + /* Strip "<drive-letter>:" */ HDstrncpy(temp_file_name, &file_name[2], temp_file_name_len); temp_file_name[temp_file_name_len - 1] = '\0'; } /* end if */ } /* end if */ - /* try searching from paths set in the environment variable */ + /* Try searching from paths set in the environment variable */ if(src_file == NULL) { char *env_prefix; - if (HDstrcmp(prefix_type, H5D_ACS_VDS_PREFIX_NAME) == 0) + /* Get the appropriate environment variable */ + if(H5F_PREFIX_VDS == prefix_type) env_prefix = HDgetenv("HDF5_VDS_PREFIX"); - else if (HDstrcmp(prefix_type, H5L_ACS_ELINK_PREFIX_NAME) == 0) + else if(H5F_PREFIX_ELINK == prefix_type) env_prefix = HDgetenv("HDF5_EXT_PREFIX"); else - HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, NULL, "prefix name is not sensible") + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, NULL, "prefix type is not sensible") + + /* If environment variable is defined, iterate through prefixes it defines */ if(NULL != env_prefix) { char *tmp_env_prefix, *saved_env; + /* Make a copy of the environment variable string */ if(NULL == (saved_env = tmp_env_prefix = H5MM_strdup(env_prefix))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + /* Loop over prefixes in environment variable */ while((tmp_env_prefix) && (*tmp_env_prefix)) { char *out_prefix_name; @@ -630,65 +654,74 @@ H5F_prefix_open_file(hid_t plist_id, H5F_t *primary_file, const char *prefix_typ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename") } /* end if */ - src_file = H5F_efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id); + /* Try opening file */ + src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); + + /* Release copy of file name */ full_name = (char *)H5MM_xfree(full_name); - if(src_file != NULL) + + /* Check for file not opened */ + if(NULL == src_file) + /* Reset the error stack */ + H5E_clear_stack(NULL); + /* Leave if file was opened */ + else break; - H5E_clear_stack(NULL); } /* end if */ } /* end while */ + saved_env = (char *)H5MM_xfree(saved_env); } /* end if */ } /* end if */ - /* try searching from property list */ - if(src_file == NULL) { - ssize_t size = 0; - H5E_BEGIN_TRY { - if (HDstrcmp(prefix_type, H5D_ACS_VDS_PREFIX_NAME) == 0) - size = H5Pget_virtual_prefix(plist_id, NULL, 0); - else if (HDstrcmp(prefix_type, H5L_ACS_ELINK_PREFIX_NAME) == 0) - size = H5Pget_elink_prefix(plist_id, NULL, 0); - } H5E_END_TRY; - if(size <= 0) - my_prefix = NULL; - else { - /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */ - if(NULL == (my_prefix = (char *)H5MM_malloc((size_t)size + 1))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate prefix buffer") - if (HDstrcmp(prefix_type, H5D_ACS_VDS_PREFIX_NAME) == 0) - size = H5Pget_virtual_prefix(plist_id, my_prefix, (size_t)size+1); - else if (HDstrcmp(prefix_type, H5L_ACS_ELINK_PREFIX_NAME) == 0) - size = H5Pget_elink_prefix(plist_id, my_prefix, (size_t)size+1); - if(size < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file prefix") - if(my_prefix) { - if(H5F__build_name(my_prefix, temp_file_name, &full_name/*out*/) < 0) - HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename") - my_prefix = (char *)H5MM_xfree(my_prefix); - if(NULL == (src_file = H5F_efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id))) - H5E_clear_stack(NULL); - full_name = (char *)H5MM_xfree(full_name); - } - } - } + /* Try searching from property list */ + if(src_file == NULL && prop_prefix) { + /* Construct name to open */ + if(H5F__build_name(prop_prefix, temp_file_name, &full_name/*out*/) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename") + + /* Try opening file */ + src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); - /* try searching from main file's "extpath": see description in H5F_open() & H5_build_extpath() */ + /* Release name */ + full_name = (char *)H5MM_xfree(full_name); + + /* Check for file not opened */ + if(NULL == src_file) + /* Reset the error stack */ + H5E_clear_stack(NULL); + } /* end if */ + + /* Try searching from main file's "extpath": see description in H5F_open() & H5_build_extpath() */ if(src_file == NULL) { char *dspath; if(NULL != (dspath = H5F_EXTPATH(primary_file))) { + /* Construct name to open */ if(H5F__build_name(dspath, temp_file_name, &full_name/*out*/) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename") - if(NULL == (src_file = H5F_efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id))) - H5E_clear_stack(NULL); + + /* Try opening file */ + src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); + + /* Release name */ full_name = (char *)H5MM_xfree(full_name); + + /* Check for file not opened */ + if(NULL == src_file) + /* Reset the error stack */ + H5E_clear_stack(NULL); } /* end if */ } /* end if */ - /* try the relative file_name stored in temp_file_name */ + /* Try the relative file_name stored in temp_file_name */ if(src_file == NULL) { - if(NULL == (src_file = H5F_efc_open(primary_file, temp_file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id))) + /* Try opening file */ + src_file = H5F__efc_open(primary_file, temp_file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); + + /* Check for file not opened */ + if(NULL == src_file) + /* Reset the error stack */ H5E_clear_stack(NULL); } /* end if */ @@ -714,19 +747,24 @@ H5F_prefix_open_file(hid_t plist_id, H5F_t *primary_file, const char *prefix_typ actual_file_name = (char *)H5MM_xfree(actual_file_name); /* Try opening with the resolved name */ - if(NULL == (src_file = H5F_efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id, dxpl_id))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file, file name = '%s', temp_file_name = '%s'", file_name, temp_file_name) + src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id); + + /* Release name */ full_name = (char *)H5MM_xfree(full_name); + + /* Check for file not opened */ + if(NULL == src_file) + /* Reset the error stack */ + H5E_clear_stack(NULL); } /* end if */ /* Success */ ret_value = src_file; + done: if((NULL == ret_value) && src_file) if(H5F_efc_close(primary_file, src_file) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "can't close source file") - if(my_prefix) - my_prefix = (char *)H5MM_xfree(my_prefix); if(full_name) full_name = (char *)H5MM_xfree(full_name); if(temp_file_name) @@ -737,7 +775,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_prefix_open_file() */ - + /*------------------------------------------------------------------------- * Function: H5F__is_hdf5 * @@ -752,28 +790,20 @@ done: *------------------------------------------------------------------------- */ htri_t -H5F__is_hdf5(const char *name, hid_t meta_dxpl_id, hid_t raw_dxpl_id) +H5F__is_hdf5(const char *name) { H5FD_t *file = NULL; /* Low-level file struct */ - H5FD_io_info_t fdio_info; /* File driver I/O info */ haddr_t sig_addr; /* Addess of hdf5 file signature */ htri_t ret_value = FAIL; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE_VOL /* Open the file at the virtual file layer */ if(NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, H5P_FILE_ACCESS_DEFAULT, HADDR_UNDEF))) - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") - - /* Set up the file driver info */ - fdio_info.file = file; - if(NULL == (fdio_info.meta_dxpl = (H5P_genplist_t *)H5I_object(meta_dxpl_id))) - HGOTO_ERROR(H5E_CACHE, H5E_BADATOM, FAIL, "can't get new property list object") - if(NULL == (fdio_info.raw_dxpl = (H5P_genplist_t *)H5I_object(raw_dxpl_id))) - HGOTO_ERROR(H5E_CACHE, H5E_BADATOM, FAIL, "can't get new property list object") + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to open file") /* The file is an hdf5 file if the hdf5 file signature can be found */ - if(H5FD_locate_signature(&fdio_info, &sig_addr) < 0) + if(H5FD_locate_signature(file, &sig_addr) < 0) HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "unable to locate file signature") ret_value = (HADDR_UNDEF != sig_addr); @@ -783,10 +813,10 @@ done: if(H5FD_close(file) < 0 && ret_value >= 0) HDONE_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file") - FUNC_LEAVE_NOAPI(ret_value) + FUNC_LEAVE_NOAPI_VOL(ret_value) } /* end H5F__is_hdf5() */ - + /*------------------------------------------------------------------------- * Function: H5F_new * @@ -1032,7 +1062,7 @@ done: if(!shared) { /* Attempt to clean up some of the shared file structures */ if(f->shared->efc) - if(H5F_efc_destroy(f->shared->efc) < 0) + if(H5F__efc_destroy(f->shared->efc) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "can't destroy external file cache") if(f->shared->fcpl_id > 0) if(H5I_dec_ref(f->shared->fcpl_id) < 0) @@ -1046,7 +1076,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_new() */ - + /*------------------------------------------------------------------------- * Function: H5F__dest * @@ -1059,7 +1089,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) +H5F__dest(H5F_t *f, hbool_t flush) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1071,14 +1101,13 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) if(1 == f->shared->nrefs) { int actype; /* metadata cache type (enum value) */ - H5F_io_info2_t fio_info; /* I/O info for operation */ /* Flush at this point since the file will be closed (phase 1). * Only try to flush the file if it was opened with write access, and if * the caller requested a flush. */ if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) - if(H5F__flush_phase1(f, meta_dxpl_id) < 0) + if(H5F__flush_phase1(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush cached data (phase 1)") @@ -1086,7 +1115,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) * This allows the cache to set up for creating a metadata cache * image if this has been requested. */ - if(H5AC_prep_for_file_close(f, meta_dxpl_id) < 0) + if(H5AC_prep_for_file_close(f) < 0) /* Push error, but keep going */ HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "metadata cache prep for close failed") @@ -1095,7 +1124,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) * the caller requested a flush. */ if((H5F_ACC_RDWR & H5F_INTENT(f)) && flush) - if(H5F__flush_phase2(f, meta_dxpl_id, raw_dxpl_id, TRUE) < 0) + if(H5F__flush_phase2(f, TRUE) < 0) /* Push error, but keep going */ HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush cached data (phase 2)") @@ -1109,7 +1138,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) /* Release the external file cache */ if(f->shared->efc) { - if(H5F_efc_destroy(f->shared->efc) < 0) + if(H5F__efc_destroy(f->shared->efc) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache") f->shared->efc = NULL; @@ -1142,7 +1171,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) * -- JRM */ if(H5F_ACC_RDWR & H5F_INTENT(f)) { - if(H5MF_close(f, meta_dxpl_id) < 0) + if(H5MF_close(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info") @@ -1160,7 +1189,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS); /* Mark EOA info dirty in cache, so change will get encoded */ - if(H5F_eoa_dirty(f, meta_dxpl_id) < 0) + if(H5F_eoa_dirty(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") @@ -1171,12 +1200,12 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) * At most, this should change the superblock or the * superblock extension messages. */ - if(H5MF_free_aggrs(f, meta_dxpl_id) < 0) + if(H5MF_free_aggrs(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") /* Truncate the file to the current allocated size */ - if(H5FD_truncate(f->shared->lf, meta_dxpl_id, TRUE) < 0) + if(H5FD_truncate(f->shared->lf, TRUE) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") @@ -1215,19 +1244,15 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") /* Shutdown the metadata cache */ - if(H5AC_dest(f, meta_dxpl_id)) + /* (Flushes any remaining dirty entries, which should only be the + * superblock and / or driver info at this point) + */ + if(H5AC_dest(f)) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") - /* Set up I/O info for operation */ - fio_info.f = f; - if(NULL == (fio_info.meta_dxpl = (H5P_genplist_t *)H5I_object(meta_dxpl_id))) - HDONE_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))) - HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - /* Shutdown the page buffer cache */ - if(H5PB_dest(&fio_info) < 0) + if(H5PB_dest(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing page buffer cache") @@ -1248,7 +1273,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) } /* end if */ /* Destroy other components of the file */ - if(H5F__accum_reset(&fio_info, TRUE) < 0) + if(H5F__accum_reset(f, TRUE) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file") if(H5FO_dest(f) < 0) @@ -1303,9 +1328,81 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) f = H5FL_FREE(H5F_t, f); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_dest() */ +} /* end H5F__dest() */ + +/*------------------------------------------------------------------------- + * Function: H5F__create + * + * Purpose: Internal routine to create a file. + * + * Note: This routine is needed so that there's a non-API routine for + * creating files that can set up VOL / SWMR info + * (which need a DXPL). + * + * Return: Success: Non-NULL, pointer to new file object. + * Failure: NULL + * + * Programmer: Quincey Koziol + * December 13, 2017 + * + *------------------------------------------------------------------------- + */ +H5F_t * +H5F__create(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) +{ + H5F_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(filename); + + /* Create a new file or truncate an existing file. */ + if(NULL == (ret_value = H5F_open(filename, flags, fcpl_id, fapl_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") + +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* end H5F__create() */ + +/*------------------------------------------------------------------------- + * Function: H5F__open + * + * Purpose: Internal routine to open a file. + * + * Note: This routine is needed so that there's a non-API routine for + * opening files that can set up VOL / SWMR info + * (which need a DXPL). + * + * Return: Success: Non-NULL, pointer to new file object. + * Failure: NULL + * + * Programmer: Quincey Koziol + * December 13, 2017 + * + *------------------------------------------------------------------------- + */ +H5F_t * +H5F__open(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id) +{ + H5F_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(filename); + + /* Open the file */ + if(NULL == (ret_value = H5F_open(filename, flags, fcpl_id, fapl_id))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file") + +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* end H5F__open() */ + + /*------------------------------------------------------------------------- * Function: H5F_open * @@ -1380,8 +1477,7 @@ H5F__dest(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t flush) *------------------------------------------------------------------------- */ H5F_t * -H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, - hid_t meta_dxpl_id) +H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id) { H5F_t *file = NULL; /*the success return value */ H5F_file_t *shared = NULL; /*shared part of `file' */ @@ -1390,18 +1486,17 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_class_t *drvr; /*file driver class info */ H5P_genplist_t *a_plist; /*file access property list */ H5F_close_degree_t fc_degree; /*file close degree */ - hid_t raw_dxpl_id = H5AC_rawdata_dxpl_id; /* Raw data dxpl used by library */ size_t page_buf_size; unsigned page_buf_min_meta_perc; unsigned page_buf_min_raw_perc; hbool_t set_flag = FALSE; /*set the status_flags in the superblock */ hbool_t clear = FALSE; /*clear the status_flags */ hbool_t evict_on_close; /* evict on close value from plist */ - H5F_t *ret_value = NULL; /*actual return value */ char *lock_env_var = NULL;/*env var pointer */ 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 */ + 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 */ FUNC_ENTER_NOAPI(NULL) @@ -1588,19 +1683,19 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, /* Initialize information about the superblock and allocate space for it */ /* (Writes superblock extension messages, if there are any) */ - if(H5F__super_init(file, meta_dxpl_id) < 0) + if(H5F__super_init(file) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock") /* Create and open the root group */ /* (This must be after the space for the superblock is allocated in * the file, since the superblock must be at offset 0) */ - if(H5G_mkroot(file, meta_dxpl_id, TRUE) < 0) + if(H5G_mkroot(file, TRUE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group") } /* end if */ else if (1 == shared->nrefs) { /* Read the superblock if it hasn't been read before. */ - if(H5F__super_read(file, meta_dxpl_id, raw_dxpl_id, fapl_id, TRUE) < 0) + if(H5F__super_read(file, a_plist, TRUE) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock") /* Create the page buffer before initializing the superblock */ @@ -1609,7 +1704,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create page buffer") /* Open the root group */ - if(H5G_mkroot(file, meta_dxpl_id, FALSE) < 0) + if(H5G_mkroot(file, FALSE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group") } /* end if */ @@ -1683,9 +1778,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, /* Flush the superblock & superblock extension */ if(H5F_super_dirty(file) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, NULL, "unable to mark superblock as dirty") - if(H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG, meta_dxpl_id) < 0) + if(H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, NULL, "unable to flush superblock") - if(H5F_flush_tagged_metadata(file, file->shared->sblock->ext_addr, meta_dxpl_id) < 0) + if(H5F_flush_tagged_metadata(file, file->shared->sblock->ext_addr) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, NULL, "unable to flush superblock extension") /* Remove the file lock for SWMR_WRITE */ @@ -1717,13 +1812,13 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, done: if((NULL == ret_value) && file) - if(H5F__dest(file, meta_dxpl_id, raw_dxpl_id, FALSE) < 0) + if(H5F__dest(file, FALSE) < 0) HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file") FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_open() */ - + /*------------------------------------------------------------------------- * Function: H5F_flush_phase1 * @@ -1733,7 +1828,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5F__flush_phase1(H5F_t *f, hid_t meta_dxpl_id) +H5F__flush_phase1(H5F_t *f) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1743,7 +1838,7 @@ H5F__flush_phase1(H5F_t *f, hid_t meta_dxpl_id) HDassert(f); /* Flush any cached dataset storage raw data */ - if(H5D_flush(f, meta_dxpl_id) < 0) + if(H5D_flush_all(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") @@ -1753,14 +1848,14 @@ H5F__flush_phase1(H5F_t *f, hid_t meta_dxpl_id) /* (needs to happen before cache flush, with superblock write, since the * 'eoa' value is written in superblock -QAK) */ - if(H5MF_free_aggrs(f, meta_dxpl_id) < 0) + if(H5MF_free_aggrs(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space") FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__flush_phase1() */ - + /*------------------------------------------------------------------------- * Function: H5F__flush_phase2 * @@ -1770,9 +1865,8 @@ H5F__flush_phase1(H5F_t *f, hid_t meta_dxpl_id) *------------------------------------------------------------------------- */ static herr_t -H5F__flush_phase2(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t closing) +H5F__flush_phase2(H5F_t *f, hbool_t closing) { - H5F_io_info2_t fio_info; /* I/O info for operation */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC @@ -1781,59 +1875,57 @@ H5F__flush_phase2(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t closi HDassert(f); /* Flush the entire metadata cache */ - if(H5AC_flush(f, meta_dxpl_id) < 0) + if(H5AC_flush(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache") - /* Truncate the file to the current allocated size */ #ifdef H5_HAVE_PARALLEL - if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) { + if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) /* Since we just returned from a call to H5AC_flush(), we just * passed through a barrier. Hence we can skip the barrier on - * entry to the mpio file driver call below. + * entry to the mpio file driver truncate call below, and the first + * barrier in the following call to flush the cache again. */ - H5FD_mpio_mark_pre_trunc_barrier_unecessary(f->shared->lf); - } + H5CX_set_mpi_file_flushing(TRUE); #endif /* H5_HAVE_PARALLEL */ - if(H5FD_truncate(f->shared->lf, meta_dxpl_id, closing) < 0) + + /* Truncate the file to the current allocated size */ + if(H5FD_truncate(f->shared->lf, closing) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed") /* Flush the entire metadata cache again since the EOA could have changed in the truncate call. */ - if(H5AC_flush(f, meta_dxpl_id) < 0) + if(H5AC_flush(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache") - /* Set up I/O info for operation */ - fio_info.f = f; - if(NULL == (fio_info.meta_dxpl = (H5P_genplist_t *)H5I_object(meta_dxpl_id))) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") - if(NULL == (fio_info.raw_dxpl = (H5P_genplist_t *)H5I_object(raw_dxpl_id))) - /* Push error, but keep going*/ - HDONE_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list") +#ifdef H5_HAVE_PARALLEL + if(H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) + /* Reset the "flushing the file" flag */ + H5CX_set_mpi_file_flushing(FALSE); +#endif /* H5_HAVE_PARALLEL */ /* Flush out the metadata accumulator */ - if(H5F__accum_flush(&fio_info) < 0) + if(H5F__accum_flush(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator") /* Flush the page buffer */ - if(H5PB_flush(&fio_info) < 0) + if(H5PB_flush(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "page buffer flush failed") /* Flush file buffers to disk. */ - if(H5FD_flush(f->shared->lf, meta_dxpl_id, closing) < 0) + if(H5FD_flush(f->shared->lf, closing) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "low level flush failed") FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__flush_phase2() */ - + /*------------------------------------------------------------------------- - * Function: H5F__flush + * Function: H5F__flush_real * * Purpose: Flushes cached data. * @@ -1841,7 +1933,7 @@ H5F__flush_phase2(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t closi *------------------------------------------------------------------------- */ herr_t -H5F__flush(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t closing) +H5F__flush_real(H5F_t *f) { herr_t ret_value = SUCCEED; /* Return value */ @@ -1851,45 +1943,136 @@ H5F__flush(H5F_t *f, hid_t meta_dxpl_id, hid_t raw_dxpl_id, hbool_t closing) HDassert(f); /* First phase of flushing data */ - if(H5F__flush_phase1(f, meta_dxpl_id) < 0) + if(H5F__flush_phase1(f) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data") /* Second phase of flushing data */ - if(H5F__flush_phase2(f, meta_dxpl_id, raw_dxpl_id, closing) < 0) + if(H5F__flush_phase2(f, FALSE) < 0) /* Push error, but keep going*/ HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data") FUNC_LEAVE_NOAPI(ret_value) +} /* end H5F__flush_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__flush + * + * Purpose: Internal routine to flush a file. + * + * Note: This routine is needed so that there's a non-API routine for + * flushing files that can set up VOL / SWMR info + * (which need a DXPL). + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * December 13, 2017 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F__flush(H5F_t *f, H5F_scope_t scope) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + /* Flush other files, depending on scope */ + if(H5F_SCOPE_GLOBAL == scope) { + /* Call the flush routine for mounted file hierarchies */ + if(H5F_flush_mounts(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush mounted file hierarchy") + } /* end if */ + else + /* Call the flush routine, for this file */ + if(H5F__flush_real(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information") + +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) } /* end H5F__flush() */ + +/*------------------------------------------------------------------------- + * Function: H5F__close + * + * Purpose: Internal routine to close a file. + * + * Note: This routine is needed so that there's a non-API routine for + * closing files that can set up VOL / SWMR info + * (which need a DXPL). + * + * Return: Non-negative on success / Negative on failure + * + * Programmer: Quincey Koziol + * December 16, 2017 + * + *------------------------------------------------------------------------- + */ +herr_t +H5F__close(hid_t file_id) +{ + H5F_t *f; /* File pointer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Flush file if this is the last reference to this id and we have write + * intent, unless it will be flushed by the "shared" file being closed. + * This is only necessary to replicate previous behaviour, and could be + * disabled by an option/property to improve performance. + */ + if(NULL == (f = (H5F_t *)H5I_object(file_id))) + HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "invalid file identifier") + if((f->shared->nrefs > 1) && (H5F_INTENT(f) & H5F_ACC_RDWR)) { + int nref; /* Number of references to file ID */ + + if((nref = H5I_get_ref(file_id, FALSE)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get ID ref count") + if(nref == 1) + if(H5F__flush_real(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush cache") + } /* end if */ + + /* Decrement reference count on file ID */ + /* (When it reaches zero the file will be closed) */ + if(H5I_dec_app_ref(file_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "decrementing file ID failed") +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* end H5F__close() */ + + /*------------------------------------------------------------------------- - * Function: H5F_close + * Function: H5F__close_cb * * Purpose: Closes a file or causes the close operation to be pended. - * This function is called two ways: from the API it gets called - * by H5Fclose->H5I_dec_ref->H5F_close when H5I_dec_ref() + * This function is called from the API and gets called + * by H5Fclose->H5I_dec_ref->H5F__close_cb when H5I_dec_ref() * decrements the file ID reference count to zero. The file ID * is removed from the H5I_FILE group by H5I_dec_ref() just - * before H5F_close() is called. If there are open object + * before H5F__close_cb() is called. If there are open object * headers then the close is pended by moving the file to the * H5I_FILE_CLOSING ID group (the f->closing contains the ID * assigned to file). * - * This function is also called directly from H5O_close() when - * the last object header is closed for the file and the file - * has a pending close. - * * Return: Non-negative on success/Negative on failure + * *------------------------------------------------------------------------- */ herr_t -H5F_close(H5F_t *f) +H5F__close_cb(H5F_t *f) { - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE_VOL /* Sanity check */ HDassert(f); @@ -1921,10 +2104,10 @@ H5F_close(H5F_t *f) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file") done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5F_close() */ - + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* end H5F__close_cb() */ + /*------------------------------------------------------------------------- * Function: H5F_try_close * @@ -1934,6 +2117,7 @@ done: * - The file was unmounted * * Return: Non-negative on success/Negative on failure + * *------------------------------------------------------------------------- */ herr_t @@ -2068,14 +2252,14 @@ H5F_try_close(H5F_t *f, hbool_t *was_closed /*out*/) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file") /* Unmount and close each child before closing the current file. */ - if(H5F_close_mounts(f) < 0) + if(H5F__close_mounts(f) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files") /* If there is more than one reference to the shared file struct and the * file has an external file cache, we should see if it can be closed. This * can happen if a cycle is formed with external file caches */ if(f->shared->efc && (f->shared->nrefs > 1)) - if(H5F_efc_try_close(f) < 0) + if(H5F__efc_try_close(f) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC") /* Delay flush until the shared file struct is closed, in H5F__dest. If the @@ -2087,7 +2271,7 @@ H5F_try_close(H5F_t *f, hbool_t *was_closed /*out*/) * shared H5F_file_t struct. If the reference count for the H5F_file_t * struct reaches zero then destroy it also. */ - if(H5F__dest(f, H5AC_ind_read_dxpl_id, H5AC_rawdata_dxpl_id, TRUE) < 0) + if(H5F__dest(f, TRUE) < 0) HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file") /* Since we closed the file, this should be set to TRUE */ @@ -2097,7 +2281,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_try_close() */ - + /*------------------------------------------------------------------------- * Function: H5F_get_id * @@ -2133,7 +2317,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F_get_id() */ - + /*------------------------------------------------------------------------- * Function: H5F_incr_nopen_objs * @@ -2154,7 +2338,7 @@ H5F_incr_nopen_objs(H5F_t *f) FUNC_LEAVE_NOAPI(++f->nopen_objs) } /* end H5F_incr_nopen_objs() */ - + /*------------------------------------------------------------------------- * Function: H5F_decr_nopen_objs * @@ -2175,7 +2359,7 @@ H5F_decr_nopen_objs(H5F_t *f) FUNC_LEAVE_NOAPI(--f->nopen_objs) } /* end H5F_decr_nopen_objs() */ - + /*------------------------------------------------------------------------- * Function: H5F_build_actual_name * @@ -2297,7 +2481,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_build_actual_name() */ - + /*------------------------------------------------------------------------- * Function: H5F_addr_encode_len * @@ -2334,7 +2518,7 @@ H5F_addr_encode_len(size_t addr_len, uint8_t **pp/*in,out*/, haddr_t addr) FUNC_LEAVE_NOAPI_VOID } /* end H5F_addr_encode_len() */ - + /*------------------------------------------------------------------------- * Function: H5F_addr_encode * @@ -2358,7 +2542,7 @@ H5F_addr_encode(const H5F_t *f, uint8_t **pp/*in,out*/, haddr_t addr) FUNC_LEAVE_NOAPI_VOID } /* end H5F_addr_encode() */ - + /*------------------------------------------------------------------------- * Function: H5F_addr_decode_len * @@ -2422,7 +2606,7 @@ H5F_addr_decode_len(size_t addr_len, const uint8_t **pp/*in,out*/, haddr_t *addr FUNC_LEAVE_NOAPI_VOID } /* end H5F_addr_decode_len() */ - + /*------------------------------------------------------------------------- * Function: H5F_addr_decode * @@ -2449,7 +2633,7 @@ H5F_addr_decode(const H5F_t *f, const uint8_t **pp/*in,out*/, haddr_t *addr_p/*o FUNC_LEAVE_NOAPI_VOID } /* end H5F_addr_decode() */ - + /*------------------------------------------------------------------------- * Function: H5F_set_grp_btree_shared * @@ -2475,7 +2659,7 @@ H5F_set_grp_btree_shared(H5F_t *f, H5UC_t *rc) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_grp_btree_shared() */ - + /*------------------------------------------------------------------------- * Function: H5F_set_sohm_addr * @@ -2500,7 +2684,7 @@ H5F_set_sohm_addr(H5F_t *f, haddr_t addr) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_sohm_addr() */ - + /*------------------------------------------------------------------------- * Function: H5F_set_sohm_vers * @@ -2525,7 +2709,7 @@ H5F_set_sohm_vers(H5F_t *f, unsigned vers) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_sohm_vers() */ - + /*------------------------------------------------------------------------- * Function: H5F_set_sohm_nindexes * @@ -2550,7 +2734,7 @@ H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_sohm_nindexes() */ - + /*------------------------------------------------------------------------- * Function: H5F_set_store_msg_crt_idx * @@ -2575,6 +2759,7 @@ H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_store_msg_crt_idx() */ + /*------------------------------------------------------------------------- * Function: H5F_set_libver_bounds() * @@ -2590,9 +2775,11 @@ H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag) *------------------------------------------------------------------------- */ herr_t -H5F_set_libver_bounds(H5F_t * f, H5F_libver_t low, H5F_libver_t high) +H5F_set_libver_bounds(H5F_t *f, H5F_libver_t low, H5F_libver_t high) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL /* Sanity checks */ HDassert(f); @@ -2600,32 +2787,91 @@ H5F_set_libver_bounds(H5F_t * f, H5F_libver_t low, H5F_libver_t high) /* Set the bounds only if the existing setting is different from the inputs */ if(f->shared->low_bound != low || f->shared->high_bound != high) { + /* Call the flush routine, for this file */ + /* Note: This is done in case the binary format for representing a + * metadata entry class changes when the file format low / high + * bounds are changed and an unwritten entry of that class is + * sitting in the metadata cache. + * + * If that happens, it's possible that the entry's size could + * become larger, potentially corrupting the file (if the larger + * entry is fully written, overwriting data outside its allocated + * space), or corrupting the entry (if the entry is truncated to + * fit into the allocated space). + * + * Although I'm not aware of any metadata with this behavior + * currently, it would be very difficult to guard against and / or + * detect, but if we flush everything here, the format version + * for metadata entries in the cache will be finalized and these + * sorts of problems can be avoided. + * + * QAK - April, 2018 + */ + if(H5F__flush_real(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information") + + /* Set the new bounds */ f->shared->low_bound = low; f->shared->high_bound = high; - } + } /* end if */ - FUNC_LEAVE_NOAPI(SUCCEED) +done: + FUNC_LEAVE_NOAPI(ret_value) } /* H5F_set_libver_bounds() */ /*------------------------------------------------------------------------- - * Function: H5F_get_file_image + * Function: H5F__get_freespace + * + * Purpose: Private version of H5Fget_freespace + * + * Note: This routine is needed so that there's a non-API routine + * that can set up VOL / SWMR info (which need a DXPL). + * + * Return: Success: SUCCEED + * Failure: FAIL + *------------------------------------------------------------------------- + */ +herr_t +H5F__get_freespace(H5F_t *f, hsize_t *tot_space) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + /* Go get the actual amount of free space in the file */ + if(H5MF_get_freespace(f, tot_space, NULL) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file") + +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* H5F__get_freespace() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__get_file_image * * Purpose: Private version of H5Fget_file_image * + * Note: This routine is needed so that there's a non-API routine + * that can set up VOL / SWMR info (which need a DXPL). + * * Return: Success: Bytes copied / number of bytes needed. * Failure: negative value *------------------------------------------------------------------------- */ ssize_t -H5F_get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len, hid_t meta_dxpl_id, - hid_t raw_dxpl_id) +H5F__get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len) { H5FD_t *fd_ptr; /* file driver */ haddr_t eoa; /* End of file address */ ssize_t ret_value = -1; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT + FUNC_ENTER_PACKAGE_VOL /* Check args */ if(!file || !file->shared || !file->shared->lf) @@ -2686,7 +2932,6 @@ H5F_get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len, hid_t meta_dxpl_i /* test to see if a buffer was provided -- if not, we are done */ if(buf_ptr != NULL) { - H5FD_io_info_t fdio_info; /* File driver I/O info */ size_t space_needed; /* size of file image */ hsize_t tmp; size_t tmp_size; @@ -2697,16 +2942,9 @@ H5F_get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len, hid_t meta_dxpl_i space_needed = (size_t)eoa; - /* Set up file driver I/O info object */ - fdio_info.file = fd_ptr; - if(NULL == (fdio_info.meta_dxpl = (H5P_genplist_t *)H5I_object(meta_dxpl_id))) - HGOTO_ERROR(H5E_CACHE, H5E_BADATOM, FAIL, "can't get property list object") - if(NULL == (fdio_info.raw_dxpl = (H5P_genplist_t *)H5I_object(raw_dxpl_id))) - HGOTO_ERROR(H5E_CACHE, H5E_BADATOM, FAIL, "can't get property list object") - /* read in the file image */ /* (Note compensation for base address addition in internal routine) */ - if(H5FD_read(&fdio_info, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0) + if(H5FD_read(fd_ptr, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0) HGOTO_ERROR(H5E_FILE, H5E_READERROR, FAIL, "file image read request failed") /* Offset to "status_flags" in the superblock */ @@ -2720,10 +2958,60 @@ H5F_get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len, hid_t meta_dxpl_i } /* end if */ done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5F_get_file_image() */ + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* H5F__get_file_image() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__get_info + * + * Purpose: Private version of H5Fget_info + * + * Note: This routine is needed so that there's a non-API routine + * that can set up VOL / SWMR info (which need a DXPL). + * + * Return: Success: SUCCEED + * Failure: FAIL + *------------------------------------------------------------------------- + */ +herr_t +H5F__get_info(H5F_t *f, H5F_info2_t *finfo) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + HDassert(finfo); + + /* Reset file info struct */ + HDmemset(finfo, 0, sizeof(*finfo)); + + /* Get the size of the superblock and any superblock extensions */ + if(H5F__super_size(f, &finfo->super.super_size, &finfo->super.super_ext_size) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve superblock sizes") + + /* Get the size of any persistent free space */ + if(H5MF_get_freespace(f, &finfo->free.tot_space, &finfo->free.meta_size) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve free space information") + + /* Check for SOHM info */ + if(H5F_addr_defined(f->shared->sohm_addr)) + if(H5SM_ih_size(f, &finfo->sohm.hdr_size, &finfo->sohm.msgs_info) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve SOHM index & heap storage info") + + /* Set version # fields */ + finfo->super.version = f->shared->sblock->super_vers; + finfo->sohm.version = f->shared->sohm_vers; + finfo->free.version = HDF5_FREESPACE_VERSION; +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* H5F__get_info() */ + /*------------------------------------------------------------------------- * Function: H5F_track_metadata_read_retries * @@ -2771,7 +3059,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_track_metadata_read_retries() */ - + /*------------------------------------------------------------------------- * Function: H5F_set_retries * @@ -2807,7 +3095,40 @@ H5F_set_retries(H5F_t *f) FUNC_LEAVE_NOAPI(SUCCEED) } /* H5F_set_retries() */ + +/*------------------------------------------------------------------------- + * Function: H5F__get_free_sections + * + * Purpose: Private version of H5Fget_free_sections + * + * Note: This routine is needed so that there's a non-API routine + * that can set up VOL / SWMR info (which need a DXPL). + * + * Return: Success: non-negative, the total # of free space sections + * Failure: negative + *------------------------------------------------------------------------- + */ +ssize_t +H5F__get_free_sections(H5F_t *f, H5FD_mem_t type, size_t nsects, + H5F_sect_info_t *sect_info) +{ + ssize_t ret_value = -1; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + /* Go get the actual amount of free space in the file */ + if((ret_value = H5MF_get_free_sections(f, type, nsects, sect_info)) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to get free space sections for file") + +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* H5F__get_free_sections() */ + /*------------------------------------------------------------------------- * Function: H5F_object_flush_cb * @@ -2837,7 +3158,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5F_object_flush_cb() */ - + /*------------------------------------------------------------------------- * Function: H5F__set_base_addr * @@ -2864,7 +3185,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__set_base_addr() */ - + /*------------------------------------------------------------------------- * Function: H5F__set_eoa * @@ -2891,7 +3212,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__set_eoa() */ - + /*------------------------------------------------------------------------- * Function: H5F__set_paged_aggr * @@ -2919,6 +3240,7 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5F__set_paged_aggr() */ + /*------------------------------------------------------------------------- * Function: H5F__get_max_eof_eoa * @@ -2957,7 +3279,7 @@ done: } /* end H5F__get_max_eof_eoa() */ #ifdef H5_HAVE_PARALLEL - + /*------------------------------------------------------------------------- * Function: H5F_set_coll_md_read * @@ -2981,3 +3303,384 @@ 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_PACKAGE + + /* 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: Private version of H5Fstart_swmr_write + * + * 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. + * + * Note: This routine is needed so that there's a non-API routine + * that can set up VOL / SWMR info (which need a DXPL). + * + * Return: Success: SUCCEED + * Failure: FAIL + *------------------------------------------------------------------------- + */ +herr_t +H5F__start_swmr_write(H5F_t *f) +{ + 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 */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + /* Should have write permission */ + if((H5F_INTENT(f) & H5F_ACC_RDWR) == 0) + HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file") + + /* Check superblock version */ + if(f->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((f->shared->low_bound != H5F_LIBVER_V110) || (f->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(f->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(f, &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(f, f->shared->sblock->ext_addr) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock extension") + + /* Flush data buffers */ + if(H5F__flush_real(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush f's cached information") + + /* Get the # of opened named datatypes and attributes */ + if(H5F_get_obj_count(f, 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(f, 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(f, 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 */ + + /* Flush and reset the accumulator */ + if(H5F__accum_reset(f, TRUE) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator") + + /* Turn on SWMR write in shared file open flags */ + f->shared->flags |= H5F_ACC_SWMR_WRITE; + + /* Mark the file in SWMR writing mode */ + f->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS; + + /* Set up metadata read attempts */ + f->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS; + + /* Initialize "retries" and "retries_nbins" */ + if(H5F_set_retries(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins") + + /* Turn off usage of accumulator */ + f->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA; + if(H5FD_set_feature_flags(f->shared->lf, f->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(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + + /* Flush the superblock */ + if(H5F_flush_tagged_metadata(f, H5AC__SUPERBLOCK_TAG) < 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(f) < 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], TRUE) < 0) + HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object") + + /* Unlock the file */ + if(H5FD_unlock(f->shared->lf) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to unlock the file") + +done: + if(ret_value < 0 && setup) { + HDassert(f); + + /* Re-enable accumulator */ + f->shared->feature_flags |= (unsigned)H5FD_FEAT_ACCUMULATE_METADATA; + if(H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD") + + /* Reset the # of read attempts */ + f->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS; + if(H5F_set_retries(f) < 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 */ + f->shared->flags &= ~H5F_ACC_SWMR_WRITE; + + /* Unmark the f: not in SWMR writing mode */ + f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS); + + /* Mark superblock as dirty */ + if(H5F_super_dirty(f) < 0) + HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + + /* Flush the superblock */ + if(H5F_flush_tagged_metadata(f, H5AC__SUPERBLOCK_TAG) < 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_NOAPI_VOL(ret_value) +} /* H5F__start_swmr_write() */ + + +/*------------------------------------------------------------------------- + * Function: H5F__format_convert + * + * Purpose: Private version of H5Fformat_convert + * + * Note: This routine is needed so that there's a non-API routine + * that can set up VOL / SWMR info (which need a DXPL). + * + * Return: Success: SUCCEED + * Failure: FAIL + *------------------------------------------------------------------------- + */ +herr_t +H5F__format_convert(H5F_t *f) +{ + hbool_t mark_dirty = FALSE; /* Whether to mark the file's superblock dirty */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_VOL + + /* Sanity check */ + HDassert(f); + HDassert(f->shared); + + /* Check if the superblock should be downgraded */ + if(f->shared->sblock->super_vers > HDF5_SUPERBLOCK_VERSION_V18_LATEST) { + f->shared->sblock->super_vers = HDF5_SUPERBLOCK_VERSION_V18_LATEST; + mark_dirty = TRUE; + } /* end if */ + + /* Check for persistent freespace manager, which needs to be downgraded */ + if(!(f->shared->fs_strategy == H5F_FILE_SPACE_STRATEGY_DEF && + f->shared->fs_persist == H5F_FREE_SPACE_PERSIST_DEF && + f->shared->fs_threshold == H5F_FREE_SPACE_THRESHOLD_DEF && + f->shared->fs_page_size == H5F_FILE_SPACE_PAGE_SIZE_DEF)) { + /* Check to remove free-space manager info message from superblock extension */ + if(H5F_addr_defined(f->shared->sblock->ext_addr)) + if(H5F__super_ext_remove_msg(f, H5O_FSINFO_ID) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in removing message from superblock extension") + + /* Close freespace manager */ + if(H5MF_try_close(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to free free-space address") + + /* Set non-persistent freespace manager */ + f->shared->fs_strategy = H5F_FILE_SPACE_STRATEGY_DEF; + f->shared->fs_persist = H5F_FREE_SPACE_PERSIST_DEF; + f->shared->fs_threshold = H5F_FREE_SPACE_THRESHOLD_DEF; + f->shared->fs_page_size = H5F_FILE_SPACE_PAGE_SIZE_DEF; + + /* Indicate that the superblock should be marked dirty */ + mark_dirty = TRUE; + } /* end if */ + + /* Check if we should mark the superblock dirty */ + if(mark_dirty) + /* Mark superblock as dirty */ + if(H5F_super_dirty(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + +done: + FUNC_LEAVE_NOAPI_VOL(ret_value) +} /* H5F__format_convert() */ + |