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  * Open object info algorithms.
16  *
17  * These are used to track the objects currently open in a file, for various
18  * internal mechanisms which need to be aware of such things.
19  *
20  */
21 
22 #define H5F_PACKAGE		/*suppress error about including H5Fpkg	  */
23 
24 
25 #include "H5Eprivate.h"		/* Error handling		  	*/
26 #include "H5Fpkg.h"             /* File access                          */
27 #include "H5FLprivate.h"	/* Free lists                           */
28 #include "H5FOprivate.h"        /* File objects                         */
29 #include "H5Oprivate.h"		/* Object headers		  	*/
30 
31 /* Private typedefs */
32 
33 /* Information about open objects in a file */
34 typedef struct H5FO_open_obj_t {
35     haddr_t addr;                       /* Address of object header for object */
36     void *obj;                          /* Pointer to the object            */
37     hbool_t deleted;                    /* Flag to indicate that the object was deleted from the file */
38 } H5FO_open_obj_t;
39 
40 /* Information about counted objects in a file */
41 typedef struct H5FO_obj_count_t {
42     haddr_t addr;                       /* Address of object header for object */
43     hsize_t count;                      /* Number of times object is opened */
44 } H5FO_obj_count_t;
45 
46 /* Declare a free list to manage the H5FO_open_obj_t struct */
47 H5FL_DEFINE_STATIC(H5FO_open_obj_t);
48 
49 /* Declare a free list to manage the H5FO_obj_count_t struct */
50 H5FL_DEFINE_STATIC(H5FO_obj_count_t);
51 
52 
53 /*--------------------------------------------------------------------------
54  NAME
55     H5FO_create
56  PURPOSE
57     Create an open object info set
58  USAGE
59     herr_t H5FO_create(f)
60         H5F_t *f;       IN/OUT: File to create opened object info set for
61 
62  RETURNS
63     Returns non-negative on success, negative on failure
64  DESCRIPTION
65     Create a new open object info set.
66  GLOBAL VARIABLES
67  COMMENTS, BUGS, ASSUMPTIONS
68  EXAMPLES
69  REVISION LOG
70 --------------------------------------------------------------------------*/
71 herr_t
H5FO_create(const H5F_t * f)72 H5FO_create(const H5F_t *f)
73 {
74     herr_t ret_value=SUCCEED;          /* Return value */
75 
76     FUNC_ENTER_NOAPI(FAIL)
77 
78     /* Sanity check */
79     HDassert(f);
80     HDassert(f->shared);
81 
82     /* Create container used to store open object info */
83     if((f->shared->open_objs = H5SL_create(H5SL_TYPE_HADDR, NULL)) == NULL)
84         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container")
85 
86 done:
87     FUNC_LEAVE_NOAPI(ret_value)
88 } /* end H5FO_create() */
89 
90 
91 /*--------------------------------------------------------------------------
92  NAME
93     H5FO_opened
94  PURPOSE
95     Checks if an object at an address is already open in the file.
96  USAGE
97     void * H5FO_opened(f,addr)
98         const H5F_t *f;         IN: File to check opened object info set
99         haddr_t addr;           IN: Address of object to check
100 
101  RETURNS
102     Returns a pointer to the object on success, NULL on failure
103  DESCRIPTION
104     Check is an object at an address (the address of the object's object header)
105     is already open in the file and return the ID for that object if it is open.
106  GLOBAL VARIABLES
107  COMMENTS, BUGS, ASSUMPTIONS
108  EXAMPLES
109  REVISION LOG
110 --------------------------------------------------------------------------*/
111 void *
H5FO_opened(const H5F_t * f,haddr_t addr)112 H5FO_opened(const H5F_t *f, haddr_t addr)
113 {
114     H5FO_open_obj_t *open_obj;  /* Information about open object */
115     void *ret_value;            /* Return value */
116 
117     FUNC_ENTER_NOAPI_NOERR
118 
119     /* Sanity check */
120     HDassert(f);
121     HDassert(f->shared);
122     HDassert(f->shared->open_objs);
123     HDassert(H5F_addr_defined(addr));
124 
125     /* Get the object node from the container */
126     if(NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs,&addr))) {
127         ret_value = open_obj->obj;
128         HDassert(ret_value != NULL);
129     } /* end if */
130     else
131         ret_value = NULL;
132 
133     FUNC_LEAVE_NOAPI(ret_value)
134 } /* end H5FO_opened() */
135 
136 
137 /*--------------------------------------------------------------------------
138  NAME
139     H5FO_insert
140  PURPOSE
141     Insert a newly opened object/pointer pair into the opened object info set
142  USAGE
143     herr_t H5FO_insert(f,addr,obj)
144         H5F_t *f;               IN/OUT: File's opened object info set
145         haddr_t addr;           IN: Address of object to insert
146         void *obj;              IN: Pointer to object to insert
147         hbool_t delete_flag;    IN: Whether to 'mark' this object for deletion
148 
149  RETURNS
150     Returns a non-negative on success, negative on failure
151  DESCRIPTION
152     Insert an object/ID pair into the opened object info set.
153  GLOBAL VARIABLES
154  COMMENTS, BUGS, ASSUMPTIONS
155  EXAMPLES
156  REVISION LOG
157 --------------------------------------------------------------------------*/
158 herr_t
H5FO_insert(const H5F_t * f,haddr_t addr,void * obj,hbool_t delete_flag)159 H5FO_insert(const H5F_t *f, haddr_t addr, void *obj, hbool_t delete_flag)
160 {
161     H5FO_open_obj_t *open_obj;  /* Information about open object */
162     herr_t ret_value=SUCCEED;   /* Return value */
163 
164     FUNC_ENTER_NOAPI(FAIL)
165 
166     /* Sanity check */
167     HDassert(f);
168     HDassert(f->shared);
169     HDassert(f->shared->open_objs);
170     HDassert(H5F_addr_defined(addr));
171     HDassert(obj);
172 
173     /* Allocate new opened object information structure */
174     if((open_obj=H5FL_MALLOC(H5FO_open_obj_t))==NULL)
175         HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,FAIL,"memory allocation failed")
176 
177     /* Assign information */
178     open_obj->addr=addr;
179     open_obj->obj=obj;
180     open_obj->deleted=delete_flag;
181 
182     /* Insert into container */
183     if(H5SL_insert(f->shared->open_objs,&open_obj->addr,open_obj)<0)
184         HGOTO_ERROR(H5E_CACHE,H5E_CANTINSERT,FAIL,"can't insert object into container")
185 
186 done:
187     FUNC_LEAVE_NOAPI(ret_value)
188 } /* end H5FO_insert() */
189 
190 
191 /*--------------------------------------------------------------------------
192  NAME
193     H5FO_delete
194  PURPOSE
195     Remove an opened object/ID pair from the opened object info set
196  USAGE
197     herr_t H5FO_delete(f,addr)
198         H5F_t *f;               IN/OUT: File's opened object info set
199         haddr_t addr;           IN: Address of object to remove
200 
201  RETURNS
202     Returns a non-negative on success, negative on failure
203  DESCRIPTION
204     Remove an object/ID pair from the opened object info.
205  GLOBAL VARIABLES
206  COMMENTS, BUGS, ASSUMPTIONS
207  EXAMPLES
208  REVISION LOG
209 --------------------------------------------------------------------------*/
210 herr_t
H5FO_delete(H5F_t * f,hid_t dxpl_id,haddr_t addr)211 H5FO_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
212 {
213     H5FO_open_obj_t *open_obj;  /* Information about open object */
214     herr_t ret_value=SUCCEED;   /* Return value */
215 
216     FUNC_ENTER_NOAPI(FAIL)
217 
218     /* Sanity check */
219     HDassert(f);
220     HDassert(f->shared);
221     HDassert(f->shared->open_objs);
222     HDassert(H5F_addr_defined(addr));
223 
224     /* Remove from container */
225     if(NULL == (open_obj = (H5FO_open_obj_t *)H5SL_remove(f->shared->open_objs, &addr)))
226         HGOTO_ERROR(H5E_CACHE,H5E_CANTRELEASE,FAIL,"can't remove object from container")
227 
228     /* Check if the object was deleted from the file */
229     if(open_obj->deleted) {
230         if(H5O_delete(f, dxpl_id, addr) < 0)
231             HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
232     } /* end if */
233 
234     /* Release the object information */
235     open_obj = H5FL_FREE(H5FO_open_obj_t, open_obj);
236 
237 done:
238     FUNC_LEAVE_NOAPI(ret_value)
239 } /* end H5FO_delete() */
240 
241 
242 /*--------------------------------------------------------------------------
243  NAME
244     H5FO_mark
245  PURPOSE
246     Mark an object to be deleted when it is closed
247  USAGE
248     herr_t H5FO_mark(f,addr)
249         const H5F_t *f;         IN: File opened object is in
250         haddr_t addr;           IN: Address of object to delete
251 
252  RETURNS
253     Returns a non-negative ID for the object on success, negative on failure
254  DESCRIPTION
255     Mark an opened object for deletion from the file when it is closed.
256  GLOBAL VARIABLES
257  COMMENTS, BUGS, ASSUMPTIONS
258  EXAMPLES
259  REVISION LOG
260 --------------------------------------------------------------------------*/
261 herr_t
H5FO_mark(const H5F_t * f,haddr_t addr,hbool_t deleted)262 H5FO_mark(const H5F_t *f, haddr_t addr, hbool_t deleted)
263 {
264     H5FO_open_obj_t *open_obj;  /* Information about open object */
265     herr_t ret_value=SUCCEED;            /* Return value */
266 
267     FUNC_ENTER_NOAPI_NOERR
268 
269     /* Sanity check */
270     HDassert(f);
271     HDassert(f->shared);
272     HDassert(f->shared->open_objs);
273     HDassert(H5F_addr_defined(addr));
274 
275     /* Get the object node from the container */
276     if(NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr)))
277         open_obj->deleted = deleted;
278     else
279         ret_value = FAIL;
280 
281     FUNC_LEAVE_NOAPI(ret_value)
282 } /* end H5FO_mark() */
283 
284 
285 /*--------------------------------------------------------------------------
286  NAME
287     H5FO_marked
288  PURPOSE
289     Check if an object is marked to be deleted when it is closed
290  USAGE
291     hbool_t H5FO_marked(f,addr)
292         const H5F_t *f;         IN: File opened object is in
293         haddr_t addr;           IN: Address of object to delete
294 
295  RETURNS
296     Returns a TRUE/FALSE on success
297  DESCRIPTION
298     Checks if the object is currently in the "opened objects" tree and
299     whether its marks for deletion from the file when it is closed.
300  GLOBAL VARIABLES
301  COMMENTS, BUGS, ASSUMPTIONS
302  EXAMPLES
303  REVISION LOG
304 --------------------------------------------------------------------------*/
305 hbool_t
H5FO_marked(const H5F_t * f,haddr_t addr)306 H5FO_marked(const H5F_t *f, haddr_t addr)
307 {
308     H5FO_open_obj_t *open_obj;  /* Information about open object */
309     hbool_t ret_value = FALSE;  /* Return value */
310 
311     FUNC_ENTER_NOAPI_NOERR
312 
313     /* Sanity check */
314     HDassert(f);
315     HDassert(f->shared);
316     HDassert(f->shared->open_objs);
317     HDassert(H5F_addr_defined(addr));
318 
319     /* Get the object node from the container */
320     if(NULL != (open_obj = (H5FO_open_obj_t *)H5SL_search(f->shared->open_objs, &addr)))
321         ret_value = open_obj->deleted;
322 
323     FUNC_LEAVE_NOAPI(ret_value)
324 } /* end H5FO_marked() */
325 
326 
327 /*--------------------------------------------------------------------------
328  NAME
329     H5FO_dest
330  PURPOSE
331     Destroy an open object info set
332  USAGE
333     herr_t H5FO_dest(f)
334         H5F_t *f;               IN/OUT: File's opened object info set
335 
336  RETURNS
337     Returns a non-negative on success, negative on failure
338  DESCRIPTION
339     Destroy an existing open object info set.
340  GLOBAL VARIABLES
341  COMMENTS, BUGS, ASSUMPTIONS
342  EXAMPLES
343  REVISION LOG
344 --------------------------------------------------------------------------*/
345 herr_t
H5FO_dest(const H5F_t * f)346 H5FO_dest(const H5F_t *f)
347 {
348     herr_t ret_value=SUCCEED;   /* Return value */
349 
350     FUNC_ENTER_NOAPI(FAIL)
351 
352     /* Sanity check */
353     HDassert(f);
354     HDassert(f->shared);
355     HDassert(f->shared->open_objs);
356 
357     /* Check if the object info set is empty */
358     if(H5SL_count(f->shared->open_objs)!=0)
359         HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set")
360 
361     /* Release the open object info set container */
362     if(H5SL_close(f->shared->open_objs)<0)
363         HGOTO_ERROR(H5E_CACHE, H5E_CANTCLOSEOBJ, FAIL, "can't close open object info set")
364 
365     f->shared->open_objs=NULL;
366 
367 done:
368     FUNC_LEAVE_NOAPI(ret_value)
369 } /* end H5FO_dest() */
370 
371 
372 /*--------------------------------------------------------------------------
373  NAME
374     H5FO_top_create
375  PURPOSE
376     Create the "top" open object count set
377  USAGE
378     herr_t H5FO_create(f)
379         H5F_t *f;       IN/OUT: File to create opened object count set for
380 
381  RETURNS
382     Returns non-negative on success, negative on failure
383  DESCRIPTION
384     Create a new open object count set.
385  GLOBAL VARIABLES
386  COMMENTS, BUGS, ASSUMPTIONS
387  EXAMPLES
388  REVISION LOG
389 --------------------------------------------------------------------------*/
390 herr_t
H5FO_top_create(H5F_t * f)391 H5FO_top_create(H5F_t *f)
392 {
393     herr_t ret_value = SUCCEED;          /* Return value */
394 
395     FUNC_ENTER_NOAPI(FAIL)
396 
397     /* Sanity check */
398     HDassert(f);
399 
400     /* Create container used to store open object info */
401     if((f->obj_count = H5SL_create(H5SL_TYPE_HADDR, NULL)) == NULL)
402         HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container")
403 
404 done:
405     FUNC_LEAVE_NOAPI(ret_value)
406 } /* end H5FO_top_create() */
407 
408 
409 /*--------------------------------------------------------------------------
410  NAME
411     H5FO_top_incr
412  PURPOSE
413     Increment the "top" reference count for an object in a file
414  USAGE
415     herr_t H5FO_top_incr(f, addr)
416         H5F_t *f;               IN/OUT: File's opened object info set
417         haddr_t addr;           IN: Address of object to increment
418 
419  RETURNS
420     Returns a non-negative on success, negative on failure
421  DESCRIPTION
422     Increment the reference count for an object in the opened object count set.
423  GLOBAL VARIABLES
424  COMMENTS, BUGS, ASSUMPTIONS
425  EXAMPLES
426  REVISION LOG
427 --------------------------------------------------------------------------*/
428 herr_t
H5FO_top_incr(const H5F_t * f,haddr_t addr)429 H5FO_top_incr(const H5F_t *f, haddr_t addr)
430 {
431     H5FO_obj_count_t *obj_count;  /* Ref. count for object */
432     herr_t ret_value = SUCCEED;   /* Return value */
433 
434     FUNC_ENTER_NOAPI(FAIL)
435 
436     /* Sanity check */
437     HDassert(f);
438     HDassert(f->obj_count);
439     HDassert(H5F_addr_defined(addr));
440 
441     /* Get the object node from the container */
442     if(NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr))) {
443         (obj_count->count)++;
444     } /* end if */
445     else {
446         /* Allocate new opened object information structure */
447         if(NULL == (obj_count = H5FL_MALLOC(H5FO_obj_count_t)))
448             HGOTO_ERROR(H5E_CACHE,H5E_NOSPACE,FAIL,"memory allocation failed")
449 
450         /* Assign information */
451         obj_count->addr = addr;
452         obj_count->count = 1;
453 
454         /* Insert into container */
455         if(H5SL_insert(f->obj_count, &obj_count->addr, obj_count) < 0)
456             HGOTO_ERROR(H5E_CACHE,H5E_CANTINSERT,FAIL,"can't insert object into container")
457     } /* end if */
458 
459 done:
460     FUNC_LEAVE_NOAPI(ret_value)
461 } /* end H5FO_top_incr() */
462 
463 
464 /*--------------------------------------------------------------------------
465  NAME
466     H5FO_top_decr
467  PURPOSE
468     Decrement the "top" reference count for an object in a file
469  USAGE
470     herr_t H5FO_top_decr(f, addr)
471         H5F_t *f;               IN/OUT: File's opened object info set
472         haddr_t addr;           IN: Address of object to decrement
473 
474  RETURNS
475     Returns a non-negative on success, negative on failure
476  DESCRIPTION
477     Decrement the reference count for an object in the opened object count set.
478  GLOBAL VARIABLES
479  COMMENTS, BUGS, ASSUMPTIONS
480  EXAMPLES
481  REVISION LOG
482 --------------------------------------------------------------------------*/
483 herr_t
H5FO_top_decr(const H5F_t * f,haddr_t addr)484 H5FO_top_decr(const H5F_t *f, haddr_t addr)
485 {
486     H5FO_obj_count_t *obj_count;  /* Ref. count for object */
487     herr_t ret_value = SUCCEED;   /* Return value */
488 
489     FUNC_ENTER_NOAPI(FAIL)
490 
491     /* Sanity check */
492     HDassert(f);
493     HDassert(f->obj_count);
494     HDassert(H5F_addr_defined(addr));
495 
496     /* Get the object node from the container */
497     if(NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr))) {
498         /* Decrement the reference count for the object */
499         (obj_count->count)--;
500 
501         if(obj_count->count == 0) {
502             /* Remove from container */
503             if(NULL == (obj_count = (H5FO_obj_count_t *)H5SL_remove(f->obj_count, &addr)))
504                 HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "can't remove object from container")
505 
506             /* Release the object information */
507             obj_count = H5FL_FREE(H5FO_obj_count_t, obj_count);
508         } /* end if */
509     } /* end if */
510     else
511         HGOTO_ERROR(H5E_CACHE, H5E_NOTFOUND, FAIL, "can't decrement ref. count")
512 
513 done:
514     FUNC_LEAVE_NOAPI(ret_value)
515 } /* end H5FO_top_decr() */
516 
517 
518 /*--------------------------------------------------------------------------
519  NAME
520     H5FO_top_count
521  PURPOSE
522     Return the "top" reference count for an object in a file
523  USAGE
524     hsize_t H5FO_top_incr(f, addr)
525         H5F_t *f;               IN/OUT: File's opened object info set
526         haddr_t addr;           IN: Address of object to increment
527 
528  RETURNS
529     Returns a non-negative on success, negative on failure
530  DESCRIPTION
531     Retrieves the reference count for an object in the opened object count set.
532  GLOBAL VARIABLES
533  COMMENTS, BUGS, ASSUMPTIONS
534  EXAMPLES
535  REVISION LOG
536 --------------------------------------------------------------------------*/
537 hsize_t
H5FO_top_count(const H5F_t * f,haddr_t addr)538 H5FO_top_count(const H5F_t *f, haddr_t addr)
539 {
540     H5FO_obj_count_t *obj_count;        /* Ref. count for object */
541     hsize_t ret_value;                  /* Return value */
542 
543     FUNC_ENTER_NOAPI_NOINIT_NOERR
544 
545     /* Sanity check */
546     HDassert(f);
547     HDassert(f->obj_count);
548     HDassert(H5F_addr_defined(addr));
549 
550     /* Get the object node from the container */
551     if(NULL != (obj_count = (H5FO_obj_count_t *)H5SL_search(f->obj_count, &addr)))
552         ret_value = obj_count->count;
553     else
554         ret_value = 0;
555 
556     FUNC_LEAVE_NOAPI(ret_value)
557 } /* end H5FO_top_count() */
558 
559 
560 /*--------------------------------------------------------------------------
561  NAME
562     H5FO_top_dest
563  PURPOSE
564     Destroy an open object info set
565  USAGE
566     herr_t H5FO_top_dest(f)
567         H5F_t *f;               IN/OUT: File's opened object info set
568 
569  RETURNS
570     Returns a non-negative on success, negative on failure
571  DESCRIPTION
572     Destroy an existing open object info set.
573  GLOBAL VARIABLES
574  COMMENTS, BUGS, ASSUMPTIONS
575  EXAMPLES
576  REVISION LOG
577 --------------------------------------------------------------------------*/
578 herr_t
H5FO_top_dest(H5F_t * f)579 H5FO_top_dest(H5F_t *f)
580 {
581     herr_t ret_value = SUCCEED;   /* Return value */
582 
583     FUNC_ENTER_NOAPI(FAIL)
584 
585     /* Sanity check */
586     HDassert(f);
587     HDassert(f->obj_count);
588 
589     /* Check if the object count set is empty */
590     if(H5SL_count(f->obj_count) != 0)
591         HGOTO_ERROR(H5E_CACHE, H5E_CANTRELEASE, FAIL, "objects still in open object info set")
592 
593     /* Release the open object count set container */
594     if(H5SL_close(f->obj_count) < 0)
595         HGOTO_ERROR(H5E_CACHE, H5E_CANTCLOSEOBJ, FAIL, "can't close open object info set")
596 
597     f->obj_count = NULL;
598 
599 done:
600     FUNC_LEAVE_NOAPI(ret_value)
601 } /* end H5FO_top_dest() */
602 
603