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