Coverage Report

Created: 2026-01-08 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5.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
#include "H5module.h" /* This source code file is part of the H5 module */
17
18
/***********/
19
/* Headers */
20
/***********/
21
#include "H5private.h"   /* Generic Functions                        */
22
#include "H5ACprivate.h" /* Metadata cache                           */
23
#include "H5CXprivate.h" /* API Contexts                             */
24
#include "H5Dprivate.h"  /* Datasets                                 */
25
#include "H5Eprivate.h"  /* Error handling                           */
26
#include "H5FLprivate.h" /* Free lists                               */
27
#include "H5FSprivate.h" /* File free space                          */
28
#include "H5Lprivate.h"  /* Links                                    */
29
#include "H5MMprivate.h" /* Memory management                        */
30
#include "H5Pprivate.h"  /* Property lists                           */
31
#include "H5PLprivate.h" /* Plugins                                  */
32
#include "H5SLprivate.h" /* Skip lists                               */
33
#include "H5Tprivate.h"  /* Datatypes                                */
34
#include "H5TSprivate.h" /* Threadsafety                             */
35
36
/****************/
37
/* Local Macros */
38
/****************/
39
40
/******************/
41
/* Local Typedefs */
42
/******************/
43
44
/********************/
45
/* Package Typedefs */
46
/********************/
47
48
/* Node for list of 'atclose' routines to invoke at library shutdown */
49
typedef struct H5_atclose_node_t {
50
    H5_atclose_func_t         func; /* Function to invoke */
51
    void                     *ctx;  /* Context to pass to function */
52
    struct H5_atclose_node_t *next; /* Pointer to next node in list */
53
} H5_atclose_node_t;
54
55
/********************/
56
/* Local Prototypes */
57
/********************/
58
static void H5__debug_mask(const char *);
59
#ifdef H5_HAVE_PARALLEL
60
static int H5__mpi_delete_cb(MPI_Comm comm, int keyval, void *attr_val, int *flag);
61
#endif /*H5_HAVE_PARALLEL*/
62
static herr_t H5_check_version(unsigned majnum, unsigned minnum, unsigned relnum);
63
64
/*********************/
65
/* Package Variables */
66
/*********************/
67
68
/* Package initialization variable */
69
bool H5_PKG_INIT_VAR = false;
70
71
/*****************************/
72
/* Library Private Variables */
73
/*****************************/
74
75
/* Library known incompatible minor versions; develop releases are incompatible
76
 * by design. 999 is entered for testing an exception as a minor version that
77
 * will never occur.  Any released minor version found to be truly incompatible
78
 * (this should never happen) should be added to the list with 999.  999 alone
79
 * in the list indicates that there are no incompatible minor versions. */
80
static const unsigned VERS_MINOR_EXCEPTIONS[] = {999};
81
/* The size should be set to the number of minor version exceptions in the list. */
82
static const unsigned VERS_MINOR_EXCEPTIONS_SIZE = 1;
83
84
/* Library init / term status (global) */
85
bool H5_libinit_g = false; /* Library hasn't been initialized */
86
bool H5_libterm_g = false; /* Library isn't being shutdown */
87
88
char        H5_lib_vers_info_g[] = H5_VERS_INFO;
89
static bool H5_dont_atexit_g     = false;
90
H5_debug_t  H5_debug_g; /* debugging info */
91
92
/*******************/
93
/* Local Variables */
94
/*******************/
95
96
/* Linked list of registered 'atclose' functions to invoke at library shutdown */
97
static H5_atclose_node_t *H5_atclose_head = NULL;
98
99
/* Declare a free list to manage the H5_atclose_node_t struct */
100
H5FL_DEFINE_STATIC(H5_atclose_node_t);
101
102
/*--------------------------------------------------------------------------
103
NAME
104
    H5__init_package -- Initialize interface-specific information
105
USAGE
106
    herr_t H5__init_package()
107
RETURNS
108
    Non-negative on success/Negative on failure
109
DESCRIPTION
110
    Initializes any interface-specific data or routines.
111
--------------------------------------------------------------------------*/
112
herr_t
113
H5__init_package(void)
114
1
{
115
1
    herr_t ret_value = SUCCEED; /* Return value */
116
117
1
    FUNC_ENTER_PACKAGE
118
119
    /* Run the library initialization routine, if it hasn't already ran */
120
1
    if (!H5_INIT_GLOBAL && !H5_TERM_GLOBAL)
121
1
        if (H5_init_library() < 0)
122
0
            HGOTO_ERROR(H5E_LIB, H5E_CANTINIT, FAIL, "unable to initialize library");
123
124
1
done:
125
1
    FUNC_LEAVE_NOAPI(ret_value)
126
1
} /* end H5__init_package() */
127
128
/*--------------------------------------------------------------------------
129
 * NAME
130
 *   H5_init_library -- Initialize library-global information
131
 * USAGE
132
 *    herr_t H5_init_library()
133
 *
134
 * RETURNS
135
 *    Non-negative on success/Negative on failure
136
 *
137
 * DESCRIPTION
138
 *    Initializes any library-global data or routines.
139
 *
140
 *--------------------------------------------------------------------------
141
 */
