Coverage Report

Created: 2026-03-04 00:50

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