1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /****************/
15 /* Module Setup */
16 /****************/
17 
18 #include "H5Fmodule.h" /* This source code file is part of the H5F module */
19 
20 /***********/
21 /* Headers */
22 /***********/
23 #include "H5private.h"   /* Generic Functions                        */
24 #include "H5Aprivate.h"  /* Attributes                               */
25 #include "H5ACprivate.h" /* Metadata cache                           */
26 #include "H5CXprivate.h" /* API Contexts                             */
27 #include "H5Dprivate.h"  /* Datasets                                 */
28 #include "H5Eprivate.h"  /* Error handling                           */
29 #include "H5Fpkg.h"      /* File access                              */
30 #include "H5FDprivate.h" /* File drivers                             */
31 #include "H5Gprivate.h"  /* Groups                                   */
32 #include "H5Iprivate.h"  /* IDs                                      */
33 #include "H5Lprivate.h"  /* Links                                    */
34 #include "H5MFprivate.h" /* File memory management                   */
35 #include "H5MMprivate.h" /* Memory management                        */
36 #include "H5Pprivate.h"  /* Property lists                           */
37 #include "H5SMprivate.h" /* Shared Object Header Messages            */
38 #include "H5Tprivate.h"  /* Datatypes                                */
39 #include "H5VLprivate.h" /* Virtual Object Layer                     */
40 
41 #include "H5VLnative_private.h" /* Native VOL connector                     */
42 
43 /****************/
44 /* Local Macros */
45 /****************/
46 
47 /******************/
48 /* Local Typedefs */
49 /******************/
50 
51 /* Struct only used by functions H5F__get_objects and H5F__get_objects_cb */
52 typedef struct H5F_olist_t {
53     H5I_type_t obj_type;     /* Type of object to look for */
54     hid_t *    obj_id_list;  /* Pointer to the list of open IDs to return */
55     size_t *   obj_id_count; /* Number of open IDs */
56     struct {
57         hbool_t local; /* Set flag for "local" file searches */
58         union {
59             H5F_shared_t *shared; /* Pointer to shared file to look inside */
60             const H5F_t * file;   /* Pointer to file to look inside */
61         } ptr;
62     } file_info;
63     size_t list_index; /* Current index in open ID array */
64     size_t max_nobjs;  /* Maximum # of IDs to put into array */
65 } H5F_olist_t;
66 
67 /********************/
68 /* Package Typedefs */
69 /********************/
70 
71 /********************/
72 /* Local Prototypes */
73 /********************/
74 
75 static herr_t H5F__close_cb(H5VL_object_t *file_vol_obj);
76 static herr_t H5F__set_vol_conn(H5F_t *file);
77 static herr_t H5F__get_objects(const H5F_t *f, unsigned types, size_t max_index, hid_t *obj_id_list,
78                                hbool_t app_ref, size_t *obj_id_count_ptr);
79 static int    H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key);
80 static herr_t H5F__build_name(const char *prefix, const char *file_name, char **full_name /*out*/);
81 static char * H5F__getenv_prefix_name(char **env_prefix /*in,out*/);
82 static H5F_t *H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf);
83 static herr_t H5F__check_if_using_file_locks(H5P_genplist_t *fapl, hbool_t *use_file_locking);
84 static herr_t H5F__dest(H5F_t *f, hbool_t flush);
85 static herr_t H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name,
86                                      char ** /*out*/ actual_name);
87 static herr_t H5F__flush_phase1(H5F_t *f);
88 static herr_t H5F__flush_phase2(H5F_t *f, hbool_t closing);
89 
90 /*********************/
91 /* Package Variables */
92 /*********************/
93 
94 /* Package initialization variable */
95 hbool_t H5_PKG_INIT_VAR = FALSE;
96 
97 /* Based on the value of the HDF5_USE_FILE_LOCKING environment variable.
98  * TRUE/FALSE have obvious meanings. FAIL means the environment variable was
99  * not set, so the code should ignore it and use the fapl value instead.
100  */
101 htri_t use_locks_env_g = FAIL;
102 
103 /*****************************/
104 /* Library Private Variables */
105 /*****************************/
106 
107 /*******************/
108 /* Local Variables */
109 /*******************/
110 
111 /* Declare a free list to manage the H5F_t struct */
112 H5FL_DEFINE(H5F_t);
113 
114 /* Declare a free list to manage the H5F_shared_t struct */
115 H5FL_DEFINE(H5F_shared_t);
116 
117 /* File ID class */
118 static const H5I_class_t H5I_FILE_CLS[1] = {{
119     H5I_FILE,                 /* ID class value */
120     0,                        /* Class flags */
121     0,                        /* # of reserved IDs for class */
122     (H5I_free_t)H5F__close_cb /* Callback routine for closing objects of this class */
123 }};
124 
125 /*-------------------------------------------------------------------------
126  * Function: H5F_init
127  *
128  * Purpose:  Initialize the interface from some other layer.
129  *
130  * Return:   Success:    non-negative
131  *
132  *           Failure:    negative
133  *-------------------------------------------------------------------------
134  */
135 herr_t
H5F_init(void)136 H5F_init(void)
137 {
138     herr_t ret_value = SUCCEED; /* Return value */
139 
140     FUNC_ENTER_NOAPI(FAIL)
141     /* FUNC_ENTER() does all the work */
142 
143 done:
144     FUNC_LEAVE_NOAPI(ret_value)
145 } /* end H5F_init() */
146 
147 /*--------------------------------------------------------------------------
148 NAME
149    H5F__init_package -- Initialize interface-specific information
150 USAGE
151     herr_t H5F__init_package()
152 RETURNS
153     Non-negative on success/Negative on failure
154 DESCRIPTION
155     Initializes any interface-specific data or routines.
156 
157 --------------------------------------------------------------------------*/
158 herr_t
H5F__init_package(void)159 H5F__init_package(void)
160 {
161     herr_t ret_value = SUCCEED; /* Return value */
162 
163     FUNC_ENTER_PACKAGE
164 
165     /*
166      * Initialize the atom group for the file IDs.
167      */
168     if (H5I_register_type(H5I_FILE_CLS) < 0)
169         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to initialize interface")
170 
171     /* Check the file locking environment variable */
172     if (H5F__parse_file_lock_env_var(&use_locks_env_g) < 0)
173         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to parse file locking environment variable")
174 
175 done:
176     FUNC_LEAVE_NOAPI(ret_value)
177 } /* H5F__init_package() */
178 
179 /*-------------------------------------------------------------------------
180  * Function:    H5F_term_package
181  *
182  * Purpose:     Terminate this interface: free all memory and reset global
183  *              variables to their initial values.  Release all ID groups
184  *              associated with this interface.
185  *
186  * Return:      Success:    Positive if anything was done that might
187  *                          have affected other interfaces;
188  *                          zero otherwise.
189  *
190  *              Failure:    Never fails
191  *
192  *-------------------------------------------------------------------------
193  */
194 int
H5F_term_package(void)195 H5F_term_package(void)
196 {
197     int n = 0;
198 
199     FUNC_ENTER_NOAPI_NOINIT_NOERR
200 
201     if (H5_PKG_INIT_VAR) {
202         if (H5I_nmembers(H5I_FILE) > 0) {
203             (void)H5I_clear_type(H5I_FILE, FALSE, FALSE);
204             n++; /*H5I*/
205         }        /* end if */
206         else {
207             /* Make certain we've cleaned up all the shared file objects */
208             H5F_sfile_assert_num(0);
209 
210             /* Destroy the file object id group */
211             n += (H5I_dec_type_ref(H5I_FILE) > 0);
212 
213             /* Mark closed */
214             if (0 == n)
215                 H5_PKG_INIT_VAR = FALSE;
216         } /* end else */
217     }     /* end if */
218 
219     FUNC_LEAVE_NOAPI(n)
220 } /* end H5F_term_package() */
221 
222 /*-------------------------------------------------------------------------
223  * Function:    H5F__close_cb
224  *
225  * Purpose:     Closes a file or causes the close operation to be pended.
226  *              This function is called from the API and gets called
227  *              by H5Fclose->H5I_dec_ref->H5F__close_cb when H5I_dec_ref()
228  *              decrements the file ID reference count to zero.  The file ID
229  *              is removed from the H5I_FILE group by H5I_dec_ref() just
230  *              before H5F__close_cb() is called. If there are open object
231  *              headers then the close is pended by moving the file to the
232  *              H5I_FILE_CLOSING ID group (the f->closing contains the ID
233  *              assigned to file).
234  *
235  * Return:      SUCCEED/FAIL
236  *
237  *-------------------------------------------------------------------------
238  */
239 static herr_t
H5F__close_cb(H5VL_object_t * file_vol_obj)240 H5F__close_cb(H5VL_object_t *file_vol_obj)
241 {
242     herr_t ret_value = SUCCEED; /* Return value */
243 
244     FUNC_ENTER_STATIC
245 
246     /* Sanity check */
247     HDassert(file_vol_obj);
248 
249     /* Close the file */
250     if (H5VL_file_close(file_vol_obj, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL) < 0)
251         HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
252 
253     /* Free the VOL object; it is unnecessary to unwrap the VOL
254      * object before freeing it, as the object was not wrapped */
255     if (H5VL_free_object(file_vol_obj) < 0)
256         HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to free VOL object")
257 
258 done:
259     FUNC_LEAVE_NOAPI(ret_value)
260 } /* end H5F__close_cb() */
261 
262 /*-------------------------------------------------------------------------
263  * Function:    H5F__parse_file_lock_env_var
264  *
265  * Purpose:     Parses the HDF5_USE_FILE_LOCKING environment variable.
266  *
267  * NOTE:        This is done in a separate function so we can call it from
268  *              the test code.
269  *
270  * Return:      SUCCEED/FAIL
271  *
272  *-------------------------------------------------------------------------
273  */
274 herr_t
H5F__parse_file_lock_env_var(htri_t * use_locks)275 H5F__parse_file_lock_env_var(htri_t *use_locks)
276 {
277     char *lock_env_var = NULL; /* Environment variable pointer */
278 
279     FUNC_ENTER_PACKAGE_NOERR
280 
281     /* Check the file locking environment variable */
282     lock_env_var = HDgetenv("HDF5_USE_FILE_LOCKING");
283     if (lock_env_var && (!HDstrcmp(lock_env_var, "FALSE") || !HDstrcmp(lock_env_var, "0")))
284         *use_locks = FALSE; /* Override: Never use locks */
285     else if (lock_env_var && (!HDstrcmp(lock_env_var, "TRUE") || !HDstrcmp(lock_env_var, "BEST_EFFORT") ||
286                               !HDstrcmp(lock_env_var, "1")))
287         *use_locks = TRUE; /* Override: Always use locks */
288     else
289         *use_locks = FAIL; /* Environment variable not set, or not set correctly */
290 
291     FUNC_LEAVE_NOAPI(SUCCEED)
292 } /* end H5F__parse_file_lock_env_var() */
293 
294 /*-------------------------------------------------------------------------
295  * Function:    H5F__set_vol_conn
296  *
297  * Purpose:     Set the VOL connector ID and info for a file.
298  *
299  * Return:      SUCCEED/FAIL
300  *
301  *-------------------------------------------------------------------------
302  */
303 static herr_t
H5F__set_vol_conn(H5F_t * file)304 H5F__set_vol_conn(H5F_t *file)
305 {
306     H5VL_connector_prop_t connector_prop;               /* Property for VOL connector ID & info */
307     void *                new_connector_info = NULL;    /* Copy of connector info */
308     herr_t                ret_value          = SUCCEED; /* Return value */
309 
310     FUNC_ENTER_STATIC
311 
312     /* Sanity check */
313     HDassert(file);
314 
315     /* Retrieve a copy of the "top-level" connector property, before any pass-through
316      *  connectors modified or unwrapped it.
317      */
318     if (H5CX_get_vol_connector_prop(&connector_prop) < 0)
319         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get VOL connector info from API context")
320 
321     /* Sanity check */
322     HDassert(0 != connector_prop.connector_id);
323 
324     /* Retrieve the connector for the ID */
325     if (NULL == (file->shared->vol_cls = (H5VL_class_t *)H5I_object(connector_prop.connector_id)))
326         HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a VOL connector ID")
327 
328     /* Allocate and copy connector info, if it exists */
329     if (connector_prop.connector_info)
330         if (H5VL_copy_connector_info(file->shared->vol_cls, &new_connector_info,
331                                      connector_prop.connector_info) < 0)
332             HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "connector info copy failed")
333 
334     /* Cache the connector ID & info for the container */
335     file->shared->vol_id   = connector_prop.connector_id;
336     file->shared->vol_info = new_connector_info;
337     if (H5I_inc_ref(file->shared->vol_id, FALSE) < 0)
338         HGOTO_ERROR(H5E_FILE, H5E_CANTINC, FAIL, "incrementing VOL connector ID failed")
339 
340 done:
341     FUNC_LEAVE_NOAPI(ret_value)
342 } /* end H5F__set_vol_conn() */
343 
344 /*-------------------------------------------------------------------------
345  * Function:    H5F_get_access_plist
346  *
347  * Purpose:     Returns a copy of the file access property list of the
348  *              specified file.
349  *
350  *              NOTE: Make sure that, if you are going to overwrite
351  *              information in the copied property list that was
352  *              previously opened and assigned to the property list, then
353  *              you must close it before overwriting the values.
354  *
355  * Return:      Success:    Object ID for a copy of the file access
356  *                          property list.
357  *              Failure:    H5I_INVALID_HID
358  *-------------------------------------------------------------------------
359  */
360 hid_t
H5F_get_access_plist(H5F_t * f,hbool_t app_ref)361 H5F_get_access_plist(H5F_t *f, hbool_t app_ref)
362 {
363     H5P_genplist_t *      new_plist;                  /* New property list */
364     H5P_genplist_t *      old_plist;                  /* Old property list */
365     H5FD_driver_prop_t    driver_prop;                /* Property for driver ID & info */
366     hbool_t               driver_prop_copied = FALSE; /* Whether the driver property has been set up */
367     H5VL_connector_prop_t connector_prop;             /* Property for VOL connector ID & info */
368     unsigned              efc_size  = 0;
369     hid_t                 ret_value = H5I_INVALID_HID; /* Return value */
370 
371     FUNC_ENTER_NOAPI(H5I_INVALID_HID)
372 
373     /* Check args */
374     HDassert(f);
375 
376     /* Make a copy of the default file access property list */
377     if (NULL == (old_plist = (H5P_genplist_t *)H5I_object(H5P_LST_FILE_ACCESS_ID_g)))
378         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
379     if ((ret_value = H5P_copy_plist(old_plist, app_ref)) < 0)
380         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, H5I_INVALID_HID, "can't copy file access property list")
381     if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(ret_value)))
382         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list")
383 
384     /* Copy properties of the file access property list */
385     if (H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
386         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.")
387     if (H5P_set(new_plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
388         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set data cache number of slots")
389     if (H5P_set(new_plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
390         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set data cache byte size")
391     if (H5P_set(new_plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
392         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set preempt read chunks")
393     if (H5P_set(new_plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
394         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set alignment threshold")
395     if (H5P_set(new_plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
396         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set alignment")
397     if (H5P_set(new_plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
398         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set garbage collect reference")
399     if (H5P_set(new_plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
400         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set metadata cache size")
401     if (H5P_set(new_plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
402         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't sieve buffer size")
403     if (H5P_set(new_plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
404         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'small data' cache size")
405     if (H5P_set(new_plist, H5F_ACS_LIBVER_LOW_BOUND_NAME, &f->shared->low_bound) < 0)
406         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID,
407                     "can't set 'low' bound for library format versions")
408     if (H5P_set(new_plist, H5F_ACS_LIBVER_HIGH_BOUND_NAME, &f->shared->high_bound) < 0)
409         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID,
410                     "can't set 'high' bound for library format versions")
411     if (H5P_set(new_plist, H5F_ACS_METADATA_READ_ATTEMPTS_NAME, &(f->shared->read_attempts)) < 0)
412         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set 'read attempts ' flag")
413     if (H5P_set(new_plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0)
414         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set object flush callback")
415 
416     if (f->shared->efc)
417         efc_size = H5F__efc_max_nfiles(f->shared->efc);
418     if (H5P_set(new_plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
419         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set elink file cache size")
420     if (f->shared->page_buf != NULL) {
421         if (H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_SIZE_NAME, &(f->shared->page_buf->max_size)) < 0)
422             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set page buffer size")
423         if (H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_NAME,
424                     &(f->shared->page_buf->min_meta_perc)) < 0)
425             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID,
426                         "can't set minimum metadata fraction of page buffer")
427         if (H5P_set(new_plist, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME, &(f->shared->page_buf->min_raw_perc)) <
428             0)
429             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID,
430                         "can't set minimum raw data fraction of page buffer")
431     } /* end if */
432 #ifdef H5_HAVE_PARALLEL
433     if (H5P_set(new_plist, H5_COLL_MD_READ_FLAG_NAME, &(f->shared->coll_md_read)) < 0)
434         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set collective metadata read flag")
435     if (H5P_set(new_plist, H5F_ACS_COLL_MD_WRITE_FLAG_NAME, &(f->shared->coll_md_write)) < 0)
436         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set collective metadata read flag")
437     if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
438         MPI_Comm mpi_comm;
439         MPI_Info mpi_info;
440 
441         /* Retrieve and set MPI communicator */
442         if (MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(f)))
443             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get MPI communicator")
444         if (H5P_set(new_plist, H5F_ACS_MPI_PARAMS_COMM_NAME, &mpi_comm) < 0)
445             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set MPI communicator")
446 
447         /* Retrieve and set MPI info object */
448         if (H5P_get(old_plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &mpi_info) < 0)
449             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't get MPI info object")
450         if (H5P_set(new_plist, H5F_ACS_MPI_PARAMS_INFO_NAME, &mpi_info) < 0)
451             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set MPI info object")
452     }
453 #endif /* H5_HAVE_PARALLEL */
454     if (H5P_set(new_plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) <
455         0)
456         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set initial metadata cache resize config.")
457 
458     /* Prepare the driver property */
459     driver_prop.driver_id   = f->shared->lf->driver_id;
460     driver_prop.driver_info = H5FD_fapl_get(f->shared->lf);
461     driver_prop_copied      = TRUE;
462 
463     /* Set the driver property */
464     if (H5P_set(new_plist, H5F_ACS_FILE_DRV_NAME, &driver_prop) < 0)
465         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file driver ID & info")
466 
467     /* Set the VOL connector property */
468     connector_prop.connector_id   = f->shared->vol_id;
469     connector_prop.connector_info = f->shared->vol_info;
470     if (H5P_set(new_plist, H5F_ACS_VOL_CONN_NAME, &connector_prop) < 0)
471         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL connector ID & info")
472 
473     /* Set the file close degree appropriately */
474     if (f->shared->fc_degree == H5F_CLOSE_DEFAULT &&
475         H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->lf->cls->fc_degree)) < 0)
476         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file close degree")
477     else if (f->shared->fc_degree != H5F_CLOSE_DEFAULT &&
478              H5P_set(new_plist, H5F_ACS_CLOSE_DEGREE_NAME, &(f->shared->fc_degree)) < 0)
479         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set file close degree")
480 
481 done:
482     /* Release the copy of the driver info, if it was set up */
483     if (driver_prop_copied && H5FD_free_driver_info(driver_prop.driver_id, driver_prop.driver_info) < 0)
484         HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, H5I_INVALID_HID, "can't close copy of driver info")
485 
486     FUNC_LEAVE_NOAPI(ret_value)
487 } /* end H5F_get_access_plist() */
488 
489 /*-------------------------------------------------------------------------
490  * Function: H5F_get_obj_count
491  *
492  * Purpose:  Private function return the number of opened object IDs
493  *           (files, datasets, groups, datatypes) in the same file.
494  *
495  * Return:      SUCCEED on success, FAIL on failure.
496  *-------------------------------------------------------------------------
497  */
498 herr_t
H5F_get_obj_count(const H5F_t * f,unsigned types,hbool_t app_ref,size_t * obj_id_count_ptr)499 H5F_get_obj_count(const H5F_t *f, unsigned types, hbool_t app_ref, size_t *obj_id_count_ptr)
500 {
501     herr_t ret_value = SUCCEED;
502 
503     FUNC_ENTER_NOAPI(FAIL)
504 
505     /* Sanity check */
506     HDassert(obj_id_count_ptr);
507 
508     /* Perform the query */
509     if ((ret_value = H5F__get_objects(f, types, 0, NULL, app_ref, obj_id_count_ptr)) < 0)
510         HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F__get_objects failed")
511 
512 done:
513     FUNC_LEAVE_NOAPI(ret_value)
514 } /* end H5F_get_obj_count() */
515 
516 /*-------------------------------------------------------------------------
517  * Function:    H5F_get_obj_ids
518  *
519  * Purpose:     Private function to return a list of opened object IDs.
520  *
521  * Return:      Non-negative on success; can't fail.
522  *-------------------------------------------------------------------------
523  */
524 herr_t
H5F_get_obj_ids(const H5F_t * f,unsigned types,size_t max_objs,hid_t * oid_list,hbool_t app_ref,size_t * obj_id_count_ptr)525 H5F_get_obj_ids(const H5F_t *f, unsigned types, size_t max_objs, hid_t *oid_list, hbool_t app_ref,
526                 size_t *obj_id_count_ptr)
527 {
528     herr_t ret_value = SUCCEED; /* Return value */
529 
530     FUNC_ENTER_NOAPI(FAIL)
531 
532     /* Sanity check */
533     HDassert(obj_id_count_ptr);
534 
535     /* Perform the query */
536     if ((ret_value = H5F__get_objects(f, types, max_objs, oid_list, app_ref, obj_id_count_ptr)) < 0)
537         HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F__get_objects failed")
538 
539 done:
540     FUNC_LEAVE_NOAPI(ret_value)
541 } /* end H5F_get_obj_ids() */
542 
543 /*---------------------------------------------------------------------------
544  * Function:    H5F__get_objects
545  *
546  * Purpose:     This function is called by H5F_get_obj_count or
547  *              H5F_get_obj_ids to get number of object IDs and/or a
548  *              list of opened object IDs (in return value).
549  *
550  * Return:      SUCCEED/FAIL
551  *---------------------------------------------------------------------------
552  */
553 static herr_t
H5F__get_objects(const H5F_t * f,unsigned types,size_t max_nobjs,hid_t * obj_id_list,hbool_t app_ref,size_t * obj_id_count_ptr)554 H5F__get_objects(const H5F_t *f, unsigned types, size_t max_nobjs, hid_t *obj_id_list, hbool_t app_ref,
555                  size_t *obj_id_count_ptr)
556 {
557     size_t      obj_id_count = 0;    /* Number of open IDs */
558     H5F_olist_t olist;               /* Structure to hold search results */
559     herr_t      ret_value = SUCCEED; /* Return value */
560 
561     FUNC_ENTER_STATIC
562 
563     /* Sanity check */
564     HDassert(obj_id_count_ptr);
565 
566     /* Set up search information */
567     olist.obj_id_list  = (max_nobjs == 0 ? NULL : obj_id_list);
568     olist.obj_id_count = &obj_id_count;
569     olist.list_index   = 0;
570     olist.max_nobjs    = max_nobjs;
571 
572     /* Determine if we are searching for local or global objects */
573     if (types & H5F_OBJ_LOCAL) {
574         olist.file_info.local    = TRUE;
575         olist.file_info.ptr.file = f;
576     } /* end if */
577     else {
578         olist.file_info.local      = FALSE;
579         olist.file_info.ptr.shared = f ? f->shared : NULL;
580     } /* end else */
581 
582     /* Iterate through file IDs to count the number, and put their
583      * IDs on the object list.  */
584     if (types & H5F_OBJ_FILE) {
585         olist.obj_type = H5I_FILE;
586         if (H5I_iterate(H5I_FILE, H5F__get_objects_cb, &olist, app_ref) < 0)
587             HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(1)")
588     } /* end if */
589 
590     /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
591      * or the caller wants to get the list of IDs and the list isn't full,
592      * search through dataset IDs to count number of datasets, and put their
593      * IDs on the object list */
594     if (!olist.max_nobjs || (olist.max_nobjs && olist.list_index < olist.max_nobjs)) {
595         if (types & H5F_OBJ_DATASET) {
596             olist.obj_type = H5I_DATASET;
597             if (H5I_iterate(H5I_DATASET, H5F__get_objects_cb, &olist, app_ref) < 0)
598                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(2)")
599         } /* end if */
600     }
601 
602     /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
603      * or the caller wants to get the list of IDs and the list isn't full,
604      * search through group IDs to count number of groups, and put their
605      * IDs on the object list */
606     if (!olist.max_nobjs || (olist.max_nobjs && olist.list_index < olist.max_nobjs)) {
607         if (types & H5F_OBJ_GROUP) {
608             olist.obj_type = H5I_GROUP;
609             if (H5I_iterate(H5I_GROUP, H5F__get_objects_cb, &olist, app_ref) < 0)
610                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(3)")
611         }
612     }
613 
614     /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
615      * or the caller wants to get the list of IDs and the list isn't full,
616      * search through datatype IDs to count number of named datatypes, and put their
617      * IDs on the object list */
618     if (!olist.max_nobjs || (olist.max_nobjs && olist.list_index < olist.max_nobjs)) {
619         if (types & H5F_OBJ_DATATYPE) {
620             olist.obj_type = H5I_DATATYPE;
621             if (H5I_iterate(H5I_DATATYPE, H5F__get_objects_cb, &olist, app_ref) < 0)
622                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(4)")
623         } /* end if */
624     }
625 
626     /* If the caller just wants to count the number of objects (OLIST.MAX_NOBJS is zero),
627      * or the caller wants to get the list of IDs and the list isn't full,
628      * search through attribute IDs to count number of attributes, and put their
629      * IDs on the object list */
630     if (!olist.max_nobjs || (olist.max_nobjs && olist.list_index < olist.max_nobjs)) {
631         if (types & H5F_OBJ_ATTR) {
632             olist.obj_type = H5I_ATTR;
633             if (H5I_iterate(H5I_ATTR, H5F__get_objects_cb, &olist, app_ref) < 0)
634                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "iteration failed(5)")
635         } /* end if */
636     }
637 
638     /* Set the number of objects currently open */
639     *obj_id_count_ptr = obj_id_count;
640 
641 done:
642     FUNC_LEAVE_NOAPI(ret_value)
643 } /* end H5F__get_objects() */
644 
645 /*-------------------------------------------------------------------------
646  * Function:    H5F__get_objects_cb
647  *
648  * Purpose:     H5F__get_objects' callback function.  It verifies if an
649  *              object is in the file, and either count it or put its ID
650  *              on the list.
651  *
652  * Return:      H5_ITER_STOP if the array of object IDs is filled up.
653  *              H5_ITER_CONT otherwise.
654  *-------------------------------------------------------------------------
655  */
656 static int
H5F__get_objects_cb(void * obj_ptr,hid_t obj_id,void * key)657 H5F__get_objects_cb(void *obj_ptr, hid_t obj_id, void *key)
658 {
659     H5F_olist_t *olist     = (H5F_olist_t *)key; /* Alias for search info */
660     hbool_t      add_obj   = FALSE;
661     int          ret_value = H5_ITER_CONT; /* Return value */
662 
663     FUNC_ENTER_STATIC
664 
665     HDassert(obj_ptr);
666     HDassert(olist);
667 
668     /* Count file IDs */
669     if (olist->obj_type == H5I_FILE) {
670         if ((olist->file_info.local &&
671              (!olist->file_info.ptr.file ||
672               (olist->file_info.ptr.file && (H5F_t *)obj_ptr == olist->file_info.ptr.file))) ||
673             (!olist->file_info.local &&
674              (!olist->file_info.ptr.shared ||
675               (olist->file_info.ptr.shared && ((H5F_t *)obj_ptr)->shared == olist->file_info.ptr.shared)))) {
676             add_obj = TRUE;
677         }                /* end if */
678     }                    /* end if */
679     else {               /* Either count opened object IDs or put the IDs on the list */
680         H5O_loc_t *oloc; /* Group entry info for object */
681 
682         switch (olist->obj_type) {
683             case H5I_ATTR:
684                 oloc = H5A_oloc((H5A_t *)obj_ptr);
685                 break;
686 
687             case H5I_GROUP:
688                 oloc = H5G_oloc((H5G_t *)obj_ptr);
689                 break;
690 
691             case H5I_DATASET:
692                 oloc = H5D_oloc((H5D_t *)obj_ptr);
693                 break;
694 
695             case H5I_DATATYPE:
696                 if (H5T_is_named((H5T_t *)obj_ptr) == TRUE)
697                     oloc = H5T_oloc((H5T_t *)obj_ptr);
698                 else
699                     oloc = NULL;
700                 break;
701 
702             case H5I_MAP:
703                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR,
704                             "maps not supported in native VOL connector")
705 
706             case H5I_UNINIT:
707             case H5I_BADID:
708             case H5I_FILE:
709             case H5I_DATASPACE:
710             case H5I_VFL:
711             case H5I_VOL:
712             case H5I_GENPROP_CLS:
713             case H5I_GENPROP_LST:
714             case H5I_ERROR_CLASS:
715             case H5I_ERROR_MSG:
716             case H5I_ERROR_STACK:
717             case H5I_SPACE_SEL_ITER:
718             case H5I_NTYPES:
719             default:
720                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5_ITER_ERROR, "unknown or invalid data object")
721         } /* end switch */
722 
723         if ((olist->file_info.local && ((!olist->file_info.ptr.file && olist->obj_type == H5I_DATATYPE &&
724                                          H5T_is_immutable((H5T_t *)obj_ptr) == FALSE) ||
725                                         (!olist->file_info.ptr.file && olist->obj_type != H5I_DATATYPE) ||
726                                         (oloc && oloc->file == olist->file_info.ptr.file))) ||
727             (!olist->file_info.local &&
728              ((!olist->file_info.ptr.shared && olist->obj_type == H5I_DATATYPE &&
729                H5T_is_immutable((H5T_t *)obj_ptr) == FALSE) ||
730               (!olist->file_info.ptr.shared && olist->obj_type != H5I_DATATYPE) ||
731               (oloc && oloc->file && oloc->file->shared == olist->file_info.ptr.shared)))) {
732             add_obj = TRUE;
733         } /* end if */
734     }     /* end else */
735 
736     if (add_obj) {
737         /* Add the object's ID to the ID list, if appropriate */
738         if (olist->obj_id_list) {
739             olist->obj_id_list[olist->list_index] = obj_id;
740             olist->list_index++;
741         } /* end if */
742 
743         /* Increment the number of open objects */
744         if (olist->obj_id_count)
745             (*olist->obj_id_count)++;
746 
747         /* Check if we've filled up the array.  Return H5_ITER_STOP only if
748          * we have filled up the array. Otherwise return H5_ITER_CONT(RET_VALUE is
749          * preset to H5_ITER_CONT) because H5I_iterate needs the return value of
750          * H5_ITER_CONT to continue the iteration.
751          */
752         if (olist->max_nobjs > 0 && olist->list_index >= olist->max_nobjs)
753             HGOTO_DONE(H5_ITER_STOP) /* Indicate that the iterator should stop */
754     }                                /* end if */
755 
756 done:
757     FUNC_LEAVE_NOAPI(ret_value)
758 } /* end H5F__get_objects_cb() */
759 
760 /*--------------------------------------------------------------------------
761  * Function:    H5F__build_name
762  *
763  * Purpose:     Prepend PREFIX to FILE_NAME and store in FULL_NAME
764  *
765  * Return:      SUCCEED/FAIL
766  *--------------------------------------------------------------------------*/
767 static herr_t
H5F__build_name(const char * prefix,const char * file_name,char ** full_name)768 H5F__build_name(const char *prefix, const char *file_name, char **full_name /*out*/)
769 {
770     size_t prefix_len;          /* length of prefix */
771     size_t fname_len;           /* Length of external link file name */
772     herr_t ret_value = SUCCEED; /* Return value */
773 
774     FUNC_ENTER_STATIC
775 
776     prefix_len = HDstrlen(prefix);
777     fname_len  = HDstrlen(file_name);
778 
779     /* Allocate a buffer to hold the filename + prefix + possibly the delimiter + terminating null byte */
780     if (NULL == (*full_name = (char *)H5MM_malloc(prefix_len + fname_len + 2 +
781                                                   2))) /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */
782         HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "unable to allocate filename buffer")
783 
784     /* Compose the full file name */
785     HDsnprintf(*full_name, (prefix_len + fname_len + 2 + 2), "%s%s%s",
786                prefix, /* Extra "+2" to quiet GCC warning - 2019/07/05, QAK */
787                ((prefix_len == 0 || H5_CHECK_DELIMITER(prefix[prefix_len - 1])) ? "" : H5_DIR_SEPS),
788                file_name);
789 
790 done:
791     FUNC_LEAVE_NOAPI(ret_value)
792 } /* H5F__build_name() */
793 
794 /*--------------------------------------------------------------------------
795  * Function:    H5F__getenv_prefix_name
796  *
797  * Purpose:     Get the first pathname in the list of pathnames stored in env_prefix,
798  *              which is separated by the environment delimiter.
799  *              env_prefix is modified to point to the remaining pathnames
800  *              in the list.
801  *
802  * Return:      A pointer to a pathname (can't fail but can return NULL)
803 --------------------------------------------------------------------------*/
804 static char *
H5F__getenv_prefix_name(char ** env_prefix)805 H5F__getenv_prefix_name(char **env_prefix /*in,out*/)
806 {
807     char *strret;           /* Pointer to next separator */
808     char *ret_value = NULL; /* Return value */
809 
810     FUNC_ENTER_STATIC_NOERR
811 
812     /* Set return value now */
813     ret_value = *env_prefix;
814 
815     /* Advance to next component, if possible */
816     strret = HDstrchr(*env_prefix, H5_COLON_SEPC);
817     if (strret == NULL)
818         *env_prefix = NULL;
819     else {
820         /* Advance to next component */
821         *env_prefix = strret + 1;
822 
823         /* Terminate current component (pointed to by ret_value) */
824         *strret = '\0';
825     } /* end else */
826 
827     FUNC_LEAVE_NOAPI(ret_value)
828 } /* end H5F__getenv_prefix_name() */
829 
830 /*-------------------------------------------------------------------------
831  * Function:    H5F_prefix_open_file
832  *
833  * Purpose:     Attempts to open a dataset file.
834  *
835  * Return:      Pointer to an opened file on success / NULL on failure
836  *-------------------------------------------------------------------------
837  */
838 H5F_t *
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)839 H5F_prefix_open_file(H5F_t *primary_file, H5F_prefix_open_t prefix_type, const char *prop_prefix,
840                      const char *file_name, unsigned file_intent, hid_t fapl_id)
841 {
842     H5F_t *src_file         = NULL; /* Source file */
843     char * full_name        = NULL; /* File name with prefix */
844     char * actual_file_name = NULL; /* File's actual name */
845     char * temp_file_name   = NULL; /* Temporary pointer to file name */
846     size_t temp_file_name_len;      /* Length of temporary file name */
847     H5F_t *ret_value = NULL;        /* Return value  */
848 
849     FUNC_ENTER_NOAPI_NOINIT
850 
851     /* Simplify intent flags for open calls */
852     file_intent &= (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE | H5F_ACC_SWMR_READ);
853 
854     /* Copy the file name to use */
855     if (NULL == (temp_file_name = H5MM_strdup(file_name)))
856         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
857     temp_file_name_len = HDstrlen(temp_file_name);
858 
859     /* Target file_name is an absolute pathname: see RM for detailed description */
860     if (H5_CHECK_ABSOLUTE(file_name) || H5_CHECK_ABS_PATH(file_name)) {
861         /* Try opening file */
862         src_file = H5F__efc_open(primary_file, file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
863 
864         /* Adjust temporary file name if file not opened */
865         if (NULL == src_file) {
866             char *ptr;
867 
868             /* Reset the error stack */
869             H5E_clear_stack(NULL);
870 
871             /* Get last component of file_name */
872             H5_GET_LAST_DELIMITER(file_name, ptr)
873             HDassert(ptr);
874 
875             /* Increment past delimiter */
876             ptr++;
877 
878             /* Copy into the temp. file name */
879             HDstrncpy(temp_file_name, ptr, temp_file_name_len);
880             temp_file_name[temp_file_name_len - 1] = '\0';
881         } /* end if */
882     }     /* end if */
883     else if (H5_CHECK_ABS_DRIVE(file_name)) {
884         /* Try opening file */
885         src_file = H5F__efc_open(primary_file, file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
886 
887         /* Adjust temporary file name if file not opened */
888         if (NULL == src_file) {
889             /* Reset the error stack */
890             H5E_clear_stack(NULL);
891 
892             /* Strip "<drive-letter>:" */
893             HDstrncpy(temp_file_name, &file_name[2], temp_file_name_len);
894             temp_file_name[temp_file_name_len - 1] = '\0';
895         } /* end if */
896     }     /* end if */
897 
898     /* Try searching from paths set in the environment variable */
899     if (src_file == NULL) {
900         char *env_prefix;
901 
902         /* Get the appropriate environment variable */
903         if (H5F_PREFIX_VDS == prefix_type)
904             env_prefix = HDgetenv("HDF5_VDS_PREFIX");
905         else if (H5F_PREFIX_ELINK == prefix_type)
906             env_prefix = HDgetenv("HDF5_EXT_PREFIX");
907         else
908             HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, NULL, "prefix type is not sensible")
909 
910         /* If environment variable is defined, iterate through prefixes it defines */
911         if (NULL != env_prefix) {
912             char *tmp_env_prefix, *saved_env;
913 
914             /* Make a copy of the environment variable string */
915             if (NULL == (saved_env = tmp_env_prefix = H5MM_strdup(env_prefix)))
916                 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
917 
918             /* Loop over prefixes in environment variable */
919             while ((tmp_env_prefix) && (*tmp_env_prefix)) {
920                 char *out_prefix_name;
921 
922                 out_prefix_name = H5F__getenv_prefix_name(&tmp_env_prefix /*in,out*/);
923                 if (out_prefix_name && (*out_prefix_name)) {
924                     if (H5F__build_name(out_prefix_name, temp_file_name, &full_name /*out*/) < 0) {
925                         saved_env = (char *)H5MM_xfree(saved_env);
926                         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename")
927                     } /* end if */
928 
929                     /* Try opening file */
930                     src_file =
931                         H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
932 
933                     /* Release copy of file name */
934                     full_name = (char *)H5MM_xfree(full_name);
935 
936                     /* Check for file not opened */
937                     if (NULL == src_file)
938                         /* Reset the error stack */
939                         H5E_clear_stack(NULL);
940                     /* Leave if file was opened */
941                     else
942                         break;
943                     H5E_clear_stack(NULL);
944                 } /* end if */
945             }     /* end while */
946 
947             saved_env = (char *)H5MM_xfree(saved_env);
948         } /* end if */
949     }     /* end if */
950 
951     /* Try searching from property list */
952     if (src_file == NULL && prop_prefix) {
953         /* Construct name to open */
954         if (H5F__build_name(prop_prefix, temp_file_name, &full_name /*out*/) < 0)
955             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename")
956 
957         /* Try opening file */
958         src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
959 
960         /* Release name */
961         full_name = (char *)H5MM_xfree(full_name);
962 
963         /* Check for file not opened */
964         if (NULL == src_file)
965             /* Reset the error stack */
966             H5E_clear_stack(NULL);
967     } /* end if */
968 
969     /* Try searching from main file's "extpath": see description in H5F_open() & H5_build_extpath() */
970     if (src_file == NULL) {
971         char *dspath;
972 
973         if (NULL != (dspath = H5F_EXTPATH(primary_file))) {
974             /* Construct name to open */
975             if (H5F__build_name(dspath, temp_file_name, &full_name /*out*/) < 0)
976                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename")
977 
978             /* Try opening file */
979             src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
980 
981             /* Release name */
982             full_name = (char *)H5MM_xfree(full_name);
983 
984             /* Check for file not opened */
985             if (NULL == src_file)
986                 /* Reset the error stack */
987                 H5E_clear_stack(NULL);
988         } /* end if */
989     }     /* end if */
990 
991     /* Try the relative file_name stored in temp_file_name */
992     if (src_file == NULL) {
993         /* Try opening file */
994         src_file = H5F__efc_open(primary_file, temp_file_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
995 
996         /* Check for file not opened */
997         if (NULL == src_file)
998             /* Reset the error stack */
999             H5E_clear_stack(NULL);
1000     } /* end if */
1001 
1002     /* try the 'resolved' name for the virtual file */
1003     if (src_file == NULL) {
1004         char *ptr = NULL;
1005 
1006         /* Copy resolved file name */
1007         if (NULL == (actual_file_name = H5MM_strdup(H5F_ACTUAL_NAME(primary_file))))
1008             HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "can't duplicate resolved file name string")
1009 
1010         /* get last component of file_name */
1011         H5_GET_LAST_DELIMITER(actual_file_name, ptr)
1012         if (ptr)
1013             /* Truncate filename portion from actual file name path */
1014             *ptr = '\0';
1015 
1016         /* Build new file name for the external file */
1017         if (H5F__build_name((ptr ? actual_file_name : ""), temp_file_name, &full_name /*out*/) < 0)
1018             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't prepend prefix to filename")
1019         actual_file_name = (char *)H5MM_xfree(actual_file_name);
1020 
1021         /* Try opening with the resolved name */
1022         src_file = H5F__efc_open(primary_file, full_name, file_intent, H5P_FILE_CREATE_DEFAULT, fapl_id);
1023 
1024         /* Release name */
1025         full_name = (char *)H5MM_xfree(full_name);
1026 
1027         /* Check for file not opened */
1028         if (NULL == src_file)
1029             /* Reset the error stack */
1030             H5E_clear_stack(NULL);
1031     } /* end if */
1032 
1033     /* Set return value (possibly NULL or valid H5F_t *) */
1034     ret_value = src_file;
1035 
1036 done:
1037     if ((NULL == ret_value) && src_file)
1038         if (H5F_efc_close(primary_file, src_file) < 0)
1039             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "can't close source file")
1040     if (full_name)
1041         full_name = (char *)H5MM_xfree(full_name);
1042     if (temp_file_name)
1043         temp_file_name = (char *)H5MM_xfree(temp_file_name);
1044     if (actual_file_name)
1045         actual_file_name = (char *)H5MM_xfree(actual_file_name);
1046 
1047     FUNC_LEAVE_NOAPI(ret_value)
1048 } /* H5F_prefix_open_file() */
1049 
1050 /*-------------------------------------------------------------------------
1051  * Function:    H5F__is_hdf5
1052  *
1053  * Purpose:     Check the file signature to detect an HDF5 file.
1054  *
1055  * Return:      TRUE/FALSE/FAIL
1056  *-------------------------------------------------------------------------
1057  */
1058 htri_t
H5F__is_hdf5(const char * name,hid_t fapl_id)1059 H5F__is_hdf5(const char *name, hid_t fapl_id)
1060 {
1061     H5FD_t *      file      = NULL;        /* Low-level file struct            */
1062     H5F_shared_t *shared    = NULL;        /* Shared part of file              */
1063     haddr_t       sig_addr  = HADDR_UNDEF; /* Addess of hdf5 file signature    */
1064     htri_t        ret_value = FAIL;        /* Return value                     */
1065 
1066     FUNC_ENTER_PACKAGE
1067 
1068     /* Open the file */
1069     /* NOTE:    This now uses the fapl_id that was passed in, so H5Fis_accessible()
1070      *          should work with arbitrary VFDs, unlike H5Fis_hdf5().
1071      */
1072     if (NULL == (file = H5FD_open(name, H5F_ACC_RDONLY, fapl_id, HADDR_UNDEF)))
1073         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to open file")
1074 
1075     /* If the file is already open, it's an HDF5 file
1076      *
1077      * If the file is open with an exclusive lock on an operating system that enforces
1078      * mandatory file locks (like Windows), creating a new file handle and attempting
1079      * to read through it will fail so we have to try this first.
1080      */
1081     if ((shared = H5F__sfile_search(file)) != NULL)
1082         ret_value = TRUE;
1083     else {
1084         /* The file is an HDF5 file if the HDF5 file signature can be found */
1085         if (H5FD_locate_signature(file, &sig_addr) < 0)
1086             HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL, "error while trying to locate file signature")
1087         ret_value = (HADDR_UNDEF != sig_addr);
1088     }
1089 
1090 done:
1091     /* Close the file */
1092     if (file)
1093         if (H5FD_close(file) < 0 && TRUE == ret_value)
1094             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
1095 
1096     FUNC_LEAVE_NOAPI(ret_value)
1097 } /* end H5F__is_hdf5() */
1098 
1099 /*-------------------------------------------------------------------------
1100  * Function:    H5F__new
1101  *
1102  * Purpose:     Creates a new file object and initializes it. The
1103  *              H5Fopen and H5Fcreate functions then fill in various fields.
1104  *              If SHARED is a non-null pointer then the shared info
1105  *              to which it points has the reference count incremented.
1106  *              Otherwise a new, empty shared info struct is created and
1107  *              initialized with the specified file access property list.
1108  *
1109  * Return:      Success:    Pointer to a new file struct
1110  *
1111  *              Failure:    NULL
1112  *
1113  *-------------------------------------------------------------------------
1114  */
1115 static H5F_t *
H5F__new(H5F_shared_t * shared,unsigned flags,hid_t fcpl_id,hid_t fapl_id,H5FD_t * lf)1116 H5F__new(H5F_shared_t *shared, unsigned flags, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
1117 {
1118     H5F_t *f         = NULL;
1119     H5F_t *ret_value = NULL;
1120 
1121     FUNC_ENTER_STATIC
1122 
1123     if (NULL == (f = H5FL_CALLOC(H5F_t)))
1124         HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate top file structure")
1125     f->id_exists = FALSE;
1126 
1127     if (shared) {
1128         HDassert(lf == NULL);
1129         f->shared = shared;
1130     }
1131     else {
1132         H5P_genplist_t *plist;    /* Property list */
1133         unsigned        efc_size; /* External file cache size */
1134         size_t          u;        /* Local index variable */
1135 
1136         HDassert(lf != NULL);
1137         if (NULL == (f->shared = H5FL_CALLOC(H5F_shared_t)))
1138             HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, NULL, "can't allocate shared file structure")
1139 
1140         f->shared->flags     = flags;
1141         f->shared->sohm_addr = HADDR_UNDEF;
1142         f->shared->sohm_vers = HDF5_SHAREDHEADER_VERSION;
1143         f->shared->accum.loc = HADDR_UNDEF;
1144         f->shared->lf        = lf;
1145 
1146         /* Initialization for handling file space */
1147         for (u = 0; u < NELMTS(f->shared->fs_addr); u++) {
1148             f->shared->fs_state[u] = H5F_FS_STATE_CLOSED;
1149             f->shared->fs_addr[u]  = HADDR_UNDEF;
1150             f->shared->fs_man[u]   = NULL;
1151         }
1152         /* This will be stored as eoa_pre_fsm_fsalloc in the fsinfo message */
1153         /* This is done to be backward compatible with 1.10 library that has the FSM hack */
1154         f->shared->eoa_fsm_fsalloc       = HADDR_UNDEF;
1155         f->shared->eoa_post_mdci_fsalloc = HADDR_UNDEF;
1156 
1157         /* Initialization for handling file space (for paged aggregation) */
1158         f->shared->pgend_meta_thres = H5F_FILE_SPACE_PGEND_META_THRES;
1159 
1160         /* intialize point of no return */
1161         f->shared->point_of_no_return = FALSE;
1162 
1163         /* Copy the file creation and file access property lists into the
1164          * new file handle. We do this early because some values might need
1165          * to change as the file is being opened.
1166          */
1167         if (NULL == (plist = (H5P_genplist_t *)H5I_object(fcpl_id)))
1168             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not property list")
1169         f->shared->fcpl_id = H5P_copy_plist(plist, FALSE);
1170 
1171         /* Get the FCPL values to cache */
1172         if (H5P_get(plist, H5F_CRT_ADDR_BYTE_NUM_NAME, &f->shared->sizeof_addr) < 0)
1173             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for address")
1174         if (H5P_get(plist, H5F_CRT_OBJ_BYTE_NUM_NAME, &f->shared->sizeof_size) < 0)
1175             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get byte number for object size")
1176         if (H5P_get(plist, H5F_CRT_SHMSG_NINDEXES_NAME, &f->shared->sohm_nindexes) < 0)
1177             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get number of SOHM indexes")
1178         HDassert(f->shared->sohm_nindexes < 255);
1179         if (H5P_get(plist, H5F_CRT_FILE_SPACE_STRATEGY_NAME, &f->shared->fs_strategy) < 0)
1180             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space strategy")
1181         if (H5P_get(plist, H5F_CRT_FREE_SPACE_PERSIST_NAME, &f->shared->fs_persist) < 0)
1182             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space persisting status")
1183         if (H5P_get(plist, H5F_CRT_FREE_SPACE_THRESHOLD_NAME, &f->shared->fs_threshold) < 0)
1184             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get free-space section threshold")
1185         if (H5P_get(plist, H5F_CRT_FILE_SPACE_PAGE_SIZE_NAME, &f->shared->fs_page_size) < 0)
1186             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file space page size")
1187         HDassert(f->shared->fs_page_size >= H5F_FILE_SPACE_PAGE_SIZE_MIN);
1188 
1189         /* Temporary for multi/split drivers: fail file creation
1190          * when persisting free-space or using paged aggregation strategy.
1191          */
1192         if (H5F_HAS_FEATURE(f, H5FD_FEAT_PAGED_AGGR))
1193             if (f->shared->fs_strategy == H5F_FSPACE_STRATEGY_PAGE || f->shared->fs_persist)
1194                 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't open with this strategy or persistent fs")
1195 
1196         /* Get the FAPL values to cache */
1197         if (NULL == (plist = (H5P_genplist_t *)H5I_object(fapl_id)))
1198             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
1199         if (H5P_get(plist, H5F_ACS_META_CACHE_INIT_CONFIG_NAME, &(f->shared->mdc_initCacheCfg)) < 0)
1200             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config")
1201         if (H5P_get(plist, H5F_ACS_DATA_CACHE_NUM_SLOTS_NAME, &(f->shared->rdcc_nslots)) < 0)
1202             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache number of slots")
1203         if (H5P_get(plist, H5F_ACS_DATA_CACHE_BYTE_SIZE_NAME, &(f->shared->rdcc_nbytes)) < 0)
1204             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get data cache byte size")
1205         if (H5P_get(plist, H5F_ACS_PREEMPT_READ_CHUNKS_NAME, &(f->shared->rdcc_w0)) < 0)
1206             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get preempt read chunk")
1207         if (H5P_get(plist, H5F_ACS_ALIGN_THRHD_NAME, &(f->shared->threshold)) < 0)
1208             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment threshold")
1209         if (H5P_get(plist, H5F_ACS_ALIGN_NAME, &(f->shared->alignment)) < 0)
1210             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get alignment")
1211         if (H5P_get(plist, H5F_ACS_GARBG_COLCT_REF_NAME, &(f->shared->gc_ref)) < 0)
1212             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get garbage collect reference")
1213         if (H5P_get(plist, H5F_ACS_SIEVE_BUF_SIZE_NAME, &(f->shared->sieve_buf_size)) < 0)
1214             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get sieve buffer size")
1215         if (H5P_get(plist, H5F_ACS_LIBVER_LOW_BOUND_NAME, &(f->shared->low_bound)) < 0)
1216             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'low' bound for library format versions")
1217         if (H5P_get(plist, H5F_ACS_LIBVER_HIGH_BOUND_NAME, &(f->shared->high_bound)) < 0)
1218             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'high' bound for library format versions")
1219         if (H5P_get(plist, H5F_ACS_USE_MDC_LOGGING_NAME, &(f->shared->use_mdc_logging)) < 0)
1220             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'use mdc logging' flag")
1221         if (H5P_get(plist, H5F_ACS_START_MDC_LOG_ON_ACCESS_NAME, &(f->shared->start_mdc_log_on_access)) < 0)
1222             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'start mdc log on access' flag")
1223         if (H5P_get(plist, H5F_ACS_META_BLOCK_SIZE_NAME, &(f->shared->meta_aggr.alloc_size)) < 0)
1224             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get metadata cache size")
1225         f->shared->meta_aggr.feature_flag = H5FD_FEAT_AGGREGATE_METADATA;
1226         if (H5P_get(plist, H5F_ACS_SDATA_BLOCK_SIZE_NAME, &(f->shared->sdata_aggr.alloc_size)) < 0)
1227             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get 'small data' cache size")
1228         f->shared->sdata_aggr.feature_flag = H5FD_FEAT_AGGREGATE_SMALLDATA;
1229         if (H5P_get(plist, H5F_ACS_EFC_SIZE_NAME, &efc_size) < 0)
1230             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get elink file cache size")
1231         if (efc_size > 0)
1232             if (NULL == (f->shared->efc = H5F__efc_create(efc_size)))
1233                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't create external file cache")
1234 #ifdef H5_HAVE_PARALLEL
1235         if (H5P_get(plist, H5_COLL_MD_READ_FLAG_NAME, &(f->shared->coll_md_read)) < 0)
1236             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get collective metadata read flag")
1237         if (H5P_get(plist, H5F_ACS_COLL_MD_WRITE_FLAG_NAME, &(f->shared->coll_md_write)) < 0)
1238             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get collective metadata write flag")
1239 #endif /* H5_HAVE_PARALLEL */
1240         if (H5P_get(plist, H5F_ACS_META_CACHE_INIT_IMAGE_CONFIG_NAME, &(f->shared->mdc_initCacheImageCfg)) <
1241             0)
1242             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get initial metadata cache resize config")
1243 
1244         /* Get the VFD values to cache */
1245         f->shared->maxaddr = H5FD_get_maxaddr(lf);
1246         if (!H5F_addr_defined(f->shared->maxaddr))
1247             HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "bad maximum address from VFD")
1248         if (H5FD_get_feature_flags(lf, &f->shared->feature_flags) < 0)
1249             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get feature flags from VFD")
1250 
1251         /* Require the SWMR feature flag if SWMR I/O is desired */
1252         if (!H5F_HAS_FEATURE(f, H5FD_FEAT_SUPPORTS_SWMR_IO) &&
1253             (H5F_INTENT(f) & (H5F_ACC_SWMR_WRITE | H5F_ACC_SWMR_READ)))
1254             HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "must use a SWMR-compatible VFD when SWMR is specified")
1255 
1256         if (H5FD_get_fs_type_map(lf, f->shared->fs_type_map) < 0)
1257             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get free space type mapping from VFD")
1258         if (H5MF_init_merge_flags(f->shared) < 0)
1259             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "problem initializing free space merge flags")
1260         f->shared->tmp_addr = f->shared->maxaddr;
1261         /* Disable temp. space allocation for parallel I/O (for now) */
1262         /* (When we've arranged to have the relocated metadata addresses (and
1263          *      sizes) broadcast during the "end of epoch" metadata operations,
1264          *      this can be enabled - QAK)
1265          */
1266         /* (This should be disabled when the metadata journaling branch is
1267          *      merged into the trunk and journaling is enabled, at least until
1268          *      we make it work. - QAK)
1269          */
1270         f->shared->use_tmp_space = !H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI);
1271 
1272         /* Retrieve the # of read attempts here so that sohm in superblock will get the correct # of attempts
1273          */
1274         if (H5P_get(plist, H5F_ACS_METADATA_READ_ATTEMPTS_NAME, &f->shared->read_attempts) < 0)
1275             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get the # of read attempts")
1276 
1277         /* When opening file with SWMR access, the # of read attempts is H5F_SWMR_METADATA_READ_ATTEMPTS if
1278          * not set */
1279         /* When opening file without SWMR access, the # of read attempts is always H5F_METADATA_READ_ATTEMPTS
1280          * (set or not set) */
1281         if (H5F_INTENT(f) & (H5F_ACC_SWMR_READ | H5F_ACC_SWMR_WRITE)) {
1282             /* If no value for read attempts has been set, use the default */
1283             if (!f->shared->read_attempts)
1284                 f->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS;
1285 
1286             /* Turn off accumulator with SWMR */
1287             f->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
1288             if (H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0)
1289                 HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't set feature_flags in VFD")
1290         }
1291         else {
1292             /* If no value for read attempts has been set, use the default */
1293             if (!f->shared->read_attempts)
1294                 f->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS;
1295         }
1296 
1297         /* Determine the # of bins for metdata read retries */
1298         if (H5F_set_retries(f) < 0)
1299             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't set retries and retries_nbins")
1300 
1301         /* Get the metadata cache log location (if we're logging) */
1302         {
1303             char *mdc_log_location = NULL; /* location of metadata cache log location */
1304 
1305             if (H5P_get(plist, H5F_ACS_MDC_LOG_LOCATION_NAME, &mdc_log_location) < 0)
1306                 HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get mdc log location")
1307             if (mdc_log_location != NULL) {
1308                 size_t len = HDstrlen(mdc_log_location);
1309                 if (NULL == (f->shared->mdc_log_location = (char *)H5MM_calloc((len + 1) * sizeof(char))))
1310                     HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL,
1311                                 "can't allocate memory for mdc log file name")
1312                 HDstrncpy(f->shared->mdc_log_location, mdc_log_location, len);
1313             }
1314             else
1315                 f->shared->mdc_log_location = NULL;
1316         } /* end block */
1317 
1318         /* Get object flush callback information */
1319         if (H5P_get(plist, H5F_ACS_OBJECT_FLUSH_CB_NAME, &(f->shared->object_flush)) < 0)
1320             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get object flush cb info")
1321 
1322         /* Get the VOL connector info */
1323         if (H5F__set_vol_conn(f) < 0)
1324             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "can't cache VOL connector info")
1325 
1326         /* Create a metadata cache with the specified number of elements.
1327          * The cache might be created with a different number of elements and
1328          * the access property list should be updated to reflect that.
1329          */
1330         if (H5AC_create(f, &(f->shared->mdc_initCacheCfg), &(f->shared->mdc_initCacheImageCfg)) < 0)
1331             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create metadata cache")
1332 
1333         /* Create the file's "open object" information */
1334         if (H5FO_create(f) < 0)
1335             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
1336 
1337         /* Add new "shared" struct to list of open files */
1338         if (H5F__sfile_add(f->shared) < 0)
1339             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to append to list of open files")
1340     } /* end else */
1341 
1342     f->shared->nrefs++;
1343 
1344     /* Create the file's "top open object" information */
1345     if (H5FO_top_create(f) < 0)
1346         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object data structure")
1347 
1348     /* Set return value */
1349     ret_value = f;
1350 
1351 done:
1352     if (!ret_value && f) {
1353         HDassert(NULL == f->vol_obj);
1354 
1355         if (!shared) {
1356             /* Attempt to clean up some of the shared file structures */
1357             if (f->shared->efc)
1358                 if (H5F__efc_destroy(f->shared->efc) < 0)
1359                     HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, NULL, "can't destroy external file cache")
1360             if (f->shared->fcpl_id > 0)
1361                 if (H5I_dec_ref(f->shared->fcpl_id) < 0)
1362                     HDONE_ERROR(H5E_FILE, H5E_CANTDEC, NULL, "can't close property list")
1363 
1364             f->shared = H5FL_FREE(H5F_shared_t, f->shared);
1365         }
1366 
1367         f = H5FL_FREE(H5F_t, f);
1368     }
1369 
1370     FUNC_LEAVE_NOAPI(ret_value)
1371 } /* end H5F__new() */
1372 
1373 /*-------------------------------------------------------------------------
1374  * Function:    H5F__dest
1375  *
1376  * Purpose:     Destroys a file structure.  This function flushes the cache
1377  *              but doesn't do any other cleanup other than freeing memory
1378  *              for the file struct.  The shared info for the file is freed
1379  *              only when its reference count reaches zero.
1380  *
1381  * Return:      SUCCEED/FAIL
1382  *-------------------------------------------------------------------------
1383  */
1384 static herr_t
H5F__dest(H5F_t * f,hbool_t flush)1385 H5F__dest(H5F_t *f, hbool_t flush)
1386 {
1387     herr_t ret_value = SUCCEED; /* Return value */
1388 
1389     FUNC_ENTER_STATIC
1390 
1391     /* Sanity check */
1392     HDassert(f);
1393     HDassert(f->shared);
1394 
1395     if (1 == f->shared->nrefs) {
1396         int actype; /* metadata cache type (enum value) */
1397 
1398         /* Mark this file as closing */
1399         f->shared->closing = TRUE;
1400 
1401         /* Flush at this point since the file will be closed (phase 1).
1402          * Only try to flush the file if it was opened with write access, and if
1403          * the caller requested a flush.
1404          */
1405         if ((H5F_ACC_RDWR & H5F_INTENT(f)) && flush)
1406             if (H5F__flush_phase1(f) < 0)
1407                 /* Push error, but keep going*/
1408                 HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush cached data (phase 1)")
1409 
1410         /* Notify the metadata cache that the file is about to be closed.
1411          * This allows the cache to set up for creating a metadata cache
1412          * image if this has been requested.
1413          */
1414         if (H5AC_prep_for_file_close(f) < 0)
1415             /* Push error, but keep going */
1416             HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "metadata cache prep for close failed")
1417 
1418         /* Flush at this point since the file will be closed (phase 2).
1419          * Only try to flush the file if it was opened with write access, and if
1420          * the caller requested a flush.
1421          */
1422         if ((H5F_ACC_RDWR & H5F_INTENT(f)) && flush)
1423             if (H5F__flush_phase2(f, TRUE) < 0)
1424                 /* Push error, but keep going */
1425                 HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush cached data (phase 2)")
1426 
1427         /* With the shutdown modifications, the contents of the metadata cache
1428          * should be clean at this point, with the possible exception of the
1429          * the superblock and superblock extension.
1430          *
1431          * Verify this.
1432          */
1433         HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM));
1434 
1435         /* Release the external file cache */
1436         if (f->shared->efc) {
1437             if (H5F__efc_destroy(f->shared->efc) < 0)
1438                 /* Push error, but keep going*/
1439                 HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't destroy external file cache")
1440             f->shared->efc = NULL;
1441         } /* end if */
1442 
1443         /* With the shutdown modifications, the contents of the metadata cache
1444          * should be clean at this point, with the possible exception of the
1445          * the superblock and superblock extension.
1446          *
1447          * Verify this.
1448          */
1449         HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM));
1450 
1451         /* Release objects that depend on the superblock being initialized */
1452         if (f->shared->sblock) {
1453             /* Shutdown file free space manager(s) */
1454             /* (We should release the free space information now (before
1455              *      truncating the file and before the metadata cache is shut
1456              *      down) since the free space manager is holding some data
1457              *      structures in memory and also because releasing free space
1458              *      can shrink the file's 'eoa' value)
1459              *
1460              * Update 11/1/16:
1461              *
1462              *      With recent library shutdown modifications, the free space
1463              *      managers should be settled and written to file at this point
1464              *      (assuming they are persistent).  In this case, closing the
1465              *      free space managers should have no effect on EOA.
1466              *
1467              *                                          -- JRM
1468              */
1469             if (H5F_ACC_RDWR & H5F_INTENT(f)) {
1470                 if (H5MF_close(f) < 0)
1471                     /* Push error, but keep going*/
1472                     HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file free space info")
1473 
1474                 /* at this point, only the superblock and superblock
1475                  * extension should be dirty.
1476                  */
1477                 HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM));
1478 
1479                 /* Flush the file again (if requested), as shutting down the
1480                  * free space manager may dirty some data structures again.
1481                  */
1482                 if (flush) {
1483                     /* Clear status_flags */
1484                     f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_WRITE_ACCESS);
1485                     f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS);
1486 
1487                     /* Mark EOA info dirty in cache, so change will get encoded */
1488                     if (H5F_eoa_dirty(f) < 0)
1489                         /* Push error, but keep going*/
1490                         HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
1491 
1492                     /* Release any space allocated to space aggregators,
1493                      * so that the eoa value corresponds to the end of the
1494                      * space written to in the file.
1495                      *
1496                      * At most, this should change the superblock or the
1497                      * superblock extension messages.
1498                      */
1499                     if (H5MF_free_aggrs(f) < 0)
1500                         /* Push error, but keep going*/
1501                         HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space")
1502 
1503                     /* Truncate the file to the current allocated size */
1504                     if (H5FD_truncate(f->shared->lf, TRUE) < 0)
1505                         /* Push error, but keep going*/
1506                         HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed")
1507 
1508                     /* at this point, only the superblock and superblock
1509                      * extension should be dirty.
1510                      */
1511                     HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM));
1512                 } /* end if */
1513             }     /* end if */
1514 
1515             /* if it exists, unpin the driver information block cache entry,
1516              * since we're about to destroy the cache
1517              */
1518             if (f->shared->drvinfo)
1519                 if (H5AC_unpin_entry(f->shared->drvinfo) < 0)
1520                     /* Push error, but keep going*/
1521                     HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin drvinfo")
1522 
1523             /* Unpin the superblock, since we're about to destroy the cache */
1524             if (H5AC_unpin_entry(f->shared->sblock) < 0)
1525                 /* Push error, but keep going*/
1526                 HDONE_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin superblock")
1527             f->shared->sblock = NULL;
1528         } /* end if */
1529 
1530         /* with the possible exception of the superblock and superblock
1531          * extension, the metadata cache should be clean at this point.
1532          *
1533          * Verify this.
1534          */
1535         HDassert(H5AC_cache_is_clean(f, H5AC_RING_MDFSM));
1536 
1537         /* Remove shared file struct from list of open files */
1538         if (H5F__sfile_remove(f->shared) < 0)
1539             /* Push error, but keep going*/
1540             HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
1541 
1542         /* Shutdown the metadata cache */
1543         /* (Flushes any remaining dirty entries, which should only be the
1544          *      superblock and / or driver info at this point)
1545          */
1546         if (H5AC_dest(f))
1547             /* Push error, but keep going*/
1548             HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
1549 
1550         /* Shutdown the page buffer cache */
1551         if (H5PB_dest(f->shared) < 0)
1552             /* Push error, but keep going*/
1553             HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing page buffer cache")
1554 
1555         /* Clean up the metadata cache log location string */
1556         if (f->shared->mdc_log_location)
1557             f->shared->mdc_log_location = (char *)H5MM_xfree(f->shared->mdc_log_location);
1558 
1559         /*
1560          * Do not close the root group since we didn't count it, but free
1561          * the memory associated with it.
1562          */
1563         if (f->shared->root_grp) {
1564             /* Free the root group */
1565             if (H5G_root_free(f->shared->root_grp) < 0)
1566                 /* Push error, but keep going*/
1567                 HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
1568             f->shared->root_grp = NULL;
1569         } /* end if */
1570 
1571         /* Destroy other components of the file */
1572         if (H5F__accum_reset(f->shared, TRUE) < 0)
1573             /* Push error, but keep going*/
1574             HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
1575         if (H5FO_dest(f) < 0)
1576             /* Push error, but keep going*/
1577             HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
1578         f->shared->cwfs = (struct H5HG_heap_t **)H5MM_xfree(f->shared->cwfs);
1579         if (H5G_node_close(f) < 0)
1580             /* Push error, but keep going*/
1581             HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "problems closing file")
1582 
1583         /* Destroy file creation properties */
1584         if (H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
1585             /* Push error, but keep going*/
1586             HDONE_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "not a property list")
1587         if (H5I_dec_ref(f->shared->fcpl_id) < 0)
1588             /* Push error, but keep going*/
1589             HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close property list")
1590 
1591         /* Clean up the cached VOL connector ID & info */
1592         if (f->shared->vol_info)
1593             if (H5VL_free_connector_info(f->shared->vol_id, f->shared->vol_info) < 0)
1594                 /* Push error, but keep going*/
1595                 HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to release VOL connector info object")
1596         if (f->shared->vol_id > 0)
1597             if (H5I_dec_ref(f->shared->vol_id) < 0)
1598                 /* Push error, but keep going*/
1599                 HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close VOL connector ID")
1600         f->shared->vol_cls = NULL;
1601 
1602         /* Close the file */
1603         if (H5FD_close(f->shared->lf) < 0)
1604             /* Push error, but keep going*/
1605             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
1606 
1607         /* Free mount table */
1608         f->shared->mtab.child  = (H5F_mount_t *)H5MM_xfree(f->shared->mtab.child);
1609         f->shared->mtab.nalloc = 0;
1610 
1611         /* Free the external link file */
1612         f->shared->extpath = (char *)H5MM_xfree(f->shared->extpath);
1613 
1614         /* Clean up the metadata retries array */
1615         for (actype = 0; actype < (int)H5AC_NTYPES; actype++)
1616             if (f->shared->retries[actype])
1617                 f->shared->retries[actype] = (uint32_t *)H5MM_xfree(f->shared->retries[actype]);
1618 
1619         /* Destroy shared file struct */
1620         f->shared = (H5F_shared_t *)H5FL_FREE(H5F_shared_t, f->shared);
1621     }
1622     else if (f->shared->nrefs > 0) {
1623         /*
1624          * There are other references to the shared part of the file.
1625          * Only decrement the reference count.
1626          */
1627         --f->shared->nrefs;
1628     }
1629 
1630     /* Free the non-shared part of the file */
1631     f->open_name   = (char *)H5MM_xfree(f->open_name);
1632     f->actual_name = (char *)H5MM_xfree(f->actual_name);
1633     if (f->vol_obj) {
1634         void *vol_wrap_ctx = NULL;
1635 
1636         /* If a VOL wrapping context is available, retrieve it
1637          * and unwrap file VOL object
1638          */
1639         if (H5CX_get_vol_wrap_ctx((void **)&vol_wrap_ctx) < 0)
1640             HDONE_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get VOL object wrap context")
1641         if (vol_wrap_ctx && (NULL == H5VL_object_unwrap(f->vol_obj)))
1642             HDONE_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't unwrap VOL object")
1643 
1644         if (H5VL_free_object(f->vol_obj) < 0)
1645             HDONE_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "unable to free VOL object")
1646         f->vol_obj = NULL;
1647     }
1648     if (H5FO_top_dest(f) < 0)
1649         HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "problems closing file")
1650     f->shared = NULL;
1651     f         = H5FL_FREE(H5F_t, f);
1652 
1653     FUNC_LEAVE_NOAPI(ret_value)
1654 } /* end H5F__dest() */
1655 
1656 /*-------------------------------------------------------------------------
1657  * Function:    H5F__check_if_using_file_locks
1658  *
1659  * Purpose:     Determines if this file will use file locks.
1660  *
1661  * There are three ways that file locking can be controlled:
1662  *
1663  * 1) The configure/cmake option that sets the H5_USE_FILE_LOCKING
1664  *    symbol (which is used as the default fapl value).
1665  *
1666  * 2) The H5Pset_file_locking() API call, which will override
1667  *    the configuration default.
1668  *
1669  * 3) The HDF5_USE_FILE_LOCKING environment variable, which overrides
1670  *    everything above.
1671  *
1672  * The main reason to disable file locking is to prevent errors on file
1673  * systems where locking is not supported or has been disabled (as is
1674  * often the case in parallel file systems).
1675  *
1676  * Return:      SUCCEED/FAIL
1677  *-------------------------------------------------------------------------
1678  */
1679 static herr_t
H5F__check_if_using_file_locks(H5P_genplist_t * fapl,hbool_t * use_file_locking)1680 H5F__check_if_using_file_locks(H5P_genplist_t *fapl, hbool_t *use_file_locking)
1681 {
1682     herr_t ret_value = SUCCEED; /* Return value */
1683 
1684     FUNC_ENTER_STATIC
1685 
1686     /* Make sure the out parameter has a value */
1687     *use_file_locking = TRUE;
1688 
1689     /* Check the fapl property */
1690     if (H5P_get(fapl, H5F_ACS_USE_FILE_LOCKING_NAME, use_file_locking) < 0)
1691         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get use file locking flag")
1692 
1693     /* Check the environment variable */
1694     if (use_locks_env_g != FAIL)
1695         *use_file_locking = (use_locks_env_g == TRUE) ? TRUE : FALSE;
1696 
1697 done:
1698     FUNC_LEAVE_NOAPI(ret_value)
1699 } /* end H5F__check_if_using_file_locks() */
1700 
1701 /*-------------------------------------------------------------------------
1702  * Function:    H5F_open
1703  *
1704  * Purpose:    Opens (or creates) a file.  This function understands the
1705  *        following flags which are similar in nature to the Posix
1706  *        open(2) flags.
1707  *
1708  *        H5F_ACC_RDWR:    Open with read/write access. If the file is
1709  *                currently open for read-only access then it
1710  *                will be reopened. Absence of this flag
1711  *                implies read-only access.
1712  *
1713  *        H5F_ACC_CREAT:    Create a new file if it doesn't exist yet.
1714  *                The permissions are 0666 bit-wise AND with
1715  *                the current umask.  H5F_ACC_WRITE must also
1716  *                be specified.
1717  *
1718  *        H5F_ACC_EXCL:    This flag causes H5F_open() to fail if the
1719  *                file already exists.
1720  *
1721  *        H5F_ACC_TRUNC:    The file is truncated and a new HDF5 superblock
1722  *                is written.  This operation will fail if the
1723  *                file is already open.
1724  *
1725  *        Unlinking the file name from the group directed graph while
1726  *        the file is opened causes the file to continue to exist but
1727  *        one will not be able to upgrade the file from read-only
1728  *        access to read-write access by reopening it. Disk resources
1729  *        for the file are released when all handles to the file are
1730  *        closed. NOTE: This paragraph probably only applies to Unix;
1731  *        deleting the file name in other OS's has undefined results.
1732  *
1733  *        The CREATE_PARMS argument is optional.    A null pointer will
1734  *        cause the default file creation parameters to be used.
1735  *
1736  *        The ACCESS_PARMS argument is optional.  A null pointer will
1737  *        cause the default file access parameters to be used.
1738  *
1739  * The following two tables show results of file opens for single and concurrent access:
1740  *
1741  * SINGLE PROCESS ACCESS                        CONCURRENT ACCESS
1742  *
1743  *             #1st open#                                   #1st open#
1744  *             -- SR SR -- -- SR SR --                      -- SR SR -- -- SR SR --
1745  *             -- -- SW SW SW SW -- --                      -- -- SW SW SW SW -- --
1746  *              W  W  W  W  R  R  R  R                       W  W  W  W  R  R  R  R
1747  * #2nd open#                                   #2nd open#
1748  *            --------------------------                   --------------------------
1749  *   -- --  W | s  x  x  s  x  x  f  f |          -- --  W | f  x  x  f  x  x  f  f |
1750  *   SR --  W | x  x  x  x  x  x  x  x |          SR --  W | x  x  x  x  x  x  x  x |
1751  *   SR SW  W | x  x  x  x  x  x  x  x |          SR SW  W | x  x  x  x  x  x  x  x |
1752  *   -- SW  W | f  x  x  s  x  x  f  f |          -- SW  W | f  x  x  f  x  x  f  f |
1753  *   -- SW  R | x  x  x  x  x  x  x  x |          -- SW  R | x  x  x  x  x  x  x  x |
1754  *   SR SW  R | x  x  x  x  x  x  x  x |          SR SW  R | x  x  x  x  x  x  x  x |
1755  *   SR --  R | s  x  x  s  x  x  s  f |          SR --  R | f  x  x  s  x  x  s  s |
1756  *   -- --  R | s  x  x  s  x  x  s  s |          -- --  R | f  x  x  f  x  x  s  s |
1757  *            --------------------------                   --------------------------
1758  *
1759  *      Notations:
1760  *        W:  H5F_ACC_RDWR
1761  *        R:  H5F_ACC_RDONLY
1762  *        SW: H5F_ACC_SWMR_WRITE
1763  *        SR: H5F_ACC_SWMR_READ
1764  *
1765  *        x: the first open or second open itself fails due to invalid flags combination
1766  *        f: the open fails with flags combination from both the first and second opens
1767  *        s: the open succeeds with flags combination from both the first and second opens
1768  *
1769  *
1770  * Return:    Success:    A new file pointer.
1771  *        Failure:    NULL
1772  *-------------------------------------------------------------------------
1773  */
1774 H5F_t *
H5F_open(const char * name,unsigned flags,hid_t fcpl_id,hid_t fapl_id)1775 H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
1776 {
1777     H5F_t *            file   = NULL; /*the success return value      */
1778     H5F_shared_t *     shared = NULL; /*shared part of `file'         */
1779     H5FD_t *           lf     = NULL; /*file driver part of `shared'  */
1780     unsigned           tent_flags;    /*tentative flags               */
1781     H5FD_class_t *     drvr;          /*file driver class info        */
1782     H5P_genplist_t *   a_plist;       /*file access property list     */
1783     H5F_close_degree_t fc_degree;     /*file close degree             */
1784     size_t             page_buf_size;
1785     unsigned           page_buf_min_meta_perc = 0;
1786     unsigned           page_buf_min_raw_perc  = 0;
1787     hbool_t            set_flag               = FALSE; /*set the status_flags in the superblock */
1788     hbool_t            clear                  = FALSE; /*clear the status_flags         */
1789     hbool_t            evict_on_close;                 /* evict on close value from plist  */
1790     hbool_t            use_file_locking = TRUE;        /* Using file locks? */
1791     hbool_t            ci_load          = FALSE;       /* whether MDC ci load requested */
1792     hbool_t            ci_write         = FALSE;       /* whether MDC CI write requested */
1793     H5F_t *            ret_value        = NULL;        /*actual return value           */
1794 
1795     FUNC_ENTER_NOAPI(NULL)
1796 
1797     /*
1798      * If the driver has a 'cmp' method then the driver is capable of
1799      * determining when two file handles refer to the same file and the
1800      * library can insure that when the application opens a file twice
1801      * that the two handles coordinate their operations appropriately.
1802      * Otherwise it is the application's responsibility to never open the
1803      * same file more than once at a time.
1804      */
1805     if (NULL == (drvr = H5FD_get_class(fapl_id)))
1806         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to retrieve VFL class")
1807 
1808     /* Get the file access property list, for future queries */
1809     if (NULL == (a_plist = (H5P_genplist_t *)H5I_object(fapl_id)))
1810         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not file access property list")
1811 
1812     /* Check if we are using file locking */
1813     if (H5F__check_if_using_file_locks(a_plist, &use_file_locking) < 0)
1814         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "unable to get file locking flag")
1815 
1816     /*
1817      * Opening a file is a two step process. First we try to open the
1818      * file in a way which doesn't affect its state (like not truncating
1819      * or creating it) so we can compare it with files that are already
1820      * open. If that fails then we try again with the full set of flags
1821      * (only if they're different than the original failed attempt).
1822      * However, if the file driver can't distinquish between files then
1823      * there's no reason to open the file tentatively because it's the
1824      * application's responsibility to prevent this situation (there's no
1825      * way for us to detect it here anyway).
1826      */
1827     if (drvr->cmp)
1828         tent_flags = flags & ~(H5F_ACC_CREAT | H5F_ACC_TRUNC | H5F_ACC_EXCL);
1829     else
1830         tent_flags = flags;
1831 
1832     if (NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) {
1833         if (tent_flags == flags)
1834             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x",
1835                         name, tent_flags)
1836         H5E_clear_stack(NULL);
1837         tent_flags = flags;
1838         if (NULL == (lf = H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF)))
1839             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', tent_flags = %x",
1840                         name, tent_flags)
1841     } /* end if */
1842 
1843     /* Is the file already open? */
1844     if ((shared = H5F__sfile_search(lf)) != NULL) {
1845         /*
1846          * The file is already open, so use that one instead of the one we
1847          * just opened. We only one one H5FD_t* per file so one doesn't
1848          * confuse the other.  But fail if this request was to truncate the
1849          * file (since we can't do that while the file is open), or if the
1850          * request was to create a non-existent file (since the file already
1851          * exists), or if the new request adds write access (since the
1852          * readers don't expect the file to change under them), or if the
1853          * SWMR write/read access flags don't agree.
1854          */
1855         if (H5FD_close(lf) < 0)
1856             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
1857         if (flags & H5F_ACC_TRUNC)
1858             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to truncate a file which is already open")
1859         if (flags & H5F_ACC_EXCL)
1860             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
1861         if ((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
1862             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
1863 
1864         if ((flags & H5F_ACC_SWMR_WRITE) && 0 == (shared->flags & H5F_ACC_SWMR_WRITE))
1865             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
1866                         "SWMR write access flag not the same for file that is already open")
1867         if ((flags & H5F_ACC_SWMR_READ) &&
1868             !((shared->flags & H5F_ACC_SWMR_WRITE) || (shared->flags & H5F_ACC_SWMR_READ) ||
1869               (shared->flags & H5F_ACC_RDWR)))
1870             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
1871                         "SWMR read access flag not the same for file that is already open")
1872 
1873         /* Allocate new "high-level" file struct */
1874         if ((file = H5F__new(shared, flags, fcpl_id, fapl_id, NULL)) == NULL)
1875             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create new file object")
1876     } /* end if */
1877     else {
1878         /* Check if tentative open was good enough */
1879         if (flags != tent_flags) {
1880             /*
1881              * This file is not yet open by the library and the flags we used to
1882              * open it are different than the desired flags. Close the tentative
1883              * file and open it for real.
1884              */
1885             if (H5FD_close(lf) < 0)
1886                 HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
1887 
1888             if (NULL == (lf = H5FD_open(name, flags, fapl_id, HADDR_UNDEF)))
1889                 HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
1890         } /* end if */
1891 
1892         /* Place an advisory lock on the file */
1893         if (use_file_locking)
1894             if (H5FD_lock(lf, (hbool_t)((flags & H5F_ACC_RDWR) ? TRUE : FALSE)) < 0) {
1895                 /* Locking failed - Closing will remove the lock */
1896                 if (H5FD_close(lf) < 0)
1897                     HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "unable to close low-level file info")
1898                 HGOTO_ERROR(H5E_FILE, H5E_CANTLOCKFILE, NULL, "unable to lock the file")
1899             } /* end if */
1900 
1901         /* Create the 'top' file structure */
1902         if (NULL == (file = H5F__new(NULL, flags, fcpl_id, fapl_id, lf))) {
1903             /* If this is the only time the file has been opened and the struct
1904              * returned is NULL, H5FD_close() will never be called via H5F__dest()
1905              * so we have to close lf here before heading to the error handling.
1906              */
1907             if (H5FD_close(lf) < 0)
1908                 HDONE_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
1909             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to initialize file structure")
1910         } /* end if */
1911 
1912         /* Need to set status_flags in the superblock if the driver has a 'lock' method */
1913         if (drvr->lock)
1914             set_flag = TRUE;
1915     } /* end else */
1916 
1917     /* Check to see if both SWMR and cache image are requested.  Fail if so */
1918     if (H5C_cache_image_status(file, &ci_load, &ci_write) < 0)
1919         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get MDC cache image status")
1920     if ((ci_load || ci_write) && (flags & (H5F_ACC_SWMR_READ | H5F_ACC_SWMR_WRITE)))
1921         HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, NULL, "can't have both SWMR and cache image")
1922 
1923     /* Retain the name the file was opened with */
1924     file->open_name = H5MM_xstrdup(name);
1925 
1926     /* Short cuts */
1927     shared = file->shared;
1928     lf     = shared->lf;
1929 
1930     /* Set the file locking flag. If the file is already open, the file
1931      * requested file locking flag must match that of the open file.
1932      */
1933     if (shared->nrefs == 1)
1934         file->shared->use_file_locking = use_file_locking;
1935     else if (shared->nrefs > 1)
1936         if (file->shared->use_file_locking != use_file_locking)
1937             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file locking flag values don't match")
1938 
1939     /* Check if page buffering is enabled */
1940     if (H5P_get(a_plist, H5F_ACS_PAGE_BUFFER_SIZE_NAME, &page_buf_size) < 0)
1941         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get page buffer size")
1942     if (page_buf_size) {
1943 #ifdef H5_HAVE_PARALLEL
1944         /* Collective metadata writes are not supported with page buffering */
1945         if (file->shared->coll_md_write)
1946             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
1947                         "collective metadata writes are not supported with page buffering")
1948 
1949         /* Temporary: fail file create when page buffering feature is enabled for parallel */
1950         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "page buffering is disabled for parallel")
1951 #endif /* H5_HAVE_PARALLEL */
1952         /* Query for other page buffer cache properties */
1953         if (H5P_get(a_plist, H5F_ACS_PAGE_BUFFER_MIN_META_PERC_NAME, &page_buf_min_meta_perc) < 0)
1954             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get minimum metadata fraction of page buffer")
1955         if (H5P_get(a_plist, H5F_ACS_PAGE_BUFFER_MIN_RAW_PERC_NAME, &page_buf_min_raw_perc) < 0)
1956             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, NULL, "can't get minimum raw data fraction of page buffer")
1957     } /* end if */
1958 
1959     /*
1960      * Read or write the file superblock, depending on whether the file is
1961      * empty or not.
1962      */
1963     if (0 == (MAX(H5FD_get_eof(lf, H5FD_MEM_SUPER), H5FD_get_eoa(lf, H5FD_MEM_SUPER))) &&
1964         (flags & H5F_ACC_RDWR)) {
1965         /*
1966          * We've just opened a fresh new file (or truncated one). We need
1967          * to create & write the superblock.
1968          */
1969 
1970         /* Create the page buffer before initializing the superblock */
1971         if (page_buf_size)
1972             if (H5PB_create(shared, page_buf_size, page_buf_min_meta_perc, page_buf_min_raw_perc) < 0)
1973                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create page buffer")
1974 
1975         /* Initialize information about the superblock and allocate space for it */
1976         /* (Writes superblock extension messages, if there are any) */
1977         if (H5F__super_init(file) < 0)
1978             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to allocate file superblock")
1979 
1980         /* Create and open the root group */
1981         /* (This must be after the space for the superblock is allocated in
1982          *      the file, since the superblock must be at offset 0)
1983          */
1984         if (H5G_mkroot(file, TRUE) < 0)
1985             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
1986     } /* end if */
1987     else if (1 == shared->nrefs) {
1988         /* Read the superblock if it hasn't been read before. */
1989         if (H5F__super_read(file, a_plist, TRUE) < 0)
1990             HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
1991 
1992         /* Create the page buffer before initializing the superblock */
1993         if (page_buf_size)
1994             if (H5PB_create(shared, page_buf_size, page_buf_min_meta_perc, page_buf_min_raw_perc) < 0)
1995                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create page buffer")
1996 
1997         /* Open the root group */
1998         if (H5G_mkroot(file, FALSE) < 0)
1999             HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
2000     } /* end if */
2001 
2002     /*
2003      * Decide the file close degree.  If it's the first time to open the
2004      * file, set the degree to access property list value; if it's the
2005      * second time or later, verify the access property list value matches
2006      * the degree in shared file structure.
2007      */
2008     if (H5P_get(a_plist, H5F_ACS_CLOSE_DEGREE_NAME, &fc_degree) < 0)
2009         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get file close degree")
2010     if (shared->nrefs == 1) {
2011         if (fc_degree == H5F_CLOSE_DEFAULT)
2012             shared->fc_degree = lf->cls->fc_degree;
2013         else
2014             shared->fc_degree = fc_degree;
2015     } /* end if */
2016     else if (shared->nrefs > 1) {
2017         if (fc_degree == H5F_CLOSE_DEFAULT && shared->fc_degree != lf->cls->fc_degree)
2018             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
2019         if (fc_degree != H5F_CLOSE_DEFAULT && fc_degree != shared->fc_degree)
2020             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "file close degree doesn't match")
2021     } /* end if */
2022 
2023     /* This is a private property to clear the status_flags in the super block */
2024     /* Use by h5clear and a routine in test/flush2.c to clear the test file's status_flags */
2025     if (H5P_exist_plist(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME) > 0) {
2026         if (H5P_get(a_plist, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
2027             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get clearance for status_flags")
2028         else if (clear)
2029             file->shared->sblock->status_flags = 0;
2030     } /* end if */
2031 
2032     /* Record the evict-on-close MDC behavior.  If it's the first time opening
2033      * the file, set it to access property list value; if it's the second time
2034      * or later, verify that the access property list value matches the value
2035      * in shared file structure.
2036      */
2037     if (H5P_get(a_plist, H5F_ACS_EVICT_ON_CLOSE_FLAG_NAME, &evict_on_close) < 0)
2038         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't get evict on close value")
2039     if (shared->nrefs == 1)
2040         shared->evict_on_close = evict_on_close;
2041     else if (shared->nrefs > 1) {
2042         if (shared->evict_on_close != evict_on_close)
2043             HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, NULL, "file evict-on-close value doesn't match")
2044     } /* end if */
2045 
2046     /* Formulate the absolute path for later search of target file for external links */
2047     if (shared->nrefs == 1) {
2048         if (H5_build_extpath(name, &file->shared->extpath) < 0)
2049             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build extpath")
2050     }
2051 
2052     /* Formulate the actual file name, after following symlinks, etc. */
2053     if (H5F__build_actual_name(file, a_plist, name, &file->actual_name) < 0)
2054         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to build actual name")
2055 
2056     if (set_flag) {
2057         if (H5F_INTENT(file) & H5F_ACC_RDWR) { /* Set and check consistency of status_flags */
2058             /* Skip check of status_flags for file with < superblock version 3 */
2059             if (file->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_3) {
2060 
2061                 if (file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS ||
2062                     file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS)
2063                     HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
2064                                 "file is already open for write/SWMR write (may use <h5clear file> to clear "
2065                                 "file consistency flags)")
2066             } /* version 3 superblock */
2067 
2068             file->shared->sblock->status_flags |= H5F_SUPER_WRITE_ACCESS;
2069             if (H5F_INTENT(file) & H5F_ACC_SWMR_WRITE)
2070                 file->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS;
2071 
2072             /* Flush the superblock & superblock extension */
2073             if (H5F_super_dirty(file) < 0)
2074                 HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, NULL, "unable to mark superblock as dirty")
2075             if (H5F_flush_tagged_metadata(file, H5AC__SUPERBLOCK_TAG) < 0)
2076                 HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, NULL, "unable to flush superblock")
2077             if (H5F_flush_tagged_metadata(file, file->shared->sblock->ext_addr) < 0)
2078                 HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, NULL, "unable to flush superblock extension")
2079 
2080             /* Remove the file lock for SWMR_WRITE */
2081             if (use_file_locking && (H5F_INTENT(file) & H5F_ACC_SWMR_WRITE)) {
2082                 if (H5FD_unlock(file->shared->lf) < 0)
2083                     HGOTO_ERROR(H5E_FILE, H5E_CANTUNLOCKFILE, NULL, "unable to unlock the file")
2084             }  /* end if */
2085         }      /* end if */
2086         else { /* H5F_ACC_RDONLY: check consistency of status_flags */
2087             /* Skip check of status_flags for file with < superblock version 3 */
2088             if (file->shared->sblock->super_vers >= HDF5_SUPERBLOCK_VERSION_3) {
2089                 if (H5F_INTENT(file) & H5F_ACC_SWMR_READ) {
2090                     if ((file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS &&
2091                          !(file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS)) ||
2092                         (!(file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS) &&
2093                          file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS))
2094                         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
2095                                     "file is not already open for SWMR writing")
2096                 } /* end if */
2097                 else if ((file->shared->sblock->status_flags & H5F_SUPER_WRITE_ACCESS) ||
2098                          (file->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS))
2099                     HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL,
2100                                 "file is already open for write (may use <h5clear file> to clear file "
2101                                 "consistency flags)")
2102             } /* version 3 superblock */
2103         }     /* end else */
2104     }         /* end if set_flag */
2105 
2106     /* Success */
2107     ret_value = file;
2108 
2109 done:
2110     if ((NULL == ret_value) && file)
2111         if (H5F__dest(file, FALSE) < 0)
2112             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
2113 
2114     FUNC_LEAVE_NOAPI(ret_value)
2115 } /* end H5F_open() */
2116 
2117 /*-------------------------------------------------------------------------
2118  * Function:    H5F__post_open
2119  *
2120  * Purpose:     Finishes file open after wrapper context for file has been
2121  *              set.
2122  *
2123  * Return:      SUCCEED/FAIL
2124  *
2125  *-------------------------------------------------------------------------
2126  */
2127 herr_t
H5F__post_open(H5F_t * f)2128 H5F__post_open(H5F_t *f)
2129 {
2130     herr_t ret_value = SUCCEED; /* Return value */
2131 
2132     FUNC_ENTER_PACKAGE
2133 
2134     /* Sanity check arguments */
2135     HDassert(f);
2136 
2137     /* Store a vol object in the file struct */
2138     if (NULL == (f->vol_obj = H5VL_create_object_using_vol_id(H5I_FILE, f, f->shared->vol_id)))
2139         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't create VOL object")
2140 
2141 done:
2142     FUNC_LEAVE_NOAPI(ret_value)
2143 } /* end H5F__post_open() */
2144 
2145 /*-------------------------------------------------------------------------
2146  * Function:    H5F_flush_phase1
2147  *
2148  * Purpose:     First phase of flushing cached data.
2149  *
2150  * Return:      SUCCEED/FAIL
2151  *
2152  *-------------------------------------------------------------------------
2153  */
2154 static herr_t
H5F__flush_phase1(H5F_t * f)2155 H5F__flush_phase1(H5F_t *f)
2156 {
2157     herr_t ret_value = SUCCEED; /* Return value */
2158 
2159     FUNC_ENTER_STATIC
2160 
2161     /* Sanity check arguments */
2162     HDassert(f);
2163 
2164     /* Flush any cached dataset storage raw data */
2165     if (H5D_flush_all(f) < 0)
2166         /* Push error, but keep going*/
2167         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache")
2168 
2169     /* Release any space allocated to space aggregators, so that the eoa value
2170      *  corresponds to the end of the space written to in the file.
2171      */
2172     /* (needs to happen before cache flush, with superblock write, since the
2173      *  'eoa' value is written in superblock -QAK)
2174      */
2175     if (H5MF_free_aggrs(f) < 0)
2176         /* Push error, but keep going*/
2177         HDONE_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release file space")
2178 
2179     FUNC_LEAVE_NOAPI(ret_value)
2180 } /* end H5F__flush_phase1() */
2181 
2182 /*-------------------------------------------------------------------------
2183  * Function:    H5F__flush_phase2
2184  *
2185  * Purpose:     Second phase of flushing cached data.
2186  *
2187  * Return:      SUCCEED/FAIL
2188  *
2189  *-------------------------------------------------------------------------
2190  */
2191 static herr_t
H5F__flush_phase2(H5F_t * f,hbool_t closing)2192 H5F__flush_phase2(H5F_t *f, hbool_t closing)
2193 {
2194     herr_t ret_value = SUCCEED; /* Return value */
2195 
2196     FUNC_ENTER_STATIC
2197 
2198     /* Sanity check arguments */
2199     HDassert(f);
2200 
2201     /* Inform the metadata cache that we are about to flush */
2202     if (H5AC_prep_for_file_flush(f) < 0)
2203         /* Push error, but keep going*/
2204         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "prep for MDC flush failed")
2205 
2206     /* Flush the entire metadata cache */
2207     if (H5AC_flush(f) < 0)
2208         /* Push error, but keep going*/
2209         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
2210 
2211 #ifdef H5_HAVE_PARALLEL
2212     if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI)) {
2213         /* Since we just returned from a call to H5AC_flush(), we just
2214          * passed through a barrier.  Hence we can skip the barrier on
2215          * entry to the mpio file driver truncate call below, and the first
2216          * barrier in the following call to flush the cache again.
2217          */
2218         H5CX_set_mpi_file_flushing(TRUE);
2219     }
2220 #endif /* H5_HAVE_PARALLEL */
2221 
2222     /* Truncate the file to the current allocated size */
2223     if (H5FD_truncate(f->shared->lf, closing) < 0)
2224         /* Push error, but keep going*/
2225         HDONE_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "low level truncate failed")
2226 
2227     /* Flush the entire metadata cache again since the EOA could have changed in the truncate call. */
2228     if (H5AC_flush(f) < 0)
2229         /* Push error, but keep going*/
2230         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush metadata cache")
2231 
2232 #ifdef H5_HAVE_PARALLEL
2233     if (H5F_HAS_FEATURE(f, H5FD_FEAT_HAS_MPI))
2234         /* Reset the "flushing the file" flag */
2235         H5CX_set_mpi_file_flushing(FALSE);
2236 #endif /* H5_HAVE_PARALLEL */
2237 
2238     /* Inform the metadata cache that we are done with the flush */
2239     if (H5AC_secure_from_file_flush(f) < 0)
2240         /* Push error, but keep going*/
2241         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "secure from MDC flush failed")
2242 
2243     /* Flush out the metadata accumulator */
2244     if (H5F__accum_flush(f->shared) < 0)
2245         /* Push error, but keep going*/
2246         HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush metadata accumulator")
2247 
2248     /* Flush the page buffer */
2249     if (H5PB_flush(f->shared) < 0)
2250         /* Push error, but keep going*/
2251         HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "page buffer flush failed")
2252 
2253     /* Flush file buffers to disk. */
2254     if (H5FD_flush(f->shared->lf, closing) < 0)
2255         /* Push error, but keep going*/
2256         HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "low level flush failed")
2257 
2258     FUNC_LEAVE_NOAPI(ret_value)
2259 } /* end H5F__flush_phase2() */
2260 
2261 /*-------------------------------------------------------------------------
2262  * Function:    H5F__flush
2263  *
2264  * Purpose:     Flushes cached data.
2265  *
2266  * Return:      SUCCEED/FAIL
2267  *
2268  *-------------------------------------------------------------------------
2269  */
2270 herr_t
H5F__flush(H5F_t * f)2271 H5F__flush(H5F_t *f)
2272 {
2273     herr_t ret_value = SUCCEED; /* Return value */
2274 
2275     FUNC_ENTER_PACKAGE
2276 
2277     /* Sanity check arguments */
2278     HDassert(f);
2279 
2280     /* First phase of flushing data */
2281     if (H5F__flush_phase1(f) < 0)
2282         /* Push error, but keep going*/
2283         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data")
2284 
2285     /* Second phase of flushing data */
2286     if (H5F__flush_phase2(f, FALSE) < 0)
2287         /* Push error, but keep going*/
2288         HDONE_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush file data")
2289 
2290     FUNC_LEAVE_NOAPI(ret_value)
2291 } /* end H5F__flush() */
2292 
2293 /*-------------------------------------------------------------------------
2294  * Function:    H5F__close
2295  *
2296  * Purpose:     Closes a file or causes the close operation to be pended.
2297  *              This function is called two ways: from the API it gets called
2298  *              by H5Fclose->H5I_dec_ref->H5F__close when H5I_dec_ref()
2299  *              decrements the file ID reference count to zero.  The file ID
2300  *              is removed from the H5I_FILE group by H5I_dec_ref() just
2301  *              before H5F__close() is called. If there are open object
2302  *              headers then the close is pended by moving the file to the
2303  *              H5I_FILE_CLOSING ID group (the f->closing contains the ID
2304  *              assigned to file).
2305  *
2306  *              This function is also called directly from H5O_close() when
2307  *              the last object header is closed for the file and the file
2308  *              has a pending close.
2309  *
2310  * Return:      SUCCEED/FAIL
2311  *
2312  *-------------------------------------------------------------------------
2313  */
2314 herr_t
H5F__close(H5F_t * f)2315 H5F__close(H5F_t *f)
2316 {
2317     herr_t ret_value = SUCCEED; /* Return value */
2318 
2319     FUNC_ENTER_PACKAGE
2320 
2321     /* Sanity check */
2322     HDassert(f);
2323 
2324     /* Perform checks for "semi" file close degree here, since closing the
2325      * file is not allowed if there are objects still open.
2326      */
2327     if (f->shared->fc_degree == H5F_CLOSE_SEMI) {
2328         unsigned nopen_files = 0; /* Number of open files in file/mount hierarchy */
2329         unsigned nopen_objs  = 0; /* Number of open objects in file/mount hierarchy */
2330 
2331         /* Get the number of open objects and open files on this file/mount hierarchy */
2332         if (H5F__mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
2333             HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
2334 
2335         /* If there are no other file IDs open on this file/mount hier., but
2336          * there are still open objects, issue an error and bail out now,
2337          * without decrementing the file ID's reference count and triggering
2338          * a "real" attempt at closing the file.
2339          */
2340         if (nopen_files == 1 && nopen_objs > 0)
2341             HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, there are objects still open")
2342     }
2343 
2344     /* Reset the file ID for this file */
2345     f->id_exists = FALSE;
2346 
2347     /* Attempt to close the file/mount hierarchy */
2348     if (H5F_try_close(f, NULL) < 0)
2349         HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
2350 
2351 done:
2352     FUNC_LEAVE_NOAPI(ret_value)
2353 } /* end H5F__close() */
2354 
2355 /*-------------------------------------------------------------------------
2356  * Function:    H5F_try_close
2357  *
2358  * Purpose:     Attempts to close a file due to one of several actions:
2359  *              - The reference count on the file ID dropped to zero
2360  *              - The last open object was closed in the file
2361  *              - The file was unmounted
2362  *
2363  * Return:      SUCCEED/FAIL
2364  *
2365  *-------------------------------------------------------------------------
2366  */
2367 herr_t
H5F_try_close(H5F_t * f,hbool_t * was_closed)2368 H5F_try_close(H5F_t *f, hbool_t *was_closed /*out*/)
2369 {
2370     unsigned nopen_files = 0;       /* Number of open files in file/mount hierarchy */
2371     unsigned nopen_objs  = 0;       /* Number of open objects in file/mount hierarchy */
2372     herr_t   ret_value   = SUCCEED; /* Return value */
2373 
2374     FUNC_ENTER_NOAPI_NOINIT
2375 
2376     /* Sanity check */
2377     HDassert(f);
2378     HDassert(f->shared);
2379 
2380     /* Set the was_closed flag to the default value.
2381      * This flag lets downstream code know if the file struct is
2382      * still accessible and/or likely to contain useful data.
2383      * It's needed by the evict-on-close code. Clients can ignore
2384      * this value by passing in NULL.
2385      */
2386     if (was_closed)
2387         *was_closed = FALSE;
2388 
2389     /* Check if this file is already in the process of closing */
2390     if (f->closing) {
2391         if (was_closed)
2392             *was_closed = TRUE;
2393         HGOTO_DONE(SUCCEED)
2394     }
2395 
2396     /* Get the number of open objects and open files on this file/mount hierarchy */
2397     if (H5F__mount_count_ids(f, &nopen_files, &nopen_objs) < 0)
2398         HGOTO_ERROR(H5E_SYM, H5E_MOUNT, FAIL, "problem checking mount hierarchy")
2399 
2400     /*
2401      * Close file according to close degree:
2402      *
2403      *  H5F_CLOSE_WEAK:    if there are still objects open, wait until
2404      *            they are all closed.
2405      *  H5F_CLOSE_SEMI:    if there are still objects open, return fail;
2406      *            otherwise, close file.
2407      *  H5F_CLOSE_STRONG:    if there are still objects open, close them
2408      *            first, then close file.
2409      */
2410     switch (f->shared->fc_degree) {
2411         case H5F_CLOSE_WEAK:
2412             /*
2413              * If file or object IDS are still open then delay deletion of
2414              * resources until they have all been closed.  Flush all
2415              * caches and update the object header anyway so that failing to
2416              * close all objects isn't a major problem.
2417              */
2418             if ((nopen_files + nopen_objs) > 0)
2419                 HGOTO_DONE(SUCCEED)
2420             break;
2421 
2422         case H5F_CLOSE_SEMI:
2423             /* Can leave safely if file IDs are still open on this file */
2424             if (nopen_files > 0)
2425                 HGOTO_DONE(SUCCEED)
2426 
2427             /* Sanity check: If close degree if "semi" and we have gotten this
2428              * far and there are objects left open, bail out now.
2429              */
2430             HDassert(nopen_files == 0 && nopen_objs == 0);
2431 
2432             /* If we've gotten this far (ie. there are no open objects in the file), fall through to flush &
2433              * close */
2434             break;
2435 
2436         case H5F_CLOSE_STRONG:
2437             /* If there are other open files in the hierarchy, we can leave now */
2438             if (nopen_files > 0)
2439                 HGOTO_DONE(SUCCEED)
2440 
2441             /* If we've gotten this far (ie. there are no open file IDs in the file/mount hierarchy), fall
2442              * through to flush & close */
2443             break;
2444 
2445         case H5F_CLOSE_DEFAULT:
2446         default:
2447             HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file, unknown file close degree")
2448     } /* end switch */
2449 
2450     /* Mark this file as closing (prevents re-entering file shutdown code below) */
2451     f->closing = TRUE;
2452 
2453     /* If the file close degree is "strong", close all the open objects in this file */
2454     if (f->shared->fc_degree == H5F_CLOSE_STRONG) {
2455         HDassert(nopen_files == 0);
2456 
2457         /* Forced close of all opened objects in this file */
2458         if (f->nopen_objs > 0) {
2459             size_t obj_count; /* # of open objects */
2460             hid_t  objs[128]; /* Array of objects to close */
2461             herr_t result;    /* Local result from obj ID query */
2462             size_t u;         /* Local index variable */
2463 
2464             /* Get the list of IDs of open dataset, group, & attribute objects */
2465             while ((result = H5F_get_obj_ids(
2466                         f, H5F_OBJ_LOCAL | H5F_OBJ_DATASET | H5F_OBJ_GROUP | H5F_OBJ_ATTR,
2467                         (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE, &obj_count)) <= 0 &&
2468                    obj_count != 0) {
2469 
2470                 /* Try to close all the open objects in this file */
2471                 for (u = 0; u < obj_count; u++)
2472                     if (H5I_dec_ref(objs[u]) < 0)
2473                         HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
2474             }
2475             if (result < 0)
2476                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(1)")
2477 
2478             /* Get the list of IDs of open named datatype objects */
2479             /* (Do this separately from the dataset & attribute IDs, because
2480              * they could be using one of the named datatypes and then the
2481              * open named datatype ID will get closed twice)
2482              */
2483             while ((result = H5F_get_obj_ids(f, H5F_OBJ_LOCAL | H5F_OBJ_DATATYPE,
2484                                              (int)(sizeof(objs) / sizeof(objs[0])), objs, FALSE,
2485                                              &obj_count)) <= 0 &&
2486                    obj_count != 0) {
2487 
2488                 /* Try to close all the open objects in this file */
2489                 for (u = 0; u < obj_count; u++)
2490                     if (H5I_dec_ref(objs[u]) < 0)
2491                         HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't close object")
2492             }
2493             if (result < 0)
2494                 HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "H5F_get_obj_ids failed(2)")
2495         } /* end if */
2496     }     /* end if */
2497 
2498     /* Check if this is a child file in a mounting hierarchy & proceed up the
2499      * hierarchy if so.
2500      */
2501     if (f->parent)
2502         if (H5F_try_close(f->parent, NULL) < 0)
2503             HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close parent file")
2504 
2505     /* Unmount and close each child before closing the current file. */
2506     if (H5F__close_mounts(f) < 0)
2507         HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't unmount child files")
2508 
2509     /* If there is more than one reference to the shared file struct and the
2510      * file has an external file cache, we should see if it can be closed.  This
2511      * can happen if a cycle is formed with external file caches.
2512      */
2513     if (f->shared->efc && (f->shared->nrefs > 1))
2514         if (H5F__efc_try_close(f) < 0)
2515             HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't attempt to close EFC")
2516 
2517     /* Destroy the H5F_t struct and decrement the reference count for the
2518      * shared H5F_shared_t struct. If the reference count for the H5F_shared_t
2519      * struct reaches zero then destroy it also.
2520      */
2521     if (H5F__dest(f, TRUE) < 0)
2522         HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "problems closing file")
2523 
2524     /* Since we closed the file, this should be set to TRUE */
2525     if (was_closed)
2526         *was_closed = TRUE;
2527 done:
2528     FUNC_LEAVE_NOAPI(ret_value)
2529 } /* end H5F_try_close() */
2530 
2531 /*-------------------------------------------------------------------------
2532  * Function:    H5F__reopen
2533  *
2534  * Purpose:     Reopen a file.  The new file handle which is returned points
2535  *		        to the same file as the specified file handle.  Both handles
2536  *		        share caches and other information.  The only difference
2537  *		        between the handles is that the new handle is not mounted
2538  *		        anywhere and no files are mounted on it.
2539  *
2540  * Return:      Success:    A pointer to a file struct
2541  *
2542  *              Failure:    NULL
2543  *
2544  *-------------------------------------------------------------------------
2545  */
2546 H5F_t *
H5F__reopen(H5F_t * f)2547 H5F__reopen(H5F_t *f)
2548 {
2549     H5F_t *ret_value = NULL; /* Return value */
2550 
2551     FUNC_ENTER_PACKAGE
2552 
2553     /* Get a new "top level" file struct, sharing the same "low level" file struct */
2554     if (NULL == (ret_value = H5F__new(f->shared, 0, H5P_FILE_CREATE_DEFAULT, H5P_FILE_ACCESS_DEFAULT, NULL)))
2555         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to reopen file")
2556 
2557     /* Duplicate old file's names */
2558     ret_value->open_name   = H5MM_xstrdup(f->open_name);
2559     ret_value->actual_name = H5MM_xstrdup(f->actual_name);
2560 
2561 done:
2562     FUNC_LEAVE_NOAPI(ret_value)
2563 } /* end H5F__reopen() */
2564 
2565 /*-------------------------------------------------------------------------
2566  * Function:    H5F_get_id
2567  *
2568  * Purpose:     Get the file ID, incrementing it, or "resurrecting" it as
2569  *              appropriate.
2570  *
2571  * Return:      Success:    An ID for a file
2572  *
2573  *              Failure:    H5I_INVALID_HID
2574  *
2575  *-------------------------------------------------------------------------
2576  */
2577 hid_t
H5F_get_id(H5F_t * file)2578 H5F_get_id(H5F_t *file)
2579 {
2580     hid_t ret_value = H5I_INVALID_HID; /* Return value */
2581 
2582     FUNC_ENTER_NOAPI_NOINIT
2583 
2584     HDassert(file);
2585 
2586     if (H5I_find_id(file, H5I_FILE, &ret_value) < 0 || H5I_INVALID_HID == ret_value) {
2587         /* resurrect the ID - Register an ID with the native connector */
2588         if ((ret_value = H5VL_wrap_register(H5I_FILE, file, FALSE)) < 0)
2589             HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register group")
2590         file->id_exists = TRUE;
2591     }
2592     else {
2593         /* Increment reference count on existing ID */
2594         if (H5I_inc_ref(ret_value, FALSE) < 0)
2595             HGOTO_ERROR(H5E_ATOM, H5E_CANTINC, H5I_INVALID_HID, "incrementing file ID failed")
2596     } /* end else */
2597 
2598 done:
2599     FUNC_LEAVE_NOAPI(ret_value)
2600 } /* end H5F_get_id() */
2601 
2602 /*-------------------------------------------------------------------------
2603  * Function:    H5F_incr_nopen_objs
2604  *
2605  * Purpose:     Increment the number of open objects for a file.
2606  *
2607  * Return:      Success:    The number of open objects, after the increment
2608  *              Failure:    (can't happen)
2609  *-------------------------------------------------------------------------
2610  */
2611 unsigned
H5F_incr_nopen_objs(H5F_t * f)2612 H5F_incr_nopen_objs(H5F_t *f)
2613 {
2614     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2615     FUNC_ENTER_NOAPI_NOINIT_NOERR
2616 
2617     HDassert(f);
2618 
2619     FUNC_LEAVE_NOAPI(++f->nopen_objs)
2620 } /* end H5F_incr_nopen_objs() */
2621 
2622 /*-------------------------------------------------------------------------
2623  * Function:    H5F_decr_nopen_objs
2624  *
2625  * Purpose:     Decrement the number of open objects for a file.
2626  *
2627  * Return:      Success:    The number of open objects, after the decrement
2628  *              Failure:    (can't happen)
2629  *-------------------------------------------------------------------------
2630  */
2631 unsigned
H5F_decr_nopen_objs(H5F_t * f)2632 H5F_decr_nopen_objs(H5F_t *f)
2633 {
2634     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2635     FUNC_ENTER_NOAPI_NOINIT_NOERR
2636 
2637     HDassert(f);
2638 
2639     FUNC_LEAVE_NOAPI(--f->nopen_objs)
2640 } /* end H5F_decr_nopen_objs() */
2641 
2642 /*-------------------------------------------------------------------------
2643  * Function:    H5F__build_actual_name
2644  *
2645  * Purpose:     Retrieve the name of a file, after following symlinks, etc.
2646  *
2647  * Note:        Currently only working for "POSIX I/O compatible" VFDs
2648  *
2649  * Return:      SUCCEED/FAIL
2650  *-------------------------------------------------------------------------
2651  */
2652 static herr_t
H5F__build_actual_name(const H5F_t * f,const H5P_genplist_t * fapl,const char * name,char ** actual_name)2653 H5F__build_actual_name(const H5F_t *f, const H5P_genplist_t *fapl, const char *name,
2654                        char **actual_name /*out*/)
2655 {
2656     hid_t new_fapl_id = H5I_INVALID_HID; /* ID for duplicated FAPL */
2657 #ifdef H5_HAVE_SYMLINK
2658     /* This has to be declared here to avoid unfreed resources on errors */
2659     char *realname = NULL;      /* Fully resolved path name of file */
2660 #endif                          /* H5_HAVE_SYMLINK */
2661     herr_t ret_value = SUCCEED; /* Return value */
2662 
2663     FUNC_ENTER_STATIC
2664 
2665     /* Sanity check */
2666     HDassert(f);
2667     HDassert(fapl);
2668     HDassert(name);
2669     HDassert(actual_name);
2670 
2671     /* Clear actual name pointer to begin with */
2672     *actual_name = NULL;
2673 
2674 /* Assume that if the OS can't create symlinks, that we don't need to worry
2675  *      about resolving them either. -QAK
2676  */
2677 #ifdef H5_HAVE_SYMLINK
2678     /* Check for POSIX I/O compatible file handle */
2679     if (H5F_HAS_FEATURE(f, H5FD_FEAT_POSIX_COMPAT_HANDLE)) {
2680         h5_stat_t lst; /* Stat info from lstat() call */
2681 
2682         /* Call lstat() on the file's name */
2683         if (HDlstat(name, &lst) < 0)
2684             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stat info for file")
2685 
2686         /* Check for symbolic link */
2687         if (S_IFLNK == (lst.st_mode & S_IFMT)) {
2688             H5P_genplist_t *new_fapl;      /* Duplicated FAPL */
2689             int *           fd;            /* POSIX I/O file descriptor */
2690             h5_stat_t       st;            /* Stat info from stat() call */
2691             h5_stat_t       fst;           /* Stat info from fstat() call */
2692             hbool_t         want_posix_fd; /* Flag for retrieving file descriptor from VFD */
2693 
2694             /* Allocate realname buffer */
2695             if (NULL == (realname = (char *)H5MM_calloc((size_t)PATH_MAX * sizeof(char))))
2696                 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
2697 
2698             /* Perform a sanity check that the file or link wasn't switched
2699              * between when we opened it and when we called lstat().  This is
2700              * according to the security best practices for lstat() documented
2701              * here:
2702              * https://www.securecoding.cert.org/confluence/display/seccode/POS35-C.+Avoid+race+conditions+while+checking+for+the+existence+of+a+symbolic+link
2703              */
2704 
2705             /* Copy the FAPL object to modify */
2706             if ((new_fapl_id = H5P_copy_plist(fapl, FALSE)) < 0)
2707                 HGOTO_ERROR(H5E_FILE, H5E_CANTCOPY, FAIL, "unable to copy file access property list")
2708             if (NULL == (new_fapl = (H5P_genplist_t *)H5I_object(new_fapl_id)))
2709                 HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL, "can't get property list")
2710 
2711             /* Set the character encoding on the new property list */
2712             want_posix_fd = TRUE;
2713             if (H5P_set(new_fapl, H5F_ACS_WANT_POSIX_FD_NAME, &want_posix_fd) < 0)
2714                 HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set character encoding")
2715 
2716             /* Retrieve the file handle */
2717             if (H5F_get_vfd_handle(f, new_fapl_id, (void **)&fd) < 0)
2718                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve POSIX file descriptor")
2719 
2720             /* Stat the filename we're resolving */
2721             if (HDstat(name, &st) < 0)
2722                 HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to stat file")
2723 
2724             /* Stat the file we opened */
2725             if (HDfstat(*fd, &fst) < 0)
2726                 HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, "unable to fstat file")
2727 
2728             /* Verify that the files are really the same */
2729             if (st.st_mode != fst.st_mode || st.st_ino != fst.st_ino || st.st_dev != fst.st_dev)
2730                 HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "files' st_ino or st_dev fields changed!")
2731 
2732             /* Get the resolved path for the file name */
2733             if (NULL == HDrealpath(name, realname))
2734                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve real path for file")
2735 
2736             /* Duplicate the resolved path for the file name */
2737             if (NULL == (*actual_name = (char *)H5MM_strdup(realname)))
2738                 HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate real path")
2739         } /* end if */
2740     }     /* end if */
2741 #endif    /* H5_HAVE_SYMLINK */
2742 
2743     /* Check if we've resolved the file's name */
2744     if (NULL == *actual_name) {
2745         /* Just duplicate the name used to open the file */
2746         if (NULL == (*actual_name = (char *)H5MM_strdup(name)))
2747             HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't duplicate open name")
2748     } /* end else */
2749 
2750 done:
2751     /* Close the property list */
2752     if (new_fapl_id > 0)
2753         if (H5I_dec_app_ref(new_fapl_id) < 0)
2754             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEOBJ, FAIL, "can't close duplicated FAPL")
2755 #ifdef H5_HAVE_SYMLINK
2756     if (realname)
2757         realname = (char *)H5MM_xfree(realname);
2758 #endif /* H5_HAVE_SYMLINK */
2759 
2760     FUNC_LEAVE_NOAPI(ret_value)
2761 } /* H5F__build_actual_name() */
2762 
2763 /*-------------------------------------------------------------------------
2764  * Function:    H5F_addr_encode_len
2765  *
2766  * Purpose:     Encodes an address into the buffer pointed to by *PP and
2767  *              then increments the pointer to the first byte after the
2768  *              address.  An undefined value is stored as all 1's.
2769  *
2770  * Return:      void
2771  *-------------------------------------------------------------------------
2772  */
2773 void
H5F_addr_encode_len(size_t addr_len,uint8_t ** pp,haddr_t addr)2774 H5F_addr_encode_len(size_t addr_len, uint8_t **pp /*in,out*/, haddr_t addr)
2775 {
2776     unsigned u; /* Local index variable */
2777 
2778     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2779     FUNC_ENTER_NOAPI_NOINIT_NOERR
2780 
2781     HDassert(addr_len);
2782     HDassert(pp && *pp);
2783 
2784     if (H5F_addr_defined(addr)) {
2785         for (u = 0; u < addr_len; u++) {
2786             *(*pp)++ = (uint8_t)(addr & 0xff);
2787             addr >>= 8;
2788         } /* end for */
2789         HDassert("overflow" && 0 == addr);
2790     } /* end if */
2791     else {
2792         for (u = 0; u < addr_len; u++)
2793             *(*pp)++ = 0xff;
2794     } /* end else */
2795 
2796     FUNC_LEAVE_NOAPI_VOID
2797 } /* end H5F_addr_encode_len() */
2798 
2799 /*-------------------------------------------------------------------------
2800  * Function:    H5F_addr_encode
2801  *
2802  * Purpose:     Encodes an address into the buffer pointed to by *PP and
2803  *              then increments the pointer to the first byte after the
2804  *              address.  An undefined value is stored as all 1's.
2805  *
2806  * Return:      void
2807  *-------------------------------------------------------------------------
2808  */
2809 void
H5F_addr_encode(const H5F_t * f,uint8_t ** pp,haddr_t addr)2810 H5F_addr_encode(const H5F_t *f, uint8_t **pp /*in,out*/, haddr_t addr)
2811 {
2812     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2813     FUNC_ENTER_NOAPI_NOINIT_NOERR
2814 
2815     HDassert(f);
2816 
2817     H5F_addr_encode_len(H5F_SIZEOF_ADDR(f), pp, addr);
2818 
2819     FUNC_LEAVE_NOAPI_VOID
2820 } /* end H5F_addr_encode() */
2821 
2822 /*-------------------------------------------------------------------------
2823  * Function:    H5F_addr_decode_len
2824  *
2825  * Purpose:     Decodes an address from the buffer pointed to by *PP and
2826  *              updates the pointer to point to the next byte after the
2827  *              address.
2828  *
2829  *              If the value read is all 1's then the address is returned
2830  *              with an undefined value.
2831  *
2832  * Return:      void
2833  *-------------------------------------------------------------------------
2834  */
2835 void
H5F_addr_decode_len(size_t addr_len,const uint8_t ** pp,haddr_t * addr_p)2836 H5F_addr_decode_len(size_t addr_len, const uint8_t **pp /*in,out*/, haddr_t *addr_p /*out*/)
2837 {
2838     hbool_t  all_zero = TRUE; /* True if address was all zeroes */
2839     unsigned u;               /* Local index variable */
2840 
2841     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2842     FUNC_ENTER_NOAPI_NOINIT_NOERR
2843 
2844     HDassert(addr_len);
2845     HDassert(pp && *pp);
2846     HDassert(addr_p);
2847 
2848     /* Reset value in destination */
2849     *addr_p = 0;
2850 
2851     /* Decode bytes from address */
2852     for (u = 0; u < addr_len; u++) {
2853         uint8_t c; /* Local decoded byte */
2854 
2855         /* Get decoded byte (and advance pointer) */
2856         c = *(*pp)++;
2857 
2858         /* Check for non-undefined address byte value */
2859         if (c != 0xff)
2860             all_zero = FALSE;
2861 
2862         if (u < sizeof(*addr_p)) {
2863             haddr_t tmp = c; /* Local copy of address, for casting */
2864 
2865             /* Shift decoded byte to correct position */
2866             tmp <<= (u * 8); /*use tmp to get casting right */
2867 
2868             /* Merge into already decoded bytes */
2869             *addr_p |= tmp;
2870         } /* end if */
2871         else if (!all_zero)
2872             HDassert(0 == **pp); /*overflow */
2873     }                            /* end for */
2874 
2875     /* If 'all_zero' is still TRUE, the address was entirely composed of '0xff'
2876      *  bytes, which is the encoded form of 'HADDR_UNDEF', so set the destination
2877      *  to that value */
2878     if (all_zero)
2879         *addr_p = HADDR_UNDEF;
2880 
2881     FUNC_LEAVE_NOAPI_VOID
2882 } /* end H5F_addr_decode_len() */
2883 
2884 /*-------------------------------------------------------------------------
2885  * Function:    H5F_addr_decode
2886  *
2887  * Purpose:     Decodes an address from the buffer pointed to by *PP and
2888  *              updates the pointer to point to the next byte after the
2889  *              address.
2890  *
2891  *              If the value read is all 1's then the address is returned
2892  *              with an undefined value.
2893  *
2894  * Return:      void
2895  *-------------------------------------------------------------------------
2896  */
2897 void
H5F_addr_decode(const H5F_t * f,const uint8_t ** pp,haddr_t * addr_p)2898 H5F_addr_decode(const H5F_t *f, const uint8_t **pp /*in,out*/, haddr_t *addr_p /*out*/)
2899 {
2900     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2901     FUNC_ENTER_NOAPI_NOINIT_NOERR
2902 
2903     HDassert(f);
2904 
2905     H5F_addr_decode_len(H5F_SIZEOF_ADDR(f), pp, addr_p);
2906 
2907     FUNC_LEAVE_NOAPI_VOID
2908 } /* end H5F_addr_decode() */
2909 
2910 /*-------------------------------------------------------------------------
2911  * Function:    H5F_set_grp_btree_shared
2912  *
2913  * Purpose:     Set the grp_btree_shared field with a valid ref-count pointer.
2914  *
2915  * Return:      SUCCEED/FAIL
2916  *-------------------------------------------------------------------------
2917  */
2918 herr_t
H5F_set_grp_btree_shared(H5F_t * f,H5UC_t * rc)2919 H5F_set_grp_btree_shared(H5F_t *f, H5UC_t *rc)
2920 {
2921     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2922     FUNC_ENTER_NOAPI_NOINIT_NOERR
2923 
2924     /* Sanity check */
2925     HDassert(f);
2926     HDassert(f->shared);
2927     HDassert(rc);
2928 
2929     f->shared->grp_btree_shared = rc;
2930 
2931     FUNC_LEAVE_NOAPI(SUCCEED)
2932 } /* H5F_set_grp_btree_shared() */
2933 
2934 /*-------------------------------------------------------------------------
2935  * Function:    H5F_set_sohm_addr
2936  *
2937  * Purpose:     Set the sohm_addr field with a new value.
2938  *
2939  * Return:      SUCCEED/FAIL
2940  *-------------------------------------------------------------------------
2941  */
2942 herr_t
H5F_set_sohm_addr(H5F_t * f,haddr_t addr)2943 H5F_set_sohm_addr(H5F_t *f, haddr_t addr)
2944 {
2945     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2946     FUNC_ENTER_NOAPI_NOINIT_NOERR
2947 
2948     /* Sanity check */
2949     HDassert(f);
2950     HDassert(f->shared);
2951 
2952     f->shared->sohm_addr = addr;
2953 
2954     FUNC_LEAVE_NOAPI(SUCCEED)
2955 } /* H5F_set_sohm_addr() */
2956 
2957 /*-------------------------------------------------------------------------
2958  * Function:    H5F_set_sohm_vers
2959  *
2960  * Purpose:     Set the sohm_vers field with a new value.
2961  *
2962  * Return:      SUCCEED/FAIL
2963  *-------------------------------------------------------------------------
2964  */
2965 herr_t
H5F_set_sohm_vers(H5F_t * f,unsigned vers)2966 H5F_set_sohm_vers(H5F_t *f, unsigned vers)
2967 {
2968     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2969     FUNC_ENTER_NOAPI_NOINIT_NOERR
2970 
2971     /* Sanity check */
2972     HDassert(f);
2973     HDassert(f->shared);
2974 
2975     f->shared->sohm_vers = vers;
2976 
2977     FUNC_LEAVE_NOAPI(SUCCEED)
2978 } /* H5F_set_sohm_vers() */
2979 
2980 /*-------------------------------------------------------------------------
2981  * Function:    H5F_set_sohm_nindexes
2982  *
2983  * Purpose:     Set the sohm_nindexes field with a new value.
2984  *
2985  * Return:      SUCCEED/FAIL
2986  *-------------------------------------------------------------------------
2987  */
2988 herr_t
H5F_set_sohm_nindexes(H5F_t * f,unsigned nindexes)2989 H5F_set_sohm_nindexes(H5F_t *f, unsigned nindexes)
2990 {
2991     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
2992     FUNC_ENTER_NOAPI_NOINIT_NOERR
2993 
2994     /* Sanity check */
2995     HDassert(f);
2996     HDassert(f->shared);
2997 
2998     f->shared->sohm_nindexes = nindexes;
2999 
3000     FUNC_LEAVE_NOAPI(SUCCEED)
3001 } /* H5F_set_sohm_nindexes() */
3002 
3003 /*-------------------------------------------------------------------------
3004  * Function:    H5F_set_store_msg_crt_idx
3005  *
3006  * Purpose:     Set the store_msg_crt_idx field with a new value.
3007  *
3008  * Return:      SUCCEED/FAIL
3009  *-------------------------------------------------------------------------
3010  */
3011 herr_t
H5F_set_store_msg_crt_idx(H5F_t * f,hbool_t flag)3012 H5F_set_store_msg_crt_idx(H5F_t *f, hbool_t flag)
3013 {
3014     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
3015     FUNC_ENTER_NOAPI_NOINIT_NOERR
3016 
3017     /* Sanity check */
3018     HDassert(f);
3019     HDassert(f->shared);
3020 
3021     f->shared->store_msg_crt_idx = flag;
3022 
3023     FUNC_LEAVE_NOAPI(SUCCEED)
3024 } /* H5F_set_store_msg_crt_idx() */
3025 
3026 /*-------------------------------------------------------------------------
3027  * Function:    H5F__set_libver_bounds()
3028  *
3029  * Purpose:     Set the file's low and high bound to the input parameters
3030  *              'low' and 'high' respectively.
3031  *              This is done only if the existing setting is different
3032  *              from the inputs.
3033  *
3034  * Return:      SUCCEED/FAIL
3035  *
3036  * Programmer:  Vailin Choi; December 2017
3037  *
3038  *-------------------------------------------------------------------------
3039  */
3040 herr_t
H5F__set_libver_bounds(H5F_t * f,H5F_libver_t low,H5F_libver_t high)3041 H5F__set_libver_bounds(H5F_t *f, H5F_libver_t low, H5F_libver_t high)
3042 {
3043     herr_t ret_value = SUCCEED; /* Return value */
3044 
3045     FUNC_ENTER_PACKAGE
3046 
3047     /* Sanity checks */
3048     HDassert(f);
3049     HDassert(f->shared);
3050 
3051     /* Set the bounds only if the existing setting is different from the inputs */
3052     if (f->shared->low_bound != low || f->shared->high_bound != high) {
3053         /* Call the flush routine, for this file */
3054         /* Note: This is done in case the binary format for representing a
3055          *      metadata entry class changes when the file format low / high
3056          *      bounds are changed and an unwritten entry of that class is
3057          *      sitting in the metadata cache.
3058          *
3059          *      If that happens, it's possible that the entry's size could
3060          *      become larger, potentially corrupting the file (if the larger
3061          *      entry is fully written, overwriting data outside its allocated
3062          *      space), or corrupting the entry (if the entry is truncated to
3063          *      fit into the allocated space).
3064          *
3065          *      Although I'm not aware of any metadata with this behavior
3066          *      currently, it would be very difficult to guard against and / or
3067          *      detect, but if we flush everything here, the format version
3068          *      for metadata entries in the cache will be finalized and these
3069          *      sorts of problems can be avoided.
3070          *
3071          *      QAK - April, 2018
3072          */
3073         if (H5F__flush(f) < 0)
3074             HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
3075 
3076         /* Set the new bounds */
3077         f->shared->low_bound  = low;
3078         f->shared->high_bound = high;
3079     }
3080 
3081 done:
3082     FUNC_LEAVE_NOAPI(ret_value)
3083 } /* H5F__set_libver_bounds() */
3084 
3085 /*-------------------------------------------------------------------------
3086  * Function:    H5F__get_file_image
3087  *
3088  * Purpose:     Private version of H5Fget_file_image
3089  *
3090  * Return:      Success:        Bytes copied / number of bytes needed.
3091  *              Failure:        -1
3092  *-------------------------------------------------------------------------
3093  */
3094 ssize_t
H5F__get_file_image(H5F_t * file,void * buf_ptr,size_t buf_len)3095 H5F__get_file_image(H5F_t *file, void *buf_ptr, size_t buf_len)
3096 {
3097     H5FD_t *fd_ptr;         /* file driver */
3098     haddr_t eoa;            /* End of file address */
3099     ssize_t ret_value = -1; /* Return value */
3100 
3101     FUNC_ENTER_PACKAGE
3102 
3103     /* Check args */
3104     if (!file || !file->shared || !file->shared->lf)
3105         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, (-1), "file_id yields invalid file pointer")
3106     fd_ptr = file->shared->lf;
3107     if (!fd_ptr->cls)
3108         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, (-1), "fd_ptr yields invalid class pointer")
3109 
3110     /* the address space used by the split and multi file drivers is not
3111      * a good fit for this call.  Since the plan is to depreciate these
3112      * drivers anyway, don't bother to do a "force fit".
3113      *
3114      * The following clause tests for the multi file driver, and fails
3115      * if the supplied file has the multi file driver as its top level
3116      * file driver.  However, this test will not work if there is some
3117      * other file driver sitting on top of the multi file driver.
3118      *
3119      * I'm not sure if this is possible at present, but in all likelyhood,
3120      * it will become possible in the future.  On the other hand, we may
3121      * remove the split/multi file drivers before then.
3122      *
3123      * I am leaving this solution in for now, but we should review it,
3124      * and improve the solution if necessary.
3125      *
3126      *                                          JRM -- 11/11/22
3127      */
3128     if (HDstrcmp(fd_ptr->cls->name, "multi") == 0)
3129         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, (-1), "Not supported for multi file driver.")
3130 
3131     /* While the family file driver is conceptually fully compatible
3132      * with the get file image operation, it sets a file driver message
3133      * in the super block that prevents the image being opened with any
3134      * driver other than the family file driver.  Needless to say, this
3135      * rather defeats the purpose of the get file image operation.
3136      *
3137      * While this problem is quire solvable, the required time and
3138      * resources are lacking at present.  Hence, for now, we don't
3139      * allow the get file image operation to be performed on files
3140      * opened with the family file driver.
3141      *
3142      * Observe that the following test only looks at the top level
3143      * driver, and fails if there is some other driver sitting on to
3144      * of the family file driver.
3145      *
3146      * I don't think this can happen at present, but that may change
3147      * in the future.
3148      *                                   JRM -- 12/21/11
3149      */
3150     if (HDstrcmp(fd_ptr->cls->name, "family") == 0)
3151         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, (-1), "Not supported for family file driver.")
3152 
3153     /* Go get the actual file size */
3154     if (HADDR_UNDEF == (eoa = H5FD_get_eoa(file->shared->lf, H5FD_MEM_DEFAULT)))
3155         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, (-1), "unable to get file size")
3156 
3157     /* set ret_value = to eoa -- will overwrite this if appropriate */
3158     ret_value = (ssize_t)eoa;
3159 
3160     /* test to see if a buffer was provided -- if not, we are done */
3161     if (buf_ptr != NULL) {
3162         size_t   space_needed; /* size of file image */
3163         unsigned tmp, tmp_size;
3164 
3165         /* Check for buffer too small */
3166         if ((haddr_t)buf_len < eoa)
3167             HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, (-1), "supplied buffer too small")
3168 
3169         space_needed = (size_t)eoa;
3170 
3171         /* read in the file image */
3172         /* (Note compensation for base address addition in internal routine) */
3173         if (H5FD_read(fd_ptr, H5FD_MEM_DEFAULT, 0, space_needed, buf_ptr) < 0)
3174             HGOTO_ERROR(H5E_FILE, H5E_READERROR, (-1), "file image read request failed")
3175 
3176         /* Offset to "status_flags" in the superblock */
3177         tmp = H5F_SUPER_STATUS_FLAGS_OFF(file->shared->sblock->super_vers);
3178 
3179         /* Size of "status_flags" depends on the superblock version */
3180         tmp_size = H5F_SUPER_STATUS_FLAGS_SIZE(file->shared->sblock->super_vers);
3181 
3182         /* Clear "status_flags" */
3183         HDmemset((uint8_t *)buf_ptr + tmp, 0, tmp_size);
3184     } /* end if */
3185 
3186 done:
3187     FUNC_LEAVE_NOAPI(ret_value)
3188 } /* H5F__get_file_image() */
3189 
3190 /*-------------------------------------------------------------------------
3191  * Function:    H5F__get_info
3192  *
3193  * Purpose:     Private version of H5Fget_info
3194  *
3195  * Return:      Success:        SUCCEED
3196  *              Failure:        FAIL
3197  *-------------------------------------------------------------------------
3198  */
3199 herr_t
H5F__get_info(H5F_t * f,H5F_info2_t * finfo)3200 H5F__get_info(H5F_t *f, H5F_info2_t *finfo)
3201 {
3202     herr_t ret_value = SUCCEED; /* Return value */
3203 
3204     FUNC_ENTER_PACKAGE
3205 
3206     /* Sanity check */
3207     HDassert(f);
3208     HDassert(f->shared);
3209     HDassert(finfo);
3210 
3211     /* Reset file info struct */
3212     HDmemset(finfo, 0, sizeof(*finfo));
3213 
3214     /* Get the size of the superblock and any superblock extensions */
3215     if (H5F__super_size(f, &finfo->super.super_size, &finfo->super.super_ext_size) < 0)
3216         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve superblock sizes")
3217 
3218     /* Get the size of any persistent free space */
3219     if (H5MF_get_freespace(f, &finfo->free.tot_space, &finfo->free.meta_size) < 0)
3220         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve free space information")
3221 
3222     /* Check for SOHM info */
3223     if (H5F_addr_defined(f->shared->sohm_addr))
3224         if (H5SM_ih_size(f, &finfo->sohm.hdr_size, &finfo->sohm.msgs_info) < 0)
3225             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve SOHM index & heap storage info")
3226 
3227     /* Set version # fields */
3228     finfo->super.version = f->shared->sblock->super_vers;
3229     finfo->sohm.version  = f->shared->sohm_vers;
3230     finfo->free.version  = HDF5_FREESPACE_VERSION;
3231 
3232 done:
3233     FUNC_LEAVE_NOAPI(ret_value)
3234 } /* H5F__get_info() */
3235 
3236 /*-------------------------------------------------------------------------
3237  * Function:    H5F_track_metadata_read_retries
3238  *
3239  * Purpose:     To track the # of a "retries" (log10) for a metadata item.
3240  *              This routine should be used only when:
3241  *              "retries" > 0
3242  *              f->shared->read_attempts > 1 (does not have retry when 1)
3243  *              f->shared->retries_nbins > 0 (calculated based on f->shared->read_attempts)
3244  *
3245  * Return:      SUCCEED/FAIL
3246  *-------------------------------------------------------------------------
3247  */
3248 herr_t
H5F_track_metadata_read_retries(H5F_t * f,unsigned actype,unsigned retries)3249 H5F_track_metadata_read_retries(H5F_t *f, unsigned actype, unsigned retries)
3250 {
3251     unsigned log_ind;             /* Index to the array of retries based on log10 of retries */
3252     double   tmp;                 /* Temporary value, to keep compiler quiet */
3253     herr_t   ret_value = SUCCEED; /* Return value */
3254 
3255     FUNC_ENTER_NOAPI(FAIL)
3256 
3257     /* Sanity check */
3258     HDassert(f);
3259     HDassert(f->shared->read_attempts > 1);
3260     HDassert(f->shared->retries_nbins > 0);
3261     HDassert(retries > 0);
3262     HDassert(retries < f->shared->read_attempts);
3263     HDassert(actype < H5AC_NTYPES);
3264 
3265     /* Allocate memory for retries */
3266     if (NULL == f->shared->retries[actype])
3267         if (NULL == (f->shared->retries[actype] =
3268                          (uint32_t *)H5MM_calloc((size_t)f->shared->retries_nbins * sizeof(uint32_t))))
3269             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
3270 
3271     /* Index to retries based on log10 */
3272     tmp     = HDlog10((double)retries);
3273     log_ind = (unsigned)tmp;
3274     HDassert(log_ind < f->shared->retries_nbins);
3275 
3276     /* Increment the # of the "retries" */
3277     f->shared->retries[actype][log_ind]++;
3278 
3279 done:
3280     FUNC_LEAVE_NOAPI(ret_value)
3281 } /* H5F_track_metadata_read_retries() */
3282 
3283 /*-------------------------------------------------------------------------
3284  * Function:    H5F_set_retries
3285  *
3286  * Purpose:     To initialize data structures for read retries:
3287  *              --zero out "retries"
3288  *              --set up "retries_nbins" based on read_attempts
3289  *
3290  * Return:      SUCCEED/FAIL
3291  *-------------------------------------------------------------------------
3292  */
3293 herr_t
H5F_set_retries(H5F_t * f)3294 H5F_set_retries(H5F_t *f)
3295 {
3296     double tmp; /* Temporary variable */
3297 
3298     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
3299     FUNC_ENTER_NOAPI_NOINIT_NOERR
3300 
3301     /* Sanity check */
3302     HDassert(f);
3303 
3304     /* Initialize the tracking for metadata read retries */
3305     HDmemset(f->shared->retries, 0, sizeof(f->shared->retries));
3306 
3307     /* Initialize the # of bins for retries */
3308     f->shared->retries_nbins = 0;
3309     if (f->shared->read_attempts > 1) {
3310         /* Use HDceil to ensure that the log10 value is rounded up to the
3311            nearest integer before casting to unsigned */
3312         tmp                      = HDceil(HDlog10((double)f->shared->read_attempts));
3313         f->shared->retries_nbins = (unsigned)tmp;
3314     }
3315 
3316     FUNC_LEAVE_NOAPI(SUCCEED)
3317 } /* H5F_set_retries() */
3318 
3319 /*-------------------------------------------------------------------------
3320  * Function:    H5F_object_flush_cb
3321  *
3322  * Purpose:     To invoke the callback function for object flush that is set
3323  *              in the file's access property list.
3324  *
3325  * Return:      Success:        SUCCEED
3326  *              Failure:        FAIL
3327  *-------------------------------------------------------------------------
3328  */
3329 herr_t
H5F_object_flush_cb(H5F_t * f,hid_t obj_id)3330 H5F_object_flush_cb(H5F_t *f, hid_t obj_id)
3331 {
3332     herr_t ret_value = SUCCEED; /* Return value */
3333 
3334     FUNC_ENTER_NOAPI(FAIL)
3335 
3336     /* Sanity check */
3337     HDassert(f);
3338     HDassert(f->shared);
3339 
3340     /* Invoke object flush callback if there is one */
3341     if (f->shared->object_flush.func &&
3342         f->shared->object_flush.func(obj_id, f->shared->object_flush.udata) < 0)
3343         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "object flush callback returns error")
3344 
3345 done:
3346     FUNC_LEAVE_NOAPI(ret_value)
3347 } /* H5F_object_flush_cb() */
3348 
3349 /*-------------------------------------------------------------------------
3350  * Function: H5F__set_base_addr
3351  *
3352  * Purpose:  Quick and dirty routine to set the file's 'base_addr' value
3353  *
3354  * Return:   Non-negative on success/Negative on failure
3355  *-------------------------------------------------------------------------
3356  */
3357 herr_t
H5F__set_base_addr(const H5F_t * f,haddr_t addr)3358 H5F__set_base_addr(const H5F_t *f, haddr_t addr)
3359 {
3360     herr_t ret_value = SUCCEED; /* Return value */
3361 
3362     FUNC_ENTER_PACKAGE
3363 
3364     HDassert(f);
3365     HDassert(f->shared);
3366 
3367     /* Dispatch to driver */
3368     if (H5FD_set_base_addr(f->shared->lf, addr) < 0)
3369         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set_base_addr request failed")
3370 
3371 done:
3372     FUNC_LEAVE_NOAPI(ret_value)
3373 } /* end H5F__set_base_addr() */
3374 
3375 /*-------------------------------------------------------------------------
3376  * Function: H5F__set_eoa
3377  *
3378  * Purpose:  Quick and dirty routine to set the file's 'eoa' value
3379  *
3380  * Return:   Non-negative on success/Negative on failure
3381  *-------------------------------------------------------------------------
3382  */
3383 herr_t
H5F__set_eoa(const H5F_t * f,H5F_mem_t type,haddr_t addr)3384 H5F__set_eoa(const H5F_t *f, H5F_mem_t type, haddr_t addr)
3385 {
3386     herr_t ret_value = SUCCEED; /* Return value */
3387 
3388     FUNC_ENTER_PACKAGE
3389 
3390     HDassert(f);
3391     HDassert(f->shared);
3392 
3393     /* Dispatch to driver */
3394     /* (H5FD_set_eoa() will add base_addr to addr) */
3395     if (H5FD_set_eoa(f->shared->lf, type, addr) < 0)
3396         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set_eoa request failed")
3397 
3398 done:
3399     FUNC_LEAVE_NOAPI(ret_value)
3400 } /* end H5F__set_eoa() */
3401 
3402 /*-------------------------------------------------------------------------
3403  * Function: H5F__set_paged_aggr
3404  *
3405  * Purpose:  Quick and dirty routine to set the file's paged_aggr mode
3406  *
3407  * Return:   Non-negative on success/Negative on failure
3408  *-------------------------------------------------------------------------
3409  */
3410 herr_t
H5F__set_paged_aggr(const H5F_t * f,hbool_t paged)3411 H5F__set_paged_aggr(const H5F_t *f, hbool_t paged)
3412 {
3413     herr_t ret_value = SUCCEED; /* Return value */
3414 
3415     FUNC_ENTER_PACKAGE
3416 
3417     /* Sanity check */
3418     HDassert(f);
3419     HDassert(f->shared);
3420 
3421     /* Dispatch to driver */
3422     if (H5FD_set_paged_aggr(f->shared->lf, paged) < 0)
3423         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set paged aggr mode failed")
3424 
3425 done:
3426     FUNC_LEAVE_NOAPI(ret_value)
3427 } /* end H5F__set_paged_aggr() */
3428 
3429 /*-------------------------------------------------------------------------
3430  * Function:    H5F__get_max_eof_eoa
3431  *
3432  * Purpose:     Determine the maximum of (EOA, EOF) for the file
3433  *
3434  * Return:      SUCCEED/FAIL
3435  *-------------------------------------------------------------------------
3436  */
3437 herr_t
H5F__get_max_eof_eoa(const H5F_t * f,haddr_t * max_eof_eoa)3438 H5F__get_max_eof_eoa(const H5F_t *f, haddr_t *max_eof_eoa)
3439 {
3440     haddr_t eof; /* Relative address for EOF */
3441     haddr_t eoa; /* Relative address for EOA */
3442     haddr_t tmp_max;
3443     herr_t  ret_value = SUCCEED; /* Return value */
3444 
3445     FUNC_ENTER_PACKAGE
3446 
3447     /* Sanity checks */
3448     HDassert(f);
3449     HDassert(f->shared);
3450 
3451     /* Get the relative EOA and EOF */
3452     eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_DEFAULT);
3453     eof = H5FD_get_eof(f->shared->lf, H5FD_MEM_DEFAULT);
3454 
3455     /* Determine the maximum */
3456     tmp_max = MAX(eof, eoa);
3457     if (HADDR_UNDEF == tmp_max)
3458         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file get eof/eoa requests failed")
3459 
3460     *max_eof_eoa = tmp_max;
3461 
3462 done:
3463     FUNC_LEAVE_NOAPI(ret_value)
3464 } /* end H5F__get_max_eof_eoa() */
3465 
3466 /*-------------------------------------------------------------------------
3467  * Function:    H5F_get_metadata_read_retry_info
3468  *
3469  * Purpose:     Private function to retrieve the collection of read retries
3470  *              for metadata items with checksum.
3471  *
3472  * Return:      SUCCEED/FAIL
3473  *
3474  *-------------------------------------------------------------------------
3475  */
3476 herr_t
H5F_get_metadata_read_retry_info(H5F_t * file,H5F_retry_info_t * info)3477 H5F_get_metadata_read_retry_info(H5F_t *file, H5F_retry_info_t *info)
3478 {
3479     unsigned i, j;                /* Local index variable */
3480     size_t   tot_size;            /* Size of each retries[i] */
3481     herr_t   ret_value = SUCCEED; /* Return value */
3482 
3483     FUNC_ENTER_NOAPI(FAIL)
3484 
3485     /* Check args */
3486     HDassert(file);
3487     HDassert(info);
3488 
3489     /* Copy the # of bins for "retries" array */
3490     info->nbins = file->shared->retries_nbins;
3491 
3492     /* Initialize the array of "retries" */
3493     HDmemset(info->retries, 0, sizeof(info->retries));
3494 
3495     /* Return if there are no bins -- no retries */
3496     if (!info->nbins)
3497         HGOTO_DONE(SUCCEED);
3498 
3499     /* Calculate size for each retries[i] */
3500     tot_size = info->nbins * sizeof(uint32_t);
3501 
3502     /* Map and copy information to info's retries for metadata items with tracking for read retries */
3503     j = 0;
3504     for (i = 0; i < H5AC_NTYPES; i++) {
3505         switch (i) {
3506             case H5AC_OHDR_ID:
3507             case H5AC_OHDR_CHK_ID:
3508             case H5AC_BT2_HDR_ID:
3509             case H5AC_BT2_INT_ID:
3510             case H5AC_BT2_LEAF_ID:
3511             case H5AC_FHEAP_HDR_ID:
3512             case H5AC_FHEAP_DBLOCK_ID:
3513             case H5AC_FHEAP_IBLOCK_ID:
3514             case H5AC_FSPACE_HDR_ID:
3515             case H5AC_FSPACE_SINFO_ID:
3516             case H5AC_SOHM_TABLE_ID:
3517             case H5AC_SOHM_LIST_ID:
3518             case H5AC_EARRAY_HDR_ID:
3519             case H5AC_EARRAY_IBLOCK_ID:
3520             case H5AC_EARRAY_SBLOCK_ID:
3521             case H5AC_EARRAY_DBLOCK_ID:
3522             case H5AC_EARRAY_DBLK_PAGE_ID:
3523             case H5AC_FARRAY_HDR_ID:
3524             case H5AC_FARRAY_DBLOCK_ID:
3525             case H5AC_FARRAY_DBLK_PAGE_ID:
3526             case H5AC_SUPERBLOCK_ID:
3527                 HDassert(j < H5F_NUM_METADATA_READ_RETRY_TYPES);
3528                 if (file->shared->retries[i] != NULL) {
3529                     /* Allocate memory for retries[i]
3530                      *
3531                      * This memory should be released by the user with
3532                      * the H5free_memory() call.
3533                      */
3534                     if (NULL == (info->retries[j] = (uint32_t *)H5MM_malloc(tot_size)))
3535                         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
3536 
3537                     /* Copy the information */
3538                     H5MM_memcpy(info->retries[j], file->shared->retries[i], tot_size);
3539                 }
3540 
3541                 /* Increment location in info->retries[] array */
3542                 j++;
3543                 break;
3544 
3545             default:
3546                 break;
3547         }
3548     }
3549 
3550 done:
3551     FUNC_LEAVE_NOAPI(ret_value)
3552 } /* end H5F_get_metadata_read_retry_info() */
3553 
3554 /*-------------------------------------------------------------------------
3555  * Function:    H5F__start_swmr_write
3556  *
3557  * Purpose:     Private version of H5Fstart_swmr_write
3558  *
3559  *              1) Refresh opened objects: part 1
3560  *              2) Flush & reset accumulator
3561  *              3) Mark the file in SWMR writing mode
3562  *              4) Set metadata read attempts and retries info
3563  *              5) Disable accumulator
3564  *              6) Evict all cache entries except the superblock
3565  *              7) Refresh opened objects (part 2)
3566  *              8) Unlock the file
3567  *
3568  *              Pre-conditions:
3569  *
3570  *              1) The file being opened has v3 superblock
3571  *              2) The file is opened with H5F_ACC_RDWR
3572  *              3) The file is not already marked for SWMR writing
3573  *              4) Current implementaion for opened objects:
3574  *                  --only allow datasets and groups without attributes
3575  *                  --disallow named datatype with/without attributes
3576  *                  --disallow opened attributes attached to objects
3577  *
3578  * NOTE:        Currently, only opened groups and datasets are allowed
3579  *              when enabling SWMR via H5Fstart_swmr_write().
3580  *              Will later implement a different approach--
3581  *              set up flush dependency/proxy even for file opened without
3582  *              SWMR to resolve issues with opened objects.
3583  *
3584  * Return:      SUCCEED/FAIL
3585  *
3586  *-------------------------------------------------------------------------
3587  */
3588 herr_t
H5F__start_swmr_write(H5F_t * f)3589 H5F__start_swmr_write(H5F_t *f)
3590 {
3591     hbool_t     ci_load        = FALSE;  /* whether MDC ci load requested */
3592     hbool_t     ci_write       = FALSE;  /* whether MDC CI write requested */
3593     size_t      grp_dset_count = 0;      /* # of open objects: groups & datasets */
3594     size_t      nt_attr_count  = 0;      /* # of opened named datatypes  + opened attributes */
3595     hid_t *     obj_ids        = NULL;   /* List of ids */
3596     H5G_loc_t * obj_glocs      = NULL;   /* Group location of the object */
3597     H5O_loc_t * obj_olocs      = NULL;   /* Object location */
3598     H5G_name_t *obj_paths      = NULL;   /* Group hierarchy path */
3599     size_t      u;                       /* Local index variable */
3600     hbool_t     setup         = FALSE;   /* Boolean flag to indicate whether SWMR setting is enabled */
3601     H5VL_t *    vol_connector = NULL;    /* VOL connector for the file */
3602     herr_t      ret_value     = SUCCEED; /* Return value */
3603 
3604     FUNC_ENTER_PACKAGE
3605 
3606     /* Sanity check */
3607     HDassert(f);
3608     HDassert(f->shared);
3609 
3610     /* Should have write permission */
3611     if ((H5F_INTENT(f) & H5F_ACC_RDWR) == 0)
3612         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "no write intent on file")
3613 
3614     /* Check superblock version */
3615     if (f->shared->sblock->super_vers < HDF5_SUPERBLOCK_VERSION_3)
3616         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file superblock version - should be at least 3")
3617 
3618     /* Check for correct file format version */
3619     if ((f->shared->low_bound < H5F_LIBVER_V110) || (f->shared->high_bound < H5F_LIBVER_V110))
3620         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL,
3621                     "file format version does not support SWMR - needs to be 1.10 or greater")
3622 
3623     /* Should not be marked for SWMR writing mode already */
3624     if (f->shared->sblock->status_flags & H5F_SUPER_SWMR_WRITE_ACCESS)
3625         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "file already in SWMR writing mode")
3626 
3627     /* Check to see if cache image is enabled.  Fail if so */
3628     if (H5C_cache_image_status(f, &ci_load, &ci_write) < 0)
3629         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get MDC cache image status")
3630     if (ci_load || ci_write)
3631         HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL, "can't have both SWMR and MDC cache image")
3632 
3633     /* Flush the superblock extension */
3634     if (H5F_flush_tagged_metadata(f, f->shared->sblock->ext_addr) < 0)
3635         HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock extension")
3636 
3637     /* Flush data buffers */
3638     if (H5F__flush(f) < 0)
3639         HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush file's cached information")
3640 
3641     /* Get the # of opened named datatypes and attributes */
3642     if (H5F_get_obj_count(f, H5F_OBJ_DATATYPE | H5F_OBJ_ATTR, FALSE, &nt_attr_count) < 0)
3643         HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
3644     if (nt_attr_count > 0)
3645         HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "named datatypes and/or attributes opened in the file")
3646 
3647     /* Get the # of opened datasets and groups */
3648     if (H5F_get_obj_count(f, H5F_OBJ_GROUP | H5F_OBJ_DATASET, FALSE, &grp_dset_count) < 0)
3649         HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
3650 
3651     if (grp_dset_count > 0) {
3652         /* Allocate space for group and object locations */
3653         if ((obj_ids = (hid_t *)H5MM_malloc(grp_dset_count * sizeof(hid_t))) == NULL)
3654             HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for hid_t")
3655         if ((obj_glocs = (H5G_loc_t *)H5MM_malloc(grp_dset_count * sizeof(H5G_loc_t))) == NULL)
3656             HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_loc_t")
3657         if ((obj_olocs = (H5O_loc_t *)H5MM_malloc(grp_dset_count * sizeof(H5O_loc_t))) == NULL)
3658             HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5O_loc_t")
3659         if ((obj_paths = (H5G_name_t *)H5MM_malloc(grp_dset_count * sizeof(H5G_name_t))) == NULL)
3660             HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate buffer for H5G_name_t")
3661 
3662         /* Get the list of opened object ids (groups & datasets) */
3663         if (H5F_get_obj_ids(f, H5F_OBJ_GROUP | H5F_OBJ_DATASET, grp_dset_count, obj_ids, FALSE,
3664                             &grp_dset_count) < 0)
3665             HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "H5F_get_obj_ids failed")
3666 
3667         /* Save the VOL connector and the object wrapping context for the refresh step */
3668         if (grp_dset_count > 0) {
3669             H5VL_object_t *vol_obj;
3670 
3671             /* Get the VOL object for one of the IDs */
3672             if (NULL == (vol_obj = H5VL_vol_object(obj_ids[0])))
3673                 HGOTO_ERROR(H5E_FILE, H5E_BADTYPE, FAIL, "invalid object identifier")
3674 
3675             /* Get the (top) connector for the ID */
3676             vol_connector = vol_obj->connector;
3677         } /* end if */
3678 
3679         /* Gather information about opened objects (groups, datasets) in the file */
3680         /* (For refresh later on) */
3681         for (u = 0; u < grp_dset_count; u++) {
3682             H5O_loc_t *oloc; /* object location */
3683             H5G_loc_t  tmp_loc;
3684 
3685             /* Set up the id's group location */
3686             obj_glocs[u].oloc = &obj_olocs[u];
3687             obj_glocs[u].path = &obj_paths[u];
3688             H5G_loc_reset(&obj_glocs[u]);
3689 
3690             /* get the id's object location */
3691             if ((oloc = H5O_get_loc(obj_ids[u])) == NULL)
3692                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an object")
3693 
3694             /* Make deep local copy of object's location information */
3695             H5G_loc(obj_ids[u], &tmp_loc);
3696             H5G_loc_copy(&obj_glocs[u], &tmp_loc, H5_COPY_DEEP);
3697 
3698             /* Close the object */
3699             if (H5I_dec_ref(obj_ids[u]) < 0)
3700                 HGOTO_ERROR(H5E_ATOM, H5E_CANTCLOSEOBJ, FAIL, "decrementing object ID failed")
3701         } /* end for */
3702     }     /* end if */
3703 
3704     /* Flush and reset the accumulator */
3705     if (H5F__accum_reset(f->shared, TRUE) < 0)
3706         HGOTO_ERROR(H5E_IO, H5E_CANTRESET, FAIL, "can't reset accumulator")
3707 
3708     /* Turn on SWMR write in shared file open flags */
3709     f->shared->flags |= H5F_ACC_SWMR_WRITE;
3710 
3711     /* Mark the file in SWMR writing mode */
3712     f->shared->sblock->status_flags |= H5F_SUPER_SWMR_WRITE_ACCESS;
3713 
3714     /* Set up metadata read attempts */
3715     f->shared->read_attempts = H5F_SWMR_METADATA_READ_ATTEMPTS;
3716 
3717     /* Initialize "retries" and "retries_nbins" */
3718     if (H5F_set_retries(f) < 0)
3719         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins")
3720 
3721     /* Turn off usage of accumulator */
3722     f->shared->feature_flags &= ~(unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
3723     if (H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0)
3724         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD")
3725 
3726     setup = TRUE;
3727 
3728     /* Place an advisory lock on the file */
3729     if (H5F_USE_FILE_LOCKING(f)) {
3730         /* Have to unlock on Windows as Win32 doesn't support changing the lock
3731          * type (exclusive vs shared) with a second call.
3732          */
3733         if (H5FD_unlock(f->shared->lf) < 0) {
3734             HGOTO_ERROR(H5E_FILE, H5E_CANTUNLOCKFILE, FAIL, "unable to unlock the file")
3735         }
3736         if (H5FD_lock(f->shared->lf, TRUE) < 0) {
3737             HGOTO_ERROR(H5E_FILE, H5E_CANTLOCKFILE, FAIL, "unable to lock the file")
3738         }
3739     }
3740 
3741     /* Mark superblock as dirty */
3742     if (H5F_super_dirty(f) < 0)
3743         HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
3744 
3745     /* Flush the superblock */
3746     if (H5F_flush_tagged_metadata(f, H5AC__SUPERBLOCK_TAG) < 0)
3747         HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock")
3748 
3749     /* Evict all flushed entries in the cache except the pinned superblock */
3750     if (H5F__evict_cache_entries(f) < 0)
3751         HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to evict file's cached information")
3752 
3753     /* Refresh (reopen) the objects (groups & datasets) in the file */
3754     for (u = 0; u < grp_dset_count; u++)
3755         if (H5O_refresh_metadata_reopen(obj_ids[u], &obj_glocs[u], vol_connector, TRUE) < 0)
3756             HGOTO_ERROR(H5E_ATOM, H5E_CLOSEERROR, FAIL, "can't refresh-close object")
3757 
3758     /* Unlock the file */
3759     if (H5FD_unlock(f->shared->lf) < 0)
3760         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to unlock the file")
3761 
3762 done:
3763     if (ret_value < 0 && setup) {
3764 
3765         /* Re-enable accumulator */
3766         f->shared->feature_flags |= (unsigned)H5FD_FEAT_ACCUMULATE_METADATA;
3767         if (H5FD_set_feature_flags(f->shared->lf, f->shared->feature_flags) < 0)
3768             HDONE_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't set feature_flags in VFD")
3769 
3770         /* Reset the # of read attempts */
3771         f->shared->read_attempts = H5F_METADATA_READ_ATTEMPTS;
3772         if (H5F_set_retries(f) < 0)
3773             HDONE_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't set retries and retries_nbins")
3774 
3775         /* Un-set H5F_ACC_SWMR_WRITE in shared open flags */
3776         f->shared->flags &= ~H5F_ACC_SWMR_WRITE;
3777 
3778         /* Unmark the file: not in SWMR writing mode */
3779         f->shared->sblock->status_flags &= (uint8_t)(~H5F_SUPER_SWMR_WRITE_ACCESS);
3780 
3781         /* Mark superblock as dirty */
3782         if (H5F_super_dirty(f) < 0)
3783             HDONE_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
3784 
3785         /* Flush the superblock */
3786         if (H5F_flush_tagged_metadata(f, H5AC__SUPERBLOCK_TAG) < 0)
3787             HDONE_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush superblock")
3788     } /* end if */
3789 
3790     /* Free memory */
3791     if (obj_ids)
3792         H5MM_xfree(obj_ids);
3793     if (obj_glocs)
3794         H5MM_xfree(obj_glocs);
3795     if (obj_olocs)
3796         H5MM_xfree(obj_olocs);
3797     if (obj_paths)
3798         H5MM_xfree(obj_paths);
3799 
3800     FUNC_LEAVE_NOAPI(ret_value)
3801 } /* end H5F__start_swmr_write() */
3802 
3803 /*-------------------------------------------------------------------------
3804  * Function:    H5F__format_convert
3805  *
3806  * Purpose:     Private version of H5Fformat_convert
3807  *
3808  * Return:      Success:        SUCCEED
3809  *              Failure:        FAIL
3810  *-------------------------------------------------------------------------
3811  */
3812 herr_t
H5F__format_convert(H5F_t * f)3813 H5F__format_convert(H5F_t *f)
3814 {
3815     hbool_t mark_dirty = FALSE;   /* Whether to mark the file's superblock dirty */
3816     herr_t  ret_value  = SUCCEED; /* Return value */
3817 
3818     FUNC_ENTER_PACKAGE
3819 
3820     /* Sanity check */
3821     HDassert(f);
3822     HDassert(f->shared);
3823 
3824     /* Check if the superblock should be downgraded */
3825     if (f->shared->sblock->super_vers > HDF5_SUPERBLOCK_VERSION_V18_LATEST) {
3826         f->shared->sblock->super_vers = HDF5_SUPERBLOCK_VERSION_V18_LATEST;
3827         mark_dirty                    = TRUE;
3828     }
3829 
3830     /* Check for persistent freespace manager, which needs to be downgraded */
3831     if (!(f->shared->fs_strategy == H5F_FILE_SPACE_STRATEGY_DEF &&
3832           f->shared->fs_persist == H5F_FREE_SPACE_PERSIST_DEF &&
3833           f->shared->fs_threshold == H5F_FREE_SPACE_THRESHOLD_DEF &&
3834           f->shared->fs_page_size == H5F_FILE_SPACE_PAGE_SIZE_DEF)) {
3835 
3836         /* Check to remove free-space manager info message from superblock extension */
3837         if (H5F_addr_defined(f->shared->sblock->ext_addr))
3838             if (H5F__super_ext_remove_msg(f, H5O_FSINFO_ID) < 0)
3839                 HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL,
3840                             "error in removing message from superblock extension")
3841 
3842         /* Close freespace manager */
3843         if (H5MF_try_close(f) < 0)
3844             HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to free free-space address")
3845 
3846         /* Set non-persistent freespace manager */
3847         f->shared->fs_strategy  = H5F_FILE_SPACE_STRATEGY_DEF;
3848         f->shared->fs_persist   = H5F_FREE_SPACE_PERSIST_DEF;
3849         f->shared->fs_threshold = H5F_FREE_SPACE_THRESHOLD_DEF;
3850         f->shared->fs_page_size = H5F_FILE_SPACE_PAGE_SIZE_DEF;
3851 
3852         /* Indicate that the superblock should be marked dirty */
3853         mark_dirty = TRUE;
3854     } /* end if */
3855 
3856     /* Check if we should mark the superblock dirty */
3857     if (mark_dirty)
3858         /* Mark superblock as dirty */
3859         if (H5F_super_dirty(f) < 0)
3860             HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty")
3861 
3862 done:
3863     FUNC_LEAVE_NOAPI(ret_value)
3864 } /* H5F__format_convert() */
3865 
3866 /*-------------------------------------------------------------------------
3867  * Function:    H5F_get_file_id
3868  *
3869  * Purpose:     The private version of H5Iget_file_id(), obtains the file
3870  *              ID given an object ID.
3871  *
3872  * Return:      Success:    The file ID associated with the object
3873  *              Failure:    H5I_INVALID_HID
3874  *
3875  *-------------------------------------------------------------------------
3876  */
3877 hid_t
H5F_get_file_id(H5VL_object_t * vol_obj,H5I_type_t obj_type,hbool_t app_ref)3878 H5F_get_file_id(H5VL_object_t *vol_obj, H5I_type_t obj_type, hbool_t app_ref)
3879 {
3880     void *            vol_obj_file = NULL;               /* File object pointer */
3881     H5VL_loc_params_t loc_params;                        /* Location parameters */
3882     hid_t             file_id         = H5I_INVALID_HID; /* File ID for object */
3883     hbool_t           vol_wrapper_set = FALSE; /* Whether the VOL object wrapping context was set up */
3884     hid_t             ret_value       = H5I_INVALID_HID; /* Return value */
3885 
3886     FUNC_ENTER_NOAPI(H5I_INVALID_HID)
3887 
3888     /* Set location parameters */
3889     loc_params.type     = H5VL_OBJECT_BY_SELF;
3890     loc_params.obj_type = obj_type;
3891 
3892     /* Retrieve VOL file from object */
3893     if (H5VL_object_get(vol_obj, &loc_params, H5VL_OBJECT_GET_FILE, H5P_DATASET_XFER_DEFAULT, H5_REQUEST_NULL,
3894                         &vol_obj_file) < 0)
3895         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "can't retrieve file from object")
3896 
3897     /* Check if the file's ID already exists */
3898     if (H5I_find_id(vol_obj_file, H5I_FILE, &file_id) < 0)
3899         HGOTO_ERROR(H5E_FILE, H5E_CANTGET, H5I_INVALID_HID, "getting file ID failed")
3900 
3901     /* If the ID does not exist, register it with the VOL connector */
3902     if (H5I_INVALID_HID == file_id) {
3903         /* Set wrapper info in API context */
3904         if (H5VL_set_vol_wrapper(vol_obj) < 0)
3905             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set VOL wrapper info")
3906         vol_wrapper_set = TRUE;
3907 
3908         if ((file_id = H5VL_wrap_register(H5I_FILE, vol_obj_file, app_ref)) < 0)
3909             HGOTO_ERROR(H5E_FILE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to atomize file handle")
3910     } /* end if */
3911     else {
3912         /* Increment ref count on existing ID */
3913         if (H5I_inc_ref(file_id, app_ref) < 0)
3914             HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "incrementing file ID failed")
3915     } /* end else */
3916 
3917     /* Set return value */
3918     ret_value = file_id;
3919 
3920 done:
3921     /* Reset object wrapping info in API context */
3922     if (vol_wrapper_set && H5VL_reset_vol_wrapper() < 0)
3923         HDONE_ERROR(H5E_FILE, H5E_CANTRESET, H5I_INVALID_HID, "can't reset VOL wrapper info")
3924 
3925     FUNC_LEAVE_NOAPI(ret_value)
3926 } /* end H5F_get_file_id() */
3927 
3928 /*-------------------------------------------------------------------------
3929  * Function:    H5F_set_min_dset_ohdr
3930  *
3931  * Purpose:     Set the crt_dset_ohdr_flag field with a new value.
3932  *
3933  * Return:      SUCCEED/FAIL
3934  *-------------------------------------------------------------------------
3935  */
3936 herr_t
H5F_set_min_dset_ohdr(H5F_t * f,hbool_t minimize)3937 H5F_set_min_dset_ohdr(H5F_t *f, hbool_t minimize)
3938 {
3939     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
3940     FUNC_ENTER_NOAPI_NOINIT_NOERR
3941 
3942     /* Sanity check */
3943     HDassert(f);
3944     HDassert(f->shared);
3945 
3946     f->shared->crt_dset_min_ohdr_flag = minimize;
3947 
3948     FUNC_LEAVE_NOAPI(SUCCEED)
3949 } /* H5F_set_min_dset_ohdr() */
3950