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() */ |