1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /****************/
15 /* Module Setup */
16 /****************/
17 
18 
19 /***********/
20 /* Headers */
21 /***********/
22 #include "H5private.h"          /* Generic Functions                        */
23 #include "H5ACprivate.h"        /* Metadata cache                           */
24 #include "H5CXprivate.h"        /* API Contexts                             */
25 #include "H5Dprivate.h"         /* Datasets                                 */
26 #include "H5Eprivate.h"         /* Error handling                           */
27 #include "H5FLprivate.h"        /* Free lists                               */
28 #include "H5FSprivate.h"        /* File free space                          */
29 #include "H5Lprivate.h"         /* Links                                    */
30 #include "H5MMprivate.h"        /* Memory management                        */
31 #include "H5Pprivate.h"         /* Property lists                           */
32 #include "H5SLprivate.h"        /* Skip lists                               */
33 #include "H5Tprivate.h"         /* Datatypes                                */
34 
35 /****************/
36 /* Local Macros */
37 /****************/
38 
39 
40 /******************/
41 /* Local Typedefs */
42 /******************/
43 
44 
45 /********************/
46 /* Package Typedefs */
47 /********************/
48 
49 
50 /********************/
51 /* Local Prototypes */
52 /********************/
53 static void H5_debug_mask(const char*);
54 #ifdef H5_HAVE_PARALLEL
55 static int H5_mpi_delete_cb(MPI_Comm comm, int keyval, void *attr_val, int *flag);
56 #endif /*H5_HAVE_PARALLEL*/
57 
58 /*********************/
59 /* Package Variables */
60 /*********************/
61 
62 
63 /*****************************/
64 /* Library Private Variables */
65 /*****************************/
66 
67 /* HDF5 API Entered variable */
68 /* (move to H5.c when new FUNC_ENTER macros in actual use -QAK) */
69 hbool_t H5_api_entered_g = FALSE;
70 
71 /* statically initialize block for pthread_once call used in initializing */
72 /* the first global mutex                                                 */
73 #ifdef H5_HAVE_THREADSAFE
74 H5_api_t H5_g;
75 #else
76 hbool_t H5_libinit_g = FALSE;   /* Library hasn't been initialized */
77 hbool_t H5_libterm_g = FALSE;   /* Library isn't being shutdown */
78 #endif
79 
80 #ifdef H5_HAVE_MPE
81 hbool_t H5_MPEinit_g = FALSE;	/* MPE Library hasn't been initialized */
82 #endif
83 
84 char                    H5_lib_vers_info_g[] = H5_VERS_INFO;
85 static hbool_t          H5_dont_atexit_g = FALSE;
86 H5_debug_t              H5_debug_g; /* debugging info */
87 
88 
89 /*******************/
90 /* Local Variables */
91 /*******************/
92 
93 
94 /*--------------------------------------------------------------------------
95  * NAME
96  *   H5_init_library -- Initialize library-global information
97  * USAGE
98  *    herr_t H5_init_library()
99  *
100  * RETURNS
101  *    Non-negative on success/Negative on failure
102  *
103  * DESCRIPTION
104  *    Initializes any library-global data or routines.
105  *
106  *--------------------------------------------------------------------------
107  */
108 herr_t
H5_init_library(void)109 H5_init_library(void)
110 {
111     herr_t ret_value = SUCCEED;
112 
113     FUNC_ENTER_NOAPI(FAIL)
114 
115 #ifdef H5_HAVE_PARALLEL
116     {
117 	int mpi_initialized;
118 	int mpi_finalized;
119         int mpi_code;
120 
121 	MPI_Initialized(&mpi_initialized);
122 	MPI_Finalized(&mpi_finalized);
123 
124 #ifdef H5_HAVE_MPE
125         /* Initialize MPE instrumentation library. */
126         if (!H5_MPEinit_g) {
127             int mpe_code;
128             if (mpi_initialized && !mpi_finalized) {
129                 mpe_code = MPE_Init_log();
130                 HDassert(mpe_code >=0);
131                 H5_MPEinit_g = TRUE;
132             }
133         }
134 #endif /*H5_HAVE_MPE*/
135 
136         /* add an attribute on MPI_COMM_SELF to call H5_term_library
137            when it is destroyed, i.e. on MPI_Finalize */
138         if (mpi_initialized && !mpi_finalized) {
139             int key_val;
140 
141             if(MPI_SUCCESS != (mpi_code = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,
142                                                                  (MPI_Comm_delete_attr_function *)H5_mpi_delete_cb,
143                                                                  &key_val, NULL)))
144                 HMPI_GOTO_ERROR(FAIL, "MPI_Comm_create_keyval failed", mpi_code)
145 
146             if(MPI_SUCCESS != (mpi_code = MPI_Comm_set_attr(MPI_COMM_SELF, key_val, NULL)))
147                 HMPI_GOTO_ERROR(FAIL, "MPI_Comm_set_attr failed", mpi_code)
148 
149             if(MPI_SUCCESS != (mpi_code = MPI_Comm_free_keyval(&key_val)))
150                 HMPI_GOTO_ERROR(FAIL, "MPI_Comm_free_keyval failed", mpi_code)
151         }
152     }
153 #endif /*H5_HAVE_PARALLEL*/
154 
155     /*
156      * Make sure the package information is updated.
157      */
158     HDmemset(&H5_debug_g, 0, sizeof H5_debug_g);
159     H5_debug_g.pkg[H5_PKG_A].name = "a";
160     H5_debug_g.pkg[H5_PKG_AC].name = "ac";
161     H5_debug_g.pkg[H5_PKG_B].name = "b";
162     H5_debug_g.pkg[H5_PKG_D].name = "d";
163     H5_debug_g.pkg[H5_PKG_E].name = "e";
164     H5_debug_g.pkg[H5_PKG_F].name = "f";
165     H5_debug_g.pkg[H5_PKG_G].name = "g";
166     H5_debug_g.pkg[H5_PKG_HG].name = "hg";
167     H5_debug_g.pkg[H5_PKG_HL].name = "hl";
168     H5_debug_g.pkg[H5_PKG_I].name = "i";
169     H5_debug_g.pkg[H5_PKG_MF].name = "mf";
170     H5_debug_g.pkg[H5_PKG_MM].name = "mm";
171     H5_debug_g.pkg[H5_PKG_O].name = "o";
172     H5_debug_g.pkg[H5_PKG_P].name = "p";
173     H5_debug_g.pkg[H5_PKG_S].name = "s";
174     H5_debug_g.pkg[H5_PKG_T].name = "t";
175     H5_debug_g.pkg[H5_PKG_V].name = "v";
176     H5_debug_g.pkg[H5_PKG_Z].name = "z";
177 
178     /*
179      * Install atexit() library cleanup routines unless the H5dont_atexit()
180      * has been called.  Once we add something to the atexit() list it stays
181      * there permanently, so we set H5_dont_atexit_g after we add it to prevent
182      * adding it again later if the library is cosed and reopened.
183      */
184     if (!H5_dont_atexit_g) {
185 
186 #if defined(H5_HAVE_THREADSAFE) && defined(H5_HAVE_WIN_THREADS)
187         /* Clean up Win32 thread resources. Pthreads automatically cleans up.
188          * This must be entered before the library cleanup code so it's
189          * executed in LIFO order (i.e., last).
190          */
191 	    (void)HDatexit(H5TS_win32_process_exit);
192 #endif /* H5_HAVE_THREADSAFE && H5_HAVE_WIN_THREADS */
193 
194         /* Normal library termination code */
195         (void)HDatexit(H5_term_library);
196 
197         H5_dont_atexit_g = TRUE;
198     } /* end if */
199 
200     /*
201      * Initialize interfaces that might not be able to initialize themselves
202      * soon enough.  The file & dataset interfaces must be initialized because
203      * calling H5P_create() might require the file/dataset property classes to be
204      * initialized.  The property interface must be initialized before the file
205      * & dataset interfaces though, in order to provide them with the proper
206      * property classes.
207      * The link interface needs to be initialized so that link property lists
208      * have their properties registered.
209      * The FS module needs to be initialized as a result of the fix for HDFFV-10160:
210      *   It might not be initialized during normal file open.
211      *   When the application does not close the file, routines in the module might
212      *   be called via H5_term_library() when shutting down the file.
213      */
214     if(H5E_init() < 0)
215         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize error interface")
216     if(H5P_init() < 0)
217         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize property list interface")
218     if(H5T_init() < 0)
219         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize datatype interface")
220     if(H5D_init() < 0)
221         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize dataset interface")
222     if(H5AC_init() < 0)
223         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize metadata caching interface")
224     if(H5L_init() < 0)
225         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize link interface")
226     if(H5FS_init() < 0)
227         HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL, "unable to initialize FS interface")
228 
229     /* Debugging? */
230     H5_debug_mask("-all");
231     H5_debug_mask(HDgetenv("HDF5_DEBUG"));
232 
233 done:
234     FUNC_LEAVE_NOAPI(ret_value)
235 } /* end H5_init_library() */
236 
237 
238 /*-------------------------------------------------------------------------
239  * Function:	H5_term_library
240  *
241  * Purpose:	Terminate interfaces in a well-defined order due to
242  *		dependencies among the interfaces, then terminate
243  *		library-specific data.
244  *
245  * Return:	void
246  *
247  *-------------------------------------------------------------------------
248  */
249 void
H5_term_library(void)250 H5_term_library(void)
251 {
252     int	pending, ntries = 0, n;
253     size_t	at = 0;
254     char	loop[1024];
255     H5E_auto2_t func;
256 
257 #ifdef H5_HAVE_THREADSAFE
258     /* explicit locking of the API */
259     H5_FIRST_THREAD_INIT
260     H5_API_LOCK
261 #endif
262 
263     /* Don't do anything if the library is already closed */
264     if(!(H5_INIT_GLOBAL))
265         goto done;
266 
267     /* Indicate that the library is being shut down */
268     H5_TERM_GLOBAL = TRUE;
269 
270     /* Push the API context without checking for errors */
271     H5CX_push_special();
272 
273     /* Check if we should display error output */
274     (void)H5Eget_auto2(H5E_DEFAULT, &func, NULL);
275 
276     /*
277      * Terminate each interface. The termination functions return a positive
278      * value if they do something that might affect some other interface in a
279      * way that would necessitate some cleanup work in the other interface.
280      */
281 #define DOWN(F)								      \
282     (((n = H5##F##_term_package()) && (at + 8) < sizeof loop)?	      \
283      (HDsprintf(loop + at, "%s%s", (at ? "," : ""), #F),			      \
284       at += HDstrlen(loop + at),					      \
285       n):                                                                     \
286      ((n > 0 && (at + 5) < sizeof loop) ?				      \
287      (HDsprintf(loop + at, "..."),					      \
288       at += HDstrlen(loop + at),					      \
289      n) : n))
290 
291     do {
292         pending = 0;
293 
294         /* Try to organize these so the "higher" level components get shut
295          * down before "lower" level components that they might rely on. -QAK
296          */
297         pending += DOWN(L);
298 
299         /* Close the "top" of various interfaces (IDs, etc) but don't shut
300          *  down the whole interface yet, so that the object header messages
301          *  get serialized correctly for entries in the metadata cache and the
302          *  symbol table entry in the superblock gets serialized correctly, etc.
303          *  all of which is performed in the 'F' shutdown.
304          */
305         pending += DOWN(A_top);
306         pending += DOWN(D_top);
307         pending += DOWN(G_top);
308         pending += DOWN(R_top);
309         pending += DOWN(S_top);
310         pending += DOWN(T_top);
311 
312         /* Don't shut down the file code until objects in files are shut down */
313         if(pending == 0)
314             pending += DOWN(F);
315 
316         /* Don't shut down the property list code until all objects that might
317          * use property lists are shut down */
318         if(pending == 0)
319             pending += DOWN(P);
320 
321         /* Wait to shut down the "bottom" of various interfaces until the
322          *      files are closed, so pieces of the file can be serialized
323          *      correctly.
324          */
325         if(pending == 0) {
326             /* Shut down the "bottom" of the attribute, dataset, group,
327              *  reference, dataspace, and datatype interfaces, fully closing
328              *  out the interfaces now.
329              */
330             pending += DOWN(A);
331             pending += DOWN(D);
332             pending += DOWN(G);
333             pending += DOWN(R);
334             pending += DOWN(S);
335             pending += DOWN(T);
336         } /* end if */
337 
338         /* Don't shut down "low-level" components until "high-level" components
339          * have successfully shut down.  This prevents property lists and IDs
340          * from being closed "out from underneath" of the high-level objects
341          * that depend on them. -QAK
342          */
343         if(pending == 0) {
344             pending += DOWN(AC);
345             pending += DOWN(Z);
346             pending += DOWN(FD);
347             pending += DOWN(PL);
348             /* Don't shut down the error code until other APIs which use it are shut down */
349             if(pending == 0)
350                 pending += DOWN(E);
351             /* Don't shut down the ID code until other APIs which use them are shut down */
352             if(pending == 0)
353                 pending += DOWN(I);
354             /* Don't shut down the skip list code until everything that uses it is down */
355             if(pending == 0)
356                 pending += DOWN(SL);
357             /* Don't shut down the free list code until everything that uses it is down */
358             if(pending == 0)
359                 pending += DOWN(FL);
360             /* Don't shut down the API context code until _everything_ else is down */
361             if(pending == 0)
362                 pending += DOWN(CX);
363         } /* end if */
364     } while(pending && ntries++ < 100);
365 
366     if(pending) {
367         /* Only display the error message if the user is interested in them. */
368         if(func) {
369             HDfprintf(stderr, "HDF5: infinite loop closing library\n");
370             HDfprintf(stderr, "      %s\n", loop);
371 #ifndef NDEBUG
372             HDabort();
373 #endif /* NDEBUG */
374         } /* end if */
375     } /* end if */
376 
377 #ifdef H5_HAVE_MPE
378     /* Close MPE instrumentation library.  May need to move this
379      * down if any of the below code involves using the instrumentation code.
380      */
381     if(H5_MPEinit_g) {
382         int mpi_initialized;
383         int mpi_finalized;
384         int mpe_code;
385 
386         MPI_Initialized(&mpi_initialized);
387         MPI_Finalized(&mpi_finalized);
388 
389         if (mpi_initialized && !mpi_finalized) {
390             mpe_code = MPE_Finish_log("h5log");
391             HDassert(mpe_code >=0);
392         } /* end if */
393         H5_MPEinit_g = FALSE;	/* turn it off no matter what */
394     } /* end if */
395 #endif
396 
397     /* Free open debugging streams */
398     while(H5_debug_g.open_stream) {
399         H5_debug_open_stream_t  *tmp_open_stream;
400 
401         tmp_open_stream = H5_debug_g.open_stream;
402         (void)HDfclose(H5_debug_g.open_stream->stream);
403         H5_debug_g.open_stream = H5_debug_g.open_stream->next;
404         (void)H5MM_free(tmp_open_stream);
405     } /* end while */
406 
407 #if defined H5_MEMORY_ALLOC_SANITY_CHECK
408     /* Sanity check memory allocations */
409     H5MM_final_sanity_check();
410 #endif /* H5_MEMORY_ALLOC_SANITY_CHECK */
411 
412     /* Reset flag indicating that the library is being shut down */
413     H5_TERM_GLOBAL = FALSE;
414 
415     /* Mark library as closed */
416     H5_INIT_GLOBAL = FALSE;
417 
418     /* Don't pop the API context (i.e. H5CX_pop), since it's been shut down already */
419 
420 done:
421 #ifdef H5_HAVE_THREADSAFE
422     H5_API_UNLOCK
423 #endif /* H5_HAVE_THREADSAFE */
424 
425     return;
426 } /* end H5_term_library() */
427 
428 
429 /*-------------------------------------------------------------------------
430  * Function:	H5dont_atexit
431  *
432  * Purpose:	Indicates that the library is not to clean up after itself
433  *		when the application exits by calling exit() or returning
434  *		from main().  This function must be called before any other
435  *		HDF5 function or constant is used or it will have no effect.
436  *
437  *		If this function is used then certain memory buffers will not
438  *		be de-allocated nor will open files be flushed automatically.
439  *		The application may still call H5close() explicitly to
440  *		accomplish these things.
441  *
442  * Return:	Success:	non-negative
443  *
444  *		Failure:	negative if this function is called more than
445  *				once or if it is called too late.
446  *
447  *-------------------------------------------------------------------------
448  */
449 herr_t
H5dont_atexit(void)450 H5dont_atexit(void)
451 {
452     herr_t ret_value = SUCCEED;       /* Return value */
453 
454     FUNC_ENTER_API_NOINIT_NOERR_NOFS
455     H5TRACE0("e","");
456 
457     if(H5_dont_atexit_g)
458         ret_value = FAIL;
459     else
460         H5_dont_atexit_g = TRUE;
461 
462     FUNC_LEAVE_API_NOFS(ret_value)
463 } /* end H5dont_atexit() */
464 
465 
466 /*-------------------------------------------------------------------------
467  * Function:	H5garbage_collect
468  *
469  * Purpose:	Walks through all the garbage collection routines for the
470  *		library, which are supposed to free any unused memory they have
471  *		allocated.
472  *
473  *      These should probably be registered dynamically in a linked list of
474  *          functions to call, but there aren't that many right now, so we
475  *          hard-wire them...
476  *
477  * Return:	Success:	non-negative
478  *
479  *		Failure:	negative
480  *
481  *-------------------------------------------------------------------------
482  */
483 herr_t
H5garbage_collect(void)484 H5garbage_collect(void)
485 {
486     herr_t                  ret_value = SUCCEED;
487 
488     FUNC_ENTER_API(FAIL)
489     H5TRACE0("e","");
490 
491     /* Call the garbage collection routines in the library */
492     if(H5FL_garbage_coll()<0)
493         HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't garbage collect objects")
494 
495 done:
496     FUNC_LEAVE_API(ret_value)
497 }   /* end H5garbage_collect() */
498 
499 
500 /*-------------------------------------------------------------------------
501  * Function:	H5set_free_list_limits
502  *
503  * Purpose:	Sets limits on the different kinds of free lists.  Setting a value
504  *      of -1 for a limit means no limit of that type.  These limits are global
505  *      for the entire library.  Each "global" limit only applies to free lists
506  *      of that type, so if an application sets a limit of 1 MB on each of the
507  *      global lists, up to 3 MB of total storage might be allocated (1MB on
508  *      each of regular, array and block type lists).
509  *
510  *      The settings for block free lists are duplicated to factory free lists.
511  *      Factory free list limits cannot be set independently currently.
512  *
513  * Parameters:
514  *  int reg_global_lim;  IN: The limit on all "regular" free list memory used
515  *  int reg_list_lim;    IN: The limit on memory used in each "regular" free list
516  *  int arr_global_lim;  IN: The limit on all "array" free list memory used
517  *  int arr_list_lim;    IN: The limit on memory used in each "array" free list
518  *  int blk_global_lim;  IN: The limit on all "block" free list memory used
519  *  int blk_list_lim;    IN: The limit on memory used in each "block" free list
520  *
521  * Return:	Success:	non-negative
522  *
523  *		Failure:	negative
524  *
525  *-------------------------------------------------------------------------
526  */
527 herr_t
H5set_free_list_limits(int reg_global_lim,int reg_list_lim,int arr_global_lim,int arr_list_lim,int blk_global_lim,int blk_list_lim)528 H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim,
529     int arr_list_lim, int blk_global_lim, int blk_list_lim)
530 {
531     herr_t                  ret_value = SUCCEED;
532 
533     FUNC_ENTER_API(FAIL)
534     H5TRACE6("e", "IsIsIsIsIsIs", reg_global_lim, reg_list_lim, arr_global_lim,
535              arr_list_lim, blk_global_lim, blk_list_lim);
536 
537     /* Call the free list function to actually set the limits */
538     if(H5FL_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim,
539             blk_global_lim, blk_list_lim, blk_global_lim, blk_list_lim)<0)
540         HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "can't set garbage collection limits")
541 
542 done:
543     FUNC_LEAVE_API(ret_value)
544 }   /* end H5set_free_list_limits() */
545 
546 
547 /*-------------------------------------------------------------------------
548  * Function:    H5_debug_mask
549  *
550  * Purpose:     Set runtime debugging flags according to the string S.  The
551  *              string should contain file numbers and package names
552  *              separated by other characters. A file number applies to all
553  *              following package names up to the next file number. The
554  *              initial file number is `2' (the standard error stream). Each
555  *              package name can be preceded by a `+' or `-' to add or remove
556  *              the package from the debugging list (`+' is the default). The
557  *              special name `all' means all packages.
558  *
559  *              The name `trace' indicates that API tracing is to be turned
560  *              on or off.
561  *
562  *              The name 'ttop' indicates that only top-level API calls
563  *              should be shown. This also turns on tracing as if the
564  *              'trace' word was shown.
565  *
566  * Return:      void
567  *
568  *-------------------------------------------------------------------------
569  */
570 static void
H5_debug_mask(const char * s)571 H5_debug_mask(const char *s)
572 {
573     FILE	*stream = stderr;
574     char	pkg_name[32], *rest;
575     size_t	i;
576     hbool_t	clear;
577 
578     while (s && *s) {
579 
580         if (HDisalpha(*s) || '-'==*s || '+'==*s) {
581 
582             /* Enable or Disable debugging? */
583             if ('-'==*s) {
584                 clear = TRUE;
585                 s++;
586             } else if ('+'==*s) {
587                 clear = FALSE;
588                 s++;
589             } else {
590                 clear = FALSE;
591             } /* end if */
592 
593             /* Get the name */
594             for (i=0; HDisalpha(*s); i++, s++)
595                 if (i<sizeof pkg_name)
596                     pkg_name[i] = *s;
597             pkg_name[MIN(sizeof(pkg_name)-1, i)] = '\0';
598 
599             /* Trace, all, or one? */
600             if (!HDstrcmp(pkg_name, "trace")) {
601                 H5_debug_g.trace = clear ? NULL : stream;
602             } else if (!HDstrcmp(pkg_name, "ttop")) {
603                 H5_debug_g.trace = stream;
604                 H5_debug_g.ttop = (hbool_t)!clear;
605             } else if (!HDstrcmp(pkg_name, "ttimes")) {
606                 H5_debug_g.trace = stream;
607                 H5_debug_g.ttimes = (hbool_t)!clear;
608             } else if (!HDstrcmp(pkg_name, "all")) {
609                 for (i=0; i<(size_t)H5_NPKGS; i++)
610                     H5_debug_g.pkg[i].stream = clear ? NULL : stream;
611             } else {
612                 for (i=0; i<(size_t)H5_NPKGS; i++) {
613                     if (!HDstrcmp(H5_debug_g.pkg[i].name, pkg_name)) {
614                         H5_debug_g.pkg[i].stream = clear ? NULL : stream;
615                         break;
616 		            } /* end if */
617                 } /* end for */
618                 if (i>=(size_t)H5_NPKGS)
619                     HDfprintf(stderr, "HDF5_DEBUG: ignored %s\n", pkg_name);
620             } /* end if-else */
621 
622         } else if (HDisdigit(*s)) {
623             int fd = (int)HDstrtol(s, &rest, 0);
624             H5_debug_open_stream_t *open_stream;
625 
626             if((stream = HDfdopen(fd, "w")) != NULL) {
627                 (void)HDsetvbuf(stream, NULL, _IOLBF, (size_t)0);
628 
629                 if(NULL == (open_stream = (H5_debug_open_stream_t *)H5MM_malloc(sizeof(H5_debug_open_stream_t)))) {
630                     (void)HDfclose(stream);
631                     return;
632                 } /* end if */
633 
634                 open_stream->stream = stream;
635                 open_stream->next = H5_debug_g.open_stream;
636                 H5_debug_g.open_stream = open_stream;
637             } /* end if */
638 
639             s = rest;
640         } else {
641             s++;
642         } /* end if-else */
643     } /* end while */
644 
645     return;
646 
647 } /* end H5_debug_mask() */
648 
649 #ifdef H5_HAVE_PARALLEL
650 
651 /*-------------------------------------------------------------------------
652  * Function:	H5_mpi_delete_cb
653  *
654  * Purpose:	Callback attribute on MPI_COMM_SELF to terminate the HDF5
655  *              library when the communicator is destroyed, i.e. on MPI_Finalize.
656  *
657  * Return:	MPI_SUCCESS
658  *
659  *-------------------------------------------------------------------------
660  */
H5_mpi_delete_cb(MPI_Comm H5_ATTR_UNUSED comm,int H5_ATTR_UNUSED keyval,void H5_ATTR_UNUSED * attr_val,int H5_ATTR_UNUSED * flag)661 static int H5_mpi_delete_cb(MPI_Comm H5_ATTR_UNUSED comm, int H5_ATTR_UNUSED keyval, void H5_ATTR_UNUSED *attr_val, int H5_ATTR_UNUSED *flag)
662 {
663     H5_term_library();
664     return MPI_SUCCESS;
665 }
666 #endif /*H5_HAVE_PARALLEL*/
667 
668 
669 /*-------------------------------------------------------------------------
670  * Function:	H5get_libversion
671  *
672  * Purpose:	Returns the library version numbers through arguments. MAJNUM
673  *		will be the major revision number of the library, MINNUM the
674  *		minor revision number, and RELNUM the release revision number.
675  *
676  * Note:	When printing an HDF5 version number it should be printed as
677  *
678  * 		printf("%u.%u.%u", maj, min, rel)		or
679  *		printf("version %u.%u release %u", maj, min, rel)
680  *
681  * Return:	Non-negative on success/Negative on failure
682  *
683  *-------------------------------------------------------------------------
684  */
685 herr_t
H5get_libversion(unsigned * majnum,unsigned * minnum,unsigned * relnum)686 H5get_libversion(unsigned *majnum, unsigned *minnum, unsigned *relnum)
687 {
688     herr_t                  ret_value = SUCCEED;
689 
690     FUNC_ENTER_API(FAIL)
691     H5TRACE3("e", "*Iu*Iu*Iu", majnum, minnum, relnum);
692 
693     /* Set the version information */
694     if (majnum) *majnum = H5_VERS_MAJOR;
695     if (minnum) *minnum = H5_VERS_MINOR;
696     if (relnum) *relnum = H5_VERS_RELEASE;
697 
698 done:
699     FUNC_LEAVE_API(ret_value)
700 } /* end H5get_libversion() */
701 
702 
703 /*-------------------------------------------------------------------------
704  * Function:	H5check_version
705  *
706  * Purpose:	Verifies that the arguments match the version numbers
707  *		compiled into the library.  This function is intended to be
708  *		called from user to verify that the versions of header files
709  *		compiled into the application match the version of the hdf5
710  *		library.
711  *
712  * Return:	Success:	SUCCEED
713  *
714  *		Failure:	abort()
715  *
716  *-------------------------------------------------------------------------
717  */
718 #define VERSION_MISMATCH_WARNING \
719     "Warning! ***HDF5 library version mismatched error***\n" \
720     "The HDF5 header files used to compile this application do not match\n" \
721     "the version used by the HDF5 library to which this application is linked.\n" \
722     "Data corruption or segmentation faults may occur if the application continues.\n" \
723     "This can happen when an application was compiled by one version of HDF5 but\n" \
724     "linked with a different version of static or shared HDF5 library.\n" \
725     "You should recompile the application or check your shared library related\n" \
726     "settings such as 'LD_LIBRARY_PATH'.\n"
727 
728 herr_t
H5check_version(unsigned majnum,unsigned minnum,unsigned relnum)729 H5check_version(unsigned majnum, unsigned minnum, unsigned relnum)
730 {
731     char	lib_str[256];
732     char	substr[] = H5_VERS_SUBRELEASE;
733     static int	checked = 0;            /* If we've already checked the version info */
734     static unsigned int	disable_version_check = 0;      /* Set if the version check should be disabled */
735     static const char *version_mismatch_warning = VERSION_MISMATCH_WARNING;
736     herr_t      ret_value = SUCCEED;    /* Return value */
737 
738     FUNC_ENTER_API_NOINIT_NOERR_NOFS
739     H5TRACE3("e", "IuIuIu", majnum, minnum, relnum);
740 
741     /* Don't check again, if we already have */
742     if (checked)
743 	HGOTO_DONE(SUCCEED)
744 
745     {    const char *s;  /* Environment string for disabling version check */
746 
747         /* Allow different versions of the header files and library? */
748         s = HDgetenv ("HDF5_DISABLE_VERSION_CHECK");
749 
750         if (s && HDisdigit(*s))
751             disable_version_check = (unsigned int)HDstrtol (s, NULL, 0);
752     }
753 
754     if (H5_VERS_MAJOR!=majnum || H5_VERS_MINOR!=minnum ||
755             H5_VERS_RELEASE!=relnum) {
756         switch (disable_version_check) {
757 	case 0:
758 	    HDfprintf(stderr, "%s%s", version_mismatch_warning,
759 		     "You can, at your own risk, disable this warning by setting the environment\n"
760 		     "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of '1'.\n"
761 		     "Setting it to 2 or higher will suppress the warning messages totally.\n");
762 	    /* Mention the versions we are referring to */
763 	    HDfprintf (stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n",
764 		     majnum, minnum, relnum,
765 		     (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
766 	    /* Show library settings if available */
767 	    HDfprintf (stderr, "%s", H5libhdf5_settings);
768 
769 	    /* Bail out now. */
770 	    HDfputs ("Bye...\n", stderr);
771 	    HDabort ();
772 	case 1:
773 	    /* continue with a warning */
774 	    /* Note that the warning message is embedded in the format string.*/
775             HDfprintf (stderr,
776                      "%s'HDF5_DISABLE_VERSION_CHECK' "
777                      "environment variable is set to %d, application will\n"
778                      "continue at your own risk.\n",
779 		     version_mismatch_warning, disable_version_check);
780 	    /* Mention the versions we are referring to */
781 	    HDfprintf (stderr, "Headers are %u.%u.%u, library is %u.%u.%u\n",
782 		     majnum, minnum, relnum,
783 		     (unsigned)H5_VERS_MAJOR, (unsigned)H5_VERS_MINOR, (unsigned)H5_VERS_RELEASE);
784 	    /* Show library settings if available */
785 	    HDfprintf (stderr, "%s", H5libhdf5_settings);
786 	    break;
787 	default:
788 	    /* 2 or higher: continue silently */
789 	    break;
790         } /* end switch */
791 
792     } /* end if */
793 
794     /* Indicate that the version check has been performed */
795     checked = 1;
796 
797     if (!disable_version_check){
798 	/*
799 	 * Verify if H5_VERS_INFO is consistent with the other version information.
800 	 * Check only the first sizeof(lib_str) char.  Assume the information
801 	 * will fit within this size or enough significance.
802 	 */
803 	HDsnprintf(lib_str, sizeof(lib_str), "HDF5 library version: %d.%d.%d",
804 	    H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE);
805 	if(*substr) {
806 	    HDstrncat(lib_str, "-", (size_t)1);
807 	    HDstrncat(lib_str, substr, (sizeof(lib_str) - HDstrlen(lib_str)) - 1);
808 	} /* end if */
809 	if (HDstrcmp(lib_str, H5_lib_vers_info_g)){
810 	    HDfputs ("Warning!  Library version information error.\n"
811 		     "The HDF5 library version information are not "
812 		     "consistent in its source code.\nThis is NOT a fatal error "
813 		     "but should be corrected.  Setting the environment\n"
814 		     "variable 'HDF5_DISABLE_VERSION_CHECK' to a value of 1 "
815 		     "will suppress\nthis warning.\n",
816 		     stderr);
817 	    HDfprintf (stderr, "Library version information are:\n"
818 		     "H5_VERS_MAJOR=%d, H5_VERS_MINOR=%d, H5_VERS_RELEASE=%d, "
819 		     "H5_VERS_SUBRELEASE=%s,\nH5_VERS_INFO=%s\n",
820 		     H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE,
821 		     H5_VERS_SUBRELEASE, H5_VERS_INFO);
822 	} /* end if */
823     }
824 
825 done:
826     FUNC_LEAVE_API_NOFS(ret_value)
827 } /* end H5check_version() */
828 
829 
830 /*-------------------------------------------------------------------------
831  * Function:    H5open
832  *
833  * Purpose:     Initialize the library.  This is normally called
834  *              automatically, but if you find that an HDF5 library function
835  *              is failing inexplicably, then try calling this function
836  *              first.
837  *
838  * Return:	Non-negative on success/Negative on failure
839  *
840  *-------------------------------------------------------------------------
841  */
842 herr_t
H5open(void)843 H5open(void)
844 {
845     herr_t ret_value=SUCCEED;   /* Return value */
846 
847     FUNC_ENTER_API_NOCLEAR(FAIL)
848     H5TRACE0("e","");
849     /* all work is done by FUNC_ENTER() */
850 done:
851     FUNC_LEAVE_API(ret_value)
852 } /* end H5open() */
853 
854 
855 /*-------------------------------------------------------------------------
856  * Function:	H5close
857  *
858  * Purpose:	Terminate the library and release all resources.
859  *
860  * Return:	Non-negative on success/Negative on failure
861  *
862  *-------------------------------------------------------------------------
863  */
864 herr_t
H5close(void)865 H5close(void)
866 {
867     /*
868      * Don't call normal FUNC_ENTER() since we don't want to initialize the
869      * whole library just to release it all right away.  It is safe to call
870      * this function for an uninitialized library.
871      */
872     FUNC_ENTER_API_NOINIT_NOERR_NOFS
873     H5TRACE0("e","");
874 
875     H5_term_library();
876 
877     FUNC_LEAVE_API_NOFS(SUCCEED)
878 } /* end H5close() */
879 
880 
881 /*-------------------------------------------------------------------------
882  * Function:	H5allocate_memory
883  *
884  * Purpose:	    Allocate a memory buffer with the semantics of malloc().
885  *
886  *              NOTE: This function is intended for use with filter
887  *              plugins so that all allocation and free operations
888  *              use the same memory allocator. It is not intended for
889  *              use as a general memory allocator in applications.
890  *
891  * Parameters:
892  *
893  *      size:   The size of the buffer.
894  *
895  *      clear:  Whether or not to memset the buffer to 0.
896  *
897  * Return:
898  *
899  *      Success:    A pointer to the allocated buffer.
900  *
901  *      Failure:    NULL
902  *
903  *-------------------------------------------------------------------------
904  */
905 void *
H5allocate_memory(size_t size,hbool_t clear)906 H5allocate_memory(size_t size, hbool_t clear)
907 {
908     void *ret_value = NULL;
909 
910     FUNC_ENTER_API_NOINIT
911     H5TRACE2("*x", "zb", size, clear);
912 
913     if(clear)
914         ret_value = H5MM_calloc(size);
915     else
916         ret_value = H5MM_malloc(size);
917 
918     FUNC_LEAVE_API_NOINIT(ret_value)
919 } /* end H5allocate_memory() */
920 
921 
922 /*-------------------------------------------------------------------------
923  * Function:	H5resize_memory
924  *
925  * Purpose:	    Resize a memory buffer with the semantics of realloc().
926  *
927  *              NOTE: This function is intended for use with filter
928  *              plugins so that all allocation and free operations
929  *              use the same memory allocator. It is not intended for
930  *              use as a general memory allocator in applications.
931  *
932  * Parameters:
933  *
934  *      mem:    The buffer to be resized.
935  *
936  *      size:   The size of the buffer.
937  *
938  * Return:
939  *
940  *      Success:    A pointer to the resized buffer.
941  *
942  *      Failure:    NULL (the input buffer will be unchanged)
943  *
944  *-------------------------------------------------------------------------
945  */
946 void *
H5resize_memory(void * mem,size_t size)947 H5resize_memory(void *mem, size_t size)
948 {
949     void *ret_value = NULL;
950 
951     FUNC_ENTER_API_NOINIT
952     H5TRACE2("*x", "*xz", mem, size);
953 
954     ret_value = H5MM_realloc(mem, size);
955 
956     FUNC_LEAVE_API_NOINIT(ret_value)
957 } /* end H5resize_memory() */
958 
959 
960 /*-------------------------------------------------------------------------
961  * Function:	H5free_memory
962  *
963  * Purpose:	    Frees memory allocated by the library that it is the user's
964  *              responsibility to free.  Ensures that the same library
965  *              that was used to allocate the memory frees it.  Passing
966  *              NULL pointers is allowed.
967  *
968  * Return:	    SUCCEED/FAIL
969  *
970  *-------------------------------------------------------------------------
971  */
972 herr_t
H5free_memory(void * mem)973 H5free_memory(void *mem)
974 {
975     FUNC_ENTER_API_NOINIT
976     H5TRACE1("e", "*x", mem);
977 
978     /* At this time, it is impossible for this to fail. */
979     H5MM_xfree(mem);
980 
981     FUNC_LEAVE_API_NOINIT(SUCCEED)
982 } /* end H5free_memory() */
983 
984 
985 /*-------------------------------------------------------------------------
986  * Function:	H5is_library_threadsafe
987  *
988  * Purpose:	    Checks to see if the library was built with thread-safety
989  *              enabled.
990  *
991  * Return:	    SUCCEED/FAIL
992  *
993  *-------------------------------------------------------------------------
994  */
995 herr_t
H5is_library_threadsafe(hbool_t * is_ts)996 H5is_library_threadsafe(hbool_t *is_ts)
997 {
998     FUNC_ENTER_API_NOINIT
999     H5TRACE1("e", "*b", is_ts);
1000 
1001     HDassert(is_ts);
1002 
1003     /* At this time, it is impossible for this to fail. */
1004 #ifdef H5_HAVE_THREADSAFE
1005     *is_ts = TRUE;
1006 #else /* H5_HAVE_THREADSAFE */
1007     *is_ts = FALSE;
1008 #endif /* H5_HAVE_THREADSAFE */
1009 
1010     FUNC_LEAVE_API_NOINIT(SUCCEED)
1011 } /* end H5is_library_threadsafe() */
1012 
1013 
1014 #if defined(H5_HAVE_THREADSAFE) && defined(H5_BUILT_AS_DYNAMIC_LIB) \
1015     && defined(H5_HAVE_WIN32_API) && defined(H5_HAVE_WIN_THREADS)
1016 /*-------------------------------------------------------------------------
1017  * Function:    DllMain
1018  *
1019  * Purpose:     Handles various conditions in the library on Windows.
1020  *
1021  *    NOTE:     The main purpose of this is for handling Win32 thread cleanup
1022  *              on thread/process detach.
1023  *
1024  *              Only enabled when the shared Windows library is built with
1025  *              thread safety enabled.
1026  *
1027  * Return:      TRUE on success, FALSE on failure
1028  *
1029  *-------------------------------------------------------------------------
1030  */
1031 BOOL WINAPI
DllMain(_In_ HINSTANCE hinstDLL,_In_ DWORD fdwReason,_In_ LPVOID lpvReserved)1032 DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
1033 {
1034     /* Don't add our function enter/leave macros since this function will be
1035      * called before the library is initialized.
1036      *
1037      * NOTE: Do NOT call any CRT functions in DllMain!
1038      * This includes any functions that are called by from here!
1039      */
1040 
1041     BOOL fOkay = TRUE;
1042 
1043     switch(fdwReason)
1044     {
1045     case DLL_PROCESS_ATTACH:
1046         break;
1047 
1048     case DLL_PROCESS_DETACH:
1049         break;
1050 
1051     case DLL_THREAD_ATTACH:
1052 #ifdef H5_HAVE_WIN_THREADS
1053         if(H5TS_win32_thread_enter() < 0)
1054             fOkay = FALSE;
1055 #endif /* H5_HAVE_WIN_THREADS */
1056         break;
1057 
1058     case DLL_THREAD_DETACH:
1059 #ifdef H5_HAVE_WIN_THREADS
1060         if(H5TS_win32_thread_exit() < 0)
1061             fOkay = FALSE;
1062 #endif /* H5_HAVE_WIN_THREADS */
1063         break;
1064 
1065     default:
1066         /* Shouldn't get here */
1067         fOkay = FALSE;
1068         break;
1069     }
1070 
1071     return fOkay;
1072 }
1073 #endif /* H5_HAVE_WIN32_API && H5_BUILT_AS_DYNAMIC_LIB && H5_HAVE_WIN_THREADS && H5_HAVE_THREADSAFE*/
1074 
1075