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