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