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  *
16  * Created:		H5O.c
17  *			Aug  5 1997
18  *			Robb Matzke <matzke@llnl.gov>
19  *
20  * Purpose:		Object header routines.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5Omodule.h"          /* This source code file is part of the H5O module */
30 
31 
32 /***********/
33 /* Headers */
34 /***********/
35 #include "H5private.h"		/* Generic Functions			*/
36 #include "H5Eprivate.h"		/* Error handling		  	*/
37 #include "H5Fprivate.h"		/* File access				*/
38 #include "H5FLprivate.h"	/* Free lists                           */
39 #include "H5FOprivate.h"        /* File objects                         */
40 #include "H5Iprivate.h"		/* IDs			  		*/
41 #include "H5Lprivate.h"		/* Links				*/
42 #include "H5MFprivate.h"	/* File memory management		*/
43 #ifdef H5O_ENABLE_BOGUS
44 #include "H5MMprivate.h"	/* Memory management			*/
45 #endif /* H5O_ENABLE_BOGUS */
46 #include "H5Opkg.h"             /* Object headers			*/
47 #include "H5SMprivate.h"        /* Shared object header messages        */
48 
49 
50 /****************/
51 /* Local Macros */
52 /****************/
53 
54 
55 /******************/
56 /* Local Typedefs */
57 /******************/
58 
59 /* User data for recursive traversal over objects from a group */
60 typedef struct {
61     hid_t       obj_id;         /* The ID for the starting group */
62     H5G_loc_t	*start_loc;     /* Location of starting group */
63     hid_t       lapl_id;        /* LAPL for walking across links */
64     hid_t       dxpl_id; 	/* DXPL for operations */
65     H5SL_t     *visited;        /* Skip list for tracking visited nodes */
66     H5O_iterate_t op;           /* Application callback */
67     void       *op_data;        /* Application's op data */
68 } H5O_iter_visit_ud_t;
69 
70 
71 /********************/
72 /* Package Typedefs */
73 /********************/
74 
75 
76 /********************/
77 /* Local Prototypes */
78 /********************/
79 
80 static herr_t H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh);
81 static herr_t H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type);
82 static herr_t H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
83     H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
84     hid_t dxpl_id);
85 static herr_t H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr);
86 static const H5O_obj_class_t *H5O_obj_class_real(H5O_t *oh);
87 
88 
89 /*********************/
90 /* Package Variables */
91 /*********************/
92 
93 /* Package initialization variable */
94 hbool_t H5_PKG_INIT_VAR = FALSE;
95 
96 /* Header message ID to class mapping */
97 
98 /* Remember to increment H5O_MSG_TYPES in H5Opkg.h when adding a new
99  * message.
100  */
101 
102 const H5O_msg_class_t *const H5O_msg_class_g[] = {
103     H5O_MSG_NULL,		/*0x0000 Null				*/
104     H5O_MSG_SDSPACE,		/*0x0001 Dataspace			*/
105     H5O_MSG_LINFO,		/*0x0002 Link information		*/
106     H5O_MSG_DTYPE,		/*0x0003 Datatype			*/
107     H5O_MSG_FILL,       	/*0x0004 Old data storage -- fill value */
108     H5O_MSG_FILL_NEW,		/*0x0005 New data storage -- fill value */
109     H5O_MSG_LINK,		/*0x0006 Link 				*/
110     H5O_MSG_EFL,		/*0x0007 Data storage -- external data files */
111     H5O_MSG_LAYOUT,		/*0x0008 Data Layout			*/
112 #ifdef H5O_ENABLE_BOGUS
113     H5O_MSG_BOGUS_VALID,	/*0x0009 "Bogus valid" (for testing)	*/
114 #else /* H5O_ENABLE_BOGUS */
115     NULL,			/*0x0009 "Bogus valid" (for testing)	*/
116 #endif /* H5O_ENABLE_BOGUS */
117     H5O_MSG_GINFO,		/*0x000A Group information		*/
118     H5O_MSG_PLINE,		/*0x000B Data storage -- filter pipeline */
119     H5O_MSG_ATTR,		/*0x000C Attribute			*/
120     H5O_MSG_NAME,		/*0x000D Object name			*/
121     H5O_MSG_MTIME,		/*0x000E Object modification date and time */
122     H5O_MSG_SHMESG,		/*0x000F File-wide shared message table */
123     H5O_MSG_CONT,		/*0x0010 Object header continuation	*/
124     H5O_MSG_STAB,		/*0x0011 Symbol table			*/
125     H5O_MSG_MTIME_NEW,		/*0x0012 New Object modification date and time */
126     H5O_MSG_BTREEK,		/*0x0013 Non-default v1 B-tree 'K' values */
127     H5O_MSG_DRVINFO,		/*0x0014 Driver info settings		*/
128     H5O_MSG_AINFO,		/*0x0015 Attribute information		*/
129     H5O_MSG_REFCOUNT,		/*0x0016 Object's ref. count		*/
130     H5O_MSG_FSINFO,		/*0x0017 Free-space manager info        */
131     H5O_MSG_MDCI,               /*0x0018 Metadata cache image           */
132     H5O_MSG_UNKNOWN,		/*0x0019 Placeholder for unknown message */
133 #ifdef H5O_ENABLE_BOGUS
134     H5O_MSG_BOGUS_INVALID, 	/*0x001A "Bogus invalid" (for testing) 	*/
135 #else /* H5O_ENABLE_BOGUS */
136     NULL,                       /*0x001A "Bogus invalid" (for testing) 	*/
137 #endif /* H5O_ENABLE_BOGUS */
138 };
139 
140 /* Declare a free list to manage the H5O_t struct */
141 H5FL_DEFINE(H5O_t);
142 
143 /* Declare a free list to manage the H5O_mesg_t sequence information */
144 H5FL_SEQ_DEFINE(H5O_mesg_t);
145 
146 /* Declare a free list to manage the H5O_chunk_t sequence information */
147 H5FL_SEQ_DEFINE(H5O_chunk_t);
148 
149 /* Declare a free list to manage the chunk image information */
150 H5FL_BLK_DEFINE(chunk_image);
151 
152 /* Declare external the free list for H5O_cont_t sequences */
153 H5FL_SEQ_EXTERN(H5O_cont_t);
154 
155 
156 /*****************************/
157 /* Library Private Variables */
158 /*****************************/
159 
160 /* Declare external the free list for time_t's */
161 H5FL_EXTERN(time_t);
162 
163 /* Declare external the free list for H5_obj_t's */
164 H5FL_EXTERN(H5_obj_t);
165 
166 
167 /*******************/
168 /* Local Variables */
169 /*******************/
170 
171 /* Header object ID to class mapping */
172 /*
173  * Initialize the object class info table.  Begin with the most general types
174  * and end with the most specific. For instance, any object that has a
175  * datatype message is a datatype but only some of them are datasets.
176  */
177 static const H5O_obj_class_t *const H5O_obj_class_g[] = {
178     H5O_OBJ_DATATYPE,		/* Datatype object (H5O_TYPE_NAMED_DATATYPE - 2) */
179     H5O_OBJ_DATASET,		/* Dataset object (H5O_TYPE_DATASET - 1) */
180     H5O_OBJ_GROUP,		/* Group object (H5O_TYPE_GROUP - 0) */
181 };
182 
183 
184 
185 /*-------------------------------------------------------------------------
186  * Function:	H5O__init_package
187  *
188  * Purpose:	Initialize information specific to H5O interface.
189  *
190  * Return:	Non-negative on success/Negative on failure
191  *
192  * Programmer:	Quincey Koziol
193  *              Thursday, January 18, 2007
194  *
195  *-------------------------------------------------------------------------
196  */
197 herr_t
H5O__init_package(void)198 H5O__init_package(void)
199 {
200     FUNC_ENTER_PACKAGE_NOERR
201 
202     /* H5O interface sanity checks */
203     HDcompile_assert(H5O_MSG_TYPES == NELMTS(H5O_msg_class_g));
204     HDcompile_assert(sizeof(H5O_fheap_id_t) == H5O_FHEAP_ID_LEN);
205 
206     HDcompile_assert(H5O_UNKNOWN_ID < H5O_MSG_TYPES);
207 
208     FUNC_LEAVE_NOAPI(SUCCEED)
209 } /* end H5O__init_package() */
210 
211 
212 /*-------------------------------------------------------------------------
213  * Function:	H5Oopen
214  *
215  * Purpose:	Opens an object within an HDF5 file.
216  *
217  *              This function opens an object in the same way that H5Gopen2,
218  *              H5Topen2, and H5Dopen2 do. However, H5Oopen doesn't require
219  *              the type of object to be known beforehand. This can be
220  *              useful in user-defined links, for instance, when only a
221  *              path is known.
222  *
223  *              The opened object should be closed again with H5Oclose
224  *              or H5Gclose, H5Tclose, or H5Dclose.
225  *
226  * Return:	Success:	An open object identifier
227  *		Failure:	Negative
228  *
229  * Programmer:	James Laird
230  *		July 14 2006
231  *
232  *-------------------------------------------------------------------------
233  */
234 hid_t
H5Oopen(hid_t loc_id,const char * name,hid_t lapl_id)235 H5Oopen(hid_t loc_id, const char *name, hid_t lapl_id)
236 {
237     H5G_loc_t	loc;
238     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
239     hid_t       ret_value = FAIL;
240 
241     FUNC_ENTER_API(FAIL)
242     H5TRACE3("i", "i*si", loc_id, name, lapl_id);
243 
244     /* Check args */
245     if(H5G_loc(loc_id, &loc) < 0)
246         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
247     if(!name || !*name)
248         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
249 
250     /* Verify access property list and get correct dxpl */
251     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
252         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
253 
254     /* Open the object */
255     if((ret_value = H5O_open_name(&loc, name, lapl_id, dxpl_id, TRUE)) < 0)
256         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
257 
258 done:
259     FUNC_LEAVE_API(ret_value)
260 } /* end H5Oopen() */
261 
262 
263 /*-------------------------------------------------------------------------
264  * Function:	H5Oopen_by_idx
265  *
266  * Purpose:	Opens an object within an HDF5 file, according to the offset
267  *              within an index.
268  *
269  *              This function opens an object in the same way that H5Gopen,
270  *              H5Topen, and H5Dopen do. However, H5Oopen doesn't require
271  *              the type of object to be known beforehand. This can be
272  *              useful in user-defined links, for instance, when only a
273  *              path is known.
274  *
275  *              The opened object should be closed again with H5Oclose
276  *              or H5Gclose, H5Tclose, or H5Dclose.
277  *
278  * Return:	Success:	An open object identifier
279  *		Failure:	Negative
280  *
281  * Programmer:	Quincey Koziol
282  *		November 20 2006
283  *
284  *-------------------------------------------------------------------------
285  */
286 hid_t
H5Oopen_by_idx(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,hid_t lapl_id)287 H5Oopen_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
288     H5_iter_order_t order, hsize_t n, hid_t lapl_id)
289 {
290     H5G_loc_t	loc;
291     H5G_loc_t   obj_loc;                /* Location used to open group */
292     H5G_name_t  obj_path;            	/* Opened object group hier. path */
293     H5O_loc_t   obj_oloc;            	/* Opened object object location */
294     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
295     hbool_t     loc_found = FALSE;      /* Entry at 'name' found */
296     hid_t       ret_value = FAIL;
297 
298     FUNC_ENTER_API(FAIL)
299     H5TRACE6("i", "i*sIiIohi", loc_id, group_name, idx_type, order, n, lapl_id);
300 
301     /* Check args */
302     if(H5G_loc(loc_id, &loc) < 0)
303         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
304     if(!group_name || !*group_name)
305 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
306     if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
307 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
308     if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
309 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
310 
311     /* Verify access property list and get correct dxpl */
312     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
313         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
314 
315     /* Set up opened group location to fill in */
316     obj_loc.oloc = &obj_oloc;
317     obj_loc.path = &obj_path;
318     H5G_loc_reset(&obj_loc);
319 
320     /* Find the object's location, according to the order in the index */
321     if(H5G_loc_find_by_idx(&loc, group_name, idx_type, order, n, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
322         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "group not found")
323     loc_found = TRUE;
324 
325     /* Open the object */
326     if((ret_value = H5O_open_by_loc(&obj_loc, lapl_id, dxpl_id, TRUE)) < 0)
327         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
328 
329 done:
330     /* Release the object location if we failed after copying it */
331     if(ret_value < 0 && loc_found)
332         if(H5G_loc_free(&obj_loc) < 0)
333             HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
334 
335     FUNC_LEAVE_API(ret_value)
336 } /* end H5Oopen_by_idx() */
337 
338 
339 /*-------------------------------------------------------------------------
340  * Function:	H5Oopen_by_addr
341  *
342  * Purpose:	Warning! This function is EXTREMELY DANGEROUS!
343  *              Improper use can lead to FILE CORRUPTION, INACCESSIBLE DATA,
344  *              and other VERY BAD THINGS!
345  *
346  *              This function opens an object using its address within the
347  *              HDF5 file, similar to an HDF5 hard link. The open object
348  *              is identical to an object opened with H5Oopen() and should
349  *              be closed with H5Oclose() or a type-specific closing
350  *              function (such as H5Gclose() ).
351  *
352  *              This function is very dangerous if called on an invalid
353  *              address. For this reason, H5Oincr_refcount() should be
354  *              used to prevent HDF5 from deleting any object that is
355  *              referenced by address (e.g. by a user-defined link).
356  *              H5Odecr_refcount() should be used when the object is
357  *              no longer being referenced by address (e.g. when the UD link
358  *              is deleted).
359  *
360  *              The address of the HDF5 file on disk has no effect on
361  *              H5Oopen_by_addr(), nor does the use of any unusual file
362  *              drivers. The "address" is really the offset within the
363  *              HDF5 file, and HDF5's file drivers will transparently
364  *              map this to an address on disk for the filesystem.
365  *
366  * Return:	Success:	An open object identifier
367  *		Failure:	Negative
368  *
369  * Programmer:	James Laird
370  *		July 14 2006
371  *
372  *-------------------------------------------------------------------------
373  */
374 hid_t
H5Oopen_by_addr(hid_t loc_id,haddr_t addr)375 H5Oopen_by_addr(hid_t loc_id, haddr_t addr)
376 {
377     H5G_loc_t	loc;
378     H5G_loc_t   obj_loc;                /* Location used to open group */
379     H5G_name_t  obj_path;            	/* Opened object group hier. path */
380     H5O_loc_t   obj_oloc;            	/* Opened object object location */
381     hid_t       lapl_id = H5P_LINK_ACCESS_DEFAULT; /* lapl to use to open this object */
382     hid_t       ret_value = FAIL;
383 
384     FUNC_ENTER_API(FAIL)
385     H5TRACE2("i", "ia", loc_id, addr);
386 
387     /* Check args */
388     if(H5G_loc(loc_id, &loc) < 0)
389         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
390     if(!H5F_addr_defined(addr))
391         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no address supplied")
392 
393     /* Set up opened group location to fill in */
394     obj_loc.oloc = &obj_oloc;
395     obj_loc.path = &obj_path;
396     H5G_loc_reset(&obj_loc);
397     obj_loc.oloc->addr = addr;
398     obj_loc.oloc->file = loc.oloc->file;
399     H5G_name_reset(obj_loc.path);       /* objects opened through this routine don't have a path name */
400 
401     /* Open the object */
402     if((ret_value = H5O_open_by_loc(&obj_loc, lapl_id, H5AC_ind_read_dxpl_id, TRUE)) < 0)
403         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
404 
405 done:
406 
407     FUNC_LEAVE_API(ret_value)
408 } /* end H5Oopen_by_addr() */
409 
410 
411 /*-------------------------------------------------------------------------
412  * Function:	H5Olink
413  *
414  * Purpose:	Creates a hard link from NEW_NAME to the object specified
415  *		by OBJ_ID using properties defined in the Link Creation
416  *              Property List LCPL.
417  *
418  *		This function should be used to link objects that have just
419  *              been created.
420  *
421  *		NEW_NAME is interpreted relative to
422  *		NEW_LOC_ID, which is either a file ID or a
423  *		group ID.
424  *
425  * Return:	Non-negative on success/Negative on failure
426  *
427  * Programmer:	James Laird
428  *              Tuesday, December 13, 2005
429  *
430  *-------------------------------------------------------------------------
431  */
432 herr_t
H5Olink(hid_t obj_id,hid_t new_loc_id,const char * new_name,hid_t lcpl_id,hid_t lapl_id)433 H5Olink(hid_t obj_id, hid_t new_loc_id, const char *new_name, hid_t lcpl_id,
434     hid_t lapl_id)
435 {
436     H5G_loc_t	new_loc;
437     H5G_loc_t	obj_loc;
438     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
439     herr_t      ret_value = SUCCEED;       /* Return value */
440 
441     FUNC_ENTER_API(FAIL)
442     H5TRACE5("e", "ii*sii", obj_id, new_loc_id, new_name, lcpl_id, lapl_id);
443 
444     /* Check arguments */
445     if(H5G_loc(obj_id, &obj_loc) < 0)
446         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
447     if(new_loc_id == H5L_SAME_LOC)
448         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "cannot use H5L_SAME_LOC when only one location is specified")
449     if(H5G_loc(new_loc_id, &new_loc) < 0)
450         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
451     if(!new_name || !*new_name)
452         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
453 /* Avoid compiler warning on 32-bit machines */
454 #if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T
455     if(HDstrlen(new_name) > H5L_MAX_LINK_NAME_LEN)
456         HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "name too long")
457 #endif /* H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T */
458     if(lcpl_id != H5P_DEFAULT && (TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE)))
459         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a link creation property list")
460 
461     /* Verify access property list and get correct dxpl */
462     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, obj_id, TRUE) < 0)
463         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
464 
465     /* Link to the object */
466     if(H5L_link(&new_loc, new_name, &obj_loc, lcpl_id, lapl_id, dxpl_id) < 0)
467         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create link")
468 
469 done:
470     FUNC_LEAVE_API(ret_value)
471 } /* end H5Olink() */
472 
473 
474 /*-------------------------------------------------------------------------
475  * Function:	H5Oincr_refcount
476  *
477  * Purpose:	Warning! This function is EXTREMELY DANGEROUS!
478  *              Improper use can lead to FILE CORRUPTION, INACCESSIBLE DATA,
479  *              and other VERY BAD THINGS!
480  *
481  *              This function increments the "hard link" reference count
482  *              for an object. It should be used when a user-defined link
483  *              that references an object by address is created. When the
484  *              link is deleted, H5Odecr_refcount should be used.
485  *
486  * Return:	Success:	Non-negative
487  *		Failure:	Negative
488  *
489  * Programmer:	James Laird
490  *		July 14 2006
491  *
492  *-------------------------------------------------------------------------
493  */
494 herr_t
H5Oincr_refcount(hid_t object_id)495 H5Oincr_refcount(hid_t object_id)
496 {
497     H5O_loc_t  *oloc;
498     herr_t      ret_value = SUCCEED;
499 
500     FUNC_ENTER_API(FAIL)
501     H5TRACE1("e", "i", object_id);
502 
503     /* Get the object's oloc so we can adjust its link count */
504     if((oloc = H5O_get_loc(object_id)) == NULL)
505         HGOTO_ERROR(H5E_ATOM, H5E_BADVALUE, FAIL, "unable to get object location from ID")
506 
507     if(H5O_link(oloc, 1, H5AC_ind_read_dxpl_id) < 0)
508         HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "modifying object link count failed")
509 
510 done:
511     FUNC_LEAVE_API(ret_value)
512 } /* end H5O_incr_refcount() */
513 
514 
515 /*-------------------------------------------------------------------------
516  * Function:	H5Odecr_refcount
517  *
518  * Purpose:	Warning! This function is EXTREMELY DANGEROUS!
519  *              Improper use can lead to FILE CORRUPTION, INACCESSIBLE DATA,
520  *              and other VERY BAD THINGS!
521  *
522  *              This function decrements the "hard link" reference count
523  *              for an object. It should be used when user-defined links
524  *              that reference an object by address are deleted, and only
525  *              after H5Oincr_refcount has already been used.
526  *
527  * Return:	Success:	Non-negative
528  *		Failure:	Negative
529  *
530  * Programmer:	James Laird
531  *		July 14 2006
532  *
533  *-------------------------------------------------------------------------
534  */
535 herr_t
H5Odecr_refcount(hid_t object_id)536 H5Odecr_refcount(hid_t object_id)
537 {
538     H5O_loc_t  *oloc;
539     herr_t      ret_value = SUCCEED;
540 
541     FUNC_ENTER_API(FAIL)
542     H5TRACE1("e", "i", object_id);
543 
544     /* Get the object's oloc so we can adjust its link count */
545     if((oloc = H5O_get_loc(object_id)) == NULL)
546         HGOTO_ERROR(H5E_ATOM, H5E_BADVALUE, FAIL, "unable to get object location from ID")
547 
548     if(H5O_link(oloc, -1, H5AC_ind_read_dxpl_id) < 0)
549         HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "modifying object link count failed")
550 
551 done:
552     FUNC_LEAVE_API(ret_value)
553 } /* end H5Odecr_refcount() */
554 
555 
556 /*-------------------------------------------------------------------------
557  * Function:	H5Oexists_by_name
558  *
559  * Purpose:	Determine if a linked-to object exists
560  *
561  * Return:	Success:	TRUE/FALSE
562  * 		Failure:	Negative
563  *
564  * Programmer:	Quincey Koziol
565  *		February  2 2010
566  *
567  *-------------------------------------------------------------------------
568  */
569 htri_t
H5Oexists_by_name(hid_t loc_id,const char * name,hid_t lapl_id)570 H5Oexists_by_name(hid_t loc_id, const char *name, hid_t lapl_id)
571 {
572     H5G_loc_t	loc;                    /* Location info */
573     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
574     htri_t      ret_value = FAIL;       /* Return value */
575 
576     FUNC_ENTER_API(FAIL)
577     H5TRACE3("t", "i*si", loc_id, name, lapl_id);
578 
579     /* Check args */
580     if(H5G_loc(loc_id, &loc) < 0)
581         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
582     if(!name || !*name)
583         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
584 
585     /* Verify access property list and get correct dxpl */
586     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
587         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
588 
589     /* Check if the object exists */
590     if((ret_value = H5G_loc_exists(&loc, name, lapl_id, dxpl_id)) < 0)
591         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine if '%s' exists", name)
592 
593 done:
594     FUNC_LEAVE_API(ret_value)
595 } /* end H5Oexists_by_name() */
596 
597 
598 /*-------------------------------------------------------------------------
599  * Function:	H5Oget_info
600  *
601  * Purpose:	Retrieve information about an object.
602  *
603  * Return:	Success:	Non-negative
604  *		Failure:	Negative
605  *
606  * Programmer:	Quincey Koziol
607  *		November 21 2006
608  *
609  *-------------------------------------------------------------------------
610  */
611 herr_t
H5Oget_info(hid_t loc_id,H5O_info_t * oinfo)612 H5Oget_info(hid_t loc_id, H5O_info_t *oinfo)
613 {
614     H5G_loc_t	loc;                    /* Location of group */
615     herr_t      ret_value = SUCCEED;    /* Return value */
616 
617     FUNC_ENTER_API(FAIL)
618     H5TRACE2("e", "i*x", loc_id, oinfo);
619 
620     /* Check args */
621     if(H5G_loc(loc_id, &loc) < 0)
622         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
623     if(!oinfo)
624         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct")
625 
626     /* Retrieve the object's information */
627     if(H5G_loc_info(&loc, ".", TRUE, oinfo/*out*/, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_read_dxpl_id) < 0)
628         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
629 
630 done:
631     FUNC_LEAVE_API(ret_value)
632 } /* end H5Oget_info() */
633 
634 
635 /*-------------------------------------------------------------------------
636  * Function:	H5Oget_info_by_name
637  *
638  * Purpose:	Retrieve information about an object.
639  *
640  * Return:	Success:	Non-negative
641  *		Failure:	Negative
642  *
643  * Programmer:	Quincey Koziol
644  *		November 21 2006
645  *
646  *-------------------------------------------------------------------------
647  */
648 herr_t
H5Oget_info_by_name(hid_t loc_id,const char * name,H5O_info_t * oinfo,hid_t lapl_id)649 H5Oget_info_by_name(hid_t loc_id, const char *name, H5O_info_t *oinfo, hid_t lapl_id)
650 {
651     H5G_loc_t	loc;                    /* Location of group */
652     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
653     herr_t      ret_value = SUCCEED;    /* Return value */
654 
655     FUNC_ENTER_API(FAIL)
656     H5TRACE4("e", "i*s*xi", loc_id, name, oinfo, lapl_id);
657 
658     /* Check args */
659     if(H5G_loc(loc_id, &loc) < 0)
660         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
661     if(!name || !*name)
662         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
663     if(!oinfo)
664         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct")
665 
666     /* Verify access property list and get correct dxpl */
667     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
668         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
669 
670     /* Retrieve the object's information */
671     if(H5G_loc_info(&loc, name, TRUE, oinfo/*out*/, lapl_id, dxpl_id) < 0)
672         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
673 
674 done:
675     FUNC_LEAVE_API(ret_value)
676 } /* end H5Oget_info_by_name() */
677 
678 
679 /*-------------------------------------------------------------------------
680  * Function:	H5Oget_info_by_idx
681  *
682  * Purpose:	Retrieve information about an object, according to the order
683  *              of an index.
684  *
685  * Return:	Success:	Non-negative
686  *		Failure:	Negative
687  *
688  * Programmer:	Quincey Koziol
689  *		November 26 2006
690  *
691  *-------------------------------------------------------------------------
692  */
693 herr_t
H5Oget_info_by_idx(hid_t loc_id,const char * group_name,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,H5O_info_t * oinfo,hid_t lapl_id)694 H5Oget_info_by_idx(hid_t loc_id, const char *group_name, H5_index_t idx_type,
695     H5_iter_order_t order, hsize_t n, H5O_info_t *oinfo, hid_t lapl_id)
696 {
697     H5G_loc_t	loc;                    /* Location of group */
698     H5G_loc_t   obj_loc;                /* Location used to open group */
699     H5G_name_t  obj_path;            	/* Opened object group hier. path */
700     H5O_loc_t   obj_oloc;            	/* Opened object object location */
701     hbool_t     loc_found = FALSE;      /* Entry at 'name' found */
702     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
703     herr_t      ret_value = SUCCEED;    /* Return value */
704 
705     FUNC_ENTER_API(FAIL)
706     H5TRACE7("e", "i*sIiIoh*xi", loc_id, group_name, idx_type, order, n, oinfo,
707              lapl_id);
708 
709     /* Check args */
710     if(H5G_loc(loc_id, &loc) < 0)
711         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
712     if(!group_name || !*group_name)
713 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified")
714     if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
715 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
716     if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
717 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
718     if(!oinfo)
719         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no info struct")
720 
721     /* Verify access property list and get correct dxpl */
722     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
723         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
724 
725     /* Set up opened group location to fill in */
726     obj_loc.oloc = &obj_oloc;
727     obj_loc.path = &obj_path;
728     H5G_loc_reset(&obj_loc);
729 
730     /* Find the object's location, according to the order in the index */
731     if(H5G_loc_find_by_idx(&loc, group_name, idx_type, order, n, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
732         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "group not found")
733     loc_found = TRUE;
734 
735     /* Retrieve the object's information */
736     if(H5O_get_info(obj_loc.oloc, dxpl_id, TRUE, oinfo) < 0)
737         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object info")
738 
739 done:
740     /* Release the object location */
741     if(loc_found && H5G_loc_free(&obj_loc) < 0)
742         HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
743 
744     FUNC_LEAVE_API(ret_value)
745 } /* end H5Oget_info_by_idx() */
746 
747 
748 /*-------------------------------------------------------------------------
749  * Function:	H5Oset_comment
750  *
751  * Purpose:     Gives the specified object a comment.  The COMMENT string
752  *		should be a null terminated string.  An object can have only
753  *		one comment at a time.  Passing NULL for the COMMENT argument
754  *		will remove the comment property from the object.
755  *
756  * Note:	Deprecated in favor of using attributes on objects
757  *
758  * Return:	Non-negative on success/Negative on failure
759  *
760  * Programmer:	Quincey Koziol
761  *		August 30 2007
762  *
763  *-------------------------------------------------------------------------
764  */
765 herr_t
H5Oset_comment(hid_t obj_id,const char * comment)766 H5Oset_comment(hid_t obj_id, const char *comment)
767 {
768     H5G_loc_t	loc;                    /* Location of group */
769     herr_t      ret_value = SUCCEED;    /* Return value */
770 
771     FUNC_ENTER_API(FAIL)
772     H5TRACE2("e", "i*s", obj_id, comment);
773 
774     /* Check args */
775     if(H5G_loc(obj_id, &loc) < 0)
776         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
777 
778     /* (Re)set the object's comment */
779     if(H5G_loc_set_comment(&loc, ".", comment, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_read_dxpl_id) < 0)
780         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
781 
782 done:
783     FUNC_LEAVE_API(ret_value)
784 } /* end H5Oset_comment() */
785 
786 
787 /*-------------------------------------------------------------------------
788  * Function:	H5Oset_comment_by_name
789  *
790  * Purpose:     Gives the specified object a comment.  The COMMENT string
791  *		should be a null terminated string.  An object can have only
792  *		one comment at a time.  Passing NULL for the COMMENT argument
793  *		will remove the comment property from the object.
794  *
795  * Note:	Deprecated in favor of using attributes on objects
796  *
797  * Return:	Non-negative on success/Negative on failure
798  *
799  * Programmer:	Quincey Koziol
800  *		August 30 2007
801  *
802  *-------------------------------------------------------------------------
803  */
804 herr_t
H5Oset_comment_by_name(hid_t loc_id,const char * name,const char * comment,hid_t lapl_id)805 H5Oset_comment_by_name(hid_t loc_id, const char *name, const char *comment,
806     hid_t lapl_id)
807 {
808     H5G_loc_t	loc;                    /* Location of group */
809     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
810     herr_t      ret_value = SUCCEED;    /* Return value */
811 
812     FUNC_ENTER_API(FAIL)
813     H5TRACE4("e", "i*s*si", loc_id, name, comment, lapl_id);
814 
815     /* Check args */
816     if(H5G_loc(loc_id, &loc) < 0)
817         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
818     if(!name || !*name)
819         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
820 
821     /* Verify access property list and get correct dxpl */
822     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, TRUE) < 0)
823         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
824 
825     /* (Re)set the object's comment */
826     if(H5G_loc_set_comment(&loc, name, comment, lapl_id, dxpl_id) < 0)
827         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
828 
829 done:
830     FUNC_LEAVE_API(ret_value)
831 } /* end H5Oset_comment_by_name() */
832 
833 
834 /*-------------------------------------------------------------------------
835  * Function:	H5Oget_comment
836  *
837  * Purpose:	Retrieve comment for an object.
838  *
839  * Return:	Success:	Number of bytes in the comment excluding the
840  *				null terminator.  Zero if the object has no
841  *				comment.
842  *
843  *		Failure:	Negative
844  *
845  * Programmer:	Quincey Koziol
846  *		August 30 2007
847  *
848  *-------------------------------------------------------------------------
849  */
850 ssize_t
H5Oget_comment(hid_t obj_id,char * comment,size_t bufsize)851 H5Oget_comment(hid_t obj_id, char *comment, size_t bufsize)
852 {
853     H5G_loc_t	loc;                    /* Location of group */
854     ssize_t     ret_value;              /* Return value */
855 
856     FUNC_ENTER_API(FAIL)
857     H5TRACE3("Zs", "i*sz", obj_id, comment, bufsize);
858 
859     /* Check args */
860     if(H5G_loc(obj_id, &loc) < 0)
861         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
862 
863     /* Retrieve the object's comment */
864     if((ret_value = H5G_loc_get_comment(&loc, ".", comment/*out*/, bufsize, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_read_dxpl_id)) < 0)
865         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
866 
867 done:
868     FUNC_LEAVE_API(ret_value)
869 } /* end H5Oget_comment() */
870 
871 
872 /*-------------------------------------------------------------------------
873  * Function:	H5Oget_comment_by_name
874  *
875  * Purpose:	Retrieve comment for an object.
876  *
877  * Return:	Success:	Number of bytes in the comment excluding the
878  *				null terminator.  Zero if the object has no
879  *				comment.
880  *
881  *		Failure:	Negative
882  *
883  * Programmer:	Quincey Koziol
884  *		August 30 2007
885  *
886  *-------------------------------------------------------------------------
887  */
888 ssize_t
H5Oget_comment_by_name(hid_t loc_id,const char * name,char * comment,size_t bufsize,hid_t lapl_id)889 H5Oget_comment_by_name(hid_t loc_id, const char *name, char *comment, size_t bufsize,
890     hid_t lapl_id)
891 {
892     H5G_loc_t	loc;                    /* Location of group */
893     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
894     ssize_t     ret_value;              /* Return value */
895 
896     FUNC_ENTER_API(FAIL)
897     H5TRACE5("Zs", "i*s*szi", loc_id, name, comment, bufsize, lapl_id);
898 
899     /* Check args */
900     if(H5G_loc(loc_id, &loc) < 0)
901         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
902     if(!name || !*name)
903         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
904 
905     /* Verify access property list and get correct dxpl */
906     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
907         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
908 
909     /* Retrieve the object's comment */
910     if((ret_value = H5G_loc_get_comment(&loc, name, comment/*out*/, bufsize, lapl_id, dxpl_id)) < 0)
911         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
912 
913 done:
914     FUNC_LEAVE_API(ret_value)
915 } /* end H5Oget_comment_by_name() */
916 
917 
918 /*-------------------------------------------------------------------------
919  * Function:	H5Ovisit
920  *
921  * Purpose:	Recursively visit an object and all the objects reachable
922  *              from it.  If the starting object is a group, all the objects
923  *              linked to from that group will be visited.  Links within
924  *              each group are visited according to the order within the
925  *              specified index (unless the specified index does not exist for
926  *              a particular group, then the "name" index is used).
927  *
928  *              NOTE: Soft links and user-defined links are ignored during
929  *              this operation.
930  *
931  *              NOTE: Each _object_ reachable from the initial group will only
932  *              be visited once.  If multiple hard links point to the same
933  *              object, the first link to the object's path (according to the
934  *              iteration index and iteration order given) will be used to in
935  *              the callback about the object.
936  *
937  * Return:	Success:	The return value of the first operator that
938  *				returns non-zero, or zero if all members were
939  *				processed with no operator returning non-zero.
940  *
941  *		Failure:	Negative if something goes wrong within the
942  *				library, or the negative value returned by one
943  *				of the operators.
944  *
945  * Programmer:	Quincey Koziol
946  *		November 25 2007
947  *
948  *-------------------------------------------------------------------------
949  */
950 herr_t
H5Ovisit(hid_t obj_id,H5_index_t idx_type,H5_iter_order_t order,H5O_iterate_t op,void * op_data)951 H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
952     H5O_iterate_t op, void *op_data)
953 {
954     herr_t      ret_value;              /* Return value */
955 
956     FUNC_ENTER_API(FAIL)
957     H5TRACE5("e", "iIiIox*x", obj_id, idx_type, order, op, op_data);
958 
959     /* Check args */
960     if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
961 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
962     if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
963 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
964     if(!op)
965         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
966 
967     /* Call internal object visitation routine */
968     if((ret_value = H5O_visit(obj_id, ".", idx_type, order, op, op_data, H5P_LINK_ACCESS_DEFAULT, H5AC_ind_read_dxpl_id)) < 0)
969 	HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
970 
971 done:
972     FUNC_LEAVE_API(ret_value)
973 } /* end H5Ovisit() */
974 
975 
976 /*-------------------------------------------------------------------------
977  * Function:	H5Ovisit_by_name
978  *
979  * Purpose:	Recursively visit an object and all the objects reachable
980  *              from it.  If the starting object is a group, all the objects
981  *              linked to from that group will be visited.  Links within
982  *              each group are visited according to the order within the
983  *              specified index (unless the specified index does not exist for
984  *              a particular group, then the "name" index is used).
985  *
986  *              NOTE: Soft links and user-defined links are ignored during
987  *              this operation.
988  *
989  *              NOTE: Each _object_ reachable from the initial group will only
990  *              be visited once.  If multiple hard links point to the same
991  *              object, the first link to the object's path (according to the
992  *              iteration index and iteration order given) will be used to in
993  *              the callback about the object.
994  *
995  * Return:	Success:	The return value of the first operator that
996  *				returns non-zero, or zero if all members were
997  *				processed with no operator returning non-zero.
998  *
999  *		Failure:	Negative if something goes wrong within the
1000  *				library, or the negative value returned by one
1001  *				of the operators.
1002  *
1003  * Programmer:	Quincey Koziol
1004  *		November 24 2007
1005  *
1006  *-------------------------------------------------------------------------
1007  */
1008 herr_t
H5Ovisit_by_name(hid_t loc_id,const char * obj_name,H5_index_t idx_type,H5_iter_order_t order,H5O_iterate_t op,void * op_data,hid_t lapl_id)1009 H5Ovisit_by_name(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
1010     H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id)
1011 {
1012     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
1013     herr_t      ret_value;              /* Return value */
1014 
1015     FUNC_ENTER_API(FAIL)
1016     H5TRACE7("e", "i*sIiIox*xi", loc_id, obj_name, idx_type, order, op, op_data,
1017              lapl_id);
1018 
1019     /* Check args */
1020     if(!obj_name || !*obj_name)
1021         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
1022     if(idx_type <= H5_INDEX_UNKNOWN || idx_type >= H5_INDEX_N)
1023 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index type specified")
1024     if(order <= H5_ITER_UNKNOWN || order >= H5_ITER_N)
1025 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid iteration order specified")
1026     if(!op)
1027         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no callback operator specified")
1028 
1029     /* Verify access property list and get correct dxpl */
1030     if(H5P_verify_apl_and_dxpl(&lapl_id, H5P_CLS_LACC, &dxpl_id, loc_id, FALSE) < 0)
1031         HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
1032 
1033     /* Call internal object visitation routine */
1034     if((ret_value = H5O_visit(loc_id, obj_name, idx_type, order, op, op_data, lapl_id, dxpl_id)) < 0)
1035 	HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
1036 
1037 done:
1038     FUNC_LEAVE_API(ret_value)
1039 } /* end H5Ovisit_by_name() */
1040 
1041 
1042 /*-------------------------------------------------------------------------
1043  * Function:	H5Oclose
1044  *
1045  * Purpose:	Close an open file object.
1046  *
1047  *              This is the companion to H5Oopen. It is used to close any
1048  *              open object in an HDF5 file (but not IDs are that not file
1049  *              objects, such as property lists and dataspaces). It has
1050  *              the same effect as calling H5Gclose, H5Dclose, or H5Tclose.
1051  *
1052  * Return:	Success:	Non-negative
1053  *          Failure:	Negative
1054  *
1055  * Programmer:	James Laird
1056  *		July 14 2006
1057  *
1058  *-------------------------------------------------------------------------
1059  */
1060 herr_t
H5Oclose(hid_t object_id)1061 H5Oclose(hid_t object_id)
1062 {
1063     herr_t       ret_value = SUCCEED;
1064 
1065     FUNC_ENTER_API(FAIL)
1066     H5TRACE1("e", "i", object_id);
1067 
1068     /* Get the type of the object and close it in the correct way */
1069     switch(H5I_get_type(object_id)) {
1070         case H5I_GROUP:
1071         case H5I_DATATYPE:
1072         case H5I_DATASET:
1073             if(H5I_object(object_id) == NULL)
1074                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid object")
1075             if(H5I_dec_app_ref(object_id) < 0)
1076                 HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
1077             break;
1078 
1079         case H5I_UNINIT:
1080         case H5I_BADID:
1081         case H5I_FILE:
1082         case H5I_DATASPACE:
1083         case H5I_ATTR:
1084         case H5I_REFERENCE:
1085         case H5I_VFL:
1086         case H5I_GENPROP_CLS:
1087         case H5I_GENPROP_LST:
1088         case H5I_ERROR_CLASS:
1089         case H5I_ERROR_MSG:
1090         case H5I_ERROR_STACK:
1091         case H5I_NTYPES:
1092         default:
1093             HGOTO_ERROR(H5E_ARGS, H5E_CANTRELEASE, FAIL, "not a valid file object ID (dataset, group, or datatype)")
1094         break;
1095     } /* end switch */
1096 
1097 done:
1098     FUNC_LEAVE_API(ret_value)
1099 } /* end H5Oclose() */
1100 
1101 
1102 /*-------------------------------------------------------------------------
1103  * Function:	H5Odisable_mdc_flushes
1104  *
1105  * Purpose:	To "cork" an object:
1106  *		--keep dirty entries assoicated with the object in the metadata cache
1107  *
1108  * Return:	Success:	Non-negative
1109  *		Failure:	Negative
1110  *
1111  * Programmer:	Vailin Choi
1112  *		January 2014
1113  *
1114  *-------------------------------------------------------------------------
1115  */
1116 herr_t
H5Odisable_mdc_flushes(hid_t object_id)1117 H5Odisable_mdc_flushes(hid_t object_id)
1118 {
1119     H5O_loc_t  *oloc;			/* Object location */
1120     herr_t      ret_value = SUCCEED;	/* Return value */
1121 
1122     FUNC_ENTER_API(FAIL)
1123     H5TRACE1("e", "i", object_id);
1124 
1125     /* Get the object's oloc */
1126     if(NULL == (oloc = H5O_get_loc(object_id)))
1127         HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
1128 
1129     if(H5AC_cork(oloc->file, oloc->addr, H5AC__SET_CORK, NULL) < 0)
1130         HGOTO_ERROR(H5E_OHDR, H5E_CANTCORK, FAIL, "unable to cork an object")
1131 
1132 done:
1133     FUNC_LEAVE_API(ret_value)
1134 } /* H5Odisable_mdc_flushes() */
1135 
1136 
1137 /*-------------------------------------------------------------------------
1138  * Function:	H5Oenable_mdc_flushes
1139  *
1140  * Purpose:	To "uncork" an object
1141  *		--release keeping dirty entries associated with the object
1142  *		  in the metadata cache
1143  *
1144  * Return:	Success:	Non-negative
1145  *		Failure:	Negative
1146  *
1147  * Programmer:	Vailin Choi
1148  *		January 2014
1149  *
1150  *-------------------------------------------------------------------------
1151  */
1152 herr_t
H5Oenable_mdc_flushes(hid_t object_id)1153 H5Oenable_mdc_flushes(hid_t object_id)
1154 {
1155     H5O_loc_t  *oloc;			/* Object location */
1156     herr_t      ret_value = SUCCEED;	/* Return value */
1157 
1158     FUNC_ENTER_API(FAIL)
1159     H5TRACE1("e", "i", object_id);
1160 
1161     /* Get the object's oloc */
1162     if(NULL == (oloc = H5O_get_loc(object_id)))
1163         HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
1164 
1165     /* Set the value */
1166     if(H5AC_cork(oloc->file, oloc->addr, H5AC__UNCORK, NULL) < 0)
1167         HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
1168 
1169 done:
1170     FUNC_LEAVE_API(ret_value)
1171 } /* H5Oenable_mdc_flushes() */
1172 
1173 
1174 /*-------------------------------------------------------------------------
1175  * Function:	H5Oare_mdc_flushes_disabled
1176  *
1177  * Purpose:	Retrieve the object's "cork" status in the parameter "are_disabled":
1178  *		  TRUE if mdc flushes for the object is disabled
1179  *		  FALSE if mdc flushes for the object is not disabled
1180  *		Return error if the parameter "are_disabled" is not supplied
1181  *
1182  * Return:	Success:	Non-negative
1183  *		Failure:	Negative
1184  *
1185  * Programmer:	Vailin Choi
1186  *		January 2014
1187  *
1188  *-------------------------------------------------------------------------
1189  */
1190 herr_t
H5Oare_mdc_flushes_disabled(hid_t object_id,hbool_t * are_disabled)1191 H5Oare_mdc_flushes_disabled(hid_t object_id, hbool_t *are_disabled)
1192 {
1193     H5O_loc_t  *oloc;			/* Object location */
1194     herr_t      ret_value = SUCCEED;	/* Return value */
1195 
1196     FUNC_ENTER_API(FAIL)
1197     H5TRACE2("e", "i*b", object_id, are_disabled);
1198 
1199     /* Check args */
1200 
1201     /* Get the object's oloc */
1202     if(NULL == (oloc = H5O_get_loc(object_id)))
1203         HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
1204     if(!are_disabled)
1205         HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "unable to get object location from ID")
1206 
1207     /* Get the cork status */
1208     if(H5AC_cork(oloc->file, oloc->addr, H5AC__GET_CORKED, are_disabled) < 0)
1209         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
1210 
1211 done:
1212     FUNC_LEAVE_API(ret_value)
1213 } /* H5Oare_mdc_flushes_disabled() */
1214 
1215 
1216 /*-------------------------------------------------------------------------
1217  * Function:	H5O_create
1218  *
1219  * Purpose:	Creates a new object header. Allocates space for it and
1220  *              then calls an initialization function. The object header
1221  *              is opened for write access and should eventually be
1222  *              closed by calling H5O_close().
1223  *
1224  * Return:	Success:	Non-negative, the ENT argument contains
1225  *				information about the object header,
1226  *				including its address.
1227  *
1228  *		Failure:	Negative
1229  *
1230  * Programmer:	Robb Matzke
1231  *		matzke@llnl.gov
1232  *		Aug  5 1997
1233  *
1234  *-------------------------------------------------------------------------
1235  */
1236 herr_t
H5O_create(H5F_t * f,hid_t dxpl_id,size_t size_hint,size_t initial_rc,hid_t ocpl_id,H5O_loc_t * loc)1237 H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, size_t initial_rc,
1238     hid_t ocpl_id, H5O_loc_t *loc/*out*/)
1239 {
1240     H5P_genplist_t  *oc_plist;          /* Object creation property list */
1241     H5O_t      *oh = NULL;              /* Object header created */
1242     haddr_t     oh_addr;                /* Address of initial object header */
1243     size_t      oh_size;                /* Size of initial object header */
1244     uint8_t	oh_flags;		/* Object header's initial status flags */
1245     unsigned    insert_flags = H5AC__NO_FLAGS_SET; /* Flags for inserting object header into cache */
1246     hbool_t     store_msg_crt_idx;      /* Whether to always store message creation indices for this file */
1247     herr_t      ret_value = SUCCEED;    /* return value */
1248 
1249     FUNC_ENTER_NOAPI(FAIL)
1250 
1251     /* check args */
1252     HDassert(f);
1253     HDassert(loc);
1254     HDassert(TRUE == H5P_isa_class(ocpl_id, H5P_OBJECT_CREATE));
1255 
1256     /* Check for invalid access request */
1257     if(0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
1258         HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, FAIL, "no write intent on file")
1259 
1260     /* Make certain we allocate at least a reasonable size for the object header */
1261     size_hint = H5O_ALIGN_F(f, MAX(H5O_MIN_SIZE, size_hint));
1262 
1263     /* Get the property list */
1264     if(NULL == (oc_plist = (H5P_genplist_t *)H5I_object(ocpl_id)))
1265         HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property list")
1266 
1267     /* Get any object header status flags set by properties */
1268     if(H5P_get(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &oh_flags) < 0)
1269         HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object header flags")
1270 
1271     /* Allocate the object header and zero out header fields */
1272     if(NULL == (oh = H5FL_CALLOC(H5O_t)))
1273         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
1274 
1275     /* Initialize file-specific information for object header */
1276     store_msg_crt_idx = H5F_STORE_MSG_CRT_IDX(f);
1277     if(H5F_USE_LATEST_FLAGS(f, H5F_LATEST_OBJ_HEADER) || store_msg_crt_idx || (oh_flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED))
1278         oh->version = H5O_VERSION_LATEST;
1279     else
1280         oh->version = H5O_VERSION_1;
1281     oh->sizeof_size = H5F_SIZEOF_SIZE(f);
1282     oh->sizeof_addr = H5F_SIZEOF_ADDR(f);
1283     oh->swmr_write = !!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE);
1284 #ifdef H5O_ENABLE_BAD_MESG_COUNT
1285     /* Check whether the "bad message count" property is set */
1286     if(H5P_exist_plist(oc_plist, H5O_BAD_MESG_COUNT_NAME) > 0) {
1287         /* Retrieve bad message count flag */
1288         if(H5P_get(oc_plist, H5O_BAD_MESG_COUNT_NAME, &oh->store_bad_mesg_count) < 0)
1289             HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't get bad message count flag")
1290     } /* end if */
1291 #endif /* H5O_ENABLE_BAD_MESG_COUNT */
1292 
1293     /* Create object header proxy if doing SWMR writes */
1294     if(oh->swmr_write) {
1295         /* Create virtual entry, for use as proxy */
1296         if(NULL == (oh->proxy = H5AC_proxy_entry_create()))
1297             HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create object header proxy")
1298     } /* end if */
1299     else
1300         oh->proxy = NULL;
1301 
1302     /* Set initial status flags */
1303     oh->flags = oh_flags;
1304 
1305     /* Initialize version-specific fields */
1306     if(oh->version > H5O_VERSION_1) {
1307         /* Initialize all time fields with current time, if we are storing them */
1308         if(oh->flags & H5O_HDR_STORE_TIMES)
1309             oh->atime = oh->mtime = oh->ctime = oh->btime = H5_now();
1310         else
1311             oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
1312 
1313         /* Make certain attribute creation order tracking is enabled if
1314          *      attributes can be shared in this file.
1315          */
1316         if(store_msg_crt_idx)
1317             oh->flags |= H5O_HDR_ATTR_CRT_ORDER_TRACKED;
1318 
1319         /* Retrieve attribute storage phase change values from property list */
1320         if(H5P_get(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
1321             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get max. # of compact attributes")
1322         if(H5P_get(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
1323             HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get min. # of dense attributes")
1324 
1325         /* Check for non-default attribute storage phase change values */
1326         if(oh->max_compact != H5O_CRT_ATTR_MAX_COMPACT_DEF || oh->min_dense != H5O_CRT_ATTR_MIN_DENSE_DEF)
1327             oh->flags |= H5O_HDR_ATTR_STORE_PHASE_CHANGE;
1328 
1329         /* Determine correct value for chunk #0 size bits */
1330 /* Avoid compiler warning on 32-bit machines */
1331 #if H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T
1332         if(size_hint > 4294967295UL)
1333             oh->flags |= H5O_HDR_CHUNK0_8;
1334         else
1335 #endif /* H5_SIZEOF_SIZE_T > H5_SIZEOF_INT32_T */
1336         if(size_hint > 65535)
1337             oh->flags |= H5O_HDR_CHUNK0_4;
1338         else if(size_hint > 255)
1339             oh->flags |= H5O_HDR_CHUNK0_2;
1340     } /* end if */
1341     else {
1342         /* Reset unused time fields */
1343         oh->atime = oh->mtime = oh->ctime = oh->btime = 0;
1344     } /* end else */
1345 
1346     /* Compute total size of initial object header */
1347     /* (i.e. object header prefix and first chunk) */
1348     oh_size = (size_t)H5O_SIZEOF_HDR(oh) + size_hint;
1349 
1350     /* Allocate disk space for header and first chunk */
1351     if(HADDR_UNDEF == (oh_addr = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, (hsize_t)oh_size)))
1352         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header")
1353 
1354     /* Create the chunk list */
1355     oh->nchunks = oh->alloc_nchunks = 1;
1356     if(NULL == (oh->chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->alloc_nchunks)))
1357         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
1358 
1359     /* Initialize the first chunk */
1360     oh->chunk[0].addr = oh_addr;
1361     oh->chunk[0].size = oh_size;
1362     oh->chunk[0].gap = 0;
1363 
1364     /* Allocate enough space for the first chunk */
1365     /* (including space for serializing the object header prefix */
1366     if(NULL == (oh->chunk[0].image = H5FL_BLK_CALLOC(chunk_image, oh_size)))
1367         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
1368     oh->chunk[0].chunk_proxy = NULL;
1369 
1370     /* Put magic # for object header in first chunk */
1371     if(oh->version > H5O_VERSION_1)
1372         HDmemcpy(oh->chunk[0].image, H5O_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
1373 
1374     /* Create the message list */
1375     oh->nmesgs = 1;
1376     oh->alloc_nmesgs = H5O_NMESGS;
1377     if(NULL == (oh->mesg = H5FL_SEQ_CALLOC(H5O_mesg_t, oh->alloc_nmesgs)))
1378         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
1379 
1380     /* Initialize the initial "null" message, covering the entire first chunk */
1381     oh->mesg[0].type = H5O_MSG_NULL;
1382     oh->mesg[0].dirty = TRUE;
1383     oh->mesg[0].native = NULL;
1384     oh->mesg[0].raw = oh->chunk[0].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)) + H5O_SIZEOF_MSGHDR_OH(oh);
1385     oh->mesg[0].raw_size = size_hint - (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
1386     oh->mesg[0].chunkno = 0;
1387 
1388     /* Check for non-zero initial refcount on the object header */
1389     if(initial_rc > 0) {
1390         /* Set the initial refcount & pin the header when its inserted */
1391         oh->rc = initial_rc;
1392         insert_flags |= H5AC__PIN_ENTRY_FLAG;
1393     } /* end if */
1394 
1395     /* Set metadata tag in dxpl_id */
1396     H5_BEGIN_TAG(dxpl_id, oh_addr, FAIL);
1397 
1398     /* Cache object header */
1399     if(H5AC_insert_entry(f, dxpl_id, H5AC_OHDR, oh_addr, oh, insert_flags) < 0)
1400         HGOTO_ERROR_TAG(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to cache object header")
1401 
1402     /* Reset object header pointer, now that it's been inserted into the cache */
1403     oh = NULL;
1404 
1405     /* Reset metadata tag in dxpl_id */
1406     H5_END_TAG(FAIL);
1407 
1408     /* Set up object location */
1409     loc->file = f;
1410     loc->addr = oh_addr;
1411 
1412     /* Open it */
1413     if(H5O_open(loc) < 0)
1414         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object header")
1415 
1416 done:
1417     if(ret_value < 0 && oh)
1418         if(H5O__free(oh) < 0)
1419 	    HDONE_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy object header data")
1420 
1421     FUNC_LEAVE_NOAPI(ret_value)
1422 } /* end H5O_create() */
1423 
1424 
1425 /*-------------------------------------------------------------------------
1426  * Function:	H5O_open
1427  *
1428  * Purpose:	Opens an object header which is described by the symbol table
1429  *		entry OBJ_ENT.
1430  *
1431  * Return:	Non-negative on success/Negative on failure
1432  *
1433  * Programmer:	Robb Matzke
1434  *		Monday, January	 5, 1998
1435  *
1436  * Modification:
1437  *              Raymond Lu
1438  *              5 November 2007
1439  *              Turn off the holding file variable if it's on.  When it's
1440  *              needed, the caller will turn it on again.
1441  *-------------------------------------------------------------------------
1442  */
1443 herr_t
H5O_open(H5O_loc_t * loc)1444 H5O_open(H5O_loc_t *loc)
1445 {
1446     herr_t ret_value = SUCCEED;         /* Return value */
1447 
1448     FUNC_ENTER_NOAPI(FAIL)
1449 
1450     /* Check args */
1451     HDassert(loc);
1452     HDassert(loc->file);
1453 
1454 #ifdef H5O_DEBUG
1455     if(H5DEBUG(O))
1456 	HDfprintf(H5DEBUG(O), "> %a\n", loc->addr);
1457 #endif
1458 
1459     /* Turn off the variable for holding file or increment open-lock counters */
1460     if(loc->holding_file)
1461      	loc->holding_file = FALSE;
1462     else
1463         H5F_INCR_NOPEN_OBJS(loc->file);
1464 
1465 done:
1466     FUNC_LEAVE_NOAPI(ret_value)
1467 } /* end H5O_open() */
1468 
1469 
1470 /*-------------------------------------------------------------------------
1471  * Function:	H5O_open_name
1472  *
1473  * Purpose:	Opens an object within an HDF5 file.
1474  *
1475  * Return:	Success:	An open object identifier
1476  *		Failure:	Negative
1477  *
1478  * Programmer:	Quincey Koziol
1479  *		March  5 2007
1480  *
1481  *-------------------------------------------------------------------------
1482  */
1483 hid_t
H5O_open_name(H5G_loc_t * loc,const char * name,hid_t lapl_id,hid_t dxpl_id,hbool_t app_ref)1484 H5O_open_name(H5G_loc_t *loc, const char *name, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref)
1485 {
1486     H5G_loc_t   obj_loc;                /* Location used to open group */
1487     H5G_name_t  obj_path;            	/* Opened object group hier. path */
1488     H5O_loc_t   obj_oloc;            	/* Opened object object location */
1489     hbool_t     loc_found = FALSE;      /* Entry at 'name' found */
1490     hid_t       ret_value = FAIL;
1491 
1492     FUNC_ENTER_NOAPI(FAIL)
1493 
1494     /* Check args */
1495     HDassert(loc);
1496     HDassert(name && *name);
1497 
1498     /* Set up opened group location to fill in */
1499     obj_loc.oloc = &obj_oloc;
1500     obj_loc.path = &obj_path;
1501     H5G_loc_reset(&obj_loc);
1502 
1503     /* Find the object's location */
1504     if(H5G_loc_find(loc, name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
1505         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
1506     loc_found = TRUE;
1507 
1508     /* Open the object */
1509     if((ret_value = H5O_open_by_loc(&obj_loc, lapl_id, dxpl_id, app_ref)) < 0)
1510         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
1511 
1512 done:
1513     if(ret_value < 0 && loc_found)
1514         if(H5G_loc_free(&obj_loc) < 0)
1515             HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
1516 
1517     FUNC_LEAVE_NOAPI(ret_value)
1518 } /* end H5O_open_name() */
1519 
1520 
1521 /*-------------------------------------------------------------------------
1522  * Function:	H5O_open_by_loc
1523  *
1524  * Purpose:	Opens an object and returns an ID given its group loction.
1525  *
1526  * Return:	Success:	Open object identifier
1527  *		Failure:	Negative
1528  *
1529  * Programmer:	James Laird
1530  *		July 25 2006
1531  *
1532  *-------------------------------------------------------------------------
1533  */
1534 hid_t
H5O_open_by_loc(const H5G_loc_t * obj_loc,hid_t lapl_id,hid_t dxpl_id,hbool_t app_ref)1535 H5O_open_by_loc(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref)
1536 {
1537     const H5O_obj_class_t *obj_class;   /* Class of object for location */
1538     hid_t               ret_value = H5I_INVALID_HID;    /* Return value */
1539 
1540     FUNC_ENTER_NOAPI(FAIL)
1541 
1542     HDassert(obj_loc);
1543 
1544     /* Get the object class for this location */
1545     if(NULL == (obj_class = H5O_obj_class(obj_loc->oloc, dxpl_id)))
1546         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine object class")
1547 
1548     /* Call the object class's 'open' routine */
1549     HDassert(obj_class->open);
1550     if((ret_value = obj_class->open(obj_loc, lapl_id, dxpl_id, app_ref)) < 0)
1551         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
1552 
1553 done:
1554     FUNC_LEAVE_NOAPI(ret_value)
1555 } /* end H5O_open_by_loc() */
1556 
1557 
1558 /*-------------------------------------------------------------------------
1559  * Function:	H5O_close
1560  *
1561  * Purpose:	Closes an object header that was previously open.
1562  *
1563  * Return:	Non-negative on success/Negative on failure
1564  *
1565  * Programmer:	Robb Matzke
1566  *		Monday, January	 5, 1998
1567  *
1568  *-------------------------------------------------------------------------
1569  */
1570 herr_t
H5O_close(H5O_loc_t * loc,hbool_t * file_closed)1571 H5O_close(H5O_loc_t *loc, hbool_t *file_closed /*out*/)
1572 {
1573     herr_t ret_value = SUCCEED;   /* Return value */
1574 
1575     FUNC_ENTER_NOAPI(FAIL)
1576 
1577     /* Check args */
1578     HDassert(loc);
1579     HDassert(loc->file);
1580     HDassert(H5F_NOPEN_OBJS(loc->file) > 0);
1581 
1582     /* Set the file_closed flag to the default value.
1583      * This flag lets downstream code know if the file struct is
1584      * still accessible and/or likely to contain useful data.
1585      * It's needed by the evict-on-close code. Clients can ignore
1586      * this value by passing in NULL.
1587      */
1588     if(file_closed)
1589         *file_closed = FALSE;
1590 
1591     /* Decrement open-lock counters */
1592     H5F_DECR_NOPEN_OBJS(loc->file);
1593 
1594 #ifdef H5O_DEBUG
1595     if(H5DEBUG(O)) {
1596 	if(H5F_FILE_ID(loc->file)< 0 && 1 == H5F_NREFS(loc->file))
1597 	    HDfprintf(H5DEBUG(O), "< %a auto %lu remaining\n",
1598 		      loc->addr,
1599 		      (unsigned long)H5F_NOPEN_OBJS(loc->file));
1600 	else
1601 	    HDfprintf(H5DEBUG(O), "< %a\n", loc->addr);
1602     } /* end if */
1603 #endif
1604 
1605     /*
1606      * If the file open object count has reached the number of open mount points
1607      * (each of which has a group open in the file) attempt to close the file.
1608      */
1609     if(H5F_NOPEN_OBJS(loc->file) == H5F_NMOUNTS(loc->file))
1610         /* Attempt to close down the file hierarchy */
1611         if(H5F_try_close(loc->file, file_closed) < 0)
1612             HGOTO_ERROR(H5E_OHDR, H5E_CANTCLOSEFILE, FAIL, "problem attempting file close")
1613 
1614     /* Release location information */
1615     if(H5O_loc_free(loc) < 0)
1616         HGOTO_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "problem attempting to free location")
1617 
1618 done:
1619     FUNC_LEAVE_NOAPI(ret_value)
1620 } /* end H5O_close() */
1621 
1622 
1623 /*-------------------------------------------------------------------------
1624  * Function:	H5O_link_oh
1625  *
1626  * Purpose:	Adjust the link count for an open object header by adding
1627  *		ADJUST to the link count.
1628  *
1629  * Return:	Success:	New link count
1630  *
1631  *		Failure:	Negative
1632  *
1633  * Programmer:	Robb Matzke
1634  *		matzke@llnl.gov
1635  *		Aug  5 1997
1636  *
1637  *-------------------------------------------------------------------------
1638  */
1639 int
H5O_link_oh(H5F_t * f,int adjust,hid_t dxpl_id,H5O_t * oh,hbool_t * deleted)1640 H5O_link_oh(H5F_t *f, int adjust, hid_t dxpl_id, H5O_t *oh, hbool_t *deleted)
1641 {
1642     haddr_t addr = H5O_OH_GET_ADDR(oh);     /* Object header address */
1643     int	ret_value = -1;                     /* Return value */
1644 
1645     FUNC_ENTER_NOAPI(FAIL)
1646 
1647     /* check args */
1648     HDassert(f);
1649     HDassert(oh);
1650     HDassert(deleted);
1651 
1652     /* Check for adjusting link count */
1653     if(adjust) {
1654         if(adjust < 0) {
1655             /* Check for too large of an adjustment */
1656             if((unsigned)(-adjust) > oh->nlink)
1657                 HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "link count would be negative")
1658 
1659             /* Adjust the link count for the object header */
1660             oh->nlink = (unsigned)((int)oh->nlink + adjust);
1661 
1662             /* Mark object header as dirty in cache */
1663             if(H5AC_mark_entry_dirty(oh) < 0)
1664                 HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
1665 
1666             /* Check if the object should be deleted */
1667             if(oh->nlink == 0) {
1668                 /* Check if the object is still open by the user */
1669                 if(H5FO_opened(f, addr) != NULL) {
1670                     /* Flag the object to be deleted when it's closed */
1671                     if(H5FO_mark(f, addr, TRUE) < 0)
1672                         HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion")
1673                 } /* end if */
1674                 else {
1675                     /* Mark the object header for deletion */
1676                     *deleted = TRUE;
1677                 } /* end else */
1678             } /* end if */
1679         } /* end if */
1680         else {
1681             /* A new object, or one that will be deleted */
1682             if(0 == oh->nlink) {
1683                 /* Check if the object is currently open, but marked for deletion */
1684                 if(H5FO_marked(f, addr)) {
1685                     /* Remove "delete me" flag on the object */
1686                     if(H5FO_mark(f, addr, FALSE) < 0)
1687                         HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't mark object for deletion")
1688                 } /* end if */
1689             } /* end if */
1690 
1691             /* Adjust the link count for the object header */
1692             oh->nlink = (unsigned)((int)oh->nlink + adjust);
1693 
1694             /* Mark object header as dirty in cache */
1695             if(H5AC_mark_entry_dirty(oh) < 0)
1696                 HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
1697         } /* end if */
1698 
1699         /* Check for operations on refcount message */
1700         if(oh->version > H5O_VERSION_1) {
1701             /* Check if the object has a refcount message already */
1702             if(oh->has_refcount_msg) {
1703                 /* Check for removing refcount message */
1704                 if(oh->nlink <= 1) {
1705                     if(H5O_msg_remove_real(f, oh, H5O_MSG_REFCOUNT, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0)
1706                         HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete refcount message")
1707                     oh->has_refcount_msg = FALSE;
1708                 } /* end if */
1709                 /* Update refcount message with new link count */
1710                 else {
1711                     H5O_refcount_t refcount = oh->nlink;
1712 
1713                     if(H5O_msg_write_real(f, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0)
1714                         HGOTO_ERROR(H5E_OHDR, H5E_CANTUPDATE, FAIL, "unable to update refcount message")
1715                 } /* end else */
1716             } /* end if */
1717             else {
1718                 /* Check for adding refcount message to object */
1719                 if(oh->nlink > 1) {
1720                     H5O_refcount_t refcount = oh->nlink;
1721 
1722                     if(H5O_msg_append_real(f, dxpl_id, oh, H5O_MSG_REFCOUNT, H5O_MSG_FLAG_DONTSHARE, 0, &refcount) < 0)
1723                         HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "unable to create new refcount message")
1724                     oh->has_refcount_msg = TRUE;
1725                 } /* end if */
1726             } /* end else */
1727         } /* end if */
1728     } /* end if */
1729 
1730     /* Set return value */
1731     ret_value = (int)oh->nlink;
1732 
1733 done:
1734     FUNC_LEAVE_NOAPI(ret_value)
1735 } /* end H5O_link_oh() */
1736 
1737 
1738 /*-------------------------------------------------------------------------
1739  * Function:	H5O_link
1740  *
1741  * Purpose:	Adjust the link count for an object header by adding
1742  *		ADJUST to the link count.
1743  *
1744  * Return:	Success:	New link count
1745  *
1746  *		Failure:	Negative
1747  *
1748  * Programmer:	Robb Matzke
1749  *		matzke@llnl.gov
1750  *		Aug  5 1997
1751  *
1752  *-------------------------------------------------------------------------
1753  */
1754 int
H5O_link(const H5O_loc_t * loc,int adjust,hid_t dxpl_id)1755 H5O_link(const H5O_loc_t *loc, int adjust, hid_t dxpl_id)
1756 {
1757     H5O_t	*oh = NULL;
1758     hbool_t deleted = FALSE;            /* Whether the object was deleted */
1759     int	ret_value = -1;                 /* Return value */
1760 
1761     FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, FAIL)
1762 
1763     /* check args */
1764     HDassert(loc);
1765     HDassert(loc->file);
1766     HDassert(H5F_addr_defined(loc->addr));
1767 
1768     /* Pin the object header */
1769     if(NULL == (oh = H5O_pin(loc, dxpl_id)))
1770 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
1771 
1772     /* Call the "real" link routine */
1773     if((ret_value = H5O_link_oh(loc->file, adjust, dxpl_id, oh, &deleted)) < 0)
1774         HGOTO_ERROR(H5E_OHDR, H5E_LINKCOUNT, FAIL, "unable to adjust object link count")
1775 
1776 done:
1777     if(oh && H5O_unpin(oh) < 0)
1778 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
1779     if(ret_value >= 0 && deleted && H5O_delete(loc->file, dxpl_id, loc->addr) < 0)
1780         HDONE_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
1781 
1782     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
1783 } /* end H5O_link() */
1784 
1785 
1786 /*-------------------------------------------------------------------------
1787  * Function:	H5O_protect
1788  *
1789  * Purpose:	Wrapper around H5AC_protect for use during a H5O_protect->
1790  *              H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
1791  *              during an object's creation.
1792  *
1793  * Return:	Success:	Pointer to the object header structure for the
1794  *                              object.
1795  *		Failure:	NULL
1796  *
1797  * Programmer:	Quincey Koziol
1798  *		koziol@ncsa.uiuc.edu
1799  *		Dec 31 2002
1800  *
1801  *-------------------------------------------------------------------------
1802  */
1803 H5O_t *
H5O_protect(const H5O_loc_t * loc,hid_t dxpl_id,unsigned prot_flags,hbool_t pin_all_chunks)1804 H5O_protect(const H5O_loc_t *loc, hid_t dxpl_id, unsigned prot_flags,
1805     hbool_t pin_all_chunks)
1806 {
1807     H5O_t *oh = NULL;           /* Object header protected */
1808     H5O_cache_ud_t udata;       /* User data for protecting object header */
1809     H5O_cont_msgs_t cont_msg_info;      /* Continuation message info */
1810     unsigned file_intent;       /* R/W intent on file */
1811     H5O_t *ret_value = NULL;    /* Return value */
1812 
1813     FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, NULL)
1814 
1815     /* check args */
1816     HDassert(loc);
1817     HDassert(loc->file);
1818 
1819     /* prot_flags may only contain the H5AC__READ_ONLY_FLAG */
1820     HDassert((prot_flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
1821 
1822     /* Check for valid address */
1823     if(!H5F_addr_defined(loc->addr))
1824         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "address undefined")
1825 
1826     /* Check for write access on the file */
1827     file_intent = H5F_INTENT(loc->file);
1828     if((0 == (prot_flags & H5AC__READ_ONLY_FLAG)) && (0 == (file_intent & H5F_ACC_RDWR)))
1829 	HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, NULL, "no write intent on file")
1830 
1831     /* Construct the user data for protect callback */
1832     udata.made_attempt = FALSE;
1833     udata.v1_pfx_nmesgs = 0;
1834     udata.chunk0_size = 0;
1835     udata.oh = NULL;
1836     udata.common.f = loc->file;
1837     udata.common.dxpl_id = dxpl_id;
1838     udata.common.file_intent = file_intent;
1839     udata.common.merged_null_msgs = 0;
1840     HDmemset(&cont_msg_info, 0, sizeof(cont_msg_info));
1841     udata.common.cont_msg_info = &cont_msg_info;
1842     udata.common.addr = loc->addr;
1843 
1844     /* Lock the object header into the cache */
1845     if(NULL == (oh = (H5O_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR, loc->addr, &udata, prot_flags)))
1846 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
1847 
1848     /* Check if there are any continuation messages to process */
1849     if(cont_msg_info.nmsgs > 0) {
1850         size_t curr_msg;        /* Current continuation message to process */
1851         H5O_chk_cache_ud_t chk_udata;   /* User data for loading chunk */
1852 
1853         /* Sanity check - we should only have continuation messages to process
1854          *      when the object header is actually loaded from the file.
1855          */
1856         HDassert(udata.made_attempt == TRUE);
1857         HDassert(cont_msg_info.msgs);
1858 
1859         /* Construct the user data for protecting chunks */
1860         chk_udata.decoding = TRUE;
1861         chk_udata.oh = oh;
1862         chk_udata.chunkno = UINT_MAX;   /* Set to invalid value, for better error detection */
1863         chk_udata.common.f = loc->file;
1864         chk_udata.common.dxpl_id = dxpl_id;
1865         chk_udata.common.file_intent = file_intent;
1866         chk_udata.common.merged_null_msgs = udata.common.merged_null_msgs;
1867         chk_udata.common.cont_msg_info = &cont_msg_info;
1868 
1869         /* Read in continuation messages, until there are no more */
1870         /* (Note that loading chunks could increase the # of continuation
1871          *      messages if new ones are found - QAK, 19/11/2016)
1872          */
1873         curr_msg = 0;
1874         while(curr_msg < cont_msg_info.nmsgs) {
1875             H5O_chunk_proxy_t *chk_proxy;       /* Proxy for chunk, to bring it into memory */
1876 #ifndef NDEBUG
1877             size_t chkcnt = oh->nchunks;      /* Count of chunks (for sanity checking) */
1878 #endif /* NDEBUG */
1879 
1880             /* Bring the chunk into the cache */
1881             /* (which adds to the object header) */
1882             chk_udata.common.addr = cont_msg_info.msgs[curr_msg].addr;
1883             chk_udata.size = cont_msg_info.msgs[curr_msg].size;
1884             if(NULL == (chk_proxy = (H5O_chunk_proxy_t *)H5AC_protect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, &chk_udata, prot_flags)))
1885                 HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header chunk")
1886 
1887             /* Sanity check */
1888             HDassert(chk_proxy->oh == oh);
1889             HDassert(chk_proxy->chunkno == chkcnt);
1890             HDassert(oh->nchunks == (chkcnt + 1));
1891 
1892             /* Release the chunk from the cache */
1893             if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR_CHK, cont_msg_info.msgs[curr_msg].addr, chk_proxy, H5AC__NO_FLAGS_SET) < 0)
1894                 HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header chunk")
1895 
1896             /* Advance to next continuation message */
1897             curr_msg++;
1898         } /* end while */
1899 
1900         /* Release any continuation messages built up */
1901         cont_msg_info.msgs = (H5O_cont_t *)H5FL_SEQ_FREE(H5O_cont_t, cont_msg_info.msgs);
1902 
1903         /* Pass back out some of the chunk's user data */
1904         udata.common.merged_null_msgs = chk_udata.common.merged_null_msgs;
1905     } /* end if */
1906 
1907     /* Check for incorrect # of object header messages, if we've just loaded
1908      *  this object header from the file
1909      */
1910     if(udata.made_attempt) {
1911 /* Don't enforce the error on an incorrect # of object header messages bug
1912  *      unless strict format checking is enabled.  This allows for older
1913  *      files, created with a version of the library that had a bug in tracking
1914  *      the correct # of header messages to be read in without the library
1915  *      erroring out here. -QAK
1916  */
1917 #ifdef H5_STRICT_FORMAT_CHECKS
1918         /* Check for incorrect # of messages in v1 object header */
1919         if(oh->version == H5O_VERSION_1 &&
1920                 (oh->nmesgs + udata.common.merged_null_msgs) != udata.v1_pfx_nmesgs)
1921             HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "corrupt object header - incorrect # of messages")
1922 #endif /* H5_STRICT_FORMAT_CHECKS */
1923     } /* end if */
1924 
1925 #ifdef H5O_DEBUG
1926 H5O_assert(oh);
1927 #endif /* H5O_DEBUG */
1928 
1929     /* Pin the other chunks also when requested, so that the object header
1930      *  proxy can be set up.
1931      */
1932     if(pin_all_chunks && oh->nchunks > 1) {
1933         unsigned u;         /* Local index variable */
1934 
1935         /* Sanity check */
1936         HDassert(oh->swmr_write);
1937 
1938         /* Iterate over chunks > 0 */
1939         for(u = 1; u < oh->nchunks; u++) {
1940             H5O_chunk_proxy_t *chk_proxy;       /* Chunk proxy */
1941 
1942             /* Protect chunk */
1943             if(NULL == (chk_proxy = H5O_chunk_protect(loc->file, dxpl_id, oh, u)))
1944                 HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header chunk")
1945 
1946             /* Pin chunk proxy*/
1947             if(H5AC_pin_protected_entry(chk_proxy) < 0 )
1948                 HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, NULL, "unable to pin object header chunk")
1949 
1950             /* Unprotect chunk */
1951             if(H5O_chunk_unprotect(loc->file, dxpl_id, chk_proxy, FALSE) < 0)
1952                 HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to unprotect object header chunk")
1953 
1954             /* Preserve chunk proxy pointer for later */
1955             oh->chunk[u].chunk_proxy = chk_proxy;
1956         } /* end for */
1957 
1958         /* Set the flag for the unprotect */
1959         oh->chunks_pinned = TRUE;
1960     } /* end if */
1961 
1962     /* Set return value */
1963     ret_value = oh;
1964 
1965 done:
1966     if(ret_value == NULL && oh)
1967         if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
1968             HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
1969 
1970     FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
1971 } /* end H5O_protect() */
1972 
1973 
1974 /*-------------------------------------------------------------------------
1975  * Function:	H5O_pin
1976  *
1977  * Purpose:	Pin an object header down for use during a sequence of message
1978  *              operations, which prevents the object header from being
1979  *              evicted from the cache.
1980  *
1981  * Return:	Success:	Pointer to the object header structure for the
1982  *                              object.
1983  *		Failure:	NULL
1984  *
1985  * Programmer:	Quincey Koziol
1986  *		koziol@hdfgroup.org
1987  *		Jul 13 2008
1988  *
1989  *-------------------------------------------------------------------------
1990  */
1991 H5O_t *
H5O_pin(const H5O_loc_t * loc,hid_t dxpl_id)1992 H5O_pin(const H5O_loc_t *loc, hid_t dxpl_id)
1993 {
1994     H5O_t       *oh = NULL;             /* Object header */
1995     H5O_t       *ret_value = NULL;      /* Return value */
1996 
1997     FUNC_ENTER_NOAPI(NULL)
1998 
1999     /* check args */
2000     HDassert(loc);
2001 
2002     /* Get header */
2003     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__NO_FLAGS_SET, FALSE)))
2004 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to protect object header")
2005 
2006     /* Increment the reference count on the object header */
2007     /* (which will pin it, if appropriate) */
2008     if(H5O_inc_rc(oh) < 0)
2009         HGOTO_ERROR(H5E_OHDR, H5E_CANTINC, NULL, "unable to increment reference count on object header")
2010 
2011     /* Set the return value */
2012     ret_value = oh;
2013 
2014 done:
2015     /* Release the object header from the cache */
2016     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
2017         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
2018 
2019     FUNC_LEAVE_NOAPI(ret_value)
2020 } /* end H5O_pin() */
2021 
2022 
2023 /*-------------------------------------------------------------------------
2024  * Function:	H5O_unpin
2025  *
2026  * Purpose:	Unpin an object header, allowing it to be evicted from the
2027  *              metadata cache.
2028  *
2029  * Return:	Success:	Non-negative
2030  *		Failure:	Negative
2031  *
2032  * Programmer:	Quincey Koziol
2033  *		koziol@hdfgroup.org
2034  *		Jul 13 2008
2035  *
2036  *-------------------------------------------------------------------------
2037  */
2038 herr_t
H5O_unpin(H5O_t * oh)2039 H5O_unpin(H5O_t *oh)
2040 {
2041     herr_t ret_value = SUCCEED;      /* Return value */
2042 
2043     FUNC_ENTER_NOAPI(FAIL)
2044 
2045     /* check args */
2046     HDassert(oh);
2047 
2048     /* Decrement the reference count on the object header */
2049     /* (which will unpin it, if appropriate) */
2050     if(H5O_dec_rc(oh) < 0)
2051         HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header")
2052 
2053 done:
2054     FUNC_LEAVE_NOAPI(ret_value)
2055 } /* end H5O_unpin() */
2056 
2057 
2058 /*-------------------------------------------------------------------------
2059  * Function:	H5O_unprotect
2060  *
2061  * Purpose:	Wrapper around H5AC_unprotect for use during a H5O_protect->
2062  *              H5O_msg_append->...->H5O_msg_append->H5O_unprotect sequence of calls
2063  *              during an object's creation.
2064  *
2065  * Return:	Success:	Non-negative
2066  *		Failure:	Negative
2067  *
2068  * Programmer:	Quincey Koziol
2069  *		koziol@ncsa.uiuc.edu
2070  *		Dec 31 2002
2071  *
2072  *-------------------------------------------------------------------------
2073  */
2074 herr_t
H5O_unprotect(const H5O_loc_t * loc,hid_t dxpl_id,H5O_t * oh,unsigned oh_flags)2075 H5O_unprotect(const H5O_loc_t *loc, hid_t dxpl_id, H5O_t *oh, unsigned oh_flags)
2076 {
2077     herr_t ret_value = SUCCEED;      /* Return value */
2078 
2079     FUNC_ENTER_NOAPI(FAIL)
2080 
2081     /* check args */
2082     HDassert(loc);
2083     HDassert(oh);
2084 
2085     /* Unpin the other chunks */
2086     if(oh->chunks_pinned && oh->nchunks > 1) {
2087         unsigned u;         /* Local index variable */
2088 
2089         /* Sanity check */
2090         HDassert(oh->swmr_write);
2091 
2092         /* Iterate over chunks > 0 */
2093         for(u = 1; u < oh->nchunks; u++) {
2094             if(NULL != oh->chunk[u].chunk_proxy) {
2095                 /* Release chunk proxy */
2096                 if(H5AC_unpin_entry(oh->chunk[u].chunk_proxy) < 0)
2097                     HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header chunk")
2098                 oh->chunk[u].chunk_proxy = NULL;
2099             } /* end if */
2100         } /* end for */
2101 
2102         /* Reet the flag from the unprotect */
2103         oh->chunks_pinned = FALSE;
2104     } /* end if */
2105 
2106     /* Unprotect the object header */
2107     if(H5AC_unprotect(loc->file, dxpl_id, H5AC_OHDR, oh->chunk[0].addr, oh, oh_flags) < 0)
2108         HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
2109 
2110 done:
2111     FUNC_LEAVE_NOAPI(ret_value)
2112 } /* end H5O_unprotect() */
2113 
2114 
2115 /*-------------------------------------------------------------------------
2116  * Function:	H5O_touch_oh
2117  *
2118  * Purpose:	If FORCE is non-zero then create a modification time message
2119  *		unless one already exists.  Then update any existing
2120  *		modification time message with the current time.
2121  *
2122  * Return:	Non-negative on success/Negative on failure
2123  *
2124  * Programmer:	Robb Matzke
2125  *              Monday, July 27, 1998
2126  *
2127  *-------------------------------------------------------------------------
2128  */
2129 herr_t
H5O_touch_oh(H5F_t * f,hid_t dxpl_id,H5O_t * oh,hbool_t force)2130 H5O_touch_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hbool_t force)
2131 {
2132     H5O_chunk_proxy_t *chk_proxy = NULL;        /* Chunk that message is in */
2133     hbool_t chk_dirtied = FALSE;        /* Flag for unprotecting chunk */
2134     time_t	now;                    /* Current time */
2135     herr_t      ret_value = SUCCEED;    /* Return value */
2136 
2137     FUNC_ENTER_NOAPI_NOINIT
2138 
2139     HDassert(f);
2140     HDassert(oh);
2141 
2142     /* Check if this object header is tracking times */
2143     if(oh->flags & H5O_HDR_STORE_TIMES) {
2144         /* Get current time */
2145         now = H5_now();
2146 
2147         /* Check version, to determine how to store time information */
2148         if(oh->version == H5O_VERSION_1) {
2149             size_t	idx;                    /* Index of modification time message to update */
2150 
2151             /* Look for existing message */
2152             for(idx = 0; idx < oh->nmesgs; idx++)
2153                 if(H5O_MSG_MTIME == oh->mesg[idx].type || H5O_MSG_MTIME_NEW == oh->mesg[idx].type)
2154                     break;
2155 
2156             /* Create a new message, if necessary */
2157             if(idx == oh->nmesgs) {
2158                 unsigned mesg_flags = 0;        /* Flags for message in object header */
2159 
2160                 /* If we would have to create a new message, but we aren't 'forcing' it, get out now */
2161                 if(!force)
2162                     HGOTO_DONE(SUCCEED);        /*nothing to do*/
2163 
2164                 /* Allocate space for the modification time message */
2165                 if(H5O_msg_alloc(f, dxpl_id, oh, H5O_MSG_MTIME_NEW, &mesg_flags, &now, &idx) < 0)
2166                     HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for modification time message")
2167 
2168                 /* Set the message's flags if appropriate */
2169                 oh->mesg[idx].flags = (uint8_t)mesg_flags;
2170             } /* end if */
2171 
2172             /* Protect chunk */
2173             if(NULL == (chk_proxy = H5O_chunk_protect(f, dxpl_id, oh, oh->mesg[idx].chunkno)))
2174                 HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header chunk")
2175 
2176             /* Allocate 'native' space, if necessary */
2177             if(NULL == oh->mesg[idx].native) {
2178                 if(NULL == (oh->mesg[idx].native = H5FL_MALLOC(time_t)))
2179                     HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for modification time message")
2180             } /* end if */
2181 
2182             /* Update the message */
2183             *((time_t *)(oh->mesg[idx].native)) = now;
2184 
2185             /* Mark the message as dirty */
2186             oh->mesg[idx].dirty = TRUE;
2187             chk_dirtied = TRUE;
2188         } /* end if */
2189         else {
2190             /* XXX: For now, update access time & change fields in the object header */
2191             /* (will need to add some code to update modification time appropriately) */
2192             oh->atime = oh->ctime = now;
2193 
2194             /* Mark object header as dirty in cache */
2195             if(H5AC_mark_entry_dirty(oh) < 0)
2196                 HGOTO_ERROR(H5E_OHDR, H5E_CANTMARKDIRTY, FAIL, "unable to mark object header as dirty")
2197         } /* end else */
2198     } /* end if */
2199 
2200 done:
2201     /* Release chunk */
2202     if(chk_proxy && H5O_chunk_unprotect(f, dxpl_id, chk_proxy, chk_dirtied) < 0)
2203         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to unprotect object header chunk")
2204 
2205     FUNC_LEAVE_NOAPI(ret_value)
2206 } /* end H5O_touch_oh() */
2207 
2208 
2209 /*-------------------------------------------------------------------------
2210  * Function:	H5O_touch
2211  *
2212  * Purpose:	Touch an object by setting the modification time to the
2213  *		current time and marking the object as dirty.  Unless FORCE
2214  *		is non-zero, nothing happens if there is no MTIME message in
2215  *		the object header.
2216  *
2217  * Return:	Non-negative on success/Negative on failure
2218  *
2219  * Programmer:	Robb Matzke
2220  *              Monday, July 27, 1998
2221  *
2222  *-------------------------------------------------------------------------
2223  */
2224 herr_t
H5O_touch(const H5O_loc_t * loc,hbool_t force,hid_t dxpl_id)2225 H5O_touch(const H5O_loc_t *loc, hbool_t force, hid_t dxpl_id)
2226 {
2227     H5O_t	*oh = NULL;             /* Object header to modify */
2228     unsigned 	oh_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting object header */
2229     herr_t      ret_value = SUCCEED;    /* Return value */
2230 
2231     FUNC_ENTER_NOAPI(FAIL)
2232 
2233     /* check args */
2234     HDassert(loc);
2235 
2236     /* Get the object header */
2237     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__NO_FLAGS_SET, FALSE)))
2238 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
2239 
2240     /* Create/Update the modification time message */
2241     if(H5O_touch_oh(loc->file, dxpl_id, oh, force) < 0)
2242 	HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "unable to update object modificaton time")
2243 
2244     /* Mark object header as changed */
2245     oh_flags |= H5AC__DIRTIED_FLAG;
2246 
2247 done:
2248     if(oh && H5O_unprotect(loc, dxpl_id, oh, oh_flags) < 0)
2249 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
2250 
2251     FUNC_LEAVE_NOAPI(ret_value)
2252 } /* end H5O_touch() */
2253 
2254 #ifdef H5O_ENABLE_BOGUS
2255 
2256 /*-------------------------------------------------------------------------
2257  * Function:	H5O_bogus_oh
2258  *
2259  * Purpose:	Create a "bogus" message unless one already exists.
2260  *
2261  * Return:	Non-negative on success/Negative on failure
2262  *
2263  * Programmer:	Quincey Koziol
2264  *              <koziol@ncsa.uiuc.edu>
2265  *              Tuesday, January 21, 2003
2266  *
2267  *-------------------------------------------------------------------------
2268  */
2269 herr_t
H5O_bogus_oh(H5F_t * f,hid_t dxpl_id,H5O_t * oh,unsigned bogus_id,unsigned mesg_flags)2270 H5O_bogus_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned bogus_id, unsigned mesg_flags)
2271 {
2272     size_t	idx;                /* Local index variable */
2273     H5O_msg_class_t *type;	    /* Message class type */
2274     herr_t ret_value = SUCCEED;     /* Return value */
2275 
2276     FUNC_ENTER_NOAPI(FAIL)
2277 
2278     HDassert(f);
2279     HDassert(oh);
2280 
2281     /* Look for existing message */
2282     for(idx = 0; idx < oh->nmesgs; idx++)
2283 	if(H5O_MSG_BOGUS_VALID == oh->mesg[idx].type ||
2284 	   H5O_MSG_BOGUS_INVALID == oh->mesg[idx].type)
2285             break;
2286 
2287     /* Create a new message */
2288     if(idx == oh->nmesgs) {
2289         H5O_bogus_t *bogus;             /* Pointer to the bogus information */
2290 
2291         /* Allocate the native message in memory */
2292 	if(NULL == (bogus = H5MM_malloc(sizeof(H5O_bogus_t))))
2293 	    HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "memory allocation failed for 'bogus' message")
2294 
2295         /* Update the native value */
2296         bogus->u = H5O_BOGUS_VALUE;
2297 
2298 	if(bogus_id == H5O_BOGUS_VALID_ID)
2299 	    type = H5O_MSG_BOGUS_VALID;
2300 	else if(bogus_id == H5O_BOGUS_INVALID_ID)
2301 	    type = H5O_MSG_BOGUS_INVALID;
2302 	else
2303 	    HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "invalid ID for 'bogus' message")
2304 
2305         /* Allocate space in the object header for bogus message */
2306 	if(H5O_msg_alloc(f, dxpl_id, oh, type, &mesg_flags, bogus, &idx) < 0)
2307 	    HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to allocate space for 'bogus' message")
2308 
2309         /* Point to "bogus" information (take it over) */
2310 	oh->mesg[idx].native = bogus;
2311 
2312         /* Set the appropriate flags for the message */
2313         oh->mesg[idx].flags = mesg_flags;
2314 
2315         /* Mark the message and object header as dirty */
2316         oh->mesg[idx].dirty = TRUE;
2317         oh->cache_info.is_dirty = TRUE;
2318     } /* end if */
2319 
2320 done:
2321     FUNC_LEAVE_NOAPI(ret_value)
2322 } /* end H5O_bogus_oh() */
2323 #endif /* H5O_ENABLE_BOGUS */
2324 
2325 
2326 /*-------------------------------------------------------------------------
2327  * Function:	H5O_delete
2328  *
2329  * Purpose:	Delete an object header from a file.  This frees the file
2330  *              space used for the object header (and it's continuation blocks)
2331  *              and also walks through each header message and asks it to
2332  *              remove all the pieces of the file referenced by the header.
2333  *
2334  * Return:	Non-negative on success/Negative on failure
2335  *
2336  * Programmer:	Quincey Koziol
2337  *		koziol@ncsa.uiuc.edu
2338  *		Mar 19 2003
2339  *
2340  *-------------------------------------------------------------------------
2341  */
2342 herr_t
H5O_delete(H5F_t * f,hid_t dxpl_id,haddr_t addr)2343 H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr)
2344 {
2345     H5O_t *oh = NULL;           /* Object header information */
2346     H5O_loc_t loc;              /* Object location for object to delete */
2347     unsigned oh_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting object header */
2348     hbool_t corked;
2349     herr_t ret_value = SUCCEED; /* Return value */
2350 
2351     FUNC_ENTER_NOAPI_TAG(dxpl_id, addr, FAIL)
2352 
2353     /* Check args */
2354     HDassert(f);
2355     HDassert(H5F_addr_defined(addr));
2356 
2357     /* Set up the object location */
2358     loc.file = f;
2359     loc.addr = addr;
2360     loc.holding_file = FALSE;
2361 
2362     /* Get the object header information */
2363     if(NULL == (oh = H5O_protect(&loc, dxpl_id, H5AC__NO_FLAGS_SET, FALSE)))
2364 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
2365 
2366     /* Delete object */
2367     if(H5O_delete_oh(f, dxpl_id, oh) < 0)
2368         HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "can't delete object from file")
2369 
2370     /* Uncork cache entries with tag: addr */
2371     if(H5AC_cork(f, addr, H5AC__GET_CORKED, &corked) < 0)
2372         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to retrieve an object's cork status")
2373     if(corked)
2374 	if(H5AC_cork(f, addr, H5AC__UNCORK, NULL) < 0)
2375 	    HGOTO_ERROR(H5E_OHDR, H5E_CANTUNCORK, FAIL, "unable to uncork an object")
2376 
2377     /* Mark object header as deleted */
2378     oh_flags = H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
2379 
2380 done:
2381     if(oh && H5O_unprotect(&loc, dxpl_id, oh, oh_flags) < 0)
2382 	HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
2383 
2384     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
2385 } /* end H5O_delete() */
2386 
2387 
2388 /*-------------------------------------------------------------------------
2389  * Function:	H5O_delete_oh
2390  *
2391  * Purpose:	Internal function to:
2392  *              Delete an object header from a file.  This frees the file
2393  *              space used for the object header (and it's continuation blocks)
2394  *              and also walks through each header message and asks it to
2395  *              remove all the pieces of the file referenced by the header.
2396  *
2397  * Return:	Non-negative on success/Negative on failure
2398  *
2399  * Programmer:	Quincey Koziol
2400  *		koziol@ncsa.uiuc.edu
2401  *		Mar 19 2003
2402  *
2403  *-------------------------------------------------------------------------
2404  */
2405 static herr_t
H5O_delete_oh(H5F_t * f,hid_t dxpl_id,H5O_t * oh)2406 H5O_delete_oh(H5F_t *f, hid_t dxpl_id, H5O_t *oh)
2407 {
2408     H5O_mesg_t *curr_msg;       /* Pointer to current message being operated on */
2409     unsigned	u;
2410     herr_t ret_value = SUCCEED;   /* Return value */
2411 
2412     FUNC_ENTER_NOAPI_NOINIT
2413 
2414     /* Check args */
2415     HDassert(f);
2416     HDassert(oh);
2417 
2418     /* Walk through the list of object header messages, asking each one to
2419      * delete any file space used
2420      */
2421     for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
2422         /* Free any space referred to in the file from this message */
2423         if(H5O_delete_mesg(f, dxpl_id, oh, curr_msg) < 0)
2424             HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, FAIL, "unable to delete file space for object header message")
2425     } /* end for */
2426 
2427 done:
2428     FUNC_LEAVE_NOAPI(ret_value)
2429 } /* end H5O_delete_oh() */
2430 
2431 
2432 /*-------------------------------------------------------------------------
2433  * Function:	H5O_obj_type
2434  *
2435  * Purpose:	Retrieves the type of object pointed to by `loc'.
2436  *
2437  * Return:	Success:	Non-negative
2438  *		Failure:	Negative
2439  *
2440  * Programmer:	Robb Matzke
2441  *              Wednesday, November  4, 1998
2442  *
2443  *-------------------------------------------------------------------------
2444  */
2445 herr_t
H5O_obj_type(const H5O_loc_t * loc,H5O_type_t * obj_type,hid_t dxpl_id)2446 H5O_obj_type(const H5O_loc_t *loc, H5O_type_t *obj_type, hid_t dxpl_id)
2447 {
2448     H5O_t	*oh = NULL;             /* Object header for location */
2449     herr_t      ret_value = SUCCEED;    /* Return value */
2450 
2451     FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, FAIL)
2452 
2453     /* Load the object header */
2454     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
2455 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
2456 
2457     /* Retrieve the type of the object */
2458     if(H5O_obj_type_real(oh, obj_type) < 0)
2459         HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
2460 
2461 done:
2462     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
2463 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
2464 
2465     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
2466 } /* end H5O_obj_type() */
2467 
2468 
2469 /*-------------------------------------------------------------------------
2470  * Function:	H5O_obj_type_real
2471  *
2472  * Purpose:	Returns the type of object pointed to by `oh'.
2473  *
2474  * Return:	Success:	Non-negative
2475  *		Failure:	Negative
2476  *
2477  * Programmer:	Quincey Koziol
2478  *              Monday, November 21, 2005
2479  *
2480  *-------------------------------------------------------------------------
2481  */
2482 static herr_t
H5O_obj_type_real(H5O_t * oh,H5O_type_t * obj_type)2483 H5O_obj_type_real(H5O_t *oh, H5O_type_t *obj_type)
2484 {
2485     const H5O_obj_class_t *obj_class;           /* Class of object for header */
2486 
2487     FUNC_ENTER_NOAPI_NOINIT_NOERR
2488 
2489     /* Sanity check */
2490     HDassert(oh);
2491     HDassert(obj_type);
2492 
2493     /* Look up class for object header */
2494     if(NULL == (obj_class = H5O_obj_class_real(oh))) {
2495         /* Clear error stack from "failed" class lookup */
2496         H5E_clear_stack(NULL);
2497 
2498         /* Set type to "unknown" */
2499         *obj_type = H5O_TYPE_UNKNOWN;
2500     } /* end if */
2501     else {
2502         /* Set object type */
2503         *obj_type = obj_class->type;
2504     } /* end else */
2505 
2506     FUNC_LEAVE_NOAPI(SUCCEED)
2507 } /* end H5O_obj_type_real() */
2508 
2509 
2510 /*-------------------------------------------------------------------------
2511  * Function:	H5O_obj_class
2512  *
2513  * Purpose:	Returns the class of object pointed to by `loc'.
2514  *
2515  * Return:	Success:	An object class
2516  *		Failure:	NULL
2517  *
2518  * Programmer:	Quincey Koziol
2519  *              Monday, November  6, 2006
2520  *
2521  *-------------------------------------------------------------------------
2522  */
2523 const H5O_obj_class_t *
H5O_obj_class(const H5O_loc_t * loc,hid_t dxpl_id)2524 H5O_obj_class(const H5O_loc_t *loc, hid_t dxpl_id)
2525 {
2526     H5O_t	*oh = NULL;                     /* Object header for location */
2527     const H5O_obj_class_t *ret_value = NULL;    /* Return value */
2528 
2529     FUNC_ENTER_NOAPI_NOINIT_TAG(dxpl_id, loc->addr, NULL)
2530 
2531     /* Load the object header */
2532     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
2533 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, NULL, "unable to load object header")
2534 
2535     /* Test whether entry qualifies as a particular type of object */
2536     if(NULL == (ret_value = H5O_obj_class_real(oh)))
2537         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to determine object type")
2538 
2539 done:
2540     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
2541 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
2542 
2543     FUNC_LEAVE_NOAPI_TAG(ret_value, NULL)
2544 } /* end H5O_obj_class() */
2545 
2546 
2547 /*-------------------------------------------------------------------------
2548  * Function:	H5O_obj_class_real
2549  *
2550  * Purpose:	Returns the class of object pointed to by `oh'.
2551  *
2552  * Return:	Success:	An object class
2553  *		Failure:	NULL
2554  *
2555  * Programmer:	Quincey Koziol
2556  *              Monday, November 21, 2005
2557  *
2558  *-------------------------------------------------------------------------
2559  */
2560 static const H5O_obj_class_t *
H5O_obj_class_real(H5O_t * oh)2561 H5O_obj_class_real(H5O_t *oh)
2562 {
2563     size_t	i;                      /* Local index variable */
2564     const H5O_obj_class_t *ret_value = NULL;   /* Return value */
2565 
2566     FUNC_ENTER_NOAPI(NULL)
2567 
2568     /* Sanity check */
2569     HDassert(oh);
2570 
2571     /* Test whether entry qualifies as a particular type of object */
2572     /* (Note: loop is in reverse order, to test specific objects first) */
2573     for(i = NELMTS(H5O_obj_class_g); i > 0; --i) {
2574         htri_t	isa;            /* Is entry a particular type? */
2575 
2576 	if((isa = (H5O_obj_class_g[i - 1]->isa)(oh)) < 0)
2577 	    HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to determine object type")
2578 	else if(isa)
2579 	    HGOTO_DONE(H5O_obj_class_g[i - 1])
2580     } /* end for */
2581 
2582     if(0 == i)
2583 	HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to determine object type")
2584 
2585 done:
2586     FUNC_LEAVE_NOAPI(ret_value)
2587 } /* end H5O_obj_class_real() */
2588 
2589 
2590 /*-------------------------------------------------------------------------
2591  * Function:	H5O_get_loc
2592  *
2593  * Purpose:	Gets the object location for an object given its ID.
2594  *
2595  * Return:	Success:	Pointer to H5O_loc_t
2596  *		Failure:	NULL
2597  *
2598  * Programmer:	James Laird
2599  *		July 25 2006
2600  *
2601  *-------------------------------------------------------------------------
2602  */
2603 H5O_loc_t *
H5O_get_loc(hid_t object_id)2604 H5O_get_loc(hid_t object_id)
2605 {
2606     H5O_loc_t   *ret_value = NULL;      /* Return value */
2607 
2608     FUNC_ENTER_NOAPI_NOINIT
2609 
2610     switch(H5I_get_type(object_id)) {
2611         case H5I_GROUP:
2612             if(NULL == (ret_value = H5O_OBJ_GROUP->get_oloc(object_id)))
2613                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from group ID")
2614             break;
2615 
2616         case H5I_DATASET:
2617             if(NULL == (ret_value = H5O_OBJ_DATASET->get_oloc(object_id)))
2618                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from dataset ID")
2619             break;
2620 
2621         case H5I_DATATYPE:
2622             if(NULL == (ret_value = H5O_OBJ_DATATYPE->get_oloc(object_id)))
2623                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from datatype ID")
2624             break;
2625 
2626         case H5I_UNINIT:
2627         case H5I_BADID:
2628         case H5I_FILE:
2629         case H5I_DATASPACE:
2630         case H5I_ATTR:
2631         case H5I_REFERENCE:
2632         case H5I_VFL:
2633         case H5I_GENPROP_CLS:
2634         case H5I_GENPROP_LST:
2635         case H5I_ERROR_CLASS:
2636         case H5I_ERROR_MSG:
2637         case H5I_ERROR_STACK:
2638         case H5I_NTYPES:
2639         default:
2640             HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, NULL, "invalid object type")
2641     } /* end switch */
2642 
2643 done:
2644     FUNC_LEAVE_NOAPI(ret_value)
2645 } /* end H5O_get_loc() */
2646 
2647 
2648 /*-------------------------------------------------------------------------
2649  * Function:	H5O_loc_reset
2650  *
2651  * Purpose:	Reset a object location to an empty state
2652  *
2653  * Return:	Success:	Non-negative
2654  *		Failure:	Negative
2655  *
2656  * Programmer:	Quincey Koziol
2657  *              Monday, September 19, 2005
2658  *
2659  *-------------------------------------------------------------------------
2660  */
2661 herr_t
H5O_loc_reset(H5O_loc_t * loc)2662 H5O_loc_reset(H5O_loc_t *loc)
2663 {
2664     FUNC_ENTER_NOAPI_NOINIT_NOERR
2665 
2666     /* Check arguments */
2667     HDassert(loc);
2668 
2669     /* Clear the object location to an empty state */
2670     HDmemset(loc, 0, sizeof(H5O_loc_t));
2671     loc->addr = HADDR_UNDEF;
2672 
2673     FUNC_LEAVE_NOAPI(SUCCEED)
2674 } /* end H5O_loc_reset() */
2675 
2676 
2677 /*-------------------------------------------------------------------------
2678  * Function:    H5O_loc_copy
2679  *
2680  * Purpose:     Copy object location information
2681  *
2682  * Return:	Success:	Non-negative
2683  *		Failure:	Negative
2684  *
2685  * Programmer:	Quincey Koziol
2686  *              koziol@ncsa.uiuc.edu
2687  *              Monday, September 19, 2005
2688  *
2689  * Notes:       'depth' parameter determines how much of the group entry
2690  *              structure we want to copy.  The values are:
2691  *                  H5_COPY_SHALLOW - Copy all the field values from the source
2692  *                      to the destination, but not copying objects pointed to.
2693  *                      (Destination "takes ownership" of objects pointed to)
2694  *                  H5_COPY_DEEP - Copy all the fields from the source to
2695  *                      the destination, deep copying objects pointed to.
2696  *
2697  *-------------------------------------------------------------------------
2698  */
2699 herr_t
H5O_loc_copy(H5O_loc_t * dst,H5O_loc_t * src,H5_copy_depth_t depth)2700 H5O_loc_copy(H5O_loc_t *dst, H5O_loc_t *src, H5_copy_depth_t depth)
2701 {
2702     FUNC_ENTER_NOAPI_NOINIT_NOERR
2703 
2704     /* Check arguments */
2705     HDassert(src);
2706     HDassert(dst);
2707     HDassert(depth == H5_COPY_SHALLOW || depth == H5_COPY_DEEP);
2708 
2709     /* Copy the top level information */
2710     HDmemcpy(dst, src, sizeof(H5O_loc_t));
2711 
2712     /* Deep copy the names */
2713     if(depth == H5_COPY_DEEP) {
2714         /* If the original entry was holding open the file, this one should
2715          * hold it open, too.
2716          */
2717         if(src->holding_file)
2718             H5F_INCR_NOPEN_OBJS(dst->file);
2719     } else if(depth == H5_COPY_SHALLOW) {
2720         H5O_loc_reset(src);
2721     } /* end if */
2722 
2723     FUNC_LEAVE_NOAPI(SUCCEED)
2724 } /* end H5O_loc_copy() */
2725 
2726 
2727 /*-------------------------------------------------------------------------
2728  * Function:	H5O_loc_hold_file
2729  *
2730  * Purpose:	Have this object header hold a file open until it is
2731  *              released.
2732  *
2733  * Return:	Success:	Non-negative
2734  *		Failure:	Negative
2735  *
2736  * Programmer:	James Laird
2737  *              Wednesday, August 16, 2006
2738  *
2739  *-------------------------------------------------------------------------
2740  */
2741 herr_t
H5O_loc_hold_file(H5O_loc_t * loc)2742 H5O_loc_hold_file(H5O_loc_t *loc)
2743 {
2744     FUNC_ENTER_NOAPI_NOINIT_NOERR
2745 
2746     /* Check arguments */
2747     HDassert(loc);
2748     HDassert(loc->file);
2749 
2750     /* If this location is not already holding its file open, do so. */
2751     if(!loc->holding_file) {
2752         H5F_INCR_NOPEN_OBJS(loc->file);
2753         loc->holding_file = TRUE;
2754     } /* end if */
2755 
2756     FUNC_LEAVE_NOAPI(SUCCEED)
2757 } /* end H5O_loc_hold_file() */
2758 
2759 
2760 /*-------------------------------------------------------------------------
2761  * Function:	H5O_loc_free
2762  *
2763  * Purpose:	Release resources used by this object header location.
2764  *              Not to be confused with H5O_close; this is used on
2765  *              locations that don't correspond to open objects.
2766  *
2767  * Return:	Success:	Non-negative
2768  *		Failure:	Negative
2769  *
2770  * Programmer:	James Laird
2771  *              Wednesday, August 16, 2006
2772  *
2773  *-------------------------------------------------------------------------
2774  */
2775 herr_t
H5O_loc_free(H5O_loc_t * loc)2776 H5O_loc_free(H5O_loc_t *loc)
2777 {
2778     herr_t ret_value = SUCCEED;
2779 
2780     FUNC_ENTER_NOAPI_NOINIT
2781 
2782     /* Check arguments */
2783     HDassert(loc);
2784 
2785     /* If this location is holding its file open try to close the file. */
2786     if(loc->holding_file) {
2787         H5F_DECR_NOPEN_OBJS(loc->file);
2788         loc->holding_file = FALSE;
2789         if(H5F_NOPEN_OBJS(loc->file) <= 0) {
2790             if(H5F_try_close(loc->file, NULL) < 0)
2791                 HGOTO_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, FAIL, "can't close file")
2792         } /* end if */
2793     } /* end if */
2794 
2795 done:
2796     FUNC_LEAVE_NOAPI(ret_value)
2797 } /* end H5O_loc_free() */
2798 
2799 
2800 /*-------------------------------------------------------------------------
2801  * Function:	H5O_get_hdr_info
2802  *
2803  * Purpose:	Retrieve the object header information for an object
2804  *
2805  * Return:	Success:	Non-negative
2806  *		Failure:	Negative
2807  *
2808  * Programmer:	Quincey Koziol
2809  *		September 22 2009
2810  *
2811  *-------------------------------------------------------------------------
2812  */
2813 herr_t
H5O_get_hdr_info(const H5O_loc_t * loc,hid_t dxpl_id,H5O_hdr_info_t * hdr)2814 H5O_get_hdr_info(const H5O_loc_t *loc, hid_t dxpl_id, H5O_hdr_info_t *hdr)
2815 {
2816     H5O_t *oh = NULL;                   /* Object header */
2817     herr_t ret_value = SUCCEED;         /* Return value */
2818 
2819     FUNC_ENTER_NOAPI(FAIL)
2820 
2821     /* Check args */
2822     HDassert(loc);
2823     HDassert(hdr);
2824 
2825     /* Reset the object header info structure */
2826     HDmemset(hdr, 0, sizeof(*hdr));
2827 
2828     /* Get the object header */
2829     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
2830 	HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header")
2831 
2832     /* Get the information for the object header */
2833     if(H5O_get_hdr_info_real(oh, hdr) < 0)
2834         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info")
2835 
2836 done:
2837     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
2838 	HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header")
2839 
2840     FUNC_LEAVE_NOAPI(ret_value)
2841 } /* end H5O_get_hdr_info() */
2842 
2843 
2844 /*-------------------------------------------------------------------------
2845  * Function:	H5O_get_hdr_info_real
2846  *
2847  * Purpose:	Internal routine to retrieve the object header information for an object
2848  *
2849  * Return:	Success:	Non-negative
2850  *		Failure:	Negative
2851  *
2852  * Programmer:	Quincey Koziol
2853  *		September 22 2009
2854  *
2855  *-------------------------------------------------------------------------
2856  */
2857 static herr_t
H5O_get_hdr_info_real(const H5O_t * oh,H5O_hdr_info_t * hdr)2858 H5O_get_hdr_info_real(const H5O_t *oh, H5O_hdr_info_t *hdr)
2859 {
2860     const H5O_mesg_t *curr_msg;         /* Pointer to current message being operated on */
2861     const H5O_chunk_t *curr_chunk;	/* Pointer to current message being operated on */
2862     unsigned u;                         /* Local index variable */
2863 
2864     FUNC_ENTER_NOAPI_NOINIT_NOERR
2865 
2866     /* Check args */
2867     HDassert(oh);
2868     HDassert(hdr);
2869 
2870     /* Set the version for the object header */
2871     hdr->version = oh->version;
2872 
2873     /* Set the number of messages & chunks */
2874     H5_CHECKED_ASSIGN(hdr->nmesgs, unsigned, oh->nmesgs, size_t);
2875     H5_CHECKED_ASSIGN(hdr->nchunks, unsigned, oh->nchunks, size_t);
2876 
2877     /* Set the status flags */
2878     hdr->flags = oh->flags;
2879 
2880     /* Iterate over all the messages, accumulating message size & type information */
2881     hdr->space.meta = (hsize_t)H5O_SIZEOF_HDR(oh) + (hsize_t)(H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
2882     hdr->space.mesg = 0;
2883     hdr->space.free = 0;
2884     hdr->mesg.present = 0;
2885     hdr->mesg.shared = 0;
2886     for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
2887         uint64_t type_flag;             /* Flag for message type */
2888 
2889         /* Accumulate space usage information, based on the type of message */
2890 	if(H5O_NULL_ID == curr_msg->type->id)
2891             hdr->space.free += (hsize_t)((size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size);
2892         else if(H5O_CONT_ID == curr_msg->type->id)
2893             hdr->space.meta += (hsize_t)((size_t)H5O_SIZEOF_MSGHDR_OH(oh) + curr_msg->raw_size);
2894         else {
2895             hdr->space.meta += (hsize_t)H5O_SIZEOF_MSGHDR_OH(oh);
2896             hdr->space.mesg += curr_msg->raw_size;
2897         } /* end else */
2898 
2899         /* Set flag to indicate presence of message type */
2900         type_flag = ((uint64_t)1) << curr_msg->type->id;
2901         hdr->mesg.present |= type_flag;
2902 
2903         /* Set flag if the message is shared in some way */
2904         if(curr_msg->flags & H5O_MSG_FLAG_SHARED)                                   \
2905             hdr->mesg.shared |= type_flag;
2906     } /* end for */
2907 
2908     /* Iterate over all the chunks, adding any gaps to the free space */
2909     hdr->space.total = 0;
2910     for(u = 0, curr_chunk = &oh->chunk[0]; u < oh->nchunks; u++, curr_chunk++) {
2911         /* Accumulate the size of the header on disk */
2912         hdr->space.total += curr_chunk->size;
2913 
2914         /* If the chunk has a gap, add it to the free space */
2915         hdr->space.free += curr_chunk->gap;
2916     } /* end for */
2917 
2918     /* Sanity check that all the bytes are accounted for */
2919     HDassert(hdr->space.total == (hdr->space.free + hdr->space.meta + hdr->space.mesg));
2920 
2921     FUNC_LEAVE_NOAPI(SUCCEED)
2922 } /* end H5O_get_hdr_info_real() */
2923 
2924 
2925 /*-------------------------------------------------------------------------
2926  * Function:	H5O_get_info
2927  *
2928  * Purpose:	Retrieve the information for an object
2929  *
2930  * Return:	Success:	Non-negative
2931  *		Failure:	Negative
2932  *
2933  * Programmer:	Quincey Koziol
2934  *		November 21 2006
2935  *
2936  *-------------------------------------------------------------------------
2937  */
2938 herr_t
H5O_get_info(const H5O_loc_t * loc,hid_t dxpl_id,hbool_t want_ih_info,H5O_info_t * oinfo)2939 H5O_get_info(const H5O_loc_t *loc, hid_t dxpl_id, hbool_t want_ih_info,
2940     H5O_info_t *oinfo)
2941 {
2942     const H5O_obj_class_t *obj_class;   /* Class of object for header */
2943     H5O_t *oh = NULL;                   /* Object header */
2944     herr_t ret_value = SUCCEED;         /* Return value */
2945 
2946     FUNC_ENTER_NOAPI_TAG(dxpl_id, loc->addr, FAIL)
2947 
2948     /* Check args */
2949     HDassert(loc);
2950     HDassert(oinfo);
2951 
2952     /* Get the object header */
2953     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
2954 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
2955 
2956     /* Reset the object info structure */
2957     HDmemset(oinfo, 0, sizeof(*oinfo));
2958 
2959     /* Retrieve the file's fileno */
2960     H5F_GET_FILENO(loc->file, oinfo->fileno);
2961 
2962     /* Set the object's address */
2963     oinfo->addr = loc->addr;
2964 
2965     /* Get class for object */
2966     if(NULL == (obj_class = H5O_obj_class_real(oh)))
2967         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to determine object class")
2968 
2969     /* Retrieve the type of the object */
2970     oinfo->type = obj_class->type;
2971 
2972     /* Set the object's reference count */
2973     oinfo->rc = oh->nlink;
2974 
2975     /* Get modification time for object */
2976     if(oh->version > H5O_VERSION_1) {
2977         oinfo->atime = oh->atime;
2978         oinfo->mtime = oh->mtime;
2979         oinfo->ctime = oh->ctime;
2980         oinfo->btime = oh->btime;
2981     } /* end if */
2982     else {
2983         htri_t	exists;                 /* Flag if header message of interest exists */
2984 
2985         /* No information for access & modification fields */
2986         /* (we stopped updating the "modification time" header message for
2987          *      raw data changes, so the "modification time" header message
2988          *      is closest to the 'change time', in POSIX terms - QAK)
2989          */
2990         oinfo->atime = 0;
2991         oinfo->mtime = 0;
2992         oinfo->btime = 0;
2993 
2994         /* Might be information for modification time */
2995         if((exists = H5O_msg_exists_oh(oh, H5O_MTIME_ID)) < 0)
2996             HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "unable to check for MTIME message")
2997         if(exists > 0) {
2998             /* Get "old style" modification time info */
2999             if(NULL == H5O_msg_read_oh(loc->file, dxpl_id, oh, H5O_MTIME_ID, &oinfo->ctime))
3000                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read MTIME message")
3001         } /* end if */
3002         else {
3003             /* Check for "new style" modification time info */
3004             if((exists = H5O_msg_exists_oh(oh, H5O_MTIME_NEW_ID)) < 0)
3005                 HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "unable to check for MTIME_NEW message")
3006             if(exists > 0) {
3007                 /* Get "new style" modification time info */
3008                 if(NULL == H5O_msg_read_oh(loc->file, dxpl_id, oh, H5O_MTIME_NEW_ID, &oinfo->ctime))
3009                     HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read MTIME_NEW message")
3010             } /* end if */
3011             else
3012                 oinfo->ctime = 0;
3013         } /* end else */
3014     } /* end else */
3015 
3016     /* Get the information for the object header */
3017     if(H5O_get_hdr_info_real(oh, &oinfo->hdr) < 0)
3018         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object header info")
3019 
3020     /* Retrieve # of attributes */
3021     if(H5O_attr_count_real(loc->file, dxpl_id, oh, &oinfo->num_attrs) < 0)
3022         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve attribute count")
3023 
3024     /* Get B-tree & heap metadata storage size, if requested */
3025     if(want_ih_info) {
3026         /* Check for 'bh_info' callback for this type of object */
3027         if(obj_class->bh_info) {
3028             /* Call the object's class 'bh_info' routine */
3029             if((obj_class->bh_info)(loc, dxpl_id, oh, &oinfo->meta_size.obj) < 0)
3030                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve object's btree & heap info")
3031         } /* end if */
3032 
3033         /* Get B-tree & heap info for any attributes */
3034         if(oinfo->num_attrs > 0) {
3035             if(H5O_attr_bh_info(loc->file, dxpl_id, oh, &oinfo->meta_size.attr) < 0)
3036                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't retrieve attribute btree & heap info")
3037         } /* end if */
3038     } /* end if */
3039 
3040 done:
3041     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
3042 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
3043 
3044     FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
3045 } /* end H5O_get_info() */
3046 
3047 
3048 /*-------------------------------------------------------------------------
3049  * Function:	H5O_get_create_plist
3050  *
3051  * Purpose:	Retrieve the object creation properties for an object
3052  *
3053  * Return:	Success:	Non-negative
3054  *		Failure:	Negative
3055  *
3056  * Programmer:	Quincey Koziol
3057  *		November 28 2006
3058  *
3059  *-------------------------------------------------------------------------
3060  */
3061 herr_t
H5O_get_create_plist(const H5O_loc_t * loc,hid_t dxpl_id,H5P_genplist_t * oc_plist)3062 H5O_get_create_plist(const H5O_loc_t *loc, hid_t dxpl_id, H5P_genplist_t *oc_plist)
3063 {
3064     H5O_t *oh = NULL;                   /* Object header */
3065     herr_t ret_value = SUCCEED;         /* Return value */
3066 
3067     FUNC_ENTER_NOAPI(FAIL)
3068 
3069     /* Check args */
3070     HDassert(loc);
3071     HDassert(oc_plist);
3072 
3073     /* Get the object header */
3074     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
3075 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
3076 
3077     /* Set property values, if they were used for the object */
3078     if(oh->version > H5O_VERSION_1) {
3079         uint8_t ohdr_flags;             /* "User-visible" object header status flags */
3080 
3081         /* Set attribute storage values */
3082         if(H5P_set(oc_plist, H5O_CRT_ATTR_MAX_COMPACT_NAME, &oh->max_compact) < 0)
3083             HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set max. # of compact attributes in property list")
3084         if(H5P_set(oc_plist, H5O_CRT_ATTR_MIN_DENSE_NAME, &oh->min_dense) < 0)
3085             HGOTO_ERROR(H5E_OHDR, H5E_CANTSET, FAIL, "can't set min. # of dense attributes in property list")
3086 
3087         /* Mask off non-"user visible" flags */
3088         ohdr_flags = oh->flags & (H5O_HDR_ATTR_CRT_ORDER_TRACKED | H5O_HDR_ATTR_CRT_ORDER_INDEXED | H5O_HDR_STORE_TIMES);
3089 
3090         /* Set object header flags */
3091         if(H5P_set(oc_plist, H5O_CRT_OHDR_FLAGS_NAME, &ohdr_flags) < 0)
3092             HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set object header flags")
3093     } /* end if */
3094 
3095 done:
3096     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
3097 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
3098 
3099     FUNC_LEAVE_NOAPI(ret_value)
3100 } /* end H5O_get_create_plist() */
3101 
3102 
3103 /*-------------------------------------------------------------------------
3104  * Function:	H5O_get_nlinks
3105  *
3106  * Purpose:	Retrieve the number of link messages read in from the file
3107  *
3108  * Return:	Success:	Non-negative
3109  *		Failure:	Negative
3110  *
3111  * Programmer:	Quincey Koziol
3112  *		March 11 2007
3113  *
3114  *-------------------------------------------------------------------------
3115  */
3116 herr_t
H5O_get_nlinks(const H5O_loc_t * loc,hid_t dxpl_id,hsize_t * nlinks)3117 H5O_get_nlinks(const H5O_loc_t *loc, hid_t dxpl_id, hsize_t *nlinks)
3118 {
3119     H5O_t *oh = NULL;                   /* Object header */
3120     herr_t ret_value = SUCCEED;         /* Return value */
3121 
3122     FUNC_ENTER_NOAPI(FAIL)
3123 
3124     /* Check args */
3125     HDassert(loc);
3126     HDassert(nlinks);
3127 
3128     /* Get the object header */
3129     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
3130 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
3131 
3132     /* Retrieve the # of link messages seen when the object header was loaded */
3133     *nlinks = oh->link_msgs_seen;
3134 
3135 done:
3136     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
3137 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
3138 
3139     FUNC_LEAVE_NOAPI(ret_value)
3140 } /* end H5O_get_nlinks() */
3141 
3142 
3143 /*-------------------------------------------------------------------------
3144  * Function:	H5O_obj_create
3145  *
3146  * Purpose:	Creates an object, in an abstract manner.
3147  *
3148  * Return:	Success:	Pointer to object opened
3149  *		Failure:	NULL
3150  *
3151  * Programmer:	Quincey Koziol
3152  *		April 9 2007
3153  *
3154  *-------------------------------------------------------------------------
3155  */
3156 void *
H5O_obj_create(H5F_t * f,H5O_type_t obj_type,void * crt_info,H5G_loc_t * obj_loc,hid_t dxpl_id)3157 H5O_obj_create(H5F_t *f, H5O_type_t obj_type, void *crt_info, H5G_loc_t *obj_loc,
3158     hid_t dxpl_id)
3159 {
3160     size_t u;                           /* Local index variable */
3161     void *ret_value = NULL;             /* Return value */
3162 
3163     FUNC_ENTER_NOAPI(NULL)
3164 
3165     /* Sanity checks */
3166     HDassert(f);
3167     HDassert(obj_type >= H5O_TYPE_GROUP && obj_type <= H5O_TYPE_NAMED_DATATYPE);
3168     HDassert(crt_info);
3169     HDassert(obj_loc);
3170 
3171     /* Iterate through the object classes */
3172     for(u = 0; u < NELMTS(H5O_obj_class_g); u++) {
3173         /* Check for correct type of object to create */
3174 	if(H5O_obj_class_g[u]->type == obj_type) {
3175             /* Call the object class's 'create' routine */
3176             HDassert(H5O_obj_class_g[u]->create);
3177             if(NULL == (ret_value = H5O_obj_class_g[u]->create(f, crt_info, obj_loc, dxpl_id)))
3178                 HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, NULL, "unable to open object")
3179 
3180             /* Break out of loop */
3181             break;
3182         } /* end if */
3183     } /* end for */
3184     HDassert(ret_value);
3185 
3186 done:
3187     FUNC_LEAVE_NOAPI(ret_value)
3188 } /* end H5O_obj_create() */
3189 
3190 
3191 /*-------------------------------------------------------------------------
3192  * Function:	H5O_get_oh_addr
3193  *
3194  * Purpose:	Retrieve the address of the object header
3195  *
3196  * Note:	This routine participates in the "Inlining C struct access"
3197  *		pattern, don't call it directly, use the appropriate macro
3198  *		defined in H5Oprivate.h.
3199  *
3200  * Return:	Success:	Valid haddr_t
3201  *		Failure:	HADDR_UNDEF
3202  *
3203  * Programmer:	Quincey Koziol
3204  *		March 15 2007
3205  *
3206  *-------------------------------------------------------------------------
3207  */
3208 haddr_t
H5O_get_oh_addr(const H5O_t * oh)3209 H5O_get_oh_addr(const H5O_t *oh)
3210 {
3211     /* Use FUNC_ENTER_NOAPI_NOINIT_NOERR here to avoid performance issues */
3212     FUNC_ENTER_NOAPI_NOINIT_NOERR
3213 
3214     HDassert(oh);
3215     HDassert(oh->chunk);
3216 
3217     FUNC_LEAVE_NOAPI(oh->chunk[0].addr)
3218 } /* end H5O_get_oh_addr() */
3219 
3220 
3221 /*-------------------------------------------------------------------------
3222  * Function:	H5O_get_rc_and_type
3223  *
3224  * Purpose:	Retrieve an object's reference count and type
3225  *
3226  * Return:	Success:	Non-negative
3227  *		Failure:	Negative
3228  *
3229  * Programmer:	Quincey Koziol
3230  *		November  4 2007
3231  *
3232  *-------------------------------------------------------------------------
3233  */
3234 herr_t
H5O_get_rc_and_type(const H5O_loc_t * loc,hid_t dxpl_id,unsigned * rc,H5O_type_t * otype)3235 H5O_get_rc_and_type(const H5O_loc_t *loc, hid_t dxpl_id, unsigned *rc, H5O_type_t *otype)
3236 {
3237     H5O_t *oh = NULL;                   /* Object header */
3238     herr_t ret_value = SUCCEED;         /* Return value */
3239 
3240     FUNC_ENTER_NOAPI(FAIL)
3241 
3242     /* Check args */
3243     HDassert(loc);
3244 
3245     /* Get the object header */
3246     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
3247 	HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
3248 
3249     /* Set the object's reference count */
3250     if(rc)
3251         *rc = oh->nlink;
3252 
3253     /* Retrieve the type of the object */
3254     if(otype)
3255         if(H5O_obj_type_real(oh, otype) < 0)
3256             HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
3257 
3258 done:
3259     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
3260 	HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
3261 
3262     FUNC_LEAVE_NOAPI(ret_value)
3263 } /* end H5O_get_rc_and_type() */
3264 
3265 
3266 /*-------------------------------------------------------------------------
3267  * Function:    H5O_free_visit_visited
3268  *
3269  * Purpose:     Free the key for an object visited during a group traversal
3270  *
3271  * Return:      Non-negative on success, negative on failure
3272  *
3273  * Programmer:  Quincey Koziol
3274  *	        Nov 25, 2007
3275  *
3276  *-------------------------------------------------------------------------
3277  */
3278 static herr_t
H5O_free_visit_visited(void * item,void H5_ATTR_UNUSED * key,void H5_ATTR_UNUSED * operator_data)3279 H5O_free_visit_visited(void *item, void H5_ATTR_UNUSED *key, void H5_ATTR_UNUSED *operator_data/*in,out*/)
3280 {
3281     FUNC_ENTER_NOAPI_NOINIT_NOERR
3282 
3283     item = H5FL_FREE(H5_obj_t, item);
3284 
3285     FUNC_LEAVE_NOAPI(SUCCEED)
3286 } /* end H5O_free_visit_visited() */
3287 
3288 
3289 /*-------------------------------------------------------------------------
3290  * Function:	H5O_visit_cb
3291  *
3292  * Purpose:     Callback function for recursively visiting objects from a group
3293  *
3294  * Return:	Success:        Non-negative
3295  *		Failure:	Negative
3296  *
3297  * Programmer:	Quincey Koziol
3298  *	        Nov 25, 2007
3299  *
3300  *-------------------------------------------------------------------------
3301  */
3302 static herr_t
H5O_visit_cb(hid_t H5_ATTR_UNUSED group,const char * name,const H5L_info_t * linfo,void * _udata)3303 H5O_visit_cb(hid_t H5_ATTR_UNUSED group, const char *name, const H5L_info_t *linfo,
3304     void *_udata)
3305 {
3306     H5O_iter_visit_ud_t *udata = (H5O_iter_visit_ud_t *)_udata;     /* User data for callback */
3307     H5G_loc_t   obj_loc;                /* Location of object */
3308     H5G_name_t  obj_path;            	/* Object's group hier. path */
3309     H5O_loc_t   obj_oloc;            	/* Object's object location */
3310     hbool_t     obj_found = FALSE;      /* Object at 'name' found */
3311     herr_t ret_value = H5_ITER_CONT;    /* Return value */
3312 
3313     FUNC_ENTER_NOAPI_NOINIT
3314 
3315     /* Sanity check */
3316     HDassert(name);
3317     HDassert(linfo);
3318     HDassert(udata);
3319 
3320     /* Check if this is a hard link */
3321     if(linfo->type == H5L_TYPE_HARD) {
3322         H5_obj_t obj_pos;       /* Object "position" for this object */
3323 
3324         /* Set up opened group location to fill in */
3325         obj_loc.oloc = &obj_oloc;
3326         obj_loc.path = &obj_path;
3327         H5G_loc_reset(&obj_loc);
3328 
3329         /* Find the object using the LAPL passed in */
3330         /* (Correctly handles mounted files) */
3331         if(H5G_loc_find(udata->start_loc, name, &obj_loc/*out*/, udata->lapl_id, udata->dxpl_id) < 0)
3332             HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, H5_ITER_ERROR, "object not found")
3333         obj_found = TRUE;
3334 
3335         /* Construct unique "position" for this object */
3336         H5F_GET_FILENO(obj_oloc.file, obj_pos.fileno);
3337         obj_pos.addr = obj_oloc.addr;
3338 
3339         /* Check if we've seen the object the link references before */
3340         if(NULL == H5SL_search(udata->visited, &obj_pos)) {
3341             H5O_info_t oinfo;           /* Object info */
3342 
3343             /* Get the object's info */
3344             if(H5O_get_info(&obj_oloc, udata->dxpl_id, TRUE, &oinfo) < 0)
3345                 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, H5_ITER_ERROR, "unable to get object info")
3346 
3347             /* Make the application callback */
3348             ret_value = (udata->op)(udata->obj_id, name, &oinfo, udata->op_data);
3349 
3350             /* Check for continuing to visit objects */
3351             if(ret_value == H5_ITER_CONT) {
3352                 /* If its ref count is > 1, we add it to the list of visited objects */
3353                 /* (because it could come up again during traversal) */
3354                 if(oinfo.rc > 1) {
3355                     H5_obj_t *new_node;                  /* New object node for visited list */
3356 
3357                     /* Allocate new object "position" node */
3358                     if((new_node = H5FL_MALLOC(H5_obj_t)) == NULL)
3359                         HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, H5_ITER_ERROR, "can't allocate object node")
3360 
3361                     /* Set node information */
3362                     *new_node = obj_pos;
3363 
3364                     /* Add to list of visited objects */
3365                     if(H5SL_insert(udata->visited, new_node, new_node) < 0)
3366                         HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert object node into visited list")
3367                 } /* end if */
3368             } /* end if */
3369         } /* end if */
3370     } /* end if */
3371 
3372 done:
3373     /* Release resources */
3374     if(obj_found && H5G_loc_free(&obj_loc) < 0)
3375         HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, H5_ITER_ERROR, "can't free location")
3376 
3377     FUNC_LEAVE_NOAPI(ret_value)
3378 } /* end H5O_visit_cb() */
3379 
3380 
3381 /*-------------------------------------------------------------------------
3382  * Function:	H5O_visit
3383  *
3384  * Purpose:	Recursively visit an object and all the objects reachable
3385  *              from it.  If the starting object is a group, all the objects
3386  *              linked to from that group will be visited.  Links within
3387  *              each group are visited according to the order within the
3388  *              specified index (unless the specified index does not exist for
3389  *              a particular group, then the "name" index is used).
3390  *
3391  *              NOTE: Soft links and user-defined links are ignored during
3392  *              this operation.
3393  *
3394  *              NOTE: Each _object_ reachable from the initial group will only
3395  *              be visited once.  If multiple hard links point to the same
3396  *              object, the first link to the object's path (according to the
3397  *              iteration index and iteration order given) will be used to in
3398  *              the callback about the object.
3399  *
3400  * Return:	Success:	The return value of the first operator that
3401  *				returns non-zero, or zero if all members were
3402  *				processed with no operator returning non-zero.
3403  *
3404  *		Failure:	Negative if something goes wrong within the
3405  *				library, or the negative value returned by one
3406  *				of the operators.
3407  *
3408  * Programmer:	Quincey Koziol
3409  *		November 24 2007
3410  *
3411  *-------------------------------------------------------------------------
3412  */
3413 static herr_t
H5O_visit(hid_t loc_id,const char * obj_name,H5_index_t idx_type,H5_iter_order_t order,H5O_iterate_t op,void * op_data,hid_t lapl_id,hid_t dxpl_id)3414 H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
3415     H5_iter_order_t order, H5O_iterate_t op, void *op_data, hid_t lapl_id,
3416     hid_t dxpl_id)
3417 {
3418     H5O_iter_visit_ud_t udata;  /* User data for callback */
3419     H5G_loc_t	loc;            /* Location of reference object */
3420     H5G_loc_t   obj_loc;        /* Location used to open object */
3421     H5G_name_t  obj_path;       /* Opened object group hier. path */
3422     H5O_loc_t   obj_oloc;       /* Opened object object location */
3423     hbool_t     loc_found = FALSE;      /* Entry at 'name' found */
3424     H5O_info_t  oinfo;          /* Object info struct */
3425     hid_t       obj_id = (-1);  /* ID of object */
3426     herr_t      ret_value = FAIL;       /* Return value */
3427 
3428     FUNC_ENTER_NOAPI(FAIL)
3429 
3430     /* Portably initialize user data struct to zeros */
3431     HDmemset(&udata, 0, sizeof(udata));
3432 
3433     /* Check args */
3434     if(H5G_loc(loc_id, &loc) < 0)
3435         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
3436 
3437     /* Set up opened group location to fill in */
3438     obj_loc.oloc = &obj_oloc;
3439     obj_loc.path = &obj_path;
3440     H5G_loc_reset(&obj_loc);
3441 
3442     /* Find the object's location */
3443     if(H5G_loc_find(&loc, obj_name, &obj_loc/*out*/, lapl_id, dxpl_id) < 0)
3444         HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "object not found")
3445     loc_found = TRUE;
3446 
3447     /* Get the object's info */
3448     if(H5O_get_info(&obj_oloc, dxpl_id, TRUE, &oinfo) < 0)
3449         HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "unable to get object info")
3450 
3451     /* Open the object */
3452     /* (Takes ownership of the obj_loc information) */
3453     if((obj_id = H5O_open_by_loc(&obj_loc, lapl_id, dxpl_id, TRUE)) < 0)
3454         HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object")
3455 
3456     /* Make callback for starting object */
3457     if((ret_value = op(obj_id, ".", &oinfo, op_data)) < 0)
3458         HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "can't visit objects")
3459 
3460     /* Check return value of first callback */
3461     if(ret_value != H5_ITER_CONT)
3462         HGOTO_DONE(ret_value);
3463 
3464     /* Check for object being a group */
3465     if(oinfo.type == H5O_TYPE_GROUP) {
3466         H5G_loc_t	start_loc;          /* Location of starting group */
3467 
3468         /* Get the location of the starting group */
3469         if(H5G_loc(obj_id, &start_loc) < 0)
3470             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
3471 
3472         /* Set up user data for visiting links */
3473         udata.obj_id = obj_id;
3474         udata.start_loc = &start_loc;
3475         udata.lapl_id = lapl_id;
3476         udata.dxpl_id = dxpl_id;
3477         udata.op = op;
3478         udata.op_data = op_data;
3479 
3480         /* Create skip list to store visited object information */
3481         if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, NULL)) == NULL)
3482             HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
3483 
3484         /* If its ref count is > 1, we add it to the list of visited objects */
3485         /* (because it could come up again during traversal) */
3486         if(oinfo.rc > 1) {
3487             H5_obj_t *obj_pos;                  /* New object node for visited list */
3488 
3489             /* Allocate new object "position" node */
3490             if((obj_pos = H5FL_MALLOC(H5_obj_t)) == NULL)
3491                 HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, FAIL, "can't allocate object node")
3492 
3493             /* Construct unique "position" for this object */
3494             obj_pos->fileno = oinfo.fileno;
3495             obj_pos->addr = oinfo.addr;
3496 
3497             /* Add to list of visited objects */
3498             if(H5SL_insert(udata.visited, obj_pos, obj_pos) < 0)
3499                 HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object node into visited list")
3500         } /* end if */
3501 
3502         /* Call internal group visitation routine */
3503         if((ret_value = H5G_visit(obj_id, ".", idx_type, order, H5O_visit_cb, &udata, lapl_id, dxpl_id)) < 0)
3504             HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "object visitation failed")
3505     } /* end if */
3506 
3507 done:
3508     if(obj_id > 0) {
3509         if(H5I_dec_app_ref(obj_id) < 0)
3510             HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "unable to close object")
3511     } /* end if */
3512     else if(loc_found && H5G_loc_free(&obj_loc) < 0)
3513         HDONE_ERROR(H5E_OHDR, H5E_CANTRELEASE, FAIL, "can't free location")
3514     if(udata.visited)
3515         H5SL_destroy(udata.visited, H5O_free_visit_visited, NULL);
3516 
3517     FUNC_LEAVE_NOAPI(ret_value)
3518 } /* end H5O_visit() */
3519 
3520 
3521 /*-------------------------------------------------------------------------
3522  * Function:	H5O_inc_rc
3523  *
3524  * Purpose:	Increments the reference count on an object header
3525  *
3526  * Return:	Non-negative on success/Negative on failure
3527  *
3528  * Programmer:	Quincey Koziol
3529  *		koziol@hdfgroup.org
3530  *		Jul 13 2008
3531  *
3532  *-------------------------------------------------------------------------
3533  */
3534 herr_t
H5O_inc_rc(H5O_t * oh)3535 H5O_inc_rc(H5O_t *oh)
3536 {
3537     herr_t ret_value = SUCCEED;         /* Return value */
3538 
3539     FUNC_ENTER_NOAPI(FAIL)
3540 
3541     /* check args */
3542     HDassert(oh);
3543 
3544     /* Pin the object header when the reference count goes above 0 */
3545     if(oh->rc == 0)
3546         if(H5AC_pin_protected_entry(oh) < 0)
3547             HGOTO_ERROR(H5E_OHDR, H5E_CANTPIN, FAIL, "unable to pin object header")
3548 
3549     /* Increment reference count */
3550     oh->rc++;
3551 
3552 done:
3553     FUNC_LEAVE_NOAPI(ret_value)
3554 } /* end H5O_inc_rc() */
3555 
3556 
3557 /*-------------------------------------------------------------------------
3558  * Function:	H5O_dec_rc
3559  *
3560  * Purpose:	Decrements the reference count on an object header
3561  *
3562  * Return:	Non-negative on success/Negative on failure
3563  *
3564  * Programmer:	Quincey Koziol
3565  *		koziol@hdfgroup.org
3566  *		Jul 13 2008
3567  *
3568  *-------------------------------------------------------------------------
3569  */
3570 herr_t
H5O_dec_rc(H5O_t * oh)3571 H5O_dec_rc(H5O_t *oh)
3572 {
3573     herr_t ret_value = SUCCEED;         /* Return value */
3574 
3575     FUNC_ENTER_NOAPI(FAIL)
3576 
3577     /* check args */
3578     HDassert(oh);
3579 
3580     /* Decrement reference count */
3581     oh->rc--;
3582 
3583     /* Unpin the object header when the reference count goes back to 0 */
3584     if(oh->rc == 0)
3585         if(H5AC_unpin_entry(oh) < 0)
3586             HGOTO_ERROR(H5E_OHDR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
3587 
3588 done:
3589     FUNC_LEAVE_NOAPI(ret_value)
3590 } /* end H5O_dec_rc() */
3591 
3592 
3593 /*-------------------------------------------------------------------------
3594  * Function:   H5O_dec_rc_by_loc
3595  *
3596  * Purpose:    Decrement the refcount of an object header, using its
3597  *              object location information.
3598  *
3599  * Return:     Non-negative on success/Negative on failure
3600  *
3601  * Programmer: Quincey Koziol
3602  *             koziol@hdfgroup.org
3603  *             Oct 08 2010
3604  *
3605  *-------------------------------------------------------------------------
3606  */
3607 herr_t
H5O_dec_rc_by_loc(const H5O_loc_t * loc,hid_t dxpl_id)3608 H5O_dec_rc_by_loc(const H5O_loc_t *loc, hid_t dxpl_id)
3609 {
3610     H5O_t       *oh = NULL;             /* Object header */
3611     herr_t      ret_value = SUCCEED;    /* Return value */
3612 
3613     FUNC_ENTER_NOAPI(FAIL)
3614 
3615     /* check args */
3616     HDassert(loc);
3617 
3618     /* Get header */
3619     if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC__READ_ONLY_FLAG, FALSE)))
3620        HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to protect object header")
3621 
3622     /* Decrement the reference count on the object header */
3623     /* (which will unpin it, if appropriate) */
3624     if(H5O_dec_rc(oh) < 0)
3625         HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement reference count on object header")
3626 
3627 done:
3628     /* Release the object header from the cache */
3629     if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
3630         HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
3631 
3632     FUNC_LEAVE_NOAPI(ret_value)
3633 } /* end H5O_dec_rc_by_loc() */
3634 
3635 
3636 /*-------------------------------------------------------------------------
3637  * Function:	H5O_get_proxy
3638  *
3639  * Purpose:	Retrieve the proxy for the object header.
3640  *
3641  * Return:	Non-negative on success/Negative on failure
3642  *
3643  * Programmer:	Quincey Koziol
3644  *		July 24 2016
3645  *
3646  *-------------------------------------------------------------------------
3647  */
3648 H5AC_proxy_entry_t *
H5O_get_proxy(const H5O_t * oh)3649 H5O_get_proxy(const H5O_t *oh)
3650 {
3651     FUNC_ENTER_NOAPI_NOINIT_NOERR
3652 
3653     /* Check args */
3654     HDassert(oh);
3655 
3656     FUNC_LEAVE_NOAPI(oh->proxy)
3657 } /* end H5O_get_proxy() */
3658 
3659 
3660 /*-------------------------------------------------------------------------
3661  * Function:	H5O__free
3662  *
3663  * Purpose:	Destroys an object header.
3664  *
3665  * Return:	Non-negative on success/Negative on failure
3666  *
3667  * Programmer:	Quincey Koziol
3668  *		koziol@ncsa.uiuc.edu
3669  *		Jan 15 2003
3670  *
3671  *-------------------------------------------------------------------------
3672  */
3673 herr_t
H5O__free(H5O_t * oh)3674 H5O__free(H5O_t *oh)
3675 {
3676     unsigned	u;                      /* Local index variable */
3677     herr_t      ret_value = SUCCEED;    /* Return value */
3678 
3679     FUNC_ENTER_PACKAGE
3680 
3681     /* check args */
3682     HDassert(oh);
3683     HDassert(0 == oh->rc);
3684 
3685     /* Destroy chunks */
3686     if(oh->chunk) {
3687         for(u = 0; u < oh->nchunks; u++)
3688             oh->chunk[u].image = H5FL_BLK_FREE(chunk_image, oh->chunk[u].image);
3689 
3690         oh->chunk = (H5O_chunk_t *)H5FL_SEQ_FREE(H5O_chunk_t, oh->chunk);
3691     } /* end if */
3692 
3693     /* Destroy messages */
3694     if(oh->mesg) {
3695         for(u = 0; u < oh->nmesgs; u++) {
3696 #ifndef NDEBUG
3697             /* Verify that message is clean, unless it could have been marked
3698              * dirty by decoding */
3699             if(oh->ndecode_dirtied && oh->mesg[u].dirty)
3700                 oh->ndecode_dirtied--;
3701             else
3702                 HDassert(oh->mesg[u].dirty == 0);
3703 #endif /* NDEBUG */
3704 
3705             H5O_msg_free_mesg(&oh->mesg[u]);
3706         } /* end for */
3707 
3708         /* Make sure we accounted for all the messages dirtied by decoding */
3709         HDassert(!oh->ndecode_dirtied);
3710 
3711         oh->mesg = (H5O_mesg_t *)H5FL_SEQ_FREE(H5O_mesg_t, oh->mesg);
3712     } /* end if */
3713 
3714     /* Destroy the proxy */
3715     if(oh->proxy)
3716         if(H5AC_proxy_entry_dest(oh->proxy) < 0)
3717             HGOTO_ERROR(H5E_OHDR, H5E_CANTFREE, FAIL, "unable to destroy virtual entry used for proxy")
3718 
3719     /* destroy object header */
3720     oh = H5FL_FREE(H5O_t, oh);
3721 
3722 done:
3723     FUNC_LEAVE_NOAPI(ret_value)
3724 } /* end H5O__free() */
3725 
3726