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 files COPYING and Copyright.html. COPYING can be found at the root *
9 * of the source code distribution tree; Copyright.html can be found at the *
10 * root level of an installed copy of the electronic HDF5 document set and *
11 * is linked from the top-level documents page. It can also be found at *
12 * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
13 * access to either file, you may request a copy from help@hdfgroup.org. *
14 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /*-------------------------------------------------------------------------
17 *
18 * Created: H5Oattribute.c
19 * Dec 11 2006
20 * Quincey Koziol <koziol@hdfgroup.org>
21 *
22 * Purpose: Object header attribute routines.
23 *
24 *-------------------------------------------------------------------------
25 */
26
27 /****************/
28 /* Module Setup */
29 /****************/
30
31 #define H5A_PACKAGE /*suppress error about including H5Apkg */
32 #define H5O_PACKAGE /*suppress error about including H5Opkg */
33
34 /***********/
35 /* Headers */
36 /***********/
37 #include "H5private.h" /* Generic Functions */
38 #include "H5Apkg.h" /* Attributes */
39 #include "H5Eprivate.h" /* Error handling */
40 #include "H5MMprivate.h" /* Memory management */
41 #include "H5Opkg.h" /* Object headers */
42 #include "H5SMprivate.h" /* Shared Object Header Messages */
43 #include "H5Iprivate.h" /* IDs */
44 #include "H5Fprivate.h" /* File */
45
46
47 /****************/
48 /* Local Macros */
49 /****************/
50
51
52 /******************/
53 /* Local Typedefs */
54 /******************/
55
56 /* User data for iteration when converting attributes to dense storage */
57 typedef struct {
58 H5F_t *f; /* Pointer to file for insertion */
59 hid_t dxpl_id; /* DXPL during iteration */
60 H5O_ainfo_t *ainfo; /* Attribute info struct */
61 } H5O_iter_cvt_t;
62
63 /* User data for iteration when opening an attribute */
64 typedef struct {
65 /* down */
66 const char *name; /* Name of attribute to open */
67
68 /* up */
69 H5A_t *attr; /* Attribute data to update object header with */
70 } H5O_iter_opn_t;
71
72 /* User data for iteration when updating an attribute */
73 typedef struct {
74 /* down */
75 H5F_t *f; /* Pointer to file attribute is in */
76 hid_t dxpl_id; /* DXPL for operation */
77 H5A_t *attr; /* Attribute data to update object header with */
78
79 /* up */
80 hbool_t found; /* Whether the attribute was found */
81 } H5O_iter_wrt_t;
82
83 /* User data for iteration when renaming an attribute */
84 typedef struct {
85 /* down */
86 H5F_t *f; /* Pointer to file attribute is in */
87 hid_t dxpl_id; /* DXPL for operation */
88 const char *old_name; /* Old name of attribute */
89 const char *new_name; /* New name of attribute */
90
91 /* up */
92 hbool_t found; /* Whether the attribute was found */
93 } H5O_iter_ren_t;
94
95 /* User data for iteration when iterating over attributes */
96 typedef struct {
97 /* down */
98 H5F_t *f; /* Pointer to file attribute is in */
99 hid_t dxpl_id; /* DXPL for operation */
100 hid_t loc_id; /* ID of object being iterated over */
101 unsigned skip; /* # of attributes to skip over */
102 H5A_operator_t op; /* Callback routine for each attribute */
103 void *op_data; /* User data for callback */
104
105 /* up */
106 unsigned count; /* Count of attributes examined */
107 } H5O_iter_itr_t;
108
109 /* User data for iteration when removing an attribute */
110 typedef struct {
111 /* down */
112 H5F_t *f; /* Pointer to file attribute is in */
113 hid_t dxpl_id; /* DXPL for operation */
114 const char *name; /* Name of attribute to open */
115
116 /* up */
117 hbool_t found; /* Found attribute to delete */
118 } H5O_iter_rm_t;
119
120 /* User data for iteration when checking if an attribute exists */
121 typedef struct {
122 /* down */
123 const char *name; /* Name of attribute to open */
124
125 /* up */
126 hbool_t found; /* Found attribute */
127 } H5O_iter_xst_t;
128
129
130 /********************/
131 /* Package Typedefs */
132 /********************/
133
134
135 /********************/
136 /* Local Prototypes */
137 /********************/
138 static htri_t H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr,
139 const char* name_to_open);
140
141 /*********************/
142 /* Package Variables */
143 /*********************/
144
145
146 /*****************************/
147 /* Library Private Variables */
148 /*****************************/
149
150
151 /*******************/
152 /* Local Variables */
153 /*******************/
154
155
156
157 /*-------------------------------------------------------------------------
158 * Function: H5O_attr_to_dense_cb
159 *
160 * Purpose: Object header iterator callback routine to convert compact
161 * attributes to dense attributes
162 *
163 * Return: Non-negative on success/Negative on failure
164 *
165 * Programmer: Quincey Koziol
166 * koziol@hdfgroup.org
167 * Dec 4 2006
168 *
169 * Modifications:
170 * Vailin Choi; Sept 2011
171 * Indicate that the object header is modified and might possibly need
172 * to condense messages in the object header
173 *-------------------------------------------------------------------------
174 */
175 static herr_t
H5O_attr_to_dense_cb(H5O_t * oh,H5O_mesg_t * mesg,unsigned UNUSED sequence,unsigned * oh_modified,void * _udata)176 H5O_attr_to_dense_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
177 unsigned UNUSED sequence, unsigned *oh_modified, void *_udata/*in,out*/)
178 {
179 H5O_iter_cvt_t *udata = (H5O_iter_cvt_t *)_udata; /* Operator user data */
180 H5A_t *attr = (H5A_t *)mesg->native; /* Pointer to attribute to insert */
181 herr_t ret_value = H5_ITER_CONT; /* Return value */
182
183 FUNC_ENTER_NOAPI_NOINIT
184
185 /* check args */
186 HDassert(oh);
187 HDassert(mesg);
188 HDassert(udata);
189 HDassert(udata->f);
190 HDassert(udata->ainfo);
191 HDassert(attr);
192
193 /* Insert attribute into dense storage */
194 if(H5A_dense_insert(udata->f, udata->dxpl_id, udata->ainfo, attr) < 0)
195 HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to add to dense storage")
196
197 /* Convert message into a null message in the header */
198 /* (don't delete attribute's space in the file though) */
199 if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, FALSE) < 0)
200 HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
201
202 /* Indicate that the object header was modified */
203 *oh_modified = H5O_MODIFY_CONDENSE;
204
205 done:
206 FUNC_LEAVE_NOAPI(ret_value)
207 } /* end H5O_attr_to_dense_cb() */
208
209
210 /*-------------------------------------------------------------------------
211 * Function: H5O_attr_create
212 *
213 * Purpose: Create a new attribute in the object header.
214 *
215 * Return: Non-negative on success/Negative on failure
216 *
217 * Programmer: Quincey Koziol
218 * Friday, December 8, 2006
219 *
220 *-------------------------------------------------------------------------
221 */
222 herr_t
H5O_attr_create(const H5O_loc_t * loc,hid_t dxpl_id,H5A_t * attr)223 H5O_attr_create(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
224 {
225 H5O_t *oh = NULL; /* Pointer to actual object header */
226 H5O_ainfo_t ainfo; /* Attribute information for object */
227 htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
228 herr_t ret_value = SUCCEED; /* Return value */
229
230 FUNC_ENTER_NOAPI_NOINIT
231
232 /* Check arguments */
233 HDassert(loc);
234 HDassert(attr);
235
236 /* Pin the object header */
237 if(NULL == (oh = H5O_pin(loc, dxpl_id)))
238 HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
239
240 /* Check if this object already has attribute information */
241 if(oh->version > H5O_VERSION_1) {
242 hbool_t new_ainfo = FALSE; /* Flag to indicate that the attribute information is new */
243 htri_t ainfo_exists; /* Whether the attribute info was retrieved */
244
245 /* Check for (& retrieve if available) attribute info */
246 if((ainfo_exists = H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo)) < 0)
247 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
248 if(!ainfo_exists) {
249 /* Initialize attribute information */
250 ainfo.track_corder = (hbool_t)((oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? TRUE : FALSE);
251 ainfo.index_corder = (hbool_t)((oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) ? TRUE : FALSE);
252 ainfo.max_crt_idx = 0;
253 ainfo.corder_bt2_addr = HADDR_UNDEF;
254 ainfo.nattrs = 0;
255 ainfo.fheap_addr = HADDR_UNDEF;
256 ainfo.name_bt2_addr = HADDR_UNDEF;
257
258 /* Set flag to add attribute information to object header */
259 new_ainfo = TRUE;
260 } /* end if */
261 else {
262 /* Sanity check attribute info read in */
263 HDassert(ainfo.nattrs > 0);
264 HDassert(ainfo.track_corder == ((oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) > 0));
265 HDassert(ainfo.index_corder == ((oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) > 0));
266 } /* end else */
267
268 /* Check if switching to "dense" attribute storage is possible */
269 if(!H5F_addr_defined(ainfo.fheap_addr)) {
270 htri_t sharable; /* Whether the attribute will be shared */
271 size_t raw_size = 0; /* Raw size of message */
272
273 /* Check for attribute being sharable */
274 if((sharable = H5SM_can_share(loc->file, dxpl_id, NULL, NULL, H5O_ATTR_ID, attr)) < 0)
275 HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't determine attribute sharing status")
276 else if(sharable == FALSE) {
277 /* Compute the size needed to encode the attribute */
278 raw_size = (H5O_MSG_ATTR->raw_size)(loc->file, FALSE, attr);
279 } /* end if */
280
281 /* Check for condititions for switching to "dense" attribute storage are met */
282 if(ainfo.nattrs == oh->max_compact || (!sharable && raw_size >= H5O_MESG_MAX_SIZE)) {
283 H5O_iter_cvt_t udata; /* User data for callback */
284 H5O_mesg_operator_t op; /* Wrapper for operator */
285
286 /* Create dense storage for attributes */
287 if(H5A_dense_create(loc->file, dxpl_id, &ainfo) < 0)
288 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to create dense storage for attributes")
289
290 /* Set up user data for callback */
291 udata.f = loc->file;
292 udata.dxpl_id = dxpl_id;
293 udata.ainfo = &ainfo;
294
295 /* Iterate over existing attributes, moving them to dense storage */
296 op.op_type = H5O_MESG_OP_LIB;
297 op.u.lib_op = H5O_attr_to_dense_cb;
298 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
299 HGOTO_ERROR(H5E_ATTR, H5E_CANTCONVERT, FAIL, "error converting attributes to dense storage")
300 } /* end if */
301 } /* end if */
302
303 /* Increment attribute count on object */
304 ainfo.nattrs++;
305
306 /* Check whether we're tracking the creation index on attributes */
307 if(ainfo.track_corder) {
308 /* Check for attribute creation order index on the object wrapping around */
309 if(ainfo.max_crt_idx == H5O_MAX_CRT_ORDER_IDX)
310 HGOTO_ERROR(H5E_ATTR, H5E_CANTINC, FAIL, "attribute creation index can't be incremented")
311
312 /* Set the creation order index on the attribute & incr. creation order index */
313 attr->shared->crt_idx = ainfo.max_crt_idx++;
314 } /* end if */
315 else
316 /* Set "bogus" creation index for attribute */
317 attr->shared->crt_idx = H5O_MAX_CRT_ORDER_IDX;
318
319 /* Add the attribute information message, if one is needed */
320 if(new_ainfo) {
321 if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, &ainfo) < 0)
322 HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute info message")
323 } /* end if */
324 /* Otherwise, update existing message */
325 else {
326 if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, &ainfo) < 0)
327 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info message")
328 } /* end else */
329 } /* end if */
330 else {
331 /* Set "bogus" creation index for attribute */
332 attr->shared->crt_idx = H5O_MAX_CRT_ORDER_IDX;
333
334 /* Set attribute info value to get attribute into object header */
335 ainfo.fheap_addr = HADDR_UNDEF;
336 } /* end else */
337
338 /* Check for storing attribute with dense storage */
339 if(H5F_addr_defined(ainfo.fheap_addr)) {
340 /* Insert attribute into dense storage */
341 if(H5A_dense_insert(loc->file, dxpl_id, &ainfo, attr) < 0)
342 HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
343 } /* end if */
344 else {
345 /* Append new message to object header */
346 if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, attr) < 0)
347 HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to create new attribute in header")
348 } /* end else */
349
350 /* Increment reference count for shared attribute object for the
351 * object handle created by the caller function H5A_create. The count
352 * for the cached object header has been incremented in the step above
353 * (in H5O_msg_append_real). The dense storage doesn't need a count. */
354 attr->shared->nrefs += 1;
355
356 /* Was new attribute shared? */
357 if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, attr)) > 0) {
358 hsize_t attr_rc; /* Attribute's ref count in shared message storage */
359
360 /* Retrieve ref count for shared attribute */
361 if(H5SM_get_refcount(loc->file, dxpl_id, H5O_ATTR_ID, &attr->sh_loc, &attr_rc) < 0)
362 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve shared message ref count")
363
364 /* If this is not the first copy of the attribute in the shared message
365 * storage, decrement the reference count on any shared components
366 * of the attribute. This is done because the shared message
367 * storage's "try delete" call doesn't call the message class's
368 * "delete" callback until the reference count drops to zero.
369 * However, attributes have already increased the reference
370 * count on shared components before passing the attribute
371 * to the shared message code to manage, causing an asymmetry
372 * in the reference counting for any shared components.
373 *
374 * The alternate solution is to have the shared message's "try
375 * delete" code always call the message class's "delete" callback,
376 * even when the reference count is positive. This can be done
377 * without an appreciable performance hit (by using H5HF_op() in
378 * the shared message comparison v2 B-tree callback), but it has
379 * the undesirable side-effect of leaving the reference count on
380 * the attribute's shared components artificially (and possibly
381 * misleadingly) high, because there's only one shared attribute
382 * referencing the shared components, not <refcount for the
383 * shared attribute> objects referencing the shared components.
384 *
385 * *ick* -QAK, 2007/01/08
386 */
387 if(attr_rc > 1) {
388 if(H5O_attr_delete(loc->file, dxpl_id, oh, attr) < 0)
389 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
390 } /* end if */
391 } /* end if */
392 else if(shared_mesg < 0)
393 HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
394
395 /* Update the modification time, if any */
396 if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
397 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
398
399 done:
400 if(oh && H5O_unpin(oh) < 0)
401 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
402
403 FUNC_LEAVE_NOAPI(ret_value)
404 } /* end H5O_attr_create() */
405
406
407 /*-------------------------------------------------------------------------
408 * Function: H5O_attr_open_cb
409 *
410 * Purpose: Object header iterator callback routine to open an
411 * attribute stored compactly.
412 *
413 * Return: Non-negative on success/Negative on failure
414 *
415 * Programmer: Quincey Koziol
416 * koziol@hdfgroup.org
417 * Dec 11 2006
418 *
419 * Modifications:
420 * Vailin Choi; September 2011
421 * Change oh_modified from boolean to unsigned
422 * (See H5Oprivate.h for possible flags)
423 *-------------------------------------------------------------------------
424 */
425 static herr_t
H5O_attr_open_cb(H5O_t * oh,H5O_mesg_t * mesg,unsigned sequence,unsigned UNUSED * oh_modified,void * _udata)426 H5O_attr_open_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/, unsigned sequence,
427 unsigned UNUSED *oh_modified, void *_udata/*in,out*/)
428 {
429 H5O_iter_opn_t *udata = (H5O_iter_opn_t *)_udata; /* Operator user data */
430 herr_t ret_value = H5_ITER_CONT; /* Return value */
431
432 FUNC_ENTER_NOAPI_NOINIT
433
434 /* check args */
435 HDassert(oh);
436 HDassert(mesg);
437 HDassert(!udata->attr);
438
439 /* Check for correct attribute message to modify */
440 if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
441 /* Make a copy of the attribute to return */
442 if(NULL == (udata->attr = H5A_copy(NULL, (H5A_t *)mesg->native)))
443 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "unable to copy attribute")
444
445 /* Assign [somewhat arbitrary] creation order value, for older versions
446 * of the format or if creation order is not tracked */
447 if(oh->version == H5O_VERSION_1
448 || !(oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED))
449 udata->attr->shared->crt_idx = sequence;
450
451 /* Stop iterating */
452 ret_value = H5_ITER_STOP;
453 } /* end if */
454
455 done:
456 FUNC_LEAVE_NOAPI(ret_value)
457 } /* end H5O_attr_open_cb() */
458
459
460 /*-------------------------------------------------------------------------
461 * Function: H5O_attr_open_by_name
462 *
463 * Purpose: Open an existing attribute in an object header.
464 *
465 * Return: Non-negative on success/Negative on failure
466 *
467 * Programmer: Quincey Koziol
468 * Monday, December 11, 2006
469 *
470 * Modification:Raymond Lu
471 * 23 June 2008
472 * If the attribute is in dense storage and has already been
473 * opened, make a copy of already opened object to share some
474 * object information.
475 *-------------------------------------------------------------------------
476 */
477 H5A_t *
H5O_attr_open_by_name(const H5O_loc_t * loc,const char * name,hid_t dxpl_id)478 H5O_attr_open_by_name(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
479 {
480 H5O_t *oh = NULL; /* Pointer to actual object header */
481 H5O_ainfo_t ainfo; /* Attribute information for object */
482 H5A_t *exist_attr = NULL; /* Existing opened attribute object */
483 H5A_t *opened_attr = NULL; /* Newly opened attribute object */
484 htri_t found_open_attr = FALSE; /* Whether opened object is found */
485 H5A_t *ret_value; /* Return value */
486
487 FUNC_ENTER_NOAPI_NOINIT
488
489 /* Check arguments */
490 HDassert(loc);
491 HDassert(name);
492
493 /* Protect the object header to iterate over */
494 if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
495 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, NULL, "unable to load object header")
496
497 /* Check for attribute info stored */
498 ainfo.fheap_addr = HADDR_UNDEF;
499 if(oh->version > H5O_VERSION_1) {
500 /* Check for (& retrieve if available) attribute info */
501 if(H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo) < 0)
502 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't check for attribute info message")
503 } /* end if */
504
505 /* If found the attribute is already opened, make a copy of it to share the
506 * object information. If not, open attribute as a new object
507 */
508 if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr, name)) < 0)
509 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
510 else if(found_open_attr == TRUE) {
511 if(NULL == (opened_attr = H5A_copy(NULL, exist_attr)))
512 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy existing attribute")
513 } /* end else if */
514 else {
515 /* Check for attributes in dense storage */
516 if(H5F_addr_defined(ainfo.fheap_addr)) {
517 /* Open attribute with dense storage */
518 if(NULL == (opened_attr = H5A_dense_open(loc->file, dxpl_id, &ainfo, name)))
519 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "can't open attribute")
520 } /* end if */
521 else {
522 H5O_iter_opn_t udata; /* User data for callback */
523 H5O_mesg_operator_t op; /* Wrapper for operator */
524
525 /* Set up user data for callback */
526 udata.name = name;
527 udata.attr = NULL;
528
529 /* Iterate over attributes, to locate correct one to open */
530 op.op_type = H5O_MESG_OP_LIB;
531 op.u.lib_op = H5O_attr_open_cb;
532 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
533 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "error updating attribute")
534
535 /* Check that we found the attribute */
536 if(!udata.attr)
537 HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute: '%s'", name)
538
539 /* Get attribute opened from object header */
540 HDassert(udata.attr);
541 opened_attr = udata.attr;
542 } /* end else */
543
544 /* Mark datatype as being on disk now */
545 if(H5T_set_loc(opened_attr->shared->dt, loc->file, H5T_LOC_DISK) < 0)
546 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "invalid datatype location")
547 } /* end else */
548
549 /* Set return value */
550 ret_value = opened_attr;
551
552 done:
553 if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
554 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
555
556 /* Release any resources, on error */
557 if(NULL == ret_value && opened_attr)
558 if(H5A_close(opened_attr) < 0)
559 HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close attribute")
560
561 FUNC_LEAVE_NOAPI(ret_value)
562 } /* end H5O_attr_open_by_name() */
563
564
565 /*-------------------------------------------------------------------------
566 * Function: H5O_attr_open_by_idx_cb
567 *
568 * Purpose: Callback routine opening an attribute by index
569 *
570 * Return: Success: Non-negative
571 * Failure: Negative
572 *
573 * Programmer: Quincey Koziol
574 * koziol@hdfgroup.org
575 * Dec 18 2006
576 *
577 *-------------------------------------------------------------------------
578 */
579 static herr_t
H5O_attr_open_by_idx_cb(const H5A_t * attr,void * _ret_attr)580 H5O_attr_open_by_idx_cb(const H5A_t *attr, void *_ret_attr)
581 {
582 H5A_t **ret_attr = (H5A_t **)_ret_attr; /* 'User data' passed in */
583 herr_t ret_value = H5_ITER_STOP; /* Return value */
584
585 FUNC_ENTER_NOAPI_NOINIT
586
587 /* check arguments */
588 HDassert(attr);
589 HDassert(ret_attr);
590
591 /* Copy attribute information. Shared some attribute information. */
592 if(NULL == (*ret_attr = H5A_copy(NULL, attr)))
593 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, H5_ITER_ERROR, "can't copy attribute")
594
595 done:
596 FUNC_LEAVE_NOAPI(ret_value)
597 } /* end H5O_attr_open_by_idx_cb() */
598
599
600 /*-------------------------------------------------------------------------
601 * Function: H5O_attr_open_by_idx
602 *
603 * Purpose: Open an existing attribute in an object header according to
604 * an index.
605 *
606 * Return: Non-negative on success/Negative on failure
607 *
608 * Programmer: Quincey Koziol
609 * Monday, December 18, 2006
610 *
611 * Modification:Raymond Lu
612 * 23 June 2008
613 * After opening the attribute, check whether it's in dense
614 * storage and has already been opened. If it has, close the
615 * opened object and make a copy of already opened object.
616 *-------------------------------------------------------------------------
617 */
618 H5A_t *
H5O_attr_open_by_idx(const H5O_loc_t * loc,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,hid_t dxpl_id)619 H5O_attr_open_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
620 H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
621 {
622 H5O_t *oh = NULL; /* Object header */
623 H5A_attr_iter_op_t attr_op; /* Attribute operator */
624 H5A_t *exist_attr = NULL; /* Existing opened attribute object */
625 H5A_t *opened_attr = NULL; /* Newly opened attribute object */
626 htri_t found_open_attr = FALSE; /* Whether opened object is found */
627 H5A_t *ret_value; /* Return value */
628
629 FUNC_ENTER_NOAPI_NOINIT
630
631 /* Check arguments */
632 HDassert(loc);
633
634 /* Build attribute operator info */
635 attr_op.op_type = H5A_ATTR_OP_LIB;
636 attr_op.u.lib_op = H5O_attr_open_by_idx_cb;
637
638 /* Iterate over attributes to locate correct one */
639 if(H5O_attr_iterate_real((hid_t)-1, loc, dxpl_id, idx_type, order, n, NULL, &attr_op, &opened_attr) < 0)
640 HGOTO_ERROR(H5E_ATTR, H5E_BADITER, NULL, "can't locate attribute")
641
642 /* Protect the object header to iterate over */
643 if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
644 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, NULL, "unable to load object header")
645
646 /* Find out whether it has already been opened. If it has, close the object
647 * and make a copy of the already opened object to share the object info.
648 */
649 if(opened_attr) {
650 if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr, opened_attr->shared->name)) < 0)
651 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "failed in finding opened attribute")
652
653 /* If found that the attribute is already opened, make a copy of it
654 * and close the object just opened.
655 */
656 if(found_open_attr && exist_attr) {
657 if(H5A_close(opened_attr) < 0)
658 HGOTO_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close attribute")
659 if(NULL == (opened_attr = H5A_copy(NULL, exist_attr)))
660 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, NULL, "can't copy existing attribute")
661 } else {
662 /* Mark datatype as being on disk now */
663 if(H5T_set_loc(opened_attr->shared->dt, loc->file, H5T_LOC_DISK) < 0)
664 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, NULL, "invalid datatype location")
665 } /* end if */
666 } /* end if */
667
668 /* Set return value */
669 ret_value = opened_attr;
670
671 done:
672 if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
673 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, NULL, "unable to release object header")
674
675 /* Release any resources, on error */
676 if(NULL == ret_value && opened_attr)
677 if(H5A_close(opened_attr) < 0)
678 HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, NULL, "can't close attribute")
679
680 FUNC_LEAVE_NOAPI(ret_value)
681 } /* end H5O_attr_open_by_idx() */
682
683
684 /*-------------------------------------------------------------------------
685 * Function: H5O_attr_find_opened_attr
686 *
687 * Purpose: Find out whether an attribute has been opened by giving
688 * the name. Return the pointer to the object if found.
689 *
690 * Return: TRUE: found the already opened object
691 * FALSE: didn't find the opened object
692 * FAIL: function failed.
693 *
694 * Programmer: Raymond Lu
695 * 23 June 2008
696 *
697 *-------------------------------------------------------------------------
698 */
699 static htri_t
H5O_attr_find_opened_attr(const H5O_loc_t * loc,H5A_t ** attr,const char * name_to_open)700 H5O_attr_find_opened_attr(const H5O_loc_t *loc, H5A_t **attr, const char* name_to_open)
701 {
702 hid_t *attr_id_list = NULL; /* List of IDs for opened attributes */
703 unsigned long loc_fnum; /* File serial # for object */
704 size_t num_open_attr; /* Number of opened attributes */
705 htri_t ret_value = FALSE; /* Return value */
706
707 FUNC_ENTER_NOAPI_NOINIT
708
709 /* Get file serial number for the location of attribute */
710 if(H5F_get_fileno(loc->file, &loc_fnum) < 0)
711 HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
712
713 /* Count all opened attributes */
714 if(H5F_get_obj_count(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, FALSE, &num_open_attr) < 0)
715 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't count opened attributes")
716
717 /* Find out whether the attribute has been opened */
718 if(num_open_attr) {
719 size_t check_num_attr; /* Number of open attribute IDs */
720 size_t u; /* Local index variable */
721
722 /* Allocate space for the attribute ID list */
723 if(NULL == (attr_id_list = (hid_t *)H5MM_malloc(num_open_attr * sizeof(hid_t))))
724 HGOTO_ERROR(H5E_ATTR, H5E_CANTALLOC, FAIL, "unable to allocate memory for attribute ID list")
725
726 /* Retrieve the IDs of all opened attributes */
727 if(H5F_get_obj_ids(loc->file, H5F_OBJ_ATTR | H5F_OBJ_LOCAL, num_open_attr, attr_id_list, FALSE, &check_num_attr) < 0)
728 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get IDs of opened attributes")
729 if(check_num_attr != num_open_attr)
730 HGOTO_ERROR(H5E_INTERNAL, H5E_BADITER, FAIL, "open attribute count mismatch")
731
732 /* Iterate over the attributes */
733 for(u = 0; u < num_open_attr; u++) {
734 unsigned long attr_fnum; /* Attributes file serial number */
735
736 /* Get pointer to attribute */
737 if(NULL == (*attr = (H5A_t *)H5I_object_verify(attr_id_list[u], H5I_ATTR)))
738 HGOTO_ERROR(H5E_ATTR, H5E_BADTYPE, FAIL, "not an attribute")
739
740 /* Get file serial number for attribute */
741 if(H5F_get_fileno((*attr)->oloc.file, &attr_fnum) < 0)
742 HGOTO_ERROR(H5E_ATTR, H5E_BADVALUE, FAIL, "can't get file serial number")
743
744 /* Verify whether it's the right object. The attribute name, object
745 * address to which the attribute is attached, and file serial
746 * number should all match.
747 */
748 if(!HDstrcmp(name_to_open, (*attr)->shared->name) &&
749 loc->addr == (*attr)->oloc.addr &&
750 loc_fnum == attr_fnum) {
751 ret_value = TRUE;
752 break;
753 } /* end if */
754 } /* end for */
755 } /* end if */
756
757 done:
758 if(attr_id_list)
759 H5MM_free(attr_id_list);
760
761 FUNC_LEAVE_NOAPI(ret_value)
762 } /* end H5O_attr_find_opened_attr */
763
764
765 /*-------------------------------------------------------------------------
766 * Function: H5O_attr_update_shared
767 *
768 * Purpose: Update a shared attribute.
769 *
770 * Return: Non-negative on success/Negative on failure
771 *
772 * Programmer: Quincey Koziol
773 * koziol@hdfgroup.org
774 * Jan 2 2007
775 *
776 *-------------------------------------------------------------------------
777 */
778 herr_t
H5O_attr_update_shared(H5F_t * f,hid_t dxpl_id,H5O_t * oh,H5A_t * attr,H5O_shared_t * update_sh_mesg)779 H5O_attr_update_shared(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5A_t *attr,
780 H5O_shared_t *update_sh_mesg)
781 {
782 H5O_shared_t sh_mesg; /* Shared object header message */
783 hsize_t attr_rc; /* Attribute's ref count in shared message storage */
784 htri_t shared_mesg; /* Whether the message should be shared */
785 herr_t ret_value = SUCCEED; /* Return value */
786
787 FUNC_ENTER_NOAPI_NOINIT
788
789 /* check args */
790 HDassert(f);
791 HDassert(attr);
792
793 /* Extract shared message info from current attribute (for later use) */
794 if(H5O_set_shared(&sh_mesg, &(attr->sh_loc)) < 0)
795 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't get shared message")
796
797 /* Reset existing sharing information */
798 if(H5O_msg_reset_share(H5O_ATTR_ID, attr) < 0)
799 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to reset attribute sharing")
800
801 /* Store new version of message as a SOHM */
802 /* (should always work, since we're not changing the size of the attribute) */
803 if((shared_mesg = H5SM_try_share(f, dxpl_id, oh, 0, H5O_ATTR_ID, attr, NULL)) == 0)
804 HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "attribute changed sharing status")
805 else if(shared_mesg < 0)
806 HGOTO_ERROR(H5E_ATTR, H5E_BADMESG, FAIL, "can't share attribute")
807
808 /* Retrieve shared message storage ref count for new shared attribute */
809 if(H5SM_get_refcount(f, dxpl_id, H5O_ATTR_ID, &attr->sh_loc, &attr_rc) < 0)
810 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve shared message ref count")
811
812 /* If the newly shared attribute needs to share "ownership" of the shared
813 * components (ie. its reference count is 1), increment the reference
814 * count on any shared components of the attribute, so that they won't
815 * be removed from the file by the following "delete" operation on the
816 * original attribute shared message info. (Essentially a "copy on
817 * write" operation).
818 *
819 * *ick* -QAK, 2007/01/08
820 */
821 if(attr_rc == 1) {
822 /* Increment reference count on attribute components */
823 if(H5O_attr_link(f, dxpl_id, oh, attr) < 0)
824 HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
825 } /* end if */
826
827 /* Remove the old attribute from the SOHM storage */
828 if(H5SM_delete(f, dxpl_id, oh, &sh_mesg) < 0)
829 HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute in shared storage")
830
831 /* Extract updated shared message info from modified attribute, if requested */
832 if(update_sh_mesg)
833 if(H5O_set_shared(update_sh_mesg, &(attr->sh_loc)) < 0)
834 HGOTO_ERROR(H5E_ATTR, H5E_CANTCOPY, FAIL, "can't get shared message")
835
836 done:
837 FUNC_LEAVE_NOAPI(ret_value)
838 } /* end H5O_attr_update_shared() */
839
840
841 /*-------------------------------------------------------------------------
842 * Function: H5O_attr_write_cb
843 *
844 * Purpose: Object header iterator callback routine to update an
845 * attribute stored compactly.
846 *
847 * Return: Non-negative on success/Negative on failure
848 *
849 * Programmer: Quincey Koziol
850 * koziol@hdfgroup.org
851 * Dec 4 2006
852 *
853 * Modification:Raymond Lu
854 * 4 June 2008
855 * Took out the data copying part because the attribute data
856 * is shared between attribute handle and object header.
857 *
858 * Modifications:
859 * Vailin Choi; Sept 2011
860 * Indicate that the object header is modified but does not need to
861 * condense messages in the object header
862 *-------------------------------------------------------------------------
863 */
864 static herr_t
H5O_attr_write_cb(H5O_t * oh,H5O_mesg_t * mesg,unsigned UNUSED sequence,unsigned * oh_modified,void * _udata)865 H5O_attr_write_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
866 unsigned UNUSED sequence, unsigned *oh_modified, void *_udata/*in,out*/)
867 {
868 H5O_iter_wrt_t *udata = (H5O_iter_wrt_t *)_udata; /* Operator user data */
869 H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
870 hbool_t chk_dirtied = FALSE; /* Flag for unprotecting chunk */
871 herr_t ret_value = H5_ITER_CONT; /* Return value */
872
873 FUNC_ENTER_NOAPI_NOINIT
874
875 /* check args */
876 HDassert(oh);
877 HDassert(mesg);
878 HDassert(!udata->found);
879
880 /* Check for correct attribute message to modify */
881 if(0 == HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->attr->shared->name)) {
882 /* Protect chunk */
883 if(NULL == (chk_proxy = H5O_chunk_protect(udata->f, udata->dxpl_id, oh, mesg->chunkno)))
884 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to load object header chunk")
885
886 /* Because the attribute structure is shared now. The only situation that requires
887 * copying the data is when the metadata cache evicts and reloads this attribute.
888 * The shared attribute structure will be different in that situation. SLU-2010/7/29 */
889 if(((H5A_t *)mesg->native)->shared != udata->attr->shared) {
890 /* Sanity check */
891 HDassert(((H5A_t *)mesg->native)->shared->data);
892 HDassert(udata->attr->shared->data);
893 HDassert(((H5A_t *)mesg->native)->shared->data != udata->attr->shared->data);
894
895 /* (Needs to occur before updating the shared message, or the hash
896 * value on the old & new messages will be the same) */
897 HDmemcpy(((H5A_t *)mesg->native)->shared->data, udata->attr->shared->data, udata->attr->shared->data_size);
898 } /* end if */
899
900 /* Mark the message as modified */
901 mesg->dirty = TRUE;
902 chk_dirtied = TRUE;
903
904 /* Release chunk */
905 if(H5O_chunk_unprotect(udata->f, udata->dxpl_id, chk_proxy, chk_dirtied) < 0)
906 HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
907 chk_proxy = NULL;
908
909 /* Update the shared attribute in the SOHM storage */
910 if(mesg->flags & H5O_MSG_FLAG_SHARED)
911 if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, udata->attr, (H5O_shared_t *)mesg->native) < 0)
912 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage")
913
914 /* Indicate that the object header was modified */
915 *oh_modified = H5O_MODIFY;
916
917 /* Indicate that the attribute was found */
918 udata->found = TRUE;
919
920 /* Stop iterating */
921 ret_value = H5_ITER_STOP;
922 } /* end if */
923
924 done:
925 /* Release chunk, if not already done */
926 if(chk_proxy && H5O_chunk_unprotect(udata->f, udata->dxpl_id, chk_proxy, chk_dirtied) < 0)
927 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
928
929 FUNC_LEAVE_NOAPI(ret_value)
930 } /* end H5O_attr_write_cb() */
931
932
933 /*-------------------------------------------------------------------------
934 * Function: H5O_attr_write
935 *
936 * Purpose: Write a new value to an attribute.
937 *
938 * Return: Non-negative on success/Negative on failure
939 *
940 * Programmer: Quincey Koziol
941 * Monday, December 4, 2006
942 *
943 *-------------------------------------------------------------------------
944 */
945 herr_t
H5O_attr_write(const H5O_loc_t * loc,hid_t dxpl_id,H5A_t * attr)946 H5O_attr_write(const H5O_loc_t *loc, hid_t dxpl_id, H5A_t *attr)
947 {
948 H5O_t *oh = NULL; /* Pointer to actual object header */
949 H5O_ainfo_t ainfo; /* Attribute information for object */
950 herr_t ret_value = SUCCEED; /* Return value */
951
952 FUNC_ENTER_NOAPI_NOINIT
953
954 /* Check arguments */
955 HDassert(loc);
956 HDassert(attr);
957
958 /* Pin the object header */
959 if(NULL == (oh = H5O_pin(loc, dxpl_id)))
960 HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
961
962 /* Check for attribute info stored */
963 ainfo.fheap_addr = HADDR_UNDEF;
964 if(oh->version > H5O_VERSION_1) {
965 /* Check for (& retrieve if available) attribute info */
966 if(H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo) < 0)
967 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
968 } /* end if */
969
970 /* Check for attributes stored densely */
971 if(H5F_addr_defined(ainfo.fheap_addr)) {
972 /* Modify the attribute data in dense storage */
973 if(H5A_dense_write(loc->file, dxpl_id, &ainfo, attr) < 0)
974 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
975 } /* end if */
976 else {
977 H5O_iter_wrt_t udata; /* User data for callback */
978 H5O_mesg_operator_t op; /* Wrapper for operator */
979
980 /* Set up user data for callback */
981 udata.f = loc->file;
982 udata.dxpl_id = dxpl_id;
983 udata.attr = attr;
984 udata.found = FALSE;
985
986 /* Iterate over attributes, to locate correct one to update */
987 op.op_type = H5O_MESG_OP_LIB;
988 op.u.lib_op = H5O_attr_write_cb;
989 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
990 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
991
992 /* Check that we found the attribute */
993 if(!udata.found)
994 HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate open attribute?")
995 } /* end else */
996
997 /* Update the modification time, if any */
998 if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
999 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
1000
1001 done:
1002 if(oh && H5O_unpin(oh) < 0)
1003 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
1004
1005 FUNC_LEAVE_NOAPI(ret_value)
1006 } /* end H5O_attr_write */
1007
1008
1009 /*-------------------------------------------------------------------------
1010 * Function: H5O_attr_rename_chk_cb
1011 *
1012 * Purpose: Object header iterator callback routine to check for
1013 * duplicate name during rename
1014 *
1015 * Return: Non-negative on success/Negative on failure
1016 *
1017 * Programmer: Quincey Koziol
1018 * koziol@hdfgroup.org
1019 * Dec 5 2006
1020 *
1021 * Modifications:
1022 * Vailin Choi; September 2011
1023 * Change "oh_modified" from boolean to unsigned
1024 * (See H5Oprivate.h for possible flags)
1025 *-------------------------------------------------------------------------
1026 */
1027 static herr_t
H5O_attr_rename_chk_cb(H5O_t UNUSED * oh,H5O_mesg_t * mesg,unsigned UNUSED sequence,unsigned UNUSED * oh_modified,void * _udata)1028 H5O_attr_rename_chk_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
1029 unsigned UNUSED sequence, unsigned UNUSED *oh_modified, void *_udata/*in,out*/)
1030 {
1031 H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
1032 herr_t ret_value = H5_ITER_CONT; /* Return value */
1033
1034 FUNC_ENTER_NOAPI_NOINIT_NOERR
1035
1036 /* check args */
1037 HDassert(oh);
1038 HDassert(mesg);
1039 HDassert(!udata->found);
1040
1041 /* Check for existing attribute with new name */
1042 if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->new_name) == 0) {
1043 /* Indicate that we found an existing attribute with the new name*/
1044 udata->found = TRUE;
1045
1046 /* Stop iterating */
1047 ret_value = H5_ITER_STOP;
1048 } /* end if */
1049
1050 FUNC_LEAVE_NOAPI(ret_value)
1051 } /* end H5O_attr_rename_chk_cb() */
1052
1053
1054 /*-------------------------------------------------------------------------
1055 * Function: H5O_attr_rename_mod_cb
1056 *
1057 * Purpose: Object header iterator callback routine to change name of
1058 * attribute during rename
1059 *
1060 * Note: This routine doesn't currently allow an attribute to change
1061 * its "shared" status, if the name change would cause a size
1062 * difference that would put it into a different category.
1063 * Something for later...
1064 *
1065 * Return: Non-negative on success/Negative on failure
1066 *
1067 * Programmer: Quincey Koziol
1068 * koziol@hdfgroup.org
1069 * Dec 5 2006
1070 *
1071 * Modifications:
1072 * Vailin Choi; Sept 2011
1073 * Indicate that the object header is modified and might possibly need
1074 * to condense messages in the object header
1075 *-------------------------------------------------------------------------
1076 */
1077 static herr_t
H5O_attr_rename_mod_cb(H5O_t * oh,H5O_mesg_t * mesg,unsigned UNUSED sequence,unsigned * oh_modified,void * _udata)1078 H5O_attr_rename_mod_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
1079 unsigned UNUSED sequence, unsigned *oh_modified, void *_udata/*in,out*/)
1080 {
1081 H5O_iter_ren_t *udata = (H5O_iter_ren_t *)_udata; /* Operator user data */
1082 H5O_chunk_proxy_t *chk_proxy = NULL; /* Chunk that message is in */
1083 hbool_t chk_dirtied = FALSE; /* Flag for unprotecting chunk */
1084 herr_t ret_value = H5_ITER_CONT; /* Return value */
1085
1086 FUNC_ENTER_NOAPI_NOINIT
1087
1088 /* check args */
1089 HDassert(oh);
1090 HDassert(mesg);
1091 HDassert(!udata->found);
1092
1093 /* Find correct attribute message to rename */
1094 if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->old_name) == 0) {
1095 unsigned old_version = ((H5A_t *)mesg->native)->shared->version; /* Old version of the attribute */
1096
1097 /* Protect chunk */
1098 if(NULL == (chk_proxy = H5O_chunk_protect(udata->f, udata->dxpl_id, oh, mesg->chunkno)))
1099 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, H5_ITER_ERROR, "unable to load object header chunk")
1100
1101 /* Change the name for the attribute */
1102 H5MM_xfree(((H5A_t *)mesg->native)->shared->name);
1103 ((H5A_t *)mesg->native)->shared->name = H5MM_xstrdup(udata->new_name);
1104
1105 /* Recompute the version to encode the attribute with */
1106 if(H5A_set_version(udata->f, ((H5A_t *)mesg->native)) < 0)
1107 HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, H5_ITER_ERROR, "unable to update attribute version")
1108
1109 /* Mark the message as modified */
1110 mesg->dirty = TRUE;
1111 chk_dirtied = TRUE;
1112
1113 /* Release chunk */
1114 if(H5O_chunk_unprotect(udata->f, udata->dxpl_id, chk_proxy, chk_dirtied) < 0)
1115 HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
1116 chk_proxy = NULL;
1117
1118 /* Check for shared message */
1119 if(mesg->flags & H5O_MSG_FLAG_SHARED) {
1120 /* Update the shared attribute in the SOHM storage */
1121 if(H5O_attr_update_shared(udata->f, udata->dxpl_id, oh, (H5A_t *)mesg->native, NULL) < 0)
1122 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, H5_ITER_ERROR, "unable to update attribute in shared storage")
1123 } /* end if */
1124 else {
1125 /* Sanity check */
1126 HDassert(H5O_msg_is_shared(H5O_ATTR_ID, (H5A_t *)mesg->native) == FALSE);
1127
1128 /* Check for attribute message changing size */
1129 if(HDstrlen(udata->new_name) != HDstrlen(udata->old_name) ||
1130 old_version != ((H5A_t *)mesg->native)->shared->version) {
1131 H5A_t *attr; /* Attribute to re-add */
1132
1133 /* Take ownership of the message's native info (the attribute)
1134 * so any shared objects in the file aren't adjusted (and
1135 * possibly deleted) when the message is released.
1136 */
1137 /* (We do this more complicated sequence of actions because the
1138 * simpler solution of adding the modified attribute first
1139 * and then deleting the old message can re-allocate the
1140 * list of messages during the "add the modified attribute"
1141 * step, invalidating the message pointer we have here - QAK)
1142 */
1143 attr = (H5A_t *)mesg->native;
1144 mesg->native = NULL;
1145
1146 /* Delete old attribute */
1147 /* (doesn't decrement the link count on shared components becuase
1148 * the "native" pointer has been reset)
1149 */
1150 if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, FALSE) < 0)
1151 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to release previous attribute")
1152
1153 *oh_modified = H5O_MODIFY_CONDENSE;
1154
1155 /* Append renamed attribute to object header */
1156 /* (Don't let it become shared) */
1157 if(H5O_msg_append_real(udata->f, udata->dxpl_id, oh, H5O_MSG_ATTR, (mesg->flags | H5O_MSG_FLAG_DONTSHARE), 0, attr) < 0)
1158 HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, H5_ITER_ERROR, "unable to relocate renamed attribute in header")
1159
1160 /* Sanity check */
1161 HDassert(H5O_msg_is_shared(H5O_ATTR_ID, attr) == FALSE);
1162
1163 /* Close the local copy of the attribute */
1164 H5A_close(attr);
1165 } /* end if */
1166 } /* end else */
1167
1168 /* Indicate that the object header was modified */
1169 *oh_modified |= H5O_MODIFY;
1170
1171 /* Indicate that we found an existing attribute with the old name */
1172 udata->found = TRUE;
1173
1174 /* Stop iterating */
1175 ret_value = H5_ITER_STOP;
1176 } /* end if */
1177
1178 done:
1179 /* Release chunk, if not already done */
1180 if(chk_proxy && H5O_chunk_unprotect(udata->f, udata->dxpl_id, chk_proxy, chk_dirtied) < 0)
1181 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, H5_ITER_ERROR, "unable to unprotect object header chunk")
1182
1183 FUNC_LEAVE_NOAPI(ret_value)
1184 } /* end H5O_attr_rename_mod_cb() */
1185
1186
1187 /*-------------------------------------------------------------------------
1188 * Function: H5O_attr_rename
1189 *
1190 * Purpose: Rename an attribute.
1191 *
1192 * Return: Non-negative on success/Negative on failure
1193 *
1194 * Programmer: Quincey Koziol
1195 * Tuesday, December 5, 2006
1196 *
1197 *-------------------------------------------------------------------------
1198 */
1199 herr_t
H5O_attr_rename(const H5O_loc_t * loc,hid_t dxpl_id,const char * old_name,const char * new_name)1200 H5O_attr_rename(const H5O_loc_t *loc, hid_t dxpl_id, const char *old_name,
1201 const char *new_name)
1202 {
1203 H5O_t *oh = NULL; /* Pointer to actual object header */
1204 H5O_ainfo_t ainfo; /* Attribute information for object */
1205 herr_t ret_value = SUCCEED; /* Return value */
1206
1207 FUNC_ENTER_NOAPI_NOINIT
1208
1209 /* Check arguments */
1210 HDassert(loc);
1211 HDassert(old_name);
1212 HDassert(new_name);
1213
1214 /* Pin the object header */
1215 if(NULL == (oh = H5O_pin(loc, dxpl_id)))
1216 HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
1217
1218 /* Check for attribute info stored */
1219 ainfo.fheap_addr = HADDR_UNDEF;
1220 if(oh->version > H5O_VERSION_1) {
1221 /* Check for (& retrieve if available) attribute info */
1222 if(H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo) < 0)
1223 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1224 } /* end if */
1225
1226 /* Check for attributes stored densely */
1227 if(H5F_addr_defined(ainfo.fheap_addr)) {
1228 /* Rename the attribute data in dense storage */
1229 if(H5A_dense_rename(loc->file, dxpl_id, &ainfo, old_name, new_name) < 0)
1230 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
1231 } /* end if */
1232 else {
1233 H5O_iter_ren_t udata; /* User data for callback */
1234 H5O_mesg_operator_t op; /* Wrapper for operator */
1235
1236 /* Set up user data for callback */
1237 udata.f = loc->file;
1238 udata.dxpl_id = dxpl_id;
1239 udata.old_name = old_name;
1240 udata.new_name = new_name;
1241 udata.found = FALSE;
1242
1243 /* Iterate over attributes, to check if "new name" exists already */
1244 op.op_type = H5O_MESG_OP_LIB;
1245 op.u.lib_op = H5O_attr_rename_chk_cb;
1246 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
1247 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
1248
1249 /* If the new name was found, indicate an error */
1250 if(udata.found)
1251 HGOTO_ERROR(H5E_ATTR, H5E_EXISTS, FAIL, "attribute with new name already exists")
1252
1253 /* Iterate over attributes again, to actually rename attribute with old name */
1254 op.op_type = H5O_MESG_OP_LIB;
1255 op.u.lib_op = H5O_attr_rename_mod_cb;
1256 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
1257 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "error updating attribute")
1258
1259 /* Check that we found the attribute to rename */
1260 if(!udata.found)
1261 HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute with old name")
1262 } /* end else */
1263
1264 /* Update the modification time, if any */
1265 if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
1266 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
1267
1268 done:
1269 if(oh && H5O_unpin(oh) < 0)
1270 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
1271
1272 FUNC_LEAVE_NOAPI(ret_value)
1273 } /* end H5O_attr_rename */
1274
1275
1276 /*-------------------------------------------------------------------------
1277 * Function: H5O_attr_iterate_real
1278 *
1279 * Purpose: Internal routine to iterate over attributes for an object.
1280 *
1281 * Return: Non-negative on success/Negative on failure
1282 *
1283 * Programmer: Quincey Koziol
1284 * Tuesday, December 5, 2006
1285 *
1286 *-------------------------------------------------------------------------
1287 */
1288 herr_t
H5O_attr_iterate_real(hid_t loc_id,const H5O_loc_t * loc,hid_t dxpl_id,H5_index_t idx_type,H5_iter_order_t order,hsize_t skip,hsize_t * last_attr,const H5A_attr_iter_op_t * attr_op,void * op_data)1289 H5O_attr_iterate_real(hid_t loc_id, const H5O_loc_t *loc, hid_t dxpl_id,
1290 H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
1291 hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data)
1292 {
1293 H5O_t *oh = NULL; /* Pointer to actual object header */
1294 H5O_ainfo_t ainfo; /* Attribute information for object */
1295 H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
1296 herr_t ret_value; /* Return value */
1297
1298 FUNC_ENTER_NOAPI_NOINIT
1299
1300 /* Check arguments */
1301 HDassert(loc);
1302 HDassert(loc->file);
1303 HDassert(H5F_addr_defined(loc->addr));
1304 HDassert(attr_op);
1305
1306 /* Protect the object header to iterate over */
1307 if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
1308 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
1309
1310 /* Check for attribute info stored */
1311 ainfo.fheap_addr = HADDR_UNDEF;
1312 if(oh->version > H5O_VERSION_1) {
1313 /* Check for (& retrieve if available) attribute info */
1314 if(H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo) < 0)
1315 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1316 } /* end if */
1317
1318 /* Check for attributes stored densely */
1319 if(H5F_addr_defined(ainfo.fheap_addr)) {
1320 /* Check for skipping too many attributes */
1321 if(skip > 0 && skip >= ainfo.nattrs)
1322 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
1323
1324 /* Release the object header */
1325 if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
1326 HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
1327 oh = NULL;
1328
1329 /* Iterate over attributes in dense storage */
1330 if((ret_value = H5A_dense_iterate(loc->file, dxpl_id, loc_id, &ainfo, idx_type, order, skip, last_attr, attr_op, op_data)) < 0)
1331 HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
1332 } /* end if */
1333 else {
1334 /* Build table of attributes for compact storage */
1335 if(H5A_compact_build_table(loc->file, dxpl_id, oh, idx_type, order, &atable) < 0)
1336 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
1337
1338 /* Release the object header */
1339 if(H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
1340 HGOTO_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
1341 oh = NULL;
1342
1343 /* Check for skipping too many attributes */
1344 if(skip > 0 && skip >= atable.nattrs)
1345 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
1346
1347 /* Iterate over attributes in table */
1348 if((ret_value = H5A_attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0)
1349 HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
1350 } /* end else */
1351
1352 done:
1353 /* Release resources */
1354 if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
1355 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
1356 if(atable.attrs && H5A_attr_release_table(&atable) < 0)
1357 HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
1358
1359 FUNC_LEAVE_NOAPI(ret_value)
1360 } /* end H5O_attr_iterate_real() */
1361
1362
1363 /*-------------------------------------------------------------------------
1364 * Function: H5O_attr_iterate
1365 *
1366 * Purpose: Iterate over attributes for an object.
1367 *
1368 * Return: Non-negative on success/Negative on failure
1369 *
1370 * Programmer: Quincey Koziol
1371 * Tuesday, December 5, 2006
1372 *
1373 *-------------------------------------------------------------------------
1374 */
1375 herr_t
H5O_attr_iterate(hid_t loc_id,hid_t dxpl_id,H5_index_t idx_type,H5_iter_order_t order,hsize_t skip,hsize_t * last_attr,const H5A_attr_iter_op_t * attr_op,void * op_data)1376 H5O_attr_iterate(hid_t loc_id, hid_t dxpl_id,
1377 H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
1378 hsize_t *last_attr, const H5A_attr_iter_op_t *attr_op, void *op_data)
1379 {
1380 H5G_loc_t loc; /* Object location */
1381 herr_t ret_value; /* Return value */
1382
1383 FUNC_ENTER_NOAPI_NOINIT
1384
1385 /* Check arguments */
1386 HDassert(attr_op);
1387
1388 /* Look up location for location ID */
1389 if(H5G_loc(loc_id, &loc) < 0)
1390 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
1391
1392 /* Iterate over attributes to locate correct one */
1393 if((ret_value = H5O_attr_iterate_real(loc_id, loc.oloc, dxpl_id, idx_type, order, skip, last_attr, attr_op, op_data)) < 0)
1394 HERROR(H5E_ATTR, H5E_BADITER, "error iterating over attributes");
1395
1396 done:
1397 FUNC_LEAVE_NOAPI(ret_value)
1398 } /* end H5O_attr_iterate() */
1399
1400
1401 /*-------------------------------------------------------------------------
1402 * Function: H5O_attr_remove_update
1403 *
1404 * Purpose: Check for reverting from dense to compact attribute storage
1405 *
1406 * Return: Non-negative on success/Negative on failure
1407 *
1408 * Programmer: Quincey Koziol
1409 * Wednesday, February 14, 2007
1410 *
1411 * Modification:Raymond Lu
1412 * 24 June 2008
1413 * When converting storage from dense to compact, if found
1414 * the attribute is already opened, use the opened message
1415 * to insert. If not, still use the message in the attribute
1416 * table. This will guarantee that the attribute message is
1417 * shared between the object in metadata cache and the opened
1418 * object.
1419 *-------------------------------------------------------------------------
1420 */
1421 static herr_t
H5O_attr_remove_update(const H5O_loc_t * loc,H5O_t * oh,H5O_ainfo_t * ainfo,hid_t dxpl_id)1422 H5O_attr_remove_update(const H5O_loc_t *loc, H5O_t *oh, H5O_ainfo_t *ainfo,
1423 hid_t dxpl_id)
1424 {
1425 H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
1426 herr_t ret_value = SUCCEED; /* Return value */
1427
1428 FUNC_ENTER_NOAPI_NOINIT
1429
1430 /* Check arguments */
1431 HDassert(loc);
1432 HDassert(oh);
1433 HDassert(ainfo);
1434
1435 /* Decrement the number of attributes on the object */
1436 ainfo->nattrs--;
1437
1438 /* Check for shifting from dense storage back to compact storage */
1439 if(H5F_addr_defined(ainfo->fheap_addr) && ainfo->nattrs < oh->min_dense) {
1440 hbool_t can_convert = TRUE; /* Whether converting to attribute messages is possible */
1441 size_t u; /* Local index */
1442
1443 /* Build the table of attributes for this object */
1444 if(H5A_dense_build_table(loc->file, dxpl_id, ainfo, H5_INDEX_NAME, H5_ITER_NATIVE, &atable) < 0)
1445 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
1446
1447 /* Inspect attributes in table for ones that can't be converted back
1448 * into attribute message form (currently only attributes which
1449 * can't fit into an object header message)
1450 */
1451 for(u = 0; u < ainfo->nattrs; u++)
1452 if(H5O_msg_size_oh(loc->file, oh, H5O_ATTR_ID, (atable.attrs[u]), (size_t)0) >= H5O_MESG_MAX_SIZE) {
1453 can_convert = FALSE;
1454 break;
1455 } /* end if */
1456
1457 /* If ok, insert attributes as object header messages */
1458 if(can_convert) {
1459 H5A_t *exist_attr = NULL;
1460 htri_t found_open_attr = FALSE;
1461
1462 /* Iterate over attributes, to put them into header */
1463 for(u = 0; u < ainfo->nattrs; u++) {
1464 htri_t shared_mesg; /* Should this message be stored in the Shared Message table? */
1465
1466 /* Check if attribute is shared */
1467 if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, (atable.attrs[u]))) < 0)
1468 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
1469 else if(shared_mesg == 0) {
1470 /* Increment reference count on attribute components */
1471 /* (so that they aren't deleted when the dense attribute storage is deleted) */
1472 if(H5O_attr_link(loc->file, dxpl_id, oh, (atable.attrs[u])) < 0)
1473 HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
1474 } /* end if */
1475 else {
1476 /* Reset 'shared' status, so attribute will be shared again */
1477 (atable.attrs[u])->sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
1478 } /* end else */
1479
1480 /* Insert attribute message into object header (Will increment
1481 reference count on shared attributes) */
1482 /* Find out whether the attribute has been opened */
1483 if((found_open_attr = H5O_attr_find_opened_attr(loc, &exist_attr, (atable.attrs[u])->shared->name)) < 0)
1484 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "failed in finding opened attribute")
1485
1486 /* If found the attribute is already opened, use the opened message to insert.
1487 If not, still use the message in the attribute table. */
1488 if(found_open_attr && exist_attr) {
1489 if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, exist_attr) < 0)
1490 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
1491
1492 } else {
1493 if(H5O_msg_append_real(loc->file, dxpl_id, oh, H5O_MSG_ATTR, 0, 0, (atable.attrs[u])) < 0)
1494 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't create message")
1495 }
1496 } /* end for */
1497
1498 /* Remove the dense storage */
1499 if(H5A_dense_delete(loc->file, dxpl_id, ainfo) < 0)
1500 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete dense attribute storage")
1501 } /* end if */
1502 } /* end if */
1503
1504 /* Check if we have deleted all the attributes and the attribute info
1505 * message should be deleted itself.
1506 */
1507 if(ainfo->nattrs == 0) {
1508 if(H5O_msg_remove_real(loc->file, oh, H5O_MSG_AINFO, H5O_ALL, NULL, NULL, TRUE, dxpl_id) < 0)
1509 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute info")
1510 } /* end if */
1511 else {
1512 if(H5O_msg_write_real(loc->file, dxpl_id, oh, H5O_MSG_AINFO, H5O_MSG_FLAG_DONTSHARE, 0, ainfo) < 0)
1513 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info message")
1514 } /* end else */
1515
1516 done:
1517 /* Release resources */
1518 if(atable.attrs && H5A_attr_release_table(&atable) < 0)
1519 HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
1520
1521 FUNC_LEAVE_NOAPI(ret_value)
1522 } /* end H5O_attr_remove_update() */
1523
1524
1525 /*-------------------------------------------------------------------------
1526 * Function: H5O_attr_remove_cb
1527 *
1528 * Purpose: Object header iterator callback routine to remove an
1529 * attribute stored compactly.
1530 *
1531 * Return: Non-negative on success/Negative on failure
1532 *
1533 * Programmer: Quincey Koziol
1534 * koziol@hdfgroup.org
1535 * Dec 11 2006
1536 *
1537 * Modifications:
1538 * Vailin Choi; Sept 2011
1539 * Indicate that the object header is modified and might possibly need
1540 * to condense messages in the object header
1541 *-------------------------------------------------------------------------
1542 */
1543 static herr_t
H5O_attr_remove_cb(H5O_t * oh,H5O_mesg_t * mesg,unsigned UNUSED sequence,unsigned * oh_modified,void * _udata)1544 H5O_attr_remove_cb(H5O_t *oh, H5O_mesg_t *mesg/*in,out*/,
1545 unsigned UNUSED sequence, unsigned *oh_modified, void *_udata/*in,out*/)
1546 {
1547 H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata; /* Operator user data */
1548 herr_t ret_value = H5_ITER_CONT; /* Return value */
1549
1550 FUNC_ENTER_NOAPI_NOINIT
1551
1552 /* check args */
1553 HDassert(oh);
1554 HDassert(mesg);
1555 HDassert(!udata->found);
1556
1557 /* Check for correct attribute message to modify */
1558 if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
1559 /* Convert message into a null message (i.e. delete it) */
1560 if(H5O_release_mesg(udata->f, udata->dxpl_id, oh, mesg, TRUE) < 0)
1561 HGOTO_ERROR(H5E_OHDR, H5E_CANTDELETE, H5_ITER_ERROR, "unable to convert into null message")
1562
1563 /* Indicate that the object header was modified */
1564 *oh_modified = H5O_MODIFY_CONDENSE;
1565
1566 /* Indicate that this message is the attribute to be deleted */
1567 udata->found = TRUE;
1568
1569 /* Stop iterating */
1570 ret_value = H5_ITER_STOP;
1571 } /* end if */
1572
1573 done:
1574 FUNC_LEAVE_NOAPI(ret_value)
1575 } /* end H5O_attr_remove_cb() */
1576
1577
1578 /*-------------------------------------------------------------------------
1579 * Function: H5O_attr_remove
1580 *
1581 * Purpose: Delete an attribute on an object.
1582 *
1583 * Return: Non-negative on success/Negative on failure
1584 *
1585 * Programmer: Quincey Koziol
1586 * Monday, December 11, 2006
1587 *
1588 *-------------------------------------------------------------------------
1589 */
1590 herr_t
H5O_attr_remove(const H5O_loc_t * loc,const char * name,hid_t dxpl_id)1591 H5O_attr_remove(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
1592 {
1593 H5O_t *oh = NULL; /* Pointer to actual object header */
1594 H5O_ainfo_t ainfo; /* Attribute information for object */
1595 htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */
1596 herr_t ret_value = SUCCEED; /* Return value */
1597
1598 FUNC_ENTER_NOAPI_NOINIT
1599
1600 /* Check arguments */
1601 HDassert(loc);
1602 HDassert(name);
1603
1604 /* Pin the object header */
1605 if(NULL == (oh = H5O_pin(loc, dxpl_id)))
1606 HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
1607
1608 /* Check for attribute info stored */
1609 ainfo.fheap_addr = HADDR_UNDEF;
1610 if(oh->version > H5O_VERSION_1) {
1611 /* Check for (& retrieve if available) attribute info */
1612 if((ainfo_exists = H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo)) < 0)
1613 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1614 } /* end if */
1615
1616 /* Check for attributes stored densely */
1617 if(H5F_addr_defined(ainfo.fheap_addr)) {
1618 /* Delete attribute from dense storage */
1619 if(H5A_dense_remove(loc->file, dxpl_id, &ainfo, name) < 0)
1620 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
1621 } /* end if */
1622 else {
1623 H5O_iter_rm_t udata; /* User data for callback */
1624 H5O_mesg_operator_t op; /* Wrapper for operator */
1625
1626 /* Set up user data for callback */
1627 udata.f = loc->file;
1628 udata.dxpl_id = dxpl_id;
1629 udata.name = name;
1630 udata.found = FALSE;
1631
1632 /* Iterate over attributes, to locate correct one to delete */
1633 op.op_type = H5O_MESG_OP_LIB;
1634 op.u.lib_op = H5O_attr_remove_cb;
1635 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
1636 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "error deleting attribute")
1637
1638 /* Check that we found the attribute */
1639 if(!udata.found)
1640 HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute")
1641 } /* end else */
1642
1643 /* Update the attribute information after removing an attribute */
1644 if(ainfo_exists)
1645 if(H5O_attr_remove_update(loc, oh, &ainfo, dxpl_id) < 0)
1646 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
1647
1648 /* Update the modification time, if any */
1649 if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
1650 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
1651
1652 done:
1653 if(oh && H5O_unpin(oh) < 0)
1654 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
1655
1656 FUNC_LEAVE_NOAPI(ret_value)
1657 } /* end H5O_attr_remove() */
1658
1659
1660 /*-------------------------------------------------------------------------
1661 * Function: H5O_attr_remove_by_idx
1662 *
1663 * Purpose: Delete an attribute on an object, according to an order within
1664 * an index.
1665 *
1666 * Return: Non-negative on success/Negative on failure
1667 *
1668 * Programmer: Quincey Koziol
1669 * Wednesday, February 14, 2007
1670 *
1671 *-------------------------------------------------------------------------
1672 */
1673 herr_t
H5O_attr_remove_by_idx(const H5O_loc_t * loc,H5_index_t idx_type,H5_iter_order_t order,hsize_t n,hid_t dxpl_id)1674 H5O_attr_remove_by_idx(const H5O_loc_t *loc, H5_index_t idx_type,
1675 H5_iter_order_t order, hsize_t n, hid_t dxpl_id)
1676 {
1677 H5O_t *oh = NULL; /* Pointer to actual object header */
1678 H5O_ainfo_t ainfo; /* Attribute information for object */
1679 htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */
1680 H5A_attr_table_t atable = {0, NULL}; /* Table of attributes */
1681 herr_t ret_value = SUCCEED; /* Return value */
1682
1683 FUNC_ENTER_NOAPI_NOINIT
1684
1685 /* Check arguments */
1686 HDassert(loc);
1687
1688 /* Pin the object header */
1689 if(NULL == (oh = H5O_pin(loc, dxpl_id)))
1690 HGOTO_ERROR(H5E_ATTR, H5E_CANTPIN, FAIL, "unable to pin object header")
1691
1692 /* Check for attribute info stored */
1693 ainfo.fheap_addr = HADDR_UNDEF;
1694 if(oh->version > H5O_VERSION_1) {
1695 /* Check for (& retrieve if available) attribute info */
1696 if((ainfo_exists = H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo)) < 0)
1697 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1698 } /* end if */
1699
1700 /* Check for attributes stored densely */
1701 if(H5F_addr_defined(ainfo.fheap_addr)) {
1702 /* Delete attribute from dense storage */
1703 if(H5A_dense_remove_by_idx(loc->file, dxpl_id, &ainfo, idx_type, order, n) < 0)
1704 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
1705 } /* end if */
1706 else {
1707 H5O_iter_rm_t udata; /* User data for callback */
1708 H5O_mesg_operator_t op; /* Wrapper for operator */
1709
1710 /* Build table of attributes for compact storage */
1711 if(H5A_compact_build_table(loc->file, dxpl_id, oh, idx_type, order, &atable) < 0)
1712 HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "error building attribute table")
1713
1714 /* Check for skipping too many attributes */
1715 if(n >= atable.nattrs)
1716 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
1717
1718 /* Set up user data for callback, to remove the attribute by name */
1719 udata.f = loc->file;
1720 udata.dxpl_id = dxpl_id;
1721 udata.name = ((atable.attrs[n])->shared)->name;
1722 udata.found = FALSE;
1723
1724 /* Iterate over attributes, to locate correct one to delete */
1725 op.op_type = H5O_MESG_OP_LIB;
1726 op.u.lib_op = H5O_attr_remove_cb;
1727 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
1728 HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "error deleting attribute")
1729
1730 /* Check that we found the attribute */
1731 if(!udata.found)
1732 HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute")
1733 } /* end else */
1734
1735 /* Update the attribute information after removing an attribute */
1736 if(ainfo_exists)
1737 if(H5O_attr_remove_update(loc, oh, &ainfo, dxpl_id) < 0)
1738 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute info")
1739
1740 /* Update the modification time, if any */
1741 if(H5O_touch_oh(loc->file, dxpl_id, oh, FALSE) < 0)
1742 HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update time on object")
1743
1744 done:
1745 if(oh && H5O_unpin(oh) < 0)
1746 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPIN, FAIL, "unable to unpin object header")
1747 if(atable.attrs && H5A_attr_release_table(&atable) < 0)
1748 HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
1749
1750 FUNC_LEAVE_NOAPI(ret_value)
1751 } /* end H5O_attr_remove_by_idx() */
1752
1753
1754 /*-------------------------------------------------------------------------
1755 * Function: H5O_attr_count_real
1756 *
1757 * Purpose: Determine the # of attributes on an object
1758 *
1759 * Return: Non-negative on success/Negative on failure
1760 *
1761 * Programmer: Quincey Koziol
1762 * Thursday, March 9, 2007
1763 *
1764 *-------------------------------------------------------------------------
1765 */
1766 herr_t
H5O_attr_count_real(H5F_t * f,hid_t dxpl_id,H5O_t * oh,hsize_t * nattrs)1767 H5O_attr_count_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, hsize_t *nattrs)
1768 {
1769 herr_t ret_value = SUCCEED; /* Return value */
1770
1771 FUNC_ENTER_NOAPI_NOINIT
1772
1773 /* Check arguments */
1774 HDassert(f);
1775 HDassert(oh);
1776 HDassert(nattrs);
1777
1778 /* Check for attributes stored densely */
1779 if(oh->version > H5O_VERSION_1) {
1780 htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */
1781 H5O_ainfo_t ainfo; /* Attribute information for object */
1782
1783 /* Attempt to get the attribute information from the object header */
1784 if((ainfo_exists = H5A_get_ainfo(f, dxpl_id, oh, &ainfo)) < 0)
1785 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1786 else if(ainfo_exists > 0)
1787 *nattrs = ainfo.nattrs;
1788 else
1789 *nattrs = 0;
1790 } /* end if */
1791 else {
1792 hsize_t attr_count; /* Number of attributes found */
1793 unsigned u; /* Local index variable */
1794
1795 /* Loop over all messages, counting the attributes */
1796 attr_count = 0;
1797 for(u = 0; u < oh->nmesgs; u++)
1798 if(oh->mesg[u].type == H5O_MSG_ATTR)
1799 attr_count++;
1800 *nattrs = attr_count;
1801 } /* end else */
1802
1803 done:
1804 FUNC_LEAVE_NOAPI(ret_value)
1805 } /* end H5O_attr_count_real */
1806
1807
1808 /*-------------------------------------------------------------------------
1809 * Function: H5O_attr_exists_cb
1810 *
1811 * Purpose: Object header iterator callback routine to check for an
1812 * attribute stored compactly, by name.
1813 *
1814 * Return: Non-negative on success/Negative on failure
1815 *
1816 * Programmer: Quincey Koziol
1817 * koziol@hdfgroup.org
1818 * Dec 11 2006
1819 *
1820 * Modifications:
1821 * Vailin Choi; September 2011
1822 * Change "oh_modified" from boolean to unsigned
1823 * (See H5Oprivate.h for possible flags)
1824 *-------------------------------------------------------------------------
1825 */
1826 static herr_t
H5O_attr_exists_cb(H5O_t UNUSED * oh,H5O_mesg_t * mesg,unsigned UNUSED sequence,unsigned UNUSED * oh_modified,void * _udata)1827 H5O_attr_exists_cb(H5O_t UNUSED *oh, H5O_mesg_t *mesg/*in,out*/,
1828 unsigned UNUSED sequence, unsigned UNUSED *oh_modified, void *_udata/*in,out*/)
1829 {
1830 H5O_iter_rm_t *udata = (H5O_iter_rm_t *)_udata; /* Operator user data */
1831 herr_t ret_value = H5_ITER_CONT; /* Return value */
1832
1833 FUNC_ENTER_NOAPI_NOINIT_NOERR
1834
1835 /* check args */
1836 HDassert(mesg);
1837 HDassert(!udata->found);
1838
1839 /* Check for correct attribute message */
1840 if(HDstrcmp(((H5A_t *)mesg->native)->shared->name, udata->name) == 0) {
1841 /* Indicate that this message is the attribute sought */
1842 udata->found = TRUE;
1843
1844 /* Stop iterating */
1845 ret_value = H5_ITER_STOP;
1846 } /* end if */
1847
1848 FUNC_LEAVE_NOAPI(ret_value)
1849 } /* end H5O_attr_exists_cb() */
1850
1851
1852 /*-------------------------------------------------------------------------
1853 * Function: H5O_attr_exists
1854 *
1855 * Purpose: Determine if an attribute with a particular name exists on an object
1856 *
1857 * Return: Non-negative on success/Negative on failure
1858 *
1859 * Programmer: Quincey Koziol
1860 * Monday, December 11, 2006
1861 *
1862 *-------------------------------------------------------------------------
1863 */
1864 htri_t
H5O_attr_exists(const H5O_loc_t * loc,const char * name,hid_t dxpl_id)1865 H5O_attr_exists(const H5O_loc_t *loc, const char *name, hid_t dxpl_id)
1866 {
1867 H5O_t *oh = NULL; /* Pointer to actual object header */
1868 H5O_ainfo_t ainfo; /* Attribute information for object */
1869 htri_t ret_value; /* Return value */
1870
1871 FUNC_ENTER_NOAPI_NOINIT
1872
1873 /* Check arguments */
1874 HDassert(loc);
1875 HDassert(name);
1876
1877 /* Protect the object header to iterate over */
1878 if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
1879 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
1880
1881 /* Check for attribute info stored */
1882 ainfo.fheap_addr = HADDR_UNDEF;
1883 if(oh->version > H5O_VERSION_1) {
1884 /* Check for (& retrieve if available) attribute info */
1885 if(H5A_get_ainfo(loc->file, dxpl_id, oh, &ainfo) < 0)
1886 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1887 } /* end if */
1888
1889 /* Check for attributes stored densely */
1890 if(H5F_addr_defined(ainfo.fheap_addr)) {
1891 /* Check if attribute exists in dense storage */
1892 if((ret_value = H5A_dense_exists(loc->file, dxpl_id, &ainfo, name)) < 0)
1893 HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute")
1894 } /* end if */
1895 else {
1896 H5O_iter_rm_t udata; /* User data for callback */
1897 H5O_mesg_operator_t op; /* Wrapper for operator */
1898
1899 /* Set up user data for callback */
1900 udata.f = loc->file;
1901 udata.dxpl_id = dxpl_id;
1902 udata.name = name;
1903 udata.found = FALSE;
1904
1905 /* Iterate over existing attributes, checking for attribute with same name */
1906 op.op_type = H5O_MESG_OP_LIB;
1907 op.u.lib_op = H5O_attr_exists_cb;
1908 if(H5O_msg_iterate_real(loc->file, oh, H5O_MSG_ATTR, &op, &udata, dxpl_id) < 0)
1909 HGOTO_ERROR(H5E_ATTR, H5E_BADITER, FAIL, "error checking for existence of attribute")
1910
1911 /* Check that we found the attribute */
1912 ret_value = (htri_t)udata.found;
1913 } /* end else */
1914
1915 done:
1916 if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
1917 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
1918
1919 FUNC_LEAVE_NOAPI(ret_value)
1920 } /* end H5O_attr_exists */
1921
1922
1923 /*-------------------------------------------------------------------------
1924 * Function: H5O_attr_bh_info
1925 *
1926 * Purpose: For 1.8 attribute, returns storage amount for btree and fractal heap
1927 *
1928 * Return: Non-negative on success/Negative on failure
1929 *
1930 * Programmer: Vailin Choi
1931 * June 19, 2007
1932 *
1933 *-------------------------------------------------------------------------
1934 */
1935 herr_t
H5O_attr_bh_info(H5F_t * f,hid_t dxpl_id,H5O_t * oh,H5_ih_info_t * bh_info)1936 H5O_attr_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
1937 {
1938 H5HF_t *fheap = NULL; /* Fractal heap handle */
1939 H5B2_t *bt2_name = NULL; /* v2 B-tree handle for name index */
1940 H5B2_t *bt2_corder = NULL; /* v2 B-tree handle for creation order index */
1941 herr_t ret_value = SUCCEED; /* Return value */
1942
1943 FUNC_ENTER_NOAPI(FAIL)
1944
1945 HDassert(f);
1946 HDassert(oh);
1947 HDassert(bh_info);
1948
1949 /* Attributes are only stored in fractal heap & indexed w/v2 B-tree in later versions */
1950 if(oh->version > H5O_VERSION_1) {
1951 H5O_ainfo_t ainfo; /* Attribute information for object */
1952 htri_t ainfo_exists = FALSE; /* Whether the attribute info exists in the file */
1953
1954 /* Check for (& retrieve if available) attribute info */
1955 if((ainfo_exists = H5A_get_ainfo(f, dxpl_id, oh, &ainfo)) < 0)
1956 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't check for attribute info message")
1957 else if(ainfo_exists > 0) {
1958 /* Check if name index available */
1959 if(H5F_addr_defined(ainfo.name_bt2_addr)) {
1960 /* Open the name index v2 B-tree */
1961 if(NULL == (bt2_name = H5B2_open(f, dxpl_id, ainfo.name_bt2_addr, NULL)))
1962 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
1963
1964 /* Get name index B-tree size */
1965 if(H5B2_size(bt2_name, dxpl_id, &(bh_info->index_size)) < 0)
1966 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve B-tree storage info")
1967 } /* end if */
1968
1969 /* Check if creation order index available */
1970 if(H5F_addr_defined(ainfo.corder_bt2_addr)) {
1971 /* Open the creation order index v2 B-tree */
1972 if(NULL == (bt2_corder = H5B2_open(f, dxpl_id, ainfo.corder_bt2_addr, NULL)))
1973 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
1974
1975 /* Get creation order index B-tree size */
1976 if(H5B2_size(bt2_corder, dxpl_id, &(bh_info->index_size)) < 0)
1977 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve B-tree storage info")
1978 } /* end if */
1979
1980 /* Get storage size of fractal heap, if it's used */
1981 if(H5F_addr_defined(ainfo.fheap_addr)) {
1982 /* Open the fractal heap for attributes */
1983 if(NULL == (fheap = H5HF_open(f, dxpl_id, ainfo.fheap_addr)))
1984 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1985
1986 /* Get heap storage size */
1987 if(H5HF_size(fheap, dxpl_id, &(bh_info->heap_size)) < 0)
1988 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve B-tree storage info")
1989 } /* end if */
1990 } /* end else */
1991 } /* end if */
1992
1993 done:
1994 /* Release resources */
1995 if(fheap && H5HF_close(fheap, dxpl_id) < 0)
1996 HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "can't close fractal heap")
1997 if(bt2_name && H5B2_close(bt2_name, dxpl_id) < 0)
1998 HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for name index")
1999 if(bt2_corder && H5B2_close(bt2_corder, dxpl_id) < 0)
2000 HDONE_ERROR(H5E_ATTR, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree for creation order index")
2001
2002 FUNC_LEAVE_NOAPI(ret_value)
2003 } /* H5O_attr_bh_info() */
2004
2005 #ifndef H5_NO_DEPRECATED_SYMBOLS
2006
2007 /*-------------------------------------------------------------------------
2008 * Function: H5O_attr_count
2009 *
2010 * Purpose: Determine the # of attributes on an object
2011 *
2012 * Return: Non-negative on success/Negative on failure
2013 *
2014 * Programmer: Quincey Koziol
2015 * Monday, December 11, 2006
2016 *
2017 *-------------------------------------------------------------------------
2018 */
2019 int
H5O_attr_count(const H5O_loc_t * loc,hid_t dxpl_id)2020 H5O_attr_count(const H5O_loc_t *loc, hid_t dxpl_id)
2021 {
2022 H5O_t *oh = NULL; /* Pointer to actual object header */
2023 hsize_t nattrs; /* Number of attributes */
2024 int ret_value; /* Return value */
2025
2026 FUNC_ENTER_NOAPI_NOINIT
2027
2028 /* Check arguments */
2029 HDassert(loc);
2030
2031 /* Protect the object header to iterate over */
2032 if(NULL == (oh = H5O_protect(loc, dxpl_id, H5AC_READ)))
2033 HGOTO_ERROR(H5E_ATTR, H5E_CANTPROTECT, FAIL, "unable to load object header")
2034
2035 /* Retrieve # of attributes on object */
2036 if(H5O_attr_count_real(loc->file, dxpl_id, oh, &nattrs) < 0)
2037 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve attribute count")
2038
2039 /* Set return value */
2040 ret_value = (int)nattrs;
2041
2042 done:
2043 if(oh && H5O_unprotect(loc, dxpl_id, oh, H5AC__NO_FLAGS_SET) < 0)
2044 HDONE_ERROR(H5E_ATTR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
2045
2046 FUNC_LEAVE_NOAPI(ret_value)
2047 } /* end H5O_attr_count */
2048 #endif /* H5_NO_DEPRECATED_SYMBOLS */
2049
2050