142
herr_t
143
H5_init_library(void)
144
2
{
145
2
    herr_t ret_value = SUCCEED;
146
147
2
    FUNC_ENTER_NOAPI(FAIL)
148
149
    /* Run the library initialization routine, if it hasn't already run */
150
2
    if (H5_INIT_GLOBAL || H5_TERM_GLOBAL)
151
1
        HGOTO_DONE(SUCCEED);
152
153
    /* Check library version */
154
    /* (Will abort() on failure) */
155
1
    H5_check_version(H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE);
156
157
    /* Set the 'library initialized' flag as early as possible, to avoid
158
     * possible re-entrancy.
159
     */
160
1
    H5_INIT_GLOBAL = true;
161
162
    /* Make sure we picked a good type for ssize_t if it wasn't present */
163
1
    HDcompile_assert(sizeof(size_t) == sizeof(ssize_t));
164
165
#ifdef H5_HAVE_PARALLEL
166
    {
167
        int mpi_initialized;
168
        int mpi_finalized;
169
        int mpi_code;
170
171
        MPI_Initialized(&mpi_initialized);
172
        MPI_Finalized(&mpi_finalized);
173
174
        /* add an attribute on MPI_COMM_SELF to call H5_term_library
175
           when it is destroyed, i.e. on MPI_Finalize */
176
        if (mpi_initialized && !mpi_finalized) {
177
            int key_val;
178
179
            if (MPI_SUCCESS != (mpi_code = MPI_Comm_create_keyval(
180
                                    MPI_COMM_NULL_COPY_FN, (MPI_Comm_delete_attr_function *)H5__mpi_delete_cb,
181
                                    &key_val, NULL)))
182
                HMPI_GOTO_ERROR(FAIL, "MPI_Comm_create_keyval failed", mpi_code)
183
184
            if (MPI_SUCCESS != (mpi_code = MPI_Comm_set_attr(MPI_COMM_SELF, key_val, NULL)))
185
                HMPI_GOTO_ERROR(FAIL, "MPI_Comm_set_attr failed", mpi_code)
186
187
            if (MPI_SUCCESS != (mpi_code = MPI_Comm_free_keyval(&key_val)))
188
                HMPI_GOTO_ERROR(FAIL, "MPI_Comm_free_keyval failed", mpi_code)
189
        }
190
    }
191
#endif /*H5_HAVE_PARALLEL*/
192
193
    /*
194
     * Make sure the package information is updated.
195
     */
196
1
    memset(&H5_debug_g, 0, sizeof H5_debug_g);
197
1
    H5_debug_g.pkg[H5_PKG_A].name  = "a";
198
1
    H5_debug_g.pkg[H5_PKG_AC].name = "ac";
199
1
    H5_debug_g.pkg[H5_PKG_B].name  = "b";
200
1
    H5_debug_g.pkg[H5_PKG_D].name  = "d";
201
1
    H5_debug_g.pkg[H5_PKG_E].name  = "e";
202
1
    H5_debug_g.pkg[H5_PKG_F].name  = "f";
203
1
    H5_debug_g.pkg[H5_PKG_G].name  = "g";
204
1
    H5_debug_g.pkg[H5_PKG_HG].name = "hg";
205
1
    H5_debug_g.pkg[H5_PKG_HL].name = "hl";
206
1
    H5_debug_g.pkg[H5_PKG_I].name  = "i";
207
1
    H5_debug_g.pkg[H5_PKG_M].name  = "m";
208
1
    H5_debug_g.pkg[H5_PKG_MF].name = "mf";
209
1
    H5_debug_g.pkg[H5_PKG_MM].name = "mm";
210
1
    H5_debug_g.pkg[H5_PKG_O].name  = "o";
211
1
    H5_debug_g.pkg[H5_PKG_P].name  = "p";
212
1
    H5_debug_g.pkg[H5_PKG_S].name  = "s";
213
1
    H5_debug_g.pkg[H5_PKG_T].name  = "t";
214
1
    H5_debug_g.pkg[H5_PKG_V].name  = "v";
215
1
    H5_debug_g.pkg[H5_PKG_VL].name = "vl";
216
1
    H5_debug_g.pkg[H5_PKG_Z].name  = "z";
217
218
    /*
219
     * Install atexit() library cleanup routines unless the H5dont_atexit()
220
     * has been called.  Once we add something to the atexit() list it stays
221
     * there permanently, so we set H5_dont_atexit_g after we add it to prevent
222
     * adding it again later if the library is closed and reopened.
223
     */
224
1
    if (!H5_dont_atexit_g) {
225
226
#ifdef H5_HAVE_THREADSAFE_API
227
        /* Clean up thread resources.
228
         *
229
         * This must be pushed before the library cleanup code so it's
230
         * executed in LIFO order (i.e., last).
231
         */
232
        (void)atexit(H5TS_term_package);
233
#endif /* H5_HAVE_THREADSAFE_API */
234
235
        /* Normal library termination code */
236
1
        (void)atexit(H5_term_library);
237
238
1
        H5_dont_atexit_g = true;
239
1
    } /* end if */
240
241
    /*
242
     * Initialize interfaces that use macros of the form "(H5OPEN <var>)", so
243
     * that the variable returned through the macros has been initialized.
244
     * Also initialize some interfaces that might not be able to initialize
245
     * themselves soon enough.
246
     *
247
     * Interfaces returning variables through a macro: H5E, H5FD, H5O, H5P, H5T
248
     *
249
     * The link interface needs to be initialized so that the external link
250
     *   class is registered.
251
     *
252
     * The FS module needs to be initialized as a result of the fix for HDFFV-10160:
253
     *   It might not be initialized during normal file open.
254
     *   When the application does not close the file, routines in the module might
255
     *   be called via H5_term_library() when shutting down the file.
256
     *
257
     * The dataspace interface needs to be initialized so that future IDs for
258
     *   dataspaces work.
259
     *
260
     * The VFD & VOL interfaces need to be initialized before the H5P interface
261
     *   so that the default VFD and default VOL connector are ready for the
262
     *   default FAPL.
263
     *
264
     */
265
1
    if (H5E_init() < 0)
266
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface");
267
1
    if (H5FD_init() < 0)
268
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize VFL interface");
269
1
    if (H5VL_init_phase1() < 0)
270
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface");
271
1
    if (H5P_init_phase1() < 0)
272
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface");
273
1
    if (H5L_init() < 0)
274
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize link interface");
275
1
    if (H5O_init() < 0)
276
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize object interface");
277
1
    if (H5FS_init() < 0)
278
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface");
279
1
    if (H5S_init() < 0)
280
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataspace interface");
281
1
    if (H5T_init() < 0)
282
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize datatype interface");
283
284
    /* Finish initializing interfaces that depend on the interfaces above */
285
1
    if (H5P_init_phase2() < 0)
286
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface");
287
1
    if (H5VL_init_phase2() < 0)
288
0
        HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize vol interface");
289
290
    /* Debugging? */
291
1
    H5__debug_mask("-all");
292
1
    H5__debug_mask(getenv("HDF5_DEBUG"));
293
294
2
done:
295
2
    FUNC_LEAVE_NOAPI(ret_value)
296
2
} /* end H5_init_library() */
297
298
/*-------------------------------------------------------------------------
299
 * Function:    H5_term_library
300
 *
301
 * Purpose:    Terminate interfaces in a well-defined order due to
302
 *        dependencies among the interfaces, then terminate
303
 *        library-specific data.
304
 *
305
 * Return:    void
306
 *
307
 *-------------------------------------------------------------------------
308
 */
