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