Coverage Report

Created: 2026-08-31 06:23

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