309
void
310
H5_term_library(void)
311
1
{
312
1
    int         pending, ntries = 0, n;
313
1
    size_t      at = 0;
314
1
    char        loop[1024];
315
1
    H5E_auto2_t func;
316
1
    H5CX_node_t api_ctx = {{0}, NULL}; /* API context node to push */
317
318
    /* Acquire the API lock */
319
    H5_API_SETUP_PUBLIC_API_VARS
320
    H5_API_LOCK
321
322
    /* Don't do anything if the library is already closed */
323
1
    if (!H5_INIT_GLOBAL)
324
0
        goto done;
325
326
    /* Indicate that the library is being shut down */
327
1
    H5_TERM_GLOBAL = true;
328
329
    /* Push the API context without checking for errors */
330
1
    H5CX_push(&api_ctx);
331
332
    /* Check if we should display error output */
333
1
    (void)H5E_get_default_auto_func(&func);
334
335
    /* Iterate over the list of 'atclose' callbacks that have been registered */
336
1
    if (H5_atclose_head) {
337
0
        H5_atclose_node_t *curr_atclose; /* Current 'atclose' node */
338
339
        /* Iterate over all 'atclose' nodes, making callbacks */
340
0
        curr_atclose = H5_atclose_head;
341
0
        while (curr_atclose) {
342
0
            H5_atclose_node_t *tmp_atclose; /* Temporary pointer to 'atclose' node */
343
344
            /* Prepare & restore library for user callback */
345
0
            H5_BEFORE_USER_CB_NOCHECK
346
0
                {
347
                    /* Invoke callback, providing context */
348
0
                    (*curr_atclose->func)(curr_atclose->ctx);
349
0
                }
350
0
            H5_AFTER_USER_CB_NOCHECK
351
352
            /* Advance to next node and free this one */
353
0
            tmp_atclose  = curr_atclose;
354
0
            curr_atclose = curr_atclose->next;
355
0
            H5FL_FREE(H5_atclose_node_t, tmp_atclose);
356
0
        } /* end while */
357
358
        /* Reset list head, in case library is re-initialized */
359
0
        H5_atclose_head = NULL;
360
0
    } /* end if */
361
362
    /*
363
     * Terminate each interface. The termination functions return a positive
364
     * value if they do something that might affect some other interface in a
365
     * way that would necessitate some cleanup work in the other interface.
366
     */
367
1
#define DOWN(F)                                                                                              \
368
2.44k
    (((n = H5##F##_term_package()) && (at + 8) < sizeof loop)                                                \
369
2.44k
         ? (sprintf(loop + at, "%s%s", (at ? "," : ""), #F), at += strlen(loop + at), n)                     \
370
2.44k
         : ((n > 0 && (at + 5) < sizeof loop) ? (sprintf(loop + at, "..."), at += strlen(loop + at), n)      \
371
2.34k
                                              : n))
372
373
101
    do {
374
101
        pending = 0;
375
376
        /* Try to organize these so the "higher" level components get shut
377
         * down before "lower" level components that they might rely on. -QAK
378
         */
379
380
        /* Close the event sets first, so that all asynchronous operations
381
         * complete before anything else attempts to shut down.
382
         */
383
101
        pending += DOWN(ES);
384
385
        /* Close down the user-facing interfaces, after the event sets */
386
101
        if (pending == 0) {
387
            /* Close the interfaces dependent on others */
388
101
            pending += DOWN(L);
389
390
            /* Close the "top" of various interfaces (IDs, etc) but don't shut
391
             * down the whole interface yet, so that the object header messages
392
             * get serialized correctly for entries in the metadata cache and the
393
             * symbol table entry in the superblock gets serialized correctly, etc.
394
             * all of which is performed in the 'F' shutdown.
395
             */
396
101
            pending += DOWN(A_top);
397
101
            pending += DOWN(D_top);
398
101
            pending += DOWN(G_top);
399
101
            pending += DOWN(M_top);
400
101
            pending += DOWN(S_top);
401
101
            pending += DOWN(T_top);
402
101
        } /* end if */
403
404
        /* Don't shut down the file code until objects in files are shut down */
405
101
        if (pending == 0)
406
100
            pending += DOWN(F);
407
408
        /* Don't shut down the property list code until all objects that might
409
         * use property lists are shut down */
410
101
        if (pending == 0)
411
99
            pending += DOWN(P);
412
413
        /* Wait to shut down the "bottom" of various interfaces until the
414
         * files are closed, so pieces of the file can be serialized
415
         * correctly.
416
         */
417
101
        if (pending == 0) {
418
            /* Shut down the "bottom" of the attribute, dataset, group,
419
             * dataspace, and datatype interfaces, fully closing
420
             * out the interfaces now.
421
             */
422
97
            pending += DOWN(A);
423
97
            pending += DOWN(D);
424
97
            pending += DOWN(G);
425
97
            pending += DOWN(M);
426
97
            pending += DOWN(S);
427
97
            pending += DOWN(T);
428
97
        } /* end if */
429
430
        /* Don't shut down "low-level" components until "high-level" components
431
         * have successfully shut down.  This prevents property lists and IDs
432
         * from being closed "out from underneath" of the high-level objects
433
         * that depend on them. -QAK
434
         */
435
101
        if (pending == 0) {
436
97
            pending += DOWN(AC);
437
            /* Shut down the "pluggable" interfaces, before the plugin framework */
438
97
            pending += DOWN(Z);
439
97
            pending += DOWN(FD);
440
97
            pending += DOWN(VL);
441
            /* Don't shut down the plugin code until all "pluggable" interfaces (Z, FD, PL) are shut down */
442
97
            if (pending == 0)
443
95
                pending += DOWN(PL);
444
            /* Don't shut down the error code until other APIs which use it are shut down */
445
97
            if (pending == 0)
446
94
                pending += DOWN(E);
447
            /* Don't shut down the ID code until other APIs which use them are shut down */
448
97
            if (pending == 0)
449
93
                pending += DOWN(I);
450
            /* Don't shut down the skip list code until everything that uses it is down */
451
97
            if (pending == 0)
452
93
                pending += DOWN(SL);
453
            /* Don't shut down the free list code until everything that uses it is down */
454
97
            if (pending == 0)
455
92
                pending += DOWN(FL);
456
            /* Don't shut down the API context code until _everything_ else is down */
457
97
            if (pending == 0)
458
0
                pending += DOWN(CX);
459
97
        } /* end if */
460
101
    } while (pending && ntries++ < 100);
461
462
1
    if (pending) {
463
        /* Only display the error message if the user is interested in them. */
464
1
        if (func) {
465
1
            fprintf(stderr, "HDF5: infinite loop closing library\n");
466
1
            fprintf(stderr, "      %s\n", loop);
467
#ifndef NDEBUG
468
            abort();
469
#endif
470
1
        }
471
1
    }
472
473
    /* Free open debugging streams */
474
1
    while (H5_debug_g.open_stream) {
475
0
        H5_debug_open_stream_t *tmp_open_stream;
476
477
0
        tmp_open_stream = H5_debug_g.open_stream;
478
0
        (void)fclose(H5_debug_g.open_stream->stream);
479
0
        H5_debug_g.open_stream = H5_debug_g.open_stream->next;
480
0
        (void)H5MM_free(tmp_open_stream);
481
0
    } /* end while */
482
483
    /* Reset flag indicating that the library is being shut down */
484
1
    H5_TERM_GLOBAL = false;
485
486
    /* Mark library as closed */
487
1
    H5_INIT_GLOBAL = false;
488
489
    /* Don't pop the API context (i.e. H5CX_pop), since it's been shut down already */
490
491
1
done:
492
    /* Release API lock */
493
    H5_API_UNLOCK
494
495
1
    return;
496
1
} /* end H5_term_library() */
497
498
/*-------------------------------------------------------------------------
499
 * Function:    H5dont_atexit
500
 *
501
 * Purpose:    Indicates that the library is not to clean up after itself
502
 *        when the application exits by calling exit() or returning
503
 *        from main().  This function must be called before any other
504
 *        HDF5 function or constant is used or it will have no effect.
505
 *
506
 *        If this function is used then certain memory buffers will not
507
 *        be de-allocated nor will open files be flushed automatically.
508
 *        The application may still call H5close() explicitly to
509
 *        accomplish these things.
510
 *
511
 * Return:    Success:    non-negative
512
 *
513
 *        Failure:    negative if this function is called more than
514
 *                once or if it is called too late.
515
 *
516
 *-------------------------------------------------------------------------
517
 */
518
herr_t
519
H5dont_atexit(void)
520
0
{
521
0
    herr_t ret_value = SUCCEED; /* Return value */
522
523
0
    FUNC_ENTER_API_NOINIT_NOERR
524
525
0
    if (H5_dont_atexit_g)
526
0
        ret_value = FAIL;
527
0
    else
528
0
        H5_dont_atexit_g = true;
529
530
0
    FUNC_LEAVE_API_NOERR(ret_value)
531
0
} /* end H5dont_atexit() */
532
533
/*-------------------------------------------------------------------------
534
 * Function:    H5garbage_collect
535
 *
536
 * Purpose:    Walks through all the garbage collection routines for the
537
 *        library, which are supposed to free any unused memory they have
538
 *        allocated.
539
 *
540
 *      These should probably be registered dynamically in a linked list of
541
 *          functions to call, but there aren't that many right now, so we
542
 *          hard-wire them...
543
 *
544
 * Return:    Success:    non-negative
545
 *
546
 *        Failure:    negative
547
 *
548
 *-------------------------------------------------------------------------
549
 */
550
herr_t
551
H5garbage_collect(void)
552
0
{
553
0
    herr_t ret_value = SUCCEED;
554
555
0
    FUNC_ENTER_API(FAIL)
556
557
    /* Call the garbage collection routines in the library */
558
0
    if (H5FL_garbage_coll() < 0)
559
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't garbage collect objects");
560
561
0
done:
562
0
    FUNC_LEAVE_API(ret_value)
563
0
} /* end H5garbage_collect() */
564
565
/*-------------------------------------------------------------------------
566
 * Function:    H5set_free_list_limits
567
 *
568
 * Purpose:    Sets limits on the different kinds of free lists.  Setting a value
569
 *      of -1 for a limit means no limit of that type.  These limits are global
570
 *      for the entire library.  Each "global" limit only applies to free lists
571
 *      of that type, so if an application sets a limit of 1 MB on each of the
572
 *      global lists, up to 3 MB of total storage might be allocated (1MB on
573
 *      each of regular, array and block type lists).
574
 *
575
 *      The settings for block free lists are duplicated to factory free lists.
576
 *      Factory free list limits cannot be set independently currently.
577
 *
578
 * Parameters:
579
 *  int reg_global_lim;  IN: The limit on all "regular" free list memory used
580
 *  int reg_list_lim;    IN: The limit on memory used in each "regular" free list
581
 *  int arr_global_lim;  IN: The limit on all "array" free list memory used
582
 *  int arr_list_lim;    IN: The limit on memory used in each "array" free list
583
 *  int blk_global_lim;  IN: The limit on all "block" free list memory used
584
 *  int blk_list_lim;    IN: The limit on memory used in each "block" free list
585
 *
586
 * Return:    Success:    non-negative
587
 *
588
 *        Failure:    negative
589
 *
590
 *-------------------------------------------------------------------------
591
 */
592
herr_t
593
H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim, int arr_list_lim,
594
                       int blk_global_lim, int blk_list_lim)
595
0
{
596
0
    herr_t ret_value = SUCCEED;
597
598
0
    FUNC_ENTER_API(FAIL)
599
600
    /* Call the free list function to actually set the limits */
601
0
    if (H5FL_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim,
602
0
                                  blk_list_lim, blk_global_lim, blk_list_lim) < 0)
603
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "can't set garbage collection limits");
604
605
0
done:
606
0
    FUNC_LEAVE_API(ret_value)
607
0
} /* end H5set_free_list_limits() */
608
609
/*-------------------------------------------------------------------------
610
 * Function:    H5get_free_list_sizes
611
 *
612
 * Purpose:    Gets the current size of the different kinds of free lists that
613
 *    the library uses to manage memory.  The free list sizes can be set with
614
 *    H5set_free_list_limits and garbage collected with H5garbage_collect.
615
 *      These lists are global for the entire library.
616
 *
617
 * Parameters:
618
 *  size_t *reg_size;    OUT: The current size of all "regular" free list memory used
619
 *  size_t *arr_size;    OUT: The current size of all "array" free list memory used
620
 *  size_t *blk_size;    OUT: The current size of all "block" free list memory used
621
 *  size_t *fac_size;    OUT: The current size of all "factory" free list memory used
622
 *
623
 * Return:    Success:    non-negative
624
 *        Failure:    negative
625
 *
626
 *-------------------------------------------------------------------------
627
 */
628
herr_t
629
H5get_free_list_sizes(size_t *reg_size /*out*/, size_t *arr_size /*out*/, size_t *blk_size /*out*/,
630
                      size_t *fac_size /*out*/)
631
0
{
632
0
    herr_t ret_value = SUCCEED; /* Return value */
633
634
0
    FUNC_ENTER_API(FAIL)
635
636
    /* Call the free list function to actually get the sizes */
637
0
    if (H5FL_get_free_list_sizes(reg_size, arr_size, blk_size, fac_size) < 0)
638
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGET, FAIL, "can't get garbage collection sizes");
639
640
0
done:
641
0
    FUNC_LEAVE_API(ret_value)
642
0
} /* end H5get_free_list_sizes() */
643
644
/*-------------------------------------------------------------------------
645
 * Function:    H5__debug_mask
646
 *
647
 * Purpose:     Set runtime debugging flags according to the string S.  The
648
 *              string should contain file numbers and package names
649
 *              separated by other characters. A file number applies to all
650
 *              following package names up to the next file number. The
651
 *              initial file number is `2' (the standard error stream). Each
652
 *              package name can be preceded by a `+' or `-' to add or remove
653
 *              the package from the debugging list (`+' is the default). The
654
 *              special name `all' means all packages.
655
 *
656
 *              The name `trace' indicates that API tracing is to be turned
657
 *              on or off.
658
 *
659
 *              The name 'ttop' indicates that only top-level API calls
660
 *              should be shown. This also turns on tracing as if the
661
 *              'trace' word was shown.
662
 *
663
 * Return:      void
664
 *
665
 *-------------------------------------------------------------------------
666
 */
667
static void
668
H5__debug_mask(const char *s)
669
2
{
670
2
    FILE  *stream = stderr;
671
2
    char   pkg_name[32], *rest;
672
2
    size_t i;
673
2
    bool   clear;
674
675
3
    while (s && *s) {
676
677
1
        if (isalpha(*s) || '-' == *s || '+' == *s) {
678
679
            /* Enable or Disable debugging? */
680
1
            if ('-' == *s) {
681
1
                clear = true;
682
1
                s++;
683
1
            }
684
0
            else if ('+' == *s) {
685
0
                clear = false;
686
0
                s++;
687
0
            }
688
0
            else {
689
0
                clear = false;
690
0
            } /* end if */
691
692
            /* Get the name */
693
3
            for (i = 0; isalpha(*s); i++, s++)
694
3
                if (i < sizeof pkg_name)
695
3
                    pkg_name[i] = *s;
696
1
            pkg_name[MIN(sizeof(pkg_name) - 1, i)] = '\0';
697
698
            /* Trace, all, or one? */
699
1
            if (!strcmp(pkg_name, "trace")) {
700
0
                H5_debug_g.trace = clear ? NULL : stream;
701
0
            }
702
1
            else if (!strcmp(pkg_name, "ttop")) {
703
0
                H5_debug_g.trace = stream;
704
0
                H5_debug_g.ttop  = (bool)!clear;
705
0
            }
706
1
            else if (!strcmp(pkg_name, "ttimes")) {
707
0
                H5_debug_g.trace  = stream;
708
0
                H5_debug_g.ttimes = (bool)!clear;
709
0
            }
710
1
            else if (!strcmp(pkg_name, "all")) {
711
21
                for (i = 0; i < (size_t)H5_NPKGS; i++)
712
20
                    H5_debug_g.pkg[i].stream = clear ? NULL : stream;
713
1
            }
714
0
            else {
715
0
                for (i = 0; i < (size_t)H5_NPKGS; i++) {
716
0
                    if (!strcmp(H5_debug_g.pkg[i].name, pkg_name)) {
717
0
                        H5_debug_g.pkg[i].stream = clear ? NULL : stream;
718
0
                        break;
719
0
                    } /* end if */
720
0
                }     /* end for */
721
0
                if (i >= (size_t)H5_NPKGS)
722
0
                    fprintf(stderr, "HDF5_DEBUG: ignored %s\n", pkg_name);
723
0
            } /* end if-else */
724
1
        }
725
0
        else if (isdigit(*s)) {
726
0
            int                     fd = (int)strtol(s, &rest, 0);
727
0
            H5_debug_open_stream_t *open_stream;
728
729
0
            if ((stream = HDfdopen(fd, "w")) != NULL) {
730
0
                (void)HDsetvbuf(stream, NULL, _IOLBF, (size_t)0);
731
732
0
                if (NULL ==
733
0
                    (open_stream = (H5_debug_open_stream_t *)H5MM_malloc(sizeof(H5_debug_open_stream_t)))) {
734
0
                    (void)fclose(stream);
735
0
                    return;
736
0
                } /* end if */
737
738
0
                open_stream->stream    = stream;
739
0
                open_stream->next      = H5_debug_g.open_stream;
740
0
                H5_debug_g.open_stream = open_stream;
741
0
            } /* end if */
742
743
0
            s = rest;
744
0
        }
745
0
        else {
746
0
            s++;
747
0
        } /* end if-else */
748
1
    }     /* end while */
749
2
} /* end H5__debug_mask() */
750
751
#ifdef H5_HAVE_PARALLEL
752
753
/*-------------------------------------------------------------------------
754
 * Function:    H5__mpi_delete_cb
755
 *
756
 * Purpose:    Callback attribute on MPI_COMM_SELF to terminate the HDF5
757
 *              library when the communicator is destroyed, i.e. on MPI_Finalize.
758
 *
759
 * Return:    MPI_SUCCESS
760
 *
761
 *-------------------------------------------------------------------------
762
 */
763
static int
764
H5__mpi_delete_cb(MPI_Comm H5_ATTR_UNUSED comm, int H5_ATTR_UNUSED keyval, void H5_ATTR_UNUSED *attr_val,
765
                  int H5_ATTR_UNUSED *flag)
766
{
767
    H5_term_library();
768
    return MPI_SUCCESS;
769
}
770
#endif /*H5_HAVE_PARALLEL*/
771
772
/*-------------------------------------------------------------------------
773
 * Function:    H5get_libversion
774
 *
775
 * Purpose:    Returns the library version numbers through arguments. MAJNUM
776
 *        will be the major revision number of the library, MINNUM the
777
 *        minor revision number, and RELNUM the release revision number.
778
 *
779
 * Note:    When printing an HDF5 version number it should be printed as
780
 *
781
 *         printf("%u.%u.%u", maj, min, rel)        or
782
 *        printf("version %u.%u release %u", maj, min, rel)
783
 *
784
 * Return:    Non-negative on success/Negative on failure
785
 *
786
 *-------------------------------------------------------------------------
787
 */
788
herr_t
789
H5get_libversion(unsigned *majnum /*out*/, unsigned *minnum /*out*/, unsigned *relnum /*out*/)
790
0
{
791
0
    herr_t ret_value = SUCCEED;
792
793
0
    FUNC_ENTER_API(FAIL)
794
795
    /* Set the version information */
796
0
    if (majnum)
797
0
        *majnum = H5_VERS_MAJOR;
798
0
    if (minnum)
799
0
        *minnum = H5_VERS_MINOR;
800
0
    if (relnum)
801
0
        *relnum = H5_VERS_RELEASE;
802
803
0
done:
804
0
    FUNC_LEAVE_API(ret_value)
805
0
} /* end H5get_libversion() */
806
807
/*-------------------------------------------------------------------------
808
 * Function:    H5__check_version
809
 *
810
 * Purpose:     Internal routine which Verifies that the arguments match the
811
 *              version numbers compiled into the library.
812
 *
813
 *              Within major.minor.release version, the expectation
814
 *              is that all minor versions are compatible, exceptions to
815
 *              this rule must be added to the VERS_MINOR_EXCEPTIONS list.
816
 *
817
 * Return:      Success:    SUCCEED
818
 *              Failure:    abort()
819
 *
820
 *-------------------------------------------------------------------------
821
 */
822
#define VERSION_MISMATCH_WARNING                                                                             \
823
1
    "Warning! ***HDF5 library version mismatched error***\n"                                                 \
824
1
    "The HDF5 header files used to compile this application do not match\n"                                  \
825
1
    "the version used by the HDF5 library to which this application is linked.\n"                            \
826
1
    "Data corruption or segmentation faults may occur if the application continues.\n"                       \
827
1
    "This can happen when an application was compiled by one version of HDF5 but\n"                          \
828
1
    "linked with a different version of static or shared HDF5 library.\n"                                    \
829
1
    "You should recompile the application or check your shared library related\n"                            \
830
1
    "settings such as 'LD_LIBRARY_PATH'.\n"
831
#define MINOR_VERSION_MISMATCH_WARNING                                                                       \
832
1
    "Warning! ***HDF5 library minor version mismatched error***\n"                                           \
833
1
    "The HDF5 header files used to compile this application are not compatible with\n"                       \
834
1
    "the version used by the HDF5 library to which this application is linked.\n"                            \
835
1
    "Data corruption or segmentation faults may occur if the application continues.\n"                       \
836
1
    "This can happen when an application was compiled by one version of HDF5 but\n"                          \
837
1
    "linked with an incompatible version of static or shared HDF5 library.\n"                                \
838
1
    "You should recompile the application or check your shared library related\n"                            \
839
1
    "settings such as 'LD_LIBRARY_PATH'.\n"
840
#define MINOR_VERSION_FORWARD_COMPATIBLE_WARNING                                                             \
841
1
    "Warning! ***HDF5 library minor version forward compatibility error***\n"                                \
842
1
    "The HDF5 header files used to compile this application are from a newer\n"                              \
843
1
    "version of the HDF5 library than the one to which this application is linked.\n"                        \
844
1
    "Data corruption or segmentation faults may occur if the application continues.\n"                       \
845
1
    "This can happen when an application was compiled by a newer version of HDF5 but\n"                      \
846
1
    "linked with an older version of static or shared HDF5 library.\n"                                       \
847
1
    "You should recompile the application or check your shared library related\n"                            \
848
1
    "settings such as 'LD_LIBRARY_PATH'.\n"
849
850
static herr_t
851
H5_check_version(unsigned majnum, unsigned minnum, unsigned relnum)
852
1
{
853
1
    char                lib_str[256];
854
1
    char                substr[]                 = H5_VERS_SUBRELEASE;
855
1
    static bool         checked                  = false; /* If we've already checked the version info */
856
1
    static unsigned int disable_version_check    = 0;     /* Set if the version check should be disabled */
857
1
    static const char  *version_mismatch_warning = VERSION_MISMATCH_WARNING;
858
1
    static const char  *minor_version_mismatch_warning           = MINOR_VERSION_MISMATCH_WARNING;
859
1
    static const char  *minor_version_forward_compatible_warning = MINOR_VERSION_FORWARD_COMPATIBLE_WARNING;
860
1
    herr_t              ret_value                                = SUCCEED; /* Return value */
861
862
1
    FUNC_ENTER_NOAPI_NOINIT_NOERR
863
864
    /* Don't check again, if we already have */
865
1
    if (checked)
866
0
        HGOTO_DONE(SUCCEED);
867
868
1
    {
869
1
        const char *s; /* Environment string for disabling version check */
870
871
        /* Allow different versions of the header files and library? */
872
1
        s = getenv("HDF5_DISABLE_VERSION_CHECK");
873
874
1
        if (s && isdigit(*s))
875
0
            disable_version_check = (unsigned int)strtol(s, NULL, 0);
876
1
    }
877
878
    /* H5_VERS_MAJOR must match */
879
1
    if (H5_VERS_MAJOR != majnum) {
880
0
        switch (disable_version_check) {
881
0
            case 0:
882
0
                fprintf(stderr, "%s%s", version_mismatch_warning,
883
0
                        "You can, at your own risk, disable this warning by setting the environment\n"
884
0
                        "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n"
885
0
                        "Setting it to 2 or higher will suppress the warning messages totally.\n");
886
                /* Mention the versions we are referring to */
887
0
                fprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum,
888
0
                        (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
889
                /* Show library build settings if available */
890
0
                fprintf(stderr, "%s", H5build_settings);
891
892
                /* Bail out now. */
893
0
                fputs("Bye...\n", stderr);
894
0
                abort();
895
0
            case 1:
896
                /* continue with a warning */
897
                /* Note that the warning message is embedded in the format string.*/
898
0
                fprintf(stderr,
899
0
                        "%s'HDF5_DISABLE_VERSION_CHECK' "
900
0
                        "environment variable is set to %d, application will\n"
901
0
                        "continue at your own risk.\n",
902
0
                        version_mismatch_warning, disable_version_check);
903
                /* Mention the versions we are referring to */
904
0
                fprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum,
905
0
                        (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
906
                /* Show library build settings if available */
907
0
                fprintf(stderr, "%s", H5build_settings);
908
0
                break;
909
0
            default:
910
                /* 2 or higher: continue silently */
911
0
                break;
912
0
        } /* end switch */
913
914
0
    } /* end if (H5_VERS_MAJOR != majnum) */
915
916
    /* H5_VERS_MINOR should be compatible, we will only add checks for exceptions */
917
    /* Library develop minor versions are incompatible by design */
918
1
    if (H5_VERS_MINOR != minnum) {
919
0
        for (unsigned i = 0; i < VERS_MINOR_EXCEPTIONS_SIZE; i++) {
920
            /* Check for incompatible headers or incompatible library */
921
0
            if (VERS_MINOR_EXCEPTIONS[i] == minnum || VERS_MINOR_EXCEPTIONS[i] == H5_VERS_MINOR) {
922
0
                switch (disable_version_check) {
923
0
                    case 0:
924
0
                        fprintf(stderr, "%s%s", minor_version_mismatch_warning,
925
0
                                "You can, at your own risk, disable this warning by setting the environment\n"
926
0
                                "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n"
927
0
                                "Setting it to 2 or higher will suppress the warning messages totally.\n");
928
                        /* Mention the versions we are referring to */
929
0
                        fprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum,
930
0
                                (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
931
932
                        /* Bail out now. */
933
0
                        fputs("Bye...\n", stderr);
934
0
                        abort();
935
0
                    case 1:
936
                        /* continue with a warning */
937
                        /* Note that the warning message is embedded in the format string.*/
938
0
                        fprintf(stderr,
939
0
                                "%s'HDF5_DISABLE_VERSION_CHECK' "
940
0
                                "environment variable is set to %d, application will\n"
941
0
                                "continue at your own risk.\n",
942
0
                                minor_version_mismatch_warning, disable_version_check);
943
                        /* Mention the versions we are referring to */
944
0
                        fprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum,
945
0
                                (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
946
0
                        break;
947
0
                    default:
948
                        /* 2 or higher: continue silently */
949
0
                        break;
950
0
                } /* end switch */
951
952
0
            } /* end if */
953
954
0
        } /* end for */
955
956
        /* Check for forward compatibility usage. */
957
0
        if (minnum > H5_VERS_MINOR) {
958
0
            switch (disable_version_check) {
959
0
                case 0:
960
0
                    fprintf(stderr, "%s%s", minor_version_forward_compatible_warning,
961
0
                            "You can, at your own risk, disable this warning by setting the environment\n"
962
0
                            "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n"
963
0
                            "Setting it to 2 or higher will suppress the warning messages totally.\n");
964
                    /* Mention the versions we are referring to */
965
0
                    fprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum,
966
0
                            (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
967
968
                    /* Bail out now. */
969
0
                    fputs("Bye...\n", stderr);
970
0
                    abort();
971
0
                case 1:
972
                    /* continue with a warning */
973
                    /* Note that the warning message is embedded in the format string.*/
974
0
                    fprintf(stderr,
975
0
                            "%s'HDF5_DISABLE_VERSION_CHECK' "
976
0
                            "environment variable is set to %d, application will\n"
977
0
                            "continue at your own risk.\n",
978
0
                            minor_version_forward_compatible_warning, disable_version_check);
979
                    /* Mention the versions we are referring to */
980
0
                    fprintf(stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n", majnum, minnum, relnum,
981
0
                            (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
982
0
                    break;
983
0
                default:
984
                    /* 2 or higher: continue silently */
985
0
                    break;
986
0
            } /* end switch */
987
0
        }
988
989
0
    } /* end if (H5_VERS_MINOR != minnum) */
990
991
    /* Indicate that the version check has been performed */
992
1
    checked = true;
993
994
1
    if (!disable_version_check) {
995
        /*
996
         * Verify if H5_VERS_INFO is consistent with the other version information.
997
         * Check only the first sizeof(lib_str) char.  Assume the information
998
         * will fit within this size or enough significance.
999
         */
1000
1
        snprintf(lib_str, sizeof(lib_str), "HDF5 library version: %d.%d.%d%s%s", H5_VERS_MAJOR, H5_VERS_MINOR,
1001
1
                 H5_VERS_RELEASE, (*substr ? "-" : ""), substr);
1002
1003
1
        if (strcmp(lib_str, H5_lib_vers_info_g) != 0) {
1004
0
            fputs("Warning!  Library version information error.\n"
1005
0
                  "The HDF5 library version information are not "
1006
0
                  "consistent in its source code.\nThis is NOT a fatal error "
1007
0
                  "but should be corrected.  Setting the environment\n"
1008
0
                  "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of 1 "
1009
0
                  "will suppress\nthis warning.\n",
1010
0
                  stderr);
1011
0
            fprintf(stderr,
1012
0
                    "Library version information are:\n"
1013
0
                    "H5_VERS_MAJOR=%d, H5_VERS_MINOR=%d, H5_VERS_RELEASE=%d, "
1014
0
                    "H5_VERS_SUBRELEASE=%s,\nH5_VERS_INFO=%s\n",
1015
0
                    H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE, H5_VERS_SUBRELEASE, H5_VERS_INFO);
1016
0
        } /* end if */
1017
1
    }
1018
1019
1
done:
1020
1
    FUNC_LEAVE_NOAPI(ret_value)
1021
1
} /* end H5__check_version() */
1022
1023
herr_t
1024
H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
1025
0
{
1026
0
    herr_t ret_value = SUCCEED; /* Return value */
1027
1028
0
    FUNC_ENTER_API_NOINIT_NOERR
1029
1030
    /* Call internal routine */
1031
    /* (Will abort() on failure) */
1032
0
    H5_check_version(majnum, minnum, relnum);
1033
1034
0
    FUNC_LEAVE_API_NOERR(ret_value)
1035
0
} /* end H5check_version() */
1036
1037
/*-------------------------------------------------------------------------
1038
 * Function:    H5open
1039
 *
1040
 * Purpose:     Initialize the library.  This is normally called
1041
 *              automatically, but if you find that an HDF5 library function
1042
 *              is failing inexplicably, then try calling this function
1043
 *              first.
1044
 *
1045
 * Return:    Non-negative on success/Negative on failure
1046
 *
1047
 *-------------------------------------------------------------------------
1048
 */
1049
herr_t
1050
H5open(void)
1051
0
{
1052
0
    herr_t ret_value = SUCCEED; /* Return value */
1053
1054
0
    FUNC_ENTER_API_NOPUSH(FAIL)
1055
1056
    /* all work is done by FUNC_ENTER() */
1057
1058
0
done:
1059
0
    FUNC_LEAVE_API_NOPUSH(ret_value)
1060
0
} /* end H5open() */
1061
1062
/*-------------------------------------------------------------------------
1063
 * Function:    H5atclose
1064
 *
1065
 * Purpose:    Register a callback for the library to invoke when it's
1066
 *        closing.  Callbacks are invoked in LIFO order.
1067
 *
1068
 * Return:    Non-negative on success/Negative on failure
1069
 *
1070
 *-------------------------------------------------------------------------
1071
 */
1072
herr_t
1073
H5atclose(H5_atclose_func_t func, void *ctx)
1074
0
{
1075
0
    H5_atclose_node_t *new_atclose;         /* New 'atclose' node */
1076
0
    herr_t             ret_value = SUCCEED; /* Return value */
1077
1078
0
    FUNC_ENTER_API(FAIL)
1079
1080
    /* Check arguments */
1081
0
    if (NULL == func)
1082
0
        HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL func pointer");
1083
1084
    /* Allocate space for the 'atclose' node */
1085
0
    if (NULL == (new_atclose = H5FL_MALLOC(H5_atclose_node_t)))
1086
0
        HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate 'atclose' node");
1087
1088
    /* Set up 'atclose' node */
1089
0
    new_atclose->func = func;
1090
0
    new_atclose->ctx  = ctx;
1091
1092
    /* Connector to linked-list of 'atclose' nodes */
1093
0
    new_atclose->next = H5_atclose_head;
1094
0
    H5_atclose_head   = new_atclose;
1095
1096
0
done:
1097
0
    FUNC_LEAVE_API(ret_value)
1098
0
} /* end H5atclose() */
1099
1100
/*-------------------------------------------------------------------------
1101
 * Function:    H5close
1102
 *
1103
 * Purpose:    Terminate the library and release all resources.
1104
 *
1105
 * Return:    Non-negative on success/Negative on failure
1106
 *
1107
 *-------------------------------------------------------------------------
1108
 */
1109
herr_t
1110
H5close(void)
1111
0
{
1112
    /*
1113
     * Don't call normal FUNC_ENTER() since we don't want to initialize the
1114
     * whole library just to release it all right away.  It is safe to call
1115
     * this function for an uninitialized library.
1116
     */
1117
0
    FUNC_ENTER_API_NAMECHECK_ONLY
1118
1119
0
    H5_term_library();
1120
1121
0
    FUNC_LEAVE_API_NAMECHECK_ONLY(SUCCEED)
1122
0
} /* end H5close() */
1123
1124
/*-------------------------------------------------------------------------
1125
 * Function:    H5allocate_memory
1126
 *
1127
 * Purpose:        Allocate a memory buffer with the semantics of malloc().
1128
 *
1129
 *              NOTE: This function is intended for use with filter
1130
 *              plugins so that all allocation and free operations
1131
 *              use the same memory allocator. It is not intended for
1132
 *              use as a general memory allocator in applications.
1133
 *
1134
 * Parameters:
1135
 *
1136
 *      size:   The size of the buffer.
1137
 *
1138
 *      clear:  Whether or not to memset the buffer to 0.
1139
 *
1140
 * Return:
1141
 *
1142
 *      Success:    A pointer to the allocated buffer or NULL if the size
1143
 *                  parameter is zero.
1144
 *
1145
 *      Failure:    NULL (but may also be NULL w/ size 0!)
1146
 *
1147
 *-------------------------------------------------------------------------
1148
 */
1149
void *H5_ATTR_MALLOC
1150
H5allocate_memory(size_t size, bool clear)
1151
0
{
1152
0
    void *ret_value = NULL;
1153
1154
0
    FUNC_ENTER_API_NOINIT
1155
1156
0
    if (0 == size)
1157
0
        HGOTO_DONE(NULL);
1158
1159
0
    if (clear)
1160
0
        ret_value = H5MM_calloc(size);
1161
0
    else
1162
0
        ret_value = H5MM_malloc(size);
1163
1164
0
done:
1165
0
    FUNC_LEAVE_API_NOINIT(ret_value)
1166
0
} /* end H5allocate_memory() */
1167
1168
/*-------------------------------------------------------------------------
1169
 * Function:    H5resize_memory
1170
 *
1171
 * Purpose:        Resize a memory buffer with the semantics of realloc().
1172
 *
1173
 *              NOTE: This function is intended for use with filter
1174
 *              plugins so that all allocation and free operations
1175
 *              use the same memory allocator. It is not intended for
1176
 *              use as a general memory allocator in applications.
1177
 *
1178
 * Parameters:
1179
 *
1180
 *      mem:    The buffer to be resized.
1181
 *
1182
 *      size:   The size of the buffer.
1183
 *
1184
 * Return:
1185
 *
1186
 *      Success:    A pointer to the resized buffer.
1187
 *
1188
 *      Failure:    NULL (the input buffer will be unchanged)
1189
 *
1190
 *-------------------------------------------------------------------------
1191
 */
1192
void *
1193
H5resize_memory(void *mem, size_t size)
1194
0
{
1195
0
    void *ret_value = NULL;
1196
1197
0
    FUNC_ENTER_API_NOINIT
1198
1199
0
    ret_value = H5MM_realloc(mem, size);
1200
1201
0
    FUNC_LEAVE_API_NOINIT(ret_value)
1202
0
} /* end H5resize_memory() */
1203
1204
/*-------------------------------------------------------------------------
1205
 * Function:    H5free_memory
1206
 *
1207
 * Purpose:        Frees memory allocated by the library that it is the user's
1208
 *              responsibility to free.  Ensures that the same library
1209
 *              that was used to allocate the memory frees it.  Passing
1210
 *              NULL pointers is allowed.
1211
 *
1212
 * Return:        SUCCEED/FAIL
1213
 *
1214
 *-------------------------------------------------------------------------
1215
 */
1216
herr_t
1217
H5free_memory(void *mem)
1218
0
{
1219
0
    FUNC_ENTER_API_NOINIT
1220
1221
    /* At this time, it is impossible for this to fail. */
1222
0
    H5MM_xfree(mem);
1223
1224
0
    FUNC_LEAVE_API_NOINIT(SUCCEED)
1225
0
} /* end H5free_memory() */
1226
1227
/*-------------------------------------------------------------------------
1228
 * Function:    H5is_library_threadsafe
1229
 *
1230
 * Purpose:        Checks to see if the library was built with thread-safety
1231
 *              enabled.
1232
 *
1233
 * Return:        SUCCEED/FAIL
1234
 *
1235
 *-------------------------------------------------------------------------
1236
 */
1237
herr_t
1238
H5is_library_threadsafe(bool *is_ts /*out*/)
1239
0
{
1240
0
    herr_t ret_value = SUCCEED; /* Return value */
1241
1242
0
    FUNC_ENTER_API_NOINIT
1243
1244
0
    if (is_ts) {
1245
#ifdef H5_HAVE_THREADSAFE_API
1246
        *is_ts = true;
1247
#else  /* H5_HAVE_THREADSAFE_API */
1248
0
        *is_ts = false;
1249
0
#endif /* H5_HAVE_THREADSAFE_API */
1250
0
    }
1251
0
    else
1252
0
        ret_value = FAIL;
1253
1254
0
    FUNC_LEAVE_API_NOINIT(ret_value)
1255
0
} /* end H5is_library_threadsafe() */
1256
1257
/*-------------------------------------------------------------------------
1258
 * Function:    H5is_library_terminating
1259
 *
1260
 * Purpose:    Checks to see if the library is shutting down.
1261
 *
1262
 * Note:    Useful for plugins to detect when the library is terminating.
1263
 *        For example, a VOL connector could check if a "file close"
1264
 *        callback was the result of the library shutdown process, or
1265
 *        an API action from the application.
1266
 *
1267
 * Return:    SUCCEED/FAIL
1268
 *
1269
 *-------------------------------------------------------------------------
1270
 */
1271
herr_t
1272
H5is_library_terminating(bool *is_terminating /*out*/)
1273
0
{
1274
0
    herr_t ret_value = SUCCEED; /* Return value */
1275
1276
0
    FUNC_ENTER_API_NOINIT
1277
1278
0
    assert(is_terminating);
1279
1280
0
    if (is_terminating)
1281
0
        *is_terminating = H5_TERM_GLOBAL;
1282
0
    else
1283
0
        ret_value = FAIL;
1284
1285
0
    FUNC_LEAVE_API_NOINIT(ret_value)
1286
0
} /* end H5is_library_terminating() */
1287
1288
/*-------------------------------------------------------------------------
1289
 * Function:    H5_user_cb_prepare
1290
 *
1291
 * Purpose:     Prepares library before a user callback
1292
 *
1293
 * Return:      SUCCEED/FAIL
1294
 *
1295
 *-------------------------------------------------------------------------
1296
 */
1297
herr_t
1298
H5_user_cb_prepare(H5_user_cb_state_t *state)
1299
4.20k
{
1300
4.20k
    herr_t ret_value = SUCCEED; /* Return value */
1301
1302
4.20k
    FUNC_ENTER_NOAPI(FAIL)
1303
1304
    /* Prepare H5E package for user callback */
1305
4.20k
    if (H5E_user_cb_prepare(&state->h5e_state) < 0)
1306
0
        HGOTO_ERROR(H5E_LIB, H5E_CANTSET, FAIL, "unable to prepare H5E package for user callback");
1307
1308
#ifdef H5_HAVE_CONCURRENCY
1309
    /* Prepare H5TS package for user callback */
1310
    if (H5TS_user_cb_prepare() < 0)
1311
        HGOTO_ERROR(H5E_LIB, H5E_CANTSET, FAIL, "unable to prepare H5TS package for user callback");
1312
#endif /* H5_HAVE_THREADSAFE_API */
1313
1314
4.20k
done:
1315
4.20k
    FUNC_LEAVE_NOAPI(ret_value)
1316
4.20k
} /* end H5_user_cb_prepare() */
1317
1318
/*-------------------------------------------------------------------------
1319
 * Function:    H5_user_cb_restore
1320
 *
1321
 * Purpose:     Restores library after a user callback
1322
 *
1323
 * Return:      SUCCEED/FAIL
1324
 *
1325
 *-------------------------------------------------------------------------
1326
 */
1327
herr_t
1328
H5_user_cb_restore(const H5_user_cb_state_t *state)
1329
4.20k
{
1330
4.20k
    herr_t ret_value = SUCCEED; /* Return value */
1331
1332
4.20k
    FUNC_ENTER_NOAPI(FAIL)
1333
1334
    /* Restore H5E package after user callback */
1335
4.20k
    if (H5E_user_cb_restore(&state->h5e_state) < 0)
1336
0
        HGOTO_ERROR(H5E_LIB, H5E_CANTRESTORE, FAIL, "unable to restore H5E package after user callback");
1337
1338
#ifdef H5_HAVE_CONCURRENCY
1339
    /* Restore H5TS package after user callback */
1340
    if (H5TS_user_cb_restore() < 0)
1341
        HGOTO_ERROR(H5E_LIB, H5E_CANTRESTORE, FAIL, "unable to restore H5TS package after user callback");
1342
#endif /* H5_HAVE_THREADSAFE_API */
1343
1344
4.20k
done:
1345
4.20k
    FUNC_LEAVE_NOAPI(ret_value)
1346
4.20k
} /* end H5_user_cb_restore() */