1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*-------------------------------------------------------------------------
15  *
16  * Created:		H5Adense.c
17  *			Dec  4 2006
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Routines for operating on "dense" attribute storage
21  *                      for an object.
22  *
23  *-------------------------------------------------------------------------
24  */
25 
26 /****************/
27 /* Module Setup */
28 /****************/
29 
30 #include "H5Amodule.h"          /* This source code file is part of the H5A module */
31 #define H5O_FRIEND		/*suppress error about including H5Opkg  */
32 
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 "H5WBprivate.h"        /* Wrapped Buffers                      */
44 
45 
46 /****************/
47 /* Local Macros */
48 /****************/
49 
50 /* v2 B-tree creation macros for 'name' field index */
51 #define H5A_NAME_BT2_NODE_SIZE          512
52 #define H5A_NAME_BT2_MERGE_PERC         40
53 #define H5A_NAME_BT2_SPLIT_PERC         100
54 
55 /* v2 B-tree creation macros for 'corder' field index */
56 #define H5A_CORDER_BT2_NODE_SIZE        512
57 #define H5A_CORDER_BT2_MERGE_PERC       40
58 #define H5A_CORDER_BT2_SPLIT_PERC       100
59 
60 /* Size of stack buffer for serialized attributes */
61 #define H5A_ATTR_BUF_SIZE               128
62 
63 
64 /******************/
65 /* Local Typedefs */
66 /******************/
67 
68 /*
69  * Data exchange structure for dense attribute storage.  This structure is
70  * passed through the v2 B-tree layer when modifying the attribute data value.
71  */
72 typedef struct H5A_bt2_od_wrt_t {
73     /* downward */
74     H5F_t  *f;                  /* Pointer to file that fractal heap is in */
75     H5HF_t *fheap;              /* Fractal heap handle to operate on */
76     H5HF_t *shared_fheap;       /* Fractal heap handle for shared messages */
77     H5A_t  *attr;               /* Attribute to write */
78     haddr_t corder_bt2_addr;    /* v2 B-tree address of creation order index */
79 } H5A_bt2_od_wrt_t;
80 
81 /*
82  * Data exchange structure to pass through the v2 B-tree layer for the
83  * H5B2_iterate function when iterating over densely stored attributes.
84  */
85 typedef struct {
86     /* downward (internal) */
87     H5F_t       *f;                     /* Pointer to file that fractal heap is in */
88     H5HF_t      *fheap;                 /* Fractal heap handle               */
89     H5HF_t      *shared_fheap;          /* Fractal heap handle for shared messages */
90     hsize_t     count;                  /* # of attributes examined          */
91 
92     /* downward (from application) */
93     hid_t       loc_id;                 /* Object ID for application callback */
94     hsize_t     skip;                   /* Number of attributes to skip      */
95     const H5A_attr_iter_op_t *attr_op;  /* Callback for each attribute       */
96     void        *op_data;               /* Callback data for each attribute  */
97 
98     /* upward */
99     int         op_ret;                 /* Return value from callback        */
100 } H5A_bt2_ud_it_t;
101 
102 /*
103  * Data exchange structure to pass through the fractal heap layer for the
104  * H5HF_op function when copying an attribute stored in densely stored attributes.
105  * (or the shared message heap)
106  */
107 typedef struct {
108     /* downward (internal) */
109     H5F_t       *f;                     /* Pointer to file that fractal heap is in */
110     const H5A_dense_bt2_name_rec_t *record;     /* v2 B-tree record for attribute */
111 
112     /* upward */
113     H5A_t  *attr;                       /* Copy of attribute                 */
114 } H5A_fh_ud_cp_t;
115 
116 /*
117  * Data exchange structure for dense attribute storage.  This structure is
118  * passed through the v2 B-tree layer when removing attributes.
119  */
120 typedef struct H5A_bt2_ud_rm_t {
121     /* downward */
122     H5A_bt2_ud_common_t common;         /* Common info for B-tree user data (must be first) */
123     haddr_t corder_bt2_addr;            /* v2 B-tree address of creation order index */
124 } H5A_bt2_ud_rm_t;
125 
126 /*
127  * Data exchange structure for dense attribute storage.  This structure is
128  * passed through the v2 B-tree layer when removing attributes by index.
129  */
130 typedef struct H5A_bt2_ud_rmbi_t {
131     /* downward */
132     H5F_t       *f;                     /* Pointer to file that fractal heap is in */
133     H5HF_t      *fheap;                 /* Fractal heap handle               */
134     H5HF_t      *shared_fheap;          /* Fractal heap handle for shared messages */
135     H5_index_t  idx_type;               /* Index type for operation */
136     haddr_t     other_bt2_addr;         /* v2 B-tree address of "other" index */
137 } H5A_bt2_ud_rmbi_t;
138 
139 
140 /********************/
141 /* Package Typedefs */
142 /********************/
143 
144 
145 /********************/
146 /* Local Prototypes */
147 /********************/
148 
149 
150 /*********************/
151 /* Package Variables */
152 /*********************/
153 
154 
155 /*****************************/
156 /* Library Private Variables */
157 /*****************************/
158 
159 
160 /*******************/
161 /* Local Variables */
162 /*******************/
163 
164 
165 
166 /*-------------------------------------------------------------------------
167  * Function:	H5A__dense_create
168  *
169  * Purpose:	Creates dense attribute storage structures for an object
170  *
171  * Return:	Non-negative on success/Negative on failure
172  *
173  * Programmer:	Quincey Koziol
174  *		koziol@hdfgroup.org
175  *		Dec  4 2006
176  *
177  *-------------------------------------------------------------------------
178  */
179 herr_t
H5A__dense_create(H5F_t * f,H5O_ainfo_t * ainfo)180 H5A__dense_create(H5F_t *f, H5O_ainfo_t *ainfo)
181 {
182     H5HF_create_t fheap_cparam;         /* Fractal heap creation parameters */
183     H5B2_create_t bt2_cparam;           /* v2 B-tree creation parameters */
184     H5HF_t *fheap = NULL;               /* Fractal heap handle */
185     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for names */
186     H5B2_t *bt2_corder = NULL;          /* v2 B-tree handle for creation order */
187     herr_t ret_value = SUCCEED;         /* Return value */
188 
189     FUNC_ENTER_PACKAGE
190 
191     /*
192      * Check arguments.
193      */
194     HDassert(f);
195     HDassert(ainfo);
196 
197     /* Set fractal heap creation parameters */
198 /* XXX: Give some control of these to applications? */
199     HDmemset(&fheap_cparam, 0, sizeof(fheap_cparam));
200     fheap_cparam.managed.width = H5O_FHEAP_MAN_WIDTH;
201     fheap_cparam.managed.start_block_size = H5O_FHEAP_MAN_START_BLOCK_SIZE;
202     fheap_cparam.managed.max_direct_size = H5O_FHEAP_MAN_MAX_DIRECT_SIZE;
203     fheap_cparam.managed.max_index = H5O_FHEAP_MAN_MAX_INDEX;
204     fheap_cparam.managed.start_root_rows = H5O_FHEAP_MAN_START_ROOT_ROWS;
205     fheap_cparam.checksum_dblocks = H5O_FHEAP_CHECKSUM_DBLOCKS;
206     fheap_cparam.max_man_size = H5O_FHEAP_MAX_MAN_SIZE;
207 
208     /* Create fractal heap for storing attributes */
209     if(NULL == (fheap = H5HF_create(f, &fheap_cparam)))
210         HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create fractal heap")
211 
212     /* Retrieve the heap's address in the file */
213     if(H5HF_get_heap_addr(fheap, &ainfo->fheap_addr) < 0)
214         HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap address")
215 #ifdef QAK
216 HDfprintf(stderr, "%s: ainfo->fheap_addr = %a\n", FUNC, ainfo->fheap_addr);
217 #endif /* QAK */
218 
219 #ifndef NDEBUG
220 {
221     size_t fheap_id_len;                /* Fractal heap ID length */
222 
223     /* Retrieve the heap's ID length in the file */
224     if(H5HF_get_id_len(fheap, &fheap_id_len) < 0)
225         HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get fractal heap ID length")
226     HDassert(fheap_id_len == H5O_FHEAP_ID_LEN);
227 #ifdef QAK
228 HDfprintf(stderr, "%s: fheap_id_len = %Zu\n", FUNC, fheap_id_len);
229 #endif /* QAK */
230 }
231 #endif /* NDEBUG */
232 
233     /* Create the name index v2 B-tree */
234     HDmemset(&bt2_cparam, 0, sizeof(bt2_cparam));
235     bt2_cparam.cls = H5A_BT2_NAME;
236     bt2_cparam.node_size = (size_t)H5A_NAME_BT2_NODE_SIZE;
237     bt2_cparam.rrec_size = 4 +          /* Name's hash value */
238             4 +                         /* Creation order index */
239             1 +                         /* Message flags */
240             H5O_FHEAP_ID_LEN;           /* Fractal heap ID */
241     bt2_cparam.split_percent = H5A_NAME_BT2_SPLIT_PERC;
242     bt2_cparam.merge_percent = H5A_NAME_BT2_MERGE_PERC;
243     if(NULL == (bt2_name = H5B2_create(f, &bt2_cparam, NULL)))
244         HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for name index")
245 
246     /* Retrieve the v2 B-tree's address in the file */
247     if(H5B2_get_addr(bt2_name, &ainfo->name_bt2_addr) < 0)
248         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get v2 B-tree address for name index")
249 #ifdef QAK
250 HDfprintf(stderr, "%s: ainfo->name_bt2_addr = %a\n", FUNC, ainfo->name_bt2_addr);
251 #endif /* QAK */
252 
253     /* Check if we should create a creation order index v2 B-tree */
254     if(ainfo->index_corder) {
255         /* Create the creation order index v2 B-tree */
256         HDmemset(&bt2_cparam, 0, sizeof(bt2_cparam));
257         bt2_cparam.cls = H5A_BT2_CORDER;
258         bt2_cparam.node_size = (size_t)H5A_CORDER_BT2_NODE_SIZE;
259         bt2_cparam.rrec_size = 4 +      /* Creation order index */
260                 1 +                     /* Message flags */
261                 H5O_FHEAP_ID_LEN;       /* Fractal heap ID */
262         bt2_cparam.split_percent = H5A_CORDER_BT2_SPLIT_PERC;
263         bt2_cparam.merge_percent = H5A_CORDER_BT2_MERGE_PERC;
264         if(NULL == (bt2_corder = H5B2_create(f, &bt2_cparam, NULL)))
265             HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to create v2 B-tree for creation order index")
266 
267         /* Retrieve the v2 B-tree's address in the file */
268         if(H5B2_get_addr(bt2_corder, &ainfo->corder_bt2_addr) < 0)
269             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get v2 B-tree address for creation order index")
270 #ifdef QAK
271 HDfprintf(stderr, "%s: ainfo->corder_bt2_addr = %a\n", FUNC, ainfo->corder_bt2_addr);
272 #endif /* QAK */
273     } /* end if */
274 
275 done:
276     /* Release resources */
277     if(fheap && H5HF_close(fheap) < 0)
278         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
279     if(bt2_name && H5B2_close(bt2_name) < 0)
280         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
281     if(bt2_corder && H5B2_close(bt2_corder) < 0)
282         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
283 
284     FUNC_LEAVE_NOAPI(ret_value)
285 } /* end H5A__dense_create() */
286 
287 
288 /*-------------------------------------------------------------------------
289  * Function:	H5A__dense_fnd_cb
290  *
291  * Purpose:	Callback when an attribute is located in an index
292  *
293  * Return:	Non-negative on success/Negative on failure
294  *
295  * Programmer:	Quincey Koziol
296  *		koziol@hdfgroup.org
297  *		Dec 11 2006
298  *
299  *-------------------------------------------------------------------------
300  */
301 static herr_t
H5A__dense_fnd_cb(const H5A_t * attr,hbool_t * took_ownership,void * _user_attr)302 H5A__dense_fnd_cb(const H5A_t *attr, hbool_t *took_ownership, void *_user_attr)
303 {
304     H5A_t const **user_attr = (H5A_t const **)_user_attr; /* User data from v2 B-tree attribute lookup */
305     herr_t ret_value = SUCCEED;         /* Return value */
306 
307     FUNC_ENTER_STATIC
308 
309     /*
310      * Check arguments.
311      */
312     HDassert(attr);
313     HDassert(user_attr);
314     HDassert(took_ownership);
315     /*
316      *  If there is an attribute already stored in "user_attr",
317      *  we need to free the dynamially allocated spaces for the
318      *  attribute, otherwise we got infinite loop closing library due to
319      *  outstanding allocation. (HDFFV-10659)
320      *
321      *  This callback is used by H5A__dense_remove() to close/free the
322      *  attribute stored in "user_attr" (via H5O__msg_free_real()) after
323      *  the attribute node is deleted from the name index v2 B-tree.
324      *  The issue is:
325      *      When deleting the attribute node from the B-tree,
326      *      if the attribute is found in the intermediate B-tree nodes,
327      *      which may be merged/redistributed, we need to free the dynamically
328      *      allocated spaces for the intermediate decoded attribute.
329      */
330     if(*user_attr != NULL) {
331         H5A_t *old_attr = *user_attr;
332         if(old_attr->shared) {
333             /* Free any dynamically allocated items */
334             if(H5A__free(old_attr) < 0)
335                 HGOTO_ERROR(H5E_ATTR, H5E_CANTRELEASE, FAIL, "can't release attribute info")
336 
337             /* Destroy shared attribute struct */
338             old_attr->shared = H5FL_FREE(H5A_shared_t, old_attr->shared);
339         } /* end if */
340 
341         old_attr = H5FL_FREE(H5A_t, old_attr);
342      } /* end if */
343 
344     /* Take over attribute ownership */
345     *user_attr = attr;
346     *took_ownership = TRUE;
347 
348 done:
349     FUNC_LEAVE_NOAPI(ret_value)
350 } /* end H5A__dense_fnd_cb() */
351 
352 
353 /*-------------------------------------------------------------------------
354  * Function:	H5A__dense_open
355  *
356  * Purpose:	Open an attribute in dense storage structures for an object
357  *
358  * Return:	Non-negative on success/Negative on failure
359  *
360  * Programmer:	Quincey Koziol
361  *		koziol@hdfgroup.org
362  *		Dec 11 2006
363  *
364  *-------------------------------------------------------------------------
365  */
366 H5A_t *
H5A__dense_open(H5F_t * f,const H5O_ainfo_t * ainfo,const char * name)367 H5A__dense_open(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name)
368 {
369     H5A_bt2_ud_common_t udata;          /* User data for v2 B-tree modify */
370     H5HF_t *fheap = NULL;               /* Fractal heap handle */
371     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
372     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
373     htri_t attr_sharable;               /* Flag indicating attributes are sharable */
374     htri_t attr_exists;                 /* Attribute exists in v2 B-tree */
375     H5A_t *ret_value = NULL;            /* Return value */
376 
377     FUNC_ENTER_PACKAGE
378 
379     /*
380      * Check arguments.
381      */
382     HDassert(f);
383     HDassert(ainfo);
384     HDassert(name);
385 
386     /* Open the fractal heap */
387     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
388         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap")
389 
390     /* Check if attributes are shared in this file */
391     if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
392         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't determine if attributes are shared")
393 
394     /* Get handle for shared message heap, if attributes are sharable */
395     if(attr_sharable) {
396         haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
397 
398         /* Retrieve the address of the shared message's fractal heap */
399         if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
400             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, NULL, "can't get shared message heap address")
401 
402         /* Check if there are any shared messages currently */
403         if(H5F_addr_defined(shared_fheap_addr)) {
404             /* Open the fractal heap for shared header messages */
405             if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
406                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open fractal heap")
407         } /* end if */
408     } /* end if */
409 
410     /* Open the name index v2 B-tree */
411     if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
412         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, NULL, "unable to open v2 B-tree for name index")
413 
414     /* Create the "udata" information for v2 B-tree record find */
415     udata.f = f;
416     udata.fheap = fheap;
417     udata.shared_fheap = shared_fheap;
418     udata.name = name;
419     udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0);
420     udata.flags = 0;
421     udata.corder = 0;
422     udata.found_op = H5A__dense_fnd_cb;       /* v2 B-tree comparison callback */
423     udata.found_op_data = &ret_value;
424 
425     /* Find & copy the attribute in the 'name' index */
426     if((attr_exists = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0)
427         HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't search for attribute in name index")
428     else if(attr_exists == FALSE)
429         HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, NULL, "can't locate attribute in name index")
430 
431 done:
432     /* Release resources */
433     if(shared_fheap && H5HF_close(shared_fheap) < 0)
434         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, NULL, "can't close fractal heap")
435     if(fheap && H5HF_close(fheap) < 0)
436         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, NULL, "can't close fractal heap")
437     if(bt2_name && H5B2_close(bt2_name) < 0)
438         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, NULL, "can't close v2 B-tree for name index")
439 
440     FUNC_LEAVE_NOAPI(ret_value)
441 } /* end H5A__dense_open() */
442 
443 
444 /*-------------------------------------------------------------------------
445  * Function:	H5A__dense_insert
446  *
447  * Purpose:	Insert an attribute into dense storage structures for an object
448  *
449  * Return:	Non-negative on success/Negative on failure
450  *
451  * Programmer:	Quincey Koziol
452  *		koziol@hdfgroup.org
453  *		Dec  4 2006
454  *
455  *-------------------------------------------------------------------------
456  */
457 herr_t
H5A__dense_insert(H5F_t * f,const H5O_ainfo_t * ainfo,H5A_t * attr)458 H5A__dense_insert(H5F_t *f, const H5O_ainfo_t *ainfo, H5A_t *attr)
459 {
460     H5A_bt2_ud_ins_t udata;             /* User data for v2 B-tree insertion */
461     H5HF_t *fheap = NULL;               /* Fractal heap handle for attributes */
462     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
463     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
464     H5B2_t *bt2_corder = NULL;          /* v2 B-tree handle for creation order index */
465     H5WB_t *wb = NULL;                  /* Wrapped buffer for attribute data */
466     uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing message */
467     unsigned mesg_flags = 0;            /* Flags for storing message */
468     htri_t attr_sharable;               /* Flag indicating attributes are sharable */
469     herr_t ret_value = SUCCEED;         /* Return value */
470 
471     FUNC_ENTER_PACKAGE
472 
473     /*
474      * Check arguments.
475      */
476     HDassert(f);
477     HDassert(ainfo);
478     HDassert(attr);
479 
480     /* Check if attributes are shared in this file */
481     if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
482         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
483 
484     /* Get handle for shared message heap, if attributes are sharable */
485     if(attr_sharable) {
486         haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
487         htri_t shared_mesg;             /* Should this message be stored in the Shared Message table? */
488 
489         /* Check if message is already shared */
490         if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, attr)) < 0)
491             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
492         else if(shared_mesg > 0)
493             /* Mark the message as shared */
494             mesg_flags |= H5O_MSG_FLAG_SHARED;
495         else {
496             /* Should this attribute be written as a SOHM? */
497             if(H5SM_try_share(f, NULL, 0, H5O_ATTR_ID, attr, &mesg_flags) < 0)
498                 HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
499 
500             /* Attributes can't be "unique be shareable" yet */
501             HDassert(!(mesg_flags & H5O_MSG_FLAG_SHAREABLE));
502         } /* end else */
503 
504         /* Retrieve the address of the shared message's fractal heap */
505         if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
506             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
507 
508         /* Check if there are any shared messages currently */
509         if(H5F_addr_defined(shared_fheap_addr)) {
510             /* Open the fractal heap for shared header messages */
511             if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
512                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
513         } /* end if */
514     } /* end if */
515 
516     /* Open the fractal heap */
517     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
518         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
519 
520     /* Check for inserting shared attribute */
521     if(mesg_flags & H5O_MSG_FLAG_SHARED) {
522         /* Sanity check */
523         HDassert(attr_sharable);
524 
525         /* Use heap ID for shared message heap */
526         udata.id = attr->sh_loc.u.heap_id;
527     } /* end if */
528     else {
529         void *attr_ptr;         /* Pointer to serialized message */
530         size_t attr_size;       /* Size of serialized attribute in the heap */
531 
532         /* Find out the size of buffer needed for serialized message */
533         if((attr_size = H5O_msg_raw_size(f, H5O_ATTR_ID, FALSE, attr)) == 0)
534             HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get message size")
535 
536         /* Wrap the local buffer for serialized attributes */
537         if(NULL == (wb = H5WB_wrap(attr_buf, sizeof(attr_buf))))
538             HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't wrap buffer")
539 
540         /* Get a pointer to a buffer that's large enough for attribute */
541         if(NULL == (attr_ptr = H5WB_actual(wb, attr_size)))
542             HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't get actual buffer")
543 
544         /* Create serialized form of attribute or shared message */
545         if(H5O_msg_encode(f, H5O_ATTR_ID, FALSE, (unsigned char *)attr_ptr, attr) < 0)
546             HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute")
547 
548         /* Insert the serialized attribute into the fractal heap */
549         /* (sets the heap ID in the user data) */
550         if(H5HF_insert(fheap, attr_size, attr_ptr, &udata.id) < 0)
551             HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert attribute into fractal heap")
552     } /* end else */
553 
554     /* Open the name index v2 B-tree */
555     if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
556         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
557 
558     /* Create the callback information for v2 B-tree record insertion */
559     udata.common.f = f;
560     udata.common.fheap = fheap;
561     udata.common.shared_fheap = shared_fheap;
562     udata.common.name = attr->shared->name;
563     udata.common.name_hash = H5_checksum_lookup3(attr->shared->name, HDstrlen(attr->shared->name), 0);
564     H5_CHECKED_ASSIGN(udata.common.flags, uint8_t, mesg_flags, unsigned);
565     udata.common.corder = attr->shared->crt_idx;
566     udata.common.found_op = NULL;
567     udata.common.found_op_data = NULL;
568     /* udata.id already set */
569 
570     /* Insert attribute into 'name' tracking v2 B-tree */
571     if(H5B2_insert(bt2_name, &udata) < 0)
572         HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree")
573 
574     /* Check if we should create a creation order index v2 B-tree record */
575     if(ainfo->index_corder) {
576         /* Open the creation order index v2 B-tree */
577         HDassert(H5F_addr_defined(ainfo->corder_bt2_addr));
578         if(NULL == (bt2_corder = H5B2_open(f, ainfo->corder_bt2_addr, NULL)))
579             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
580 
581         /* Insert the record into the creation order index v2 B-tree */
582         if(H5B2_insert(bt2_corder, &udata) < 0)
583             HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree")
584     } /* end if */
585 
586 done:
587     /* Release resources */
588     if(shared_fheap && H5HF_close(shared_fheap) < 0)
589         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
590     if(fheap && H5HF_close(fheap) < 0)
591         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
592     if(bt2_name && H5B2_close(bt2_name) < 0)
593         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
594     if(bt2_corder && H5B2_close(bt2_corder) < 0)
595         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
596     if(wb && H5WB_unwrap(wb) < 0)
597         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
598 
599     FUNC_LEAVE_NOAPI(ret_value)
600 } /* end H5A__dense_insert() */
601 
602 
603 /*-------------------------------------------------------------------------
604  * Function:	H5A__dense_write_bt2_cb2
605  *
606  * Purpose:	v2 B-tree 'modify' callback to update the record for a creation
607  *		order index
608  *
609  * Return:	Success:	0
610  *		Failure:	1
611  *
612  * Programmer:	Quincey Koziol
613  *              Tuesday, February 20, 2007
614  *
615  *-------------------------------------------------------------------------
616  */
617 static herr_t
H5A__dense_write_bt2_cb2(void * _record,void * _op_data,hbool_t * changed)618 H5A__dense_write_bt2_cb2(void *_record, void *_op_data, hbool_t *changed)
619 {
620     H5A_dense_bt2_corder_rec_t *record = (H5A_dense_bt2_corder_rec_t *)_record; /* Record from B-tree */
621     H5O_fheap_id_t *new_heap_id = (H5O_fheap_id_t *)_op_data;       /* "op data" from v2 B-tree modify */
622 
623     FUNC_ENTER_STATIC_NOERR
624 
625     /*
626      * Check arguments.
627      */
628     HDassert(record);
629     HDassert(new_heap_id);
630 
631     /* Update record's heap ID */
632     record->id = *new_heap_id;
633 
634     /* Note that the record changed */
635     *changed = TRUE;
636 
637     FUNC_LEAVE_NOAPI(SUCCEED)
638 } /* end H5A__dense_write_bt2_cb2() */
639 
640 
641 /*-------------------------------------------------------------------------
642  * Function:	H5A__dense_write_bt2_cb
643  *
644  * Purpose:	v2 B-tree 'modify' callback to update the data for an attribute
645  *
646  * Return:	Success:	0
647  *		Failure:	1
648  *
649  * Programmer:	Quincey Koziol
650  *              Tuesday, December  5, 2006
651  *
652  *-------------------------------------------------------------------------
653  */
654 static herr_t
H5A__dense_write_bt2_cb(void * _record,void * _op_data,hbool_t * changed)655 H5A__dense_write_bt2_cb(void *_record, void *_op_data, hbool_t *changed)
656 {
657     H5A_dense_bt2_name_rec_t *record = (H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
658     H5A_bt2_od_wrt_t *op_data = (H5A_bt2_od_wrt_t *)_op_data;       /* "op data" from v2 B-tree modify */
659     H5B2_t *bt2_corder = NULL;          /* v2 B-tree handle for creation order index */
660     H5WB_t *wb = NULL;                  /* Wrapped buffer for attribute data */
661     uint8_t attr_buf[H5A_ATTR_BUF_SIZE]; /* Buffer for serializing attribute */
662     herr_t ret_value = SUCCEED;         /* Return value */
663 
664     FUNC_ENTER_STATIC
665 
666     /*
667      * Check arguments.
668      */
669     HDassert(record);
670     HDassert(op_data);
671 
672     /* Check for modifying shared attribute */
673     if(record->flags & H5O_MSG_FLAG_SHARED) {
674         /* Update the shared attribute in the SOHM info */
675         if(H5O__attr_update_shared(op_data->f, NULL, op_data->attr, NULL) < 0)
676             HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute in shared storage")
677 
678         /* Update record's heap ID */
679         record->id = op_data->attr->sh_loc.u.heap_id;
680 
681         /* Check if we need to modify the creation order index with new heap ID */
682         if(H5F_addr_defined(op_data->corder_bt2_addr)) {
683             H5A_bt2_ud_common_t udata;          /* User data for v2 B-tree modify */
684 
685             /* Open the creation order index v2 B-tree */
686             if(NULL == (bt2_corder = H5B2_open(op_data->f, op_data->corder_bt2_addr, NULL)))
687                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
688 
689             /* Create the "udata" information for v2 B-tree record modify */
690             udata.f = op_data->f;
691             udata.fheap = NULL;
692             udata.shared_fheap = NULL;
693             udata.name = NULL;
694             udata.name_hash = 0;
695             udata.flags = 0;
696             udata.corder = op_data->attr->shared->crt_idx;
697             udata.found_op = NULL;
698             udata.found_op_data = NULL;
699 
700             /* Modify record for creation order index */
701             if(H5B2_modify(bt2_corder, &udata, H5A__dense_write_bt2_cb2, &op_data->attr->sh_loc.u.heap_id) < 0)
702                 HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to modify record in v2 B-tree")
703         } /* end if */
704 
705         /* Note that the record changed */
706         *changed = TRUE;
707     } /* end if */
708     else {
709         void *attr_ptr;         /* Pointer to serialized message */
710         size_t attr_size;       /* Size of serialized attribute in the heap */
711 
712         /* Find out the size of buffer needed for serialized attribute */
713         if((attr_size = H5O_msg_raw_size(op_data->f, H5O_ATTR_ID, FALSE, op_data->attr)) == 0)
714             HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get attribute size")
715 
716         /* Wrap the local buffer for serialized attributes */
717         if(NULL == (wb = H5WB_wrap(attr_buf, sizeof(attr_buf))))
718             HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "can't wrap buffer")
719 
720         /* Get a pointer to a buffer that's large enough for attribute */
721         if(NULL == (attr_ptr = H5WB_actual(wb, attr_size)))
722             HGOTO_ERROR(H5E_ATTR, H5E_NOSPACE, FAIL, "can't get actual buffer")
723 
724         /* Create serialized form of attribute */
725         if(H5O_msg_encode(op_data->f, H5O_ATTR_ID, FALSE, (unsigned char *)attr_ptr, op_data->attr) < 0)
726             HGOTO_ERROR(H5E_ATTR, H5E_CANTENCODE, FAIL, "can't encode attribute")
727 
728 /* Sanity check */
729 #ifndef NDEBUG
730 {
731     size_t obj_len;             /* Length of existing encoded attribute */
732 
733     if(H5HF_get_obj_len(op_data->fheap, &record->id, &obj_len) < 0)
734         HGOTO_ERROR(H5E_ATTR, H5E_CANTGETSIZE, FAIL, "can't get object size")
735     HDassert(obj_len == attr_size);
736 }
737 #endif /* NDEBUG */
738         /* Update existing attribute in heap */
739         /* (might be more efficient as fractal heap 'op' callback, but leave that for later -QAK) */
740         if(H5HF_write(op_data->fheap, &record->id, changed, attr_ptr) < 0)
741             HGOTO_ERROR(H5E_ATTR, H5E_CANTUPDATE, FAIL, "unable to update attribute in heap")
742     } /* end else */
743 
744 done:
745     /* Release resources */
746     if(bt2_corder && H5B2_close(bt2_corder) < 0)
747         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
748     if(wb && H5WB_unwrap(wb) < 0)
749         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
750 
751     FUNC_LEAVE_NOAPI(ret_value)
752 } /* end H5A__dense_write_bt2_cb() */
753 
754 
755 /*-------------------------------------------------------------------------
756  * Function:	H5A__dense_write
757  *
758  * Purpose:	Modify an attribute in dense storage structures for an object
759  *
760  * Return:	Non-negative on success/Negative on failure
761  *
762  * Programmer:	Quincey Koziol
763  *		koziol@hdfgroup.org
764  *		Dec  4 2006
765  *
766  *-------------------------------------------------------------------------
767  */
768 herr_t
H5A__dense_write(H5F_t * f,const H5O_ainfo_t * ainfo,H5A_t * attr)769 H5A__dense_write(H5F_t *f, const H5O_ainfo_t *ainfo, H5A_t *attr)
770 {
771     H5A_bt2_ud_common_t udata;          /* User data for v2 B-tree modify */
772     H5A_bt2_od_wrt_t op_data;           /* "Op data" for v2 B-tree modify */
773     H5HF_t *fheap = NULL;               /* Fractal heap handle */
774     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
775     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
776     htri_t attr_sharable;               /* Flag indicating attributes are sharable */
777     herr_t ret_value = SUCCEED;         /* Return value */
778 
779     FUNC_ENTER_PACKAGE
780 
781     /*
782      * Check arguments.
783      */
784     HDassert(f);
785     HDassert(ainfo);
786     HDassert(H5F_addr_defined(ainfo->fheap_addr));
787     HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
788     HDassert(attr);
789 
790     /* Check if attributes are shared in this file */
791     if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
792         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
793 
794     /* Get handle for shared message heap, if attributes are sharable */
795     if(attr_sharable) {
796         haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
797 
798         /* Retrieve the address of the shared message's fractal heap */
799         if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
800             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
801 
802         /* Check if there are any shared messages currently */
803         if(H5F_addr_defined(shared_fheap_addr)) {
804             /* Open the fractal heap for shared header messages */
805             if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
806                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
807         } /* end if */
808     } /* end if */
809 
810     /* Open the fractal heap */
811     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
812         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
813 
814     /* Open the name index v2 B-tree */
815     if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
816         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
817 
818     /* Create the "udata" information for v2 B-tree record modify */
819     udata.f = f;
820     udata.fheap = fheap;
821     udata.shared_fheap = shared_fheap;
822     udata.name = attr->shared->name;
823     udata.name_hash = H5_checksum_lookup3(attr->shared->name, HDstrlen(attr->shared->name), 0);
824     udata.flags = 0;
825     udata.corder = 0;
826     udata.found_op = NULL;
827     udata.found_op_data = NULL;
828 
829     /* Create the "op_data" for the v2 B-tree record 'modify' callback */
830     op_data.f = f;
831     op_data.fheap = fheap;
832     op_data.shared_fheap = shared_fheap;
833     op_data.attr = attr;
834     op_data.corder_bt2_addr = ainfo->corder_bt2_addr;
835 
836     /* Modify attribute through 'name' tracking v2 B-tree */
837     if(H5B2_modify(bt2_name, &udata, H5A__dense_write_bt2_cb, &op_data) < 0)
838         HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to modify record in v2 B-tree")
839 
840 done:
841     /* Release resources */
842     if(shared_fheap && H5HF_close(shared_fheap) < 0)
843         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
844     if(fheap && H5HF_close(fheap) < 0)
845         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
846     if(bt2_name && H5B2_close(bt2_name) < 0)
847         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
848 
849     FUNC_LEAVE_NOAPI(ret_value)
850 } /* end H5A__dense_write() */
851 
852 
853 /*-------------------------------------------------------------------------
854  * Function:	H5A__dense_copy_fh_cb
855  *
856  * Purpose:	Callback for fractal heap operator, to make copy of attribute
857  *              for calling routine
858  *
859  * Return:	SUCCEED/FAIL
860  *
861  * Programmer:	Quincey Koziol
862  *		koziol@hdfgroup.org
863  *		Dec  5 2006
864  *
865  *-------------------------------------------------------------------------
866  */
867 static herr_t
H5A__dense_copy_fh_cb(const void * obj,size_t obj_len,void * _udata)868 H5A__dense_copy_fh_cb(const void *obj, size_t obj_len, void *_udata)
869 {
870     H5A_fh_ud_cp_t *udata = (H5A_fh_ud_cp_t *)_udata;       /* User data for fractal heap 'op' callback */
871     herr_t ret_value = SUCCEED;   /* Return value */
872 
873     FUNC_ENTER_STATIC
874 
875     /* Decode attribute information & keep a copy */
876     /* (we make a copy instead of calling the user/library callback directly in
877      *  this routine because this fractal heap 'op' callback routine is called
878      *  with the direct block protected and if the callback routine invokes an
879      *  HDF5 routine, it could attempt to re-protect that direct block for the
880      *  heap, causing the HDF5 routine called to fail)
881      */
882     if(NULL == (udata->attr = (H5A_t *)H5O_msg_decode(udata->f, NULL, H5O_ATTR_ID, obj_len, (const unsigned char *)obj)))
883         HGOTO_ERROR(H5E_ATTR, H5E_CANTDECODE, FAIL, "can't decode attribute")
884 
885     /* Set the creation order index for the attribute */
886     udata->attr->shared->crt_idx = udata->record->corder;
887 
888     /* Check whether we should "reconstitute" the shared message info */
889     if(udata->record->flags & H5O_MSG_FLAG_SHARED)
890         H5SM_reconstitute(&(udata->attr->sh_loc), udata->f, H5O_ATTR_ID, udata->record->id);
891 
892 done:
893     FUNC_LEAVE_NOAPI(ret_value)
894 } /* end H5A__dense_copy_fh_cb() */
895 
896 
897 /*-------------------------------------------------------------------------
898  * Function:	H5A__dense_rename
899  *
900  * Purpose:	Rename an attribute in dense storage structures for an object
901  *
902  * Return:	Non-negative on success/Negative on failure
903  *
904  * Programmer:	Quincey Koziol
905  *		koziol@hdfgroup.org
906  *		Jan  3 2007
907  *
908  *-------------------------------------------------------------------------
909  */
910 herr_t
H5A__dense_rename(H5F_t * f,const H5O_ainfo_t * ainfo,const char * old_name,const char * new_name)911 H5A__dense_rename(H5F_t *f, const H5O_ainfo_t *ainfo, const char *old_name,
912     const char *new_name)
913 {
914     H5A_bt2_ud_common_t udata;          /* User data for v2 B-tree modify */
915     H5HF_t *fheap = NULL;               /* Fractal heap handle */
916     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
917     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
918     H5B2_t *bt2_corder = NULL;          /* v2 B-tree handle for creation order ndex */
919     H5A_t *attr_copy = NULL;            /* Copy of attribute to rename */
920     htri_t attr_sharable;               /* Flag indicating attributes are sharable */
921     htri_t shared_mesg;                 /* Should this message be stored in the Shared Message table? */
922     htri_t attr_exists;                 /* Attribute exists in v2 B-tree */
923     herr_t ret_value = SUCCEED;         /* Return value */
924 
925     FUNC_ENTER_PACKAGE
926 
927     /*
928      * Check arguments.
929      */
930     HDassert(f);
931     HDassert(ainfo);
932     HDassert(old_name);
933     HDassert(new_name);
934 
935     /* Check if attributes are shared in this file */
936     if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
937         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
938 
939     /* Get handle for shared message heap, if attributes are sharable */
940     if(attr_sharable) {
941         haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
942 
943         /* Retrieve the address of the shared message's fractal heap */
944         if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
945             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
946 
947         /* Check if there are any shared messages currently */
948         if(H5F_addr_defined(shared_fheap_addr)) {
949             /* Open the fractal heap for shared header messages */
950             if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
951                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
952         } /* end if */
953     } /* end if */
954 
955     /* Open the fractal heap */
956     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
957         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
958 
959     /* Open the name index v2 B-tree */
960     if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
961         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
962 
963     /* Create the "udata" information for v2 B-tree record modify */
964     udata.f = f;
965     udata.fheap = fheap;
966     udata.shared_fheap = shared_fheap;
967     udata.name = old_name;
968     udata.name_hash = H5_checksum_lookup3(old_name, HDstrlen(old_name), 0);
969     udata.flags = 0;
970     udata.corder = 0;
971     udata.found_op = H5A__dense_fnd_cb;       /* v2 B-tree comparison callback */
972     udata.found_op_data = &attr_copy;
973 
974     /* Get copy of attribute through 'name' tracking v2 B-tree */
975     if((attr_exists = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0)
976         HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
977     else if(attr_exists == FALSE)
978         HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't locate attribute in name index")
979     HDassert(attr_copy);
980 
981     /* Check if message is already shared */
982     if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, attr_copy)) < 0)
983         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error determining if message is shared")
984     else if(shared_mesg > 0) {
985         /* Reset shared status of copy */
986         /* (so it will get shared again if necessary) */
987         attr_copy->sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
988     } /* end if */
989 
990     /* Change name of attribute */
991     H5MM_xfree(attr_copy->shared->name);
992     attr_copy->shared->name = H5MM_xstrdup(new_name);
993 
994     /* Recompute the version to encode the attribute with */
995     if(H5A__set_version(f, attr_copy) < 0)
996         HGOTO_ERROR(H5E_ATTR, H5E_CANTSET, FAIL, "unable to update attribute version")
997 
998     /* Need to remove the attribute from the creation order index v2 B-tree */
999     if(ainfo->index_corder) {
1000         htri_t corder_attr_exists;  /* Attribute exists in v2 B-tree */
1001 
1002         /* Open the creation order index v2 B-tree */
1003         HDassert(H5F_addr_defined(ainfo->corder_bt2_addr));
1004         if(NULL == (bt2_corder = H5B2_open(f, ainfo->corder_bt2_addr, NULL)))
1005             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation index")
1006 
1007         /* Set up the creation order to search for */
1008         udata.corder = attr_copy->shared->crt_idx;
1009 
1010         if((corder_attr_exists = H5B2_find(bt2_corder, &udata, NULL, NULL)) < 0)
1011             HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
1012 
1013         if(corder_attr_exists) {
1014             H5A_bt2_ud_rm_t rm_udata;
1015 
1016             /* Set up the creation order in user data for the v2 B-tree 'record remove' callback */
1017             rm_udata.common.corder = attr_copy->shared->crt_idx;
1018 
1019             /* Remove the record from the creation order index v2 B-tree */
1020             if(H5B2_remove(bt2_corder, &rm_udata, NULL, NULL) < 0)
1021                 HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from creation order index v2 B-tree")
1022         }
1023     }
1024 
1025     /* Insert renamed attribute back into dense storage */
1026     /* (Possibly making it shared) */
1027     if(H5A__dense_insert(f, ainfo, attr_copy) < 0)
1028         HGOTO_ERROR(H5E_ATTR, H5E_CANTINSERT, FAIL, "unable to add to dense storage")
1029 
1030     /* Was this attribute shared? */
1031     if((shared_mesg = H5O_msg_is_shared(H5O_ATTR_ID, attr_copy)) > 0) {
1032         hsize_t attr_rc;                /* Attribute's ref count in shared message storage */
1033 
1034         /* Retrieve ref count for shared attribute */
1035         if(H5SM_get_refcount(f, H5O_ATTR_ID, &attr_copy->sh_loc, &attr_rc) < 0)
1036             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't retrieve shared message ref count")
1037 
1038         /* If the newly shared attribute needs to share "ownership" of the shared
1039          *      components (ie. its reference count is 1), increment the reference
1040          *      count on any shared components of the attribute, so that they won't
1041          *      be removed from the file.  (Essentially a "copy on write" operation).
1042          *
1043          *      *ick* -QAK, 2007/01/08
1044          */
1045         if(attr_rc == 1) {
1046             /* Increment reference count on attribute components */
1047             if(H5O__attr_link(f, NULL, attr_copy) < 0)
1048                 HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
1049         } /* end if */
1050     } /* end if */
1051     else if(shared_mesg == 0) {
1052         /* Increment reference count on attribute components */
1053         /* (so that they aren't deleted when the attribute is removed shortly) */
1054         if(H5O__attr_link(f, NULL, attr_copy) < 0)
1055             HGOTO_ERROR(H5E_ATTR, H5E_LINKCOUNT, FAIL, "unable to adjust attribute link count")
1056     } /* end if */
1057     else if(shared_mesg < 0)
1058 	HGOTO_ERROR(H5E_ATTR, H5E_WRITEERROR, FAIL, "error determining if message should be shared")
1059 
1060     /* Delete old attribute from dense storage */
1061     if(H5A__dense_remove(f, ainfo, old_name) < 0)
1062         HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
1063 
1064 done:
1065     /* Release resources */
1066     if(shared_fheap && H5HF_close(shared_fheap) < 0)
1067         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1068     if(fheap && H5HF_close(fheap) < 0)
1069         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1070     if(bt2_name && H5B2_close(bt2_name) < 0)
1071         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
1072     if(bt2_corder && H5B2_close(bt2_corder) < 0)
1073         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
1074     if(attr_copy)
1075         H5O_msg_free(H5O_ATTR_ID, attr_copy);
1076 
1077     FUNC_LEAVE_NOAPI(ret_value)
1078 } /* end H5A__dense_rename() */
1079 
1080 
1081 /*-------------------------------------------------------------------------
1082  * Function:	H5A__dense_iterate_bt2_cb
1083  *
1084  * Purpose:	v2 B-tree callback for dense attribute storage iterator
1085  *
1086  * Return:	H5_ITER_ERROR/H5_ITER_CONT/H5_ITER_STOP
1087  *
1088  * Programmer:	Quincey Koziol
1089  *		koziol@hdfgroup.org
1090  *		Dec  5 2006
1091  *
1092  *-------------------------------------------------------------------------
1093  */
1094 static herr_t
H5A__dense_iterate_bt2_cb(const void * _record,void * _bt2_udata)1095 H5A__dense_iterate_bt2_cb(const void *_record, void *_bt2_udata)
1096 {
1097     const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
1098     H5A_bt2_ud_it_t *bt2_udata = (H5A_bt2_ud_it_t *)_bt2_udata;         /* User data for callback */
1099     herr_t ret_value = H5_ITER_CONT;         /* Return value */
1100 
1101     FUNC_ENTER_STATIC
1102 
1103     /* Check for skipping attributes */
1104     if(bt2_udata->skip > 0)
1105         --bt2_udata->skip;
1106     else {
1107         H5A_fh_ud_cp_t fh_udata;        /* User data for fractal heap 'op' callback */
1108         H5HF_t *fheap;                  /* Fractal heap handle for attribute storage */
1109 
1110         /* Check for iterating over shared attribute */
1111         if(record->flags & H5O_MSG_FLAG_SHARED)
1112             fheap = bt2_udata->shared_fheap;
1113         else
1114             fheap = bt2_udata->fheap;
1115 
1116         /* Prepare user data for callback */
1117         /* down */
1118         fh_udata.f = bt2_udata->f;
1119         fh_udata.record = record;
1120         fh_udata.attr = NULL;
1121 
1122         /* Call fractal heap 'op' routine, to copy the attribute information */
1123         if(H5HF_op(fheap, &record->id, H5A__dense_copy_fh_cb, &fh_udata) < 0)
1124             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, H5_ITER_ERROR, "heap op callback failed")
1125 
1126         /* Check which type of callback to make */
1127         switch(bt2_udata->attr_op->op_type) {
1128             case H5A_ATTR_OP_APP2:
1129             {
1130                 H5A_info_t ainfo;               /* Info for attribute */
1131 
1132                 /* Get the attribute information */
1133                 if(H5A__get_info(fh_udata.attr, &ainfo) < 0)
1134                     HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, H5_ITER_ERROR, "unable to get attribute info")
1135 
1136                 /* Make the application callback */
1137                 ret_value = (bt2_udata->attr_op->u.app_op2)(bt2_udata->loc_id, fh_udata.attr->shared->name, &ainfo, bt2_udata->op_data);
1138                 break;
1139             }
1140 
1141 #ifndef H5_NO_DEPRECATED_SYMBOLS
1142             case H5A_ATTR_OP_APP:
1143                 /* Make the application callback */
1144                 ret_value = (bt2_udata->attr_op->u.app_op)(bt2_udata->loc_id, fh_udata.attr->shared->name, bt2_udata->op_data);
1145                 break;
1146 #endif /* H5_NO_DEPRECATED_SYMBOLS */
1147 
1148             case H5A_ATTR_OP_LIB:
1149                 /* Call the library's callback */
1150                 ret_value = (bt2_udata->attr_op->u.lib_op)(fh_udata.attr, bt2_udata->op_data);
1151                 break;
1152 
1153             default:
1154                 HDassert("unknown attribute op type" && 0);
1155 #ifdef NDEBUG
1156                 HGOTO_ERROR(H5E_ATTR, H5E_UNSUPPORTED, FAIL, "unsupported attribute op type")
1157 #endif /* NDEBUG */
1158         } /* end switch */
1159 
1160         /* Release the space allocated for the attribute */
1161         H5O_msg_free(H5O_ATTR_ID, fh_udata.attr);
1162     } /* end else */
1163 
1164     /* Increment the number of attributes passed through */
1165     /* (whether we skipped them or not) */
1166     bt2_udata->count++;
1167 
1168     /* Check for callback failure and pass along return value */
1169     if(ret_value < 0)
1170         HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
1171 
1172 done:
1173     FUNC_LEAVE_NOAPI(ret_value)
1174 } /* end H5A__dense_iterate_bt2_cb() */
1175 
1176 
1177 /*-------------------------------------------------------------------------
1178  * Function:	H5A__dense_iterate
1179  *
1180  * Purpose:	Iterate over attributes in dense storage structures for an object
1181  *
1182  * Return:	Non-negative on success/Negative on failure
1183  *
1184  * Programmer:	Quincey Koziol
1185  *		koziol@hdfgroup.org
1186  *		Dec  5 2006
1187  *
1188  *-------------------------------------------------------------------------
1189  */
1190 herr_t
H5A__dense_iterate(H5F_t * f,hid_t loc_id,const H5O_ainfo_t * ainfo,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)1191 H5A__dense_iterate(H5F_t *f, hid_t loc_id, const H5O_ainfo_t *ainfo,
1192     H5_index_t idx_type, H5_iter_order_t order, hsize_t skip, hsize_t *last_attr,
1193     const H5A_attr_iter_op_t *attr_op, void *op_data)
1194 {
1195     H5HF_t *fheap = NULL;               /* Fractal heap handle */
1196     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
1197     H5A_attr_table_t atable = {0, NULL};        /* Table of attributes */
1198     H5B2_t *bt2 = NULL;                 /* v2 B-tree handle for index */
1199     haddr_t bt2_addr;                   /* Address of v2 B-tree to use for lookup */
1200     herr_t ret_value = FAIL;            /* Return value */
1201 
1202     FUNC_ENTER_PACKAGE
1203 
1204     /*
1205      * Check arguments.
1206      */
1207     HDassert(f);
1208     HDassert(ainfo);
1209     HDassert(H5F_addr_defined(ainfo->fheap_addr));
1210     HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
1211     HDassert(attr_op);
1212 
1213     /* Determine the address of the index to use */
1214     if(idx_type == H5_INDEX_NAME) {
1215         /* Check if "native" order is OK - since names are hashed, getting them
1216          *      in strictly increasing or decreasing order requires building a
1217          *      table and sorting it.
1218          */
1219         if(order == H5_ITER_NATIVE) {
1220             HDassert(H5F_addr_defined(ainfo->name_bt2_addr));
1221             bt2_addr = ainfo->name_bt2_addr;
1222         } /* end if */
1223         else
1224             bt2_addr = HADDR_UNDEF;
1225     } /* end if */
1226     else {
1227         HDassert(idx_type == H5_INDEX_CRT_ORDER);
1228 
1229         /* This address may not be defined if creation order is tracked, but
1230          *      there's no index on it.  If there's no v2 B-tree that indexes
1231          *      the links, a table will be built.
1232          */
1233         bt2_addr = ainfo->corder_bt2_addr;
1234     } /* end else */
1235 
1236     /* Check on iteration order */
1237     if(order == H5_ITER_NATIVE && H5F_addr_defined(bt2_addr)) {
1238         H5A_bt2_ud_it_t udata;              /* User data for iterator callback */
1239         htri_t attr_sharable;               /* Flag indicating attributes are sharable */
1240 
1241         /* Open the fractal heap */
1242         if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
1243             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1244 
1245         /* Check if attributes are shared in this file */
1246         if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
1247             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
1248 
1249         /* Get handle for shared message heap, if attributes are sharable */
1250         if(attr_sharable) {
1251             haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
1252 
1253             /* Retrieve the address of the shared message's fractal heap */
1254             if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
1255                 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
1256 
1257             /* Check if there are any shared messages currently */
1258             if(H5F_addr_defined(shared_fheap_addr)) {
1259                 /* Open the fractal heap for shared header messages */
1260                 if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
1261                     HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1262             } /* end if */
1263         } /* end if */
1264 
1265         /* Open the index v2 B-tree */
1266         if(NULL == (bt2 = H5B2_open(f, bt2_addr, NULL)))
1267             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
1268 
1269         /* Construct the user data for v2 B-tree iterator callback */
1270         udata.f = f;
1271         udata.fheap = fheap;
1272         udata.shared_fheap = shared_fheap;
1273         udata.loc_id = loc_id;
1274         udata.skip = skip;
1275         udata.count = 0;
1276         udata.attr_op = attr_op;
1277         udata.op_data = op_data;
1278 
1279         /* Iterate over the records in the v2 B-tree's "native" order */
1280         /* (by hash of name) */
1281         if((ret_value = H5B2_iterate(bt2, H5A__dense_iterate_bt2_cb, &udata)) < 0)
1282             HERROR(H5E_ATTR, H5E_BADITER, "attribute iteration failed");
1283 
1284         /* Update the last attribute examined, if requested */
1285         if(last_attr)
1286             *last_attr = udata.count;
1287     } /* end if */
1288     else {
1289         /* Build the table of attributes for this object */
1290         /* (build table using the name index, but sort according to idx_type) */
1291         if(H5A__dense_build_table(f, ainfo, idx_type, order, &atable) < 0)
1292             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
1293 
1294         /* Iterate over attributes in table */
1295         if((ret_value = H5A__attr_iterate_table(&atable, skip, last_attr, loc_id, attr_op, op_data)) < 0)
1296             HERROR(H5E_ATTR, H5E_CANTNEXT, "iteration operator failed");
1297     } /* end else */
1298 
1299 done:
1300     /* Release resources */
1301     if(shared_fheap && H5HF_close(shared_fheap) < 0)
1302         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1303     if(fheap && H5HF_close(fheap) < 0)
1304         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1305     if(bt2 && H5B2_close(bt2) < 0)
1306         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index")
1307     if(atable.attrs && H5A__attr_release_table(&atable) < 0)
1308         HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
1309 
1310     FUNC_LEAVE_NOAPI(ret_value)
1311 } /* end H5A__dense_iterate() */
1312 
1313 
1314 /*-------------------------------------------------------------------------
1315  * Function:	H5A__dense_remove_bt2_cb
1316  *
1317  * Purpose:	v2 B-tree callback for dense attribute storage record removal
1318  *
1319  * Return:	Non-negative on success/Negative on failure
1320  *
1321  * Programmer:	Quincey Koziol
1322  *		koziol@hdfgroup.org
1323  *		Dec 11 2006
1324  *
1325  *-------------------------------------------------------------------------
1326  */
1327 static herr_t
H5A__dense_remove_bt2_cb(const void * _record,void * _udata)1328 H5A__dense_remove_bt2_cb(const void *_record, void *_udata)
1329 {
1330     const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record;
1331     H5A_bt2_ud_rm_t *udata = (H5A_bt2_ud_rm_t *)_udata;         /* User data for callback */
1332     H5A_t *attr = *(H5A_t **)udata->common.found_op_data;  /* Pointer to attribute to remove */
1333     H5B2_t *bt2_corder = NULL;          /* v2 B-tree handle for creation order index */
1334     herr_t ret_value = SUCCEED;         /* Return value */
1335 
1336     FUNC_ENTER_STATIC
1337 
1338     /* Check for removing the link from the creation order index */
1339     if(H5F_addr_defined(udata->corder_bt2_addr)) {
1340         /* Open the creation order index v2 B-tree */
1341         if(NULL == (bt2_corder = H5B2_open(udata->common.f, udata->corder_bt2_addr, NULL)))
1342             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for creation order index")
1343 
1344         /* Set up the user data for the v2 B-tree 'record remove' callback */
1345         udata->common.corder = attr->shared->crt_idx;
1346 
1347         /* Remove the record from the creation order index v2 B-tree */
1348         if(H5B2_remove(bt2_corder, udata, NULL, NULL) < 0)
1349             HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from creation order index v2 B-tree")
1350     } /* end if */
1351 
1352     /* Check for removing shared attribute */
1353     if(record->flags & H5O_MSG_FLAG_SHARED) {
1354         /* Decrement the reference count on the shared attribute message */
1355         if(H5SM_delete(udata->common.f, NULL, &(attr->sh_loc)) < 0)
1356             HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute")
1357     } /* end if */
1358     else {
1359         /* Perform the deletion action on the attribute */
1360         /* (takes care of shared & committed datatype/dataspace components) */
1361         if(H5O__attr_delete(udata->common.f, NULL, attr) < 0)
1362             HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
1363 
1364         /* Remove record from fractal heap */
1365         if(H5HF_remove(udata->common.fheap, &record->id) < 0)
1366             HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from fractal heap")
1367     } /* end else */
1368 
1369 done:
1370     /* Release resources */
1371     if(bt2_corder && H5B2_close(bt2_corder) < 0)
1372         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for creation order index")
1373 
1374     FUNC_LEAVE_NOAPI(ret_value)
1375 } /* end H5A__dense_remove_bt2_cb() */
1376 
1377 
1378 /*-------------------------------------------------------------------------
1379  * Function:	H5A__dense_remove
1380  *
1381  * Purpose:	Remove an attribute from the dense storage of an object
1382  *
1383  * Return:	Non-negative on success/Negative on failure
1384  *
1385  * Programmer:	Quincey Koziol
1386  *		koziol@hdfgroup.org
1387  *		Dec 11 2006
1388  *
1389  *-------------------------------------------------------------------------
1390  */
1391 herr_t
H5A__dense_remove(H5F_t * f,const H5O_ainfo_t * ainfo,const char * name)1392 H5A__dense_remove(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name)
1393 {
1394     H5A_bt2_ud_rm_t udata;              /* User data for v2 B-tree record removal */
1395     H5HF_t *fheap = NULL;               /* Fractal heap handle */
1396     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
1397     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
1398     H5A_t *attr_copy = NULL;            /* Copy of attribute to remove */
1399     htri_t attr_sharable;               /* Flag indicating attributes are sharable */
1400     herr_t ret_value = SUCCEED;         /* Return value */
1401 
1402     FUNC_ENTER_PACKAGE
1403 
1404     /*
1405      * Check arguments.
1406      */
1407     HDassert(f);
1408     HDassert(ainfo);
1409     HDassert(name && *name);
1410 
1411     /* Open the fractal heap */
1412     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
1413         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1414 
1415     /* Check if attributes are shared in this file */
1416     if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
1417         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
1418 
1419     /* Get handle for shared message heap, if attributes are sharable */
1420     if(attr_sharable) {
1421         haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
1422 
1423         /* Retrieve the address of the shared message's fractal heap */
1424         if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
1425             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
1426 
1427         /* Check if there are any shared messages currently */
1428         if(H5F_addr_defined(shared_fheap_addr)) {
1429             /* Open the fractal heap for shared header messages */
1430             if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
1431                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1432         } /* end if */
1433     } /* end if */
1434 
1435     /* Open the name index v2 B-tree */
1436     if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
1437         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
1438 
1439     /* Set up the user data for the v2 B-tree 'record remove' callback */
1440     udata.common.f = f;
1441     udata.common.fheap = fheap;
1442     udata.common.shared_fheap = shared_fheap;
1443     udata.common.name = name;
1444     udata.common.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0);
1445     udata.common.found_op = H5A__dense_fnd_cb;       /* v2 B-tree comparison callback */
1446     udata.common.found_op_data = &attr_copy;
1447     udata.corder_bt2_addr = ainfo->corder_bt2_addr;
1448 
1449     /* Remove the record from the name index v2 B-tree */
1450     if(H5B2_remove(bt2_name, &udata, H5A__dense_remove_bt2_cb, &udata) < 0)
1451         HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from name index v2 B-tree")
1452 
1453 done:
1454     /* Release resources */
1455     if(shared_fheap && H5HF_close(shared_fheap) < 0)
1456         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1457     if(fheap && H5HF_close(fheap) < 0)
1458         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1459     if(bt2_name && H5B2_close(bt2_name) < 0)
1460         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
1461     if(attr_copy)
1462         H5O__msg_free_real(H5O_MSG_ATTR, attr_copy);
1463 
1464     FUNC_LEAVE_NOAPI(ret_value)
1465 } /* end H5A__dense_remove() */
1466 
1467 
1468 /*-------------------------------------------------------------------------
1469  * Function:	H5A__dense_remove_by_idx_bt2_cb
1470  *
1471  * Purpose:	v2 B-tree callback for dense attribute storage record removal by index
1472  *
1473  * Return:	Non-negative on success/Negative on failure
1474  *
1475  * Programmer:	Quincey Koziol
1476  *		koziol@hdfgroup.org
1477  *		Feb 14 2007
1478  *
1479  *-------------------------------------------------------------------------
1480  */
1481 static herr_t
H5A__dense_remove_by_idx_bt2_cb(const void * _record,void * _bt2_udata)1482 H5A__dense_remove_by_idx_bt2_cb(const void *_record, void *_bt2_udata)
1483 {
1484     H5HF_t *fheap;                      /* Fractal heap handle */
1485     H5B2_t *bt2 = NULL;                 /* v2 B-tree handle for index */
1486     const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* v2 B-tree record */
1487     H5A_bt2_ud_rmbi_t *bt2_udata = (H5A_bt2_ud_rmbi_t *)_bt2_udata;         /* User data for callback */
1488     H5A_fh_ud_cp_t fh_udata;            /* User data for fractal heap 'op' callback */
1489     H5O_shared_t sh_loc;                /* Shared message info for attribute */
1490     hbool_t use_sh_loc;                 /* Whether to use the attribute's shared location or the separate one */
1491     herr_t ret_value = SUCCEED;         /* Return value */
1492 
1493     FUNC_ENTER_STATIC
1494 
1495     /* Set up the user data for fractal heap 'op' callback */
1496     fh_udata.f = bt2_udata->f;
1497     fh_udata.record = record;
1498     fh_udata.attr = NULL;
1499 
1500     /* Get correct fractal heap handle to use for operations */
1501     if(record->flags & H5O_MSG_FLAG_SHARED)
1502         fheap = bt2_udata->shared_fheap;
1503     else
1504         fheap = bt2_udata->fheap;
1505 
1506     /* Check whether to make a copy of the attribute or just need the shared location info */
1507     if(H5F_addr_defined(bt2_udata->other_bt2_addr) || !(record->flags & H5O_MSG_FLAG_SHARED)) {
1508         /* Call fractal heap 'op' routine, to make copy of attribute to remove */
1509         if(H5HF_op(fheap, &record->id, H5A__dense_copy_fh_cb, &fh_udata) < 0)
1510             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, FAIL, "attribute removal callback failed")
1511         HDassert(fh_udata.attr);
1512 
1513         /* Use the attribute's shared location */
1514         use_sh_loc = FALSE;
1515     } /* end if */
1516     else {
1517         /* Create a shared message location from the heap ID for this record */
1518         H5SM_reconstitute(&sh_loc, bt2_udata->f, H5O_ATTR_ID, record->id);
1519 
1520         /* Use the separate shared location */
1521         use_sh_loc = TRUE;
1522     } /* end else */
1523 
1524     /* Check for removing the link from the "other" index (creation order, when name used and vice versa) */
1525     if(H5F_addr_defined(bt2_udata->other_bt2_addr)) {
1526         H5A_bt2_ud_common_t other_bt2_udata;    /* Info for B-tree callbacks */
1527 
1528         /* Determine the index being used */
1529         if(bt2_udata->idx_type == H5_INDEX_NAME) {
1530             /* Set up the user data for the v2 B-tree 'record remove' callback */
1531             other_bt2_udata.corder = fh_udata.attr->shared->crt_idx;
1532         } /* end if */
1533         else {
1534             HDassert(bt2_udata->idx_type == H5_INDEX_CRT_ORDER);
1535 
1536             /* Set up the user data for the v2 B-tree 'record remove' callback */
1537             other_bt2_udata.f = bt2_udata->f;
1538             other_bt2_udata.fheap = bt2_udata->fheap;
1539             other_bt2_udata.shared_fheap = bt2_udata->shared_fheap;
1540             other_bt2_udata.name = fh_udata.attr->shared->name;
1541             other_bt2_udata.name_hash = H5_checksum_lookup3(fh_udata.attr->shared->name, HDstrlen(fh_udata.attr->shared->name), 0);
1542             other_bt2_udata.found_op = NULL;
1543             other_bt2_udata.found_op_data = NULL;
1544         } /* end else */
1545 
1546         /* Open the index v2 B-tree */
1547         if(NULL == (bt2 = H5B2_open(bt2_udata->f, bt2_udata->other_bt2_addr, NULL)))
1548             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
1549 
1550         /* Set the common information for the v2 B-tree remove operation */
1551 
1552         /* Remove the record from the "other" index v2 B-tree */
1553         if(H5B2_remove(bt2, &other_bt2_udata, NULL, NULL) < 0)
1554             HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove record from 'other' index v2 B-tree")
1555     } /* end if */
1556 
1557     /* Check for removing shared attribute */
1558     if(record->flags & H5O_MSG_FLAG_SHARED) {
1559         H5O_shared_t *sh_loc_ptr;       /* Pointer to shared message info for attribute */
1560 
1561         /* Set up pointer to correct shared location */
1562         if(use_sh_loc)
1563             sh_loc_ptr = &sh_loc;
1564         else
1565             sh_loc_ptr = &(fh_udata.attr->sh_loc);
1566 
1567         /* Decrement the reference count on the shared attribute message */
1568         if(H5SM_delete(bt2_udata->f, NULL, sh_loc_ptr) < 0)
1569             HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute")
1570     } /* end if */
1571     else {
1572         /* Perform the deletion action on the attribute */
1573         /* (takes care of shared & committed datatype/dataspace components) */
1574         if(H5O__attr_delete(bt2_udata->f, NULL, fh_udata.attr) < 0)
1575             HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
1576 
1577         /* Remove record from fractal heap */
1578         if(H5HF_remove(fheap, &record->id) < 0)
1579             HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from fractal heap")
1580     } /* end else */
1581 
1582 done:
1583     /* Release resources */
1584     if(bt2 && H5B2_close(bt2) < 0)
1585         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index")
1586     if(fh_udata.attr)
1587         H5O_msg_free(H5O_ATTR_ID, fh_udata.attr);
1588 
1589     FUNC_LEAVE_NOAPI(ret_value)
1590 } /* end H5A__dense_remove_by_idx_bt2_cb() */
1591 
1592 
1593 /*-------------------------------------------------------------------------
1594  * Function:	H5A__dense_remove_by_idx
1595  *
1596  * Purpose:	Remove an attribute from the dense storage of an object,
1597  *		according to the order within an index
1598  *
1599  * Return:	Non-negative on success/Negative on failure
1600  *
1601  * Programmer:	Quincey Koziol
1602  *		koziol@hdfgroup.org
1603  *		Feb 14 2007
1604  *
1605  *-------------------------------------------------------------------------
1606  */
1607 herr_t
H5A__dense_remove_by_idx(H5F_t * f,const H5O_ainfo_t * ainfo,H5_index_t idx_type,H5_iter_order_t order,hsize_t n)1608 H5A__dense_remove_by_idx(H5F_t *f, const H5O_ainfo_t *ainfo, H5_index_t idx_type,
1609     H5_iter_order_t order, hsize_t n)
1610 {
1611     H5HF_t *fheap = NULL;               /* Fractal heap handle */
1612     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
1613     H5A_attr_table_t atable = {0, NULL};        /* Table of attributes */
1614     H5B2_t *bt2 = NULL;                 /* v2 B-tree handle for index */
1615     haddr_t bt2_addr;                   /* Address of v2 B-tree to use for operation */
1616     herr_t ret_value = SUCCEED;         /* Return value */
1617 
1618     FUNC_ENTER_PACKAGE
1619 
1620     /*
1621      * Check arguments.
1622      */
1623     HDassert(f);
1624     HDassert(ainfo);
1625 
1626     /* Determine the address of the index to use */
1627     if(idx_type == H5_INDEX_NAME) {
1628         /* Check if "native" order is OK - since names are hashed, getting them
1629          *      in strictly increasing or decreasing order requires building a
1630          *      table and sorting it.
1631          */
1632         if(order == H5_ITER_NATIVE) {
1633             bt2_addr = ainfo->name_bt2_addr;
1634             HDassert(H5F_addr_defined(bt2_addr));
1635         } /* end if */
1636         else
1637             bt2_addr = HADDR_UNDEF;
1638     } /* end if */
1639     else {
1640         HDassert(idx_type == H5_INDEX_CRT_ORDER);
1641 
1642         /* This address may not be defined if creation order is tracked, but
1643          *      there's no index on it.  If there's no v2 B-tree that indexes
1644          *      the links, a table will be built.
1645          */
1646         bt2_addr = ainfo->corder_bt2_addr;
1647     } /* end else */
1648 
1649     /* If there is an index defined for the field, use it */
1650     if(H5F_addr_defined(bt2_addr)) {
1651         H5A_bt2_ud_rmbi_t udata;        /* User data for v2 B-tree record removal */
1652         htri_t attr_sharable;           /* Flag indicating attributes are sharable */
1653 
1654         /* Open the fractal heap */
1655         if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
1656             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1657 
1658         /* Check if attributes are shared in this file */
1659         if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
1660             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
1661 
1662         /* Get handle for shared message heap, if attributes are sharable */
1663         if(attr_sharable) {
1664             haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
1665 
1666             /* Retrieve the address of the shared message's fractal heap */
1667             if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
1668                 HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
1669 
1670             /* Check if there are any shared messages currently */
1671             if(H5F_addr_defined(shared_fheap_addr)) {
1672                 /* Open the fractal heap for shared header messages */
1673                 if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
1674                     HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1675             } /* end if */
1676         } /* end if */
1677 
1678         /* Open the index v2 B-tree */
1679         if(NULL == (bt2 = H5B2_open(f, bt2_addr, NULL)))
1680             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for index")
1681 
1682         /* Set up the user data for the v2 B-tree 'record remove' callback */
1683         udata.f = f;
1684         udata.fheap = fheap;
1685         udata.shared_fheap = shared_fheap;
1686         udata.idx_type = idx_type;
1687         udata.other_bt2_addr = idx_type == H5_INDEX_NAME ? ainfo->corder_bt2_addr : ainfo->name_bt2_addr;
1688 
1689         /* Remove the record from the name index v2 B-tree */
1690         if(H5B2_remove_by_idx(bt2, order, n, H5A__dense_remove_by_idx_bt2_cb, &udata) < 0)
1691             HGOTO_ERROR(H5E_ATTR, H5E_CANTREMOVE, FAIL, "unable to remove attribute from v2 B-tree index")
1692     } /* end if */
1693     else {
1694         /* Build the table of attributes for this object */
1695         /* (build table using the name index, but sort according to idx_type) */
1696         if(H5A__dense_build_table(f, ainfo, idx_type, order, &atable) < 0)
1697             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "error building table of attributes")
1698 
1699         /* Check for skipping too many attributes */
1700         if(n >= atable.nattrs)
1701             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid index specified")
1702 
1703         /* Delete appropriate attribute from dense storage */
1704         if(H5A__dense_remove(f, ainfo, ((atable.attrs[n])->shared)->name) < 0)
1705             HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute in dense storage")
1706     } /* end else */
1707 
1708 done:
1709     /* Release resources */
1710     if(shared_fheap && H5HF_close(shared_fheap) < 0)
1711         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1712     if(fheap && H5HF_close(fheap) < 0)
1713         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1714     if(bt2 && H5B2_close(bt2) < 0)
1715         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for index")
1716     if(atable.attrs && H5A__attr_release_table(&atable) < 0)
1717         HDONE_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to release attribute table")
1718 
1719     FUNC_LEAVE_NOAPI(ret_value)
1720 } /* end H5A__dense_remove_by_idx() */
1721 
1722 
1723 /*-------------------------------------------------------------------------
1724  * Function:	H5A__dense_exists
1725  *
1726  * Purpose:	Check if an attribute exists in dense storage structures for
1727  *              an object
1728  *
1729  * Return:	Non-negative on success/Negative on failure
1730  *
1731  * Programmer:	Quincey Koziol
1732  *		koziol@hdfgroup.org
1733  *		Dec 11 2006
1734  *
1735  *-------------------------------------------------------------------------
1736  */
1737 htri_t
H5A__dense_exists(H5F_t * f,const H5O_ainfo_t * ainfo,const char * name)1738 H5A__dense_exists(H5F_t *f, const H5O_ainfo_t *ainfo, const char *name)
1739 {
1740     H5A_bt2_ud_common_t udata;          /* User data for v2 B-tree modify */
1741     H5HF_t *fheap = NULL;               /* Fractal heap handle */
1742     H5HF_t *shared_fheap = NULL;        /* Fractal heap handle for shared header messages */
1743     H5B2_t *bt2_name = NULL;            /* v2 B-tree handle for name index */
1744     htri_t attr_sharable;               /* Flag indicating attributes are sharable */
1745     htri_t ret_value = TRUE;            /* Return value */
1746 
1747     FUNC_ENTER_PACKAGE
1748 
1749     /*
1750      * Check arguments.
1751      */
1752     HDassert(f);
1753     HDassert(ainfo);
1754     HDassert(name);
1755 
1756     /* Open the fractal heap */
1757     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
1758         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1759 
1760     /* Check if attributes are shared in this file */
1761     if((attr_sharable = H5SM_type_shared(f, H5O_ATTR_ID)) < 0)
1762         HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't determine if attributes are shared")
1763 
1764     /* Get handle for shared message heap, if attributes are sharable */
1765     if(attr_sharable) {
1766         haddr_t shared_fheap_addr;      /* Address of fractal heap to use */
1767 
1768         /* Retrieve the address of the shared message's fractal heap */
1769         if(H5SM_get_fheap_addr(f, H5O_ATTR_ID, &shared_fheap_addr) < 0)
1770             HGOTO_ERROR(H5E_ATTR, H5E_CANTGET, FAIL, "can't get shared message heap address")
1771 
1772         /* Check if there are any shared messages currently */
1773         if(H5F_addr_defined(shared_fheap_addr)) {
1774             /* Open the fractal heap for shared header messages */
1775             if(NULL == (shared_fheap = H5HF_open(f, shared_fheap_addr)))
1776                 HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1777         } /* end if */
1778     } /* end if */
1779 
1780     /* Open the name index v2 B-tree */
1781     if(NULL == (bt2_name = H5B2_open(f, ainfo->name_bt2_addr, NULL)))
1782         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index")
1783 
1784     /* Create the "udata" information for v2 B-tree record 'find' */
1785     udata.f = f;
1786     udata.fheap = fheap;
1787     udata.shared_fheap = shared_fheap;
1788     udata.name = name;
1789     udata.name_hash = H5_checksum_lookup3(name, HDstrlen(name), 0);
1790     udata.flags = 0;
1791     udata.corder = 0;
1792     udata.found_op = NULL;       /* v2 B-tree comparison callback */
1793     udata.found_op_data = NULL;
1794 
1795     /* Find the attribute in the 'name' index */
1796     if((ret_value = H5B2_find(bt2_name, &udata, NULL, NULL)) < 0)
1797         HGOTO_ERROR(H5E_ATTR, H5E_NOTFOUND, FAIL, "can't search for attribute in name index")
1798 
1799 done:
1800     /* Release resources */
1801     if(shared_fheap && H5HF_close(shared_fheap) < 0)
1802         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1803     if(fheap && H5HF_close(fheap) < 0)
1804         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1805     if(bt2_name && H5B2_close(bt2_name) < 0)
1806         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index")
1807 
1808     FUNC_LEAVE_NOAPI(ret_value)
1809 } /* end H5A__dense_exists() */
1810 
1811 
1812 /*-------------------------------------------------------------------------
1813  * Function:	H5A__dense_delete_bt2_cb
1814  *
1815  * Purpose:	v2 B-tree callback for dense attribute storage deletion
1816  *
1817  * Return:	Non-negative on success/Negative on failure
1818  *
1819  * Programmer:	Quincey Koziol
1820  *		koziol@hdfgroup.org
1821  *		Jan  3 2007
1822  *
1823  *-------------------------------------------------------------------------
1824  */
1825 static herr_t
H5A__dense_delete_bt2_cb(const void * _record,void * _bt2_udata)1826 H5A__dense_delete_bt2_cb(const void *_record, void *_bt2_udata)
1827 {
1828     const H5A_dense_bt2_name_rec_t *record = (const H5A_dense_bt2_name_rec_t *)_record; /* Record from B-tree */
1829     H5A_bt2_ud_common_t *bt2_udata = (H5A_bt2_ud_common_t *)_bt2_udata;         /* User data for callback */
1830     H5A_t *attr = NULL;                 /* Attribute being removed */
1831     herr_t ret_value = SUCCEED;         /* Return value */
1832 
1833     FUNC_ENTER_STATIC
1834 
1835     /* Check for shared attribute */
1836     if(record->flags & H5O_MSG_FLAG_SHARED) {
1837         H5O_shared_t sh_mesg;   /* Temporary shared message info */
1838 
1839         /* "reconstitute" the shared message info for the attribute */
1840         H5SM_reconstitute(&sh_mesg, bt2_udata->f, H5O_ATTR_ID, record->id);
1841 
1842         /* Decrement the reference count on the shared attribute message */
1843         if(H5SM_delete(bt2_udata->f, NULL, &sh_mesg) < 0)
1844             HGOTO_ERROR(H5E_ATTR, H5E_CANTFREE, FAIL, "unable to delete shared attribute")
1845     } /* end if */
1846     else {
1847         H5A_fh_ud_cp_t fh_udata;            /* User data for fractal heap 'op' callback */
1848 
1849         /* Prepare user data for callback */
1850         /* down */
1851         fh_udata.f = bt2_udata->f;
1852         fh_udata.record = record;
1853         /* up */
1854         fh_udata.attr = NULL;
1855 
1856         /* Call fractal heap 'op' routine, to copy the attribute information */
1857         if(H5HF_op(bt2_udata->fheap, &record->id, H5A__dense_copy_fh_cb, &fh_udata) < 0)
1858             HGOTO_ERROR(H5E_ATTR, H5E_CANTOPERATE, FAIL, "heap op callback failed")
1859         attr = fh_udata.attr;
1860 
1861         /* Perform the deletion action on the attribute */
1862         /* (takes care of shared/committed datatype & dataspace components) */
1863         if(H5O__attr_delete(bt2_udata->f, NULL, fh_udata.attr) < 0)
1864             HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete attribute")
1865     } /* end else */
1866 
1867 done:
1868     /* Release resources */
1869     if(attr)
1870         H5O__msg_free_real(H5O_MSG_ATTR, attr);
1871 
1872     FUNC_LEAVE_NOAPI(ret_value)
1873 } /* end H5A__dense_delete_bt2_cb() */
1874 
1875 
1876 /*-------------------------------------------------------------------------
1877  * Function:	H5A__dense_delete
1878  *
1879  * Purpose:	Delete all dense storage structures for attributes on an object
1880  *
1881  * Return:	Non-negative on success/Negative on failure
1882  *
1883  * Programmer:	Quincey Koziol
1884  *		koziol@hdfgroup.org
1885  *		Dec  6 2006
1886  *
1887  *-------------------------------------------------------------------------
1888  */
1889 herr_t
H5A__dense_delete(H5F_t * f,H5O_ainfo_t * ainfo)1890 H5A__dense_delete(H5F_t *f, H5O_ainfo_t *ainfo)
1891 {
1892     H5A_bt2_ud_common_t udata;          /* v2 B-tree user data for deleting attributes */
1893     H5HF_t *fheap = NULL;               /* Fractal heap handle */
1894     herr_t ret_value = SUCCEED;         /* Return value */
1895 
1896     FUNC_ENTER_PACKAGE
1897 
1898     /*
1899      * Check arguments.
1900      */
1901     HDassert(f);
1902     HDassert(ainfo);
1903 
1904     /* Open the fractal heap */
1905     if(NULL == (fheap = H5HF_open(f, ainfo->fheap_addr)))
1906         HGOTO_ERROR(H5E_ATTR, H5E_CANTOPENOBJ, FAIL, "unable to open fractal heap")
1907 
1908     /* Create the "udata" information for v2 B-tree 'delete' */
1909     udata.f = f;
1910     udata.fheap = fheap;
1911     udata.shared_fheap = NULL;
1912     udata.name = NULL;
1913     udata.name_hash = 0;
1914     udata.flags = 0;
1915     udata.found_op = NULL;       /* v2 B-tree comparison callback */
1916     udata.found_op_data = NULL;
1917 
1918     /* Delete name index v2 B-tree */
1919     if(H5B2_delete(f, ainfo->name_bt2_addr, NULL, H5A__dense_delete_bt2_cb, &udata) < 0)
1920         HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for name index")
1921     ainfo->name_bt2_addr = HADDR_UNDEF;
1922 
1923     /* Release resources */
1924     if(H5HF_close(fheap) < 0)
1925         HGOTO_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1926     fheap = NULL;
1927 
1928     /* Check if we should delete the creation order index v2 B-tree */
1929     if(H5F_addr_defined(ainfo->corder_bt2_addr)) {
1930         /* Delete the creation order index, without adjusting the ref. count on the attributes  */
1931         if(H5B2_delete(f, ainfo->corder_bt2_addr, NULL, NULL, NULL) < 0)
1932             HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index")
1933         ainfo->corder_bt2_addr = HADDR_UNDEF;
1934     } /* end if */
1935 
1936     /* Delete fractal heap */
1937     if(H5HF_delete(f, ainfo->fheap_addr) < 0)
1938         HGOTO_ERROR(H5E_ATTR, H5E_CANTDELETE, FAIL, "unable to delete fractal heap")
1939     ainfo->fheap_addr = HADDR_UNDEF;
1940 
1941 done:
1942     /* Release resources */
1943     if(fheap && H5HF_close(fheap) < 0)
1944         HDONE_ERROR(H5E_ATTR, H5E_CLOSEERROR, FAIL, "can't close fractal heap")
1945 
1946     FUNC_LEAVE_NOAPI(ret_value)
1947 } /* end H5A__dense_delete() */
1948 
1949