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