summaryrefslogtreecommitdiffstats
path: root/src/H5Fint.c
diff options
context:
space:
mode:
authorM. Scot Breitenfeld <brtnfld@hdfgroup.org>2018-05-08 22:17:45 (GMT)
committerM. Scot Breitenfeld <brtnfld@hdfgroup.org>2018-05-08 22:17:45 (GMT)
commitb69bd0771eba5810db3db25217d5f32dc479185e (patch)
treec783a54f7cd8ef2ff504299749f5e18486a0363d /src/H5Fint.c
parent525b9f40e5c112b777a28d207ccb6fd454f156fc (diff)
parent0cc480d952e2e215f006fc172485fcbabc0f599f (diff)
downloadhdf5-b69bd0771eba5810db3db25217d5f32dc479185e.zip
hdf5-b69bd0771eba5810db3db25217d5f32dc479185e.tar.gz
hdf5-b69bd0771eba5810db3db25217d5f32dc479185e.tar.bz2
Merge branch 'develop' into hdf5_1_10.sync
Diffstat (limited to 'src/H5Fint.c')
-rw-r--r--src/H5Fint.c1129
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() */
+