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