Coverage Report

Created: 2024-06-18 06:29

/src/hdf5/src/H5Gobj.c
Line
Count
Source (jump to first uncovered line)
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 COPYING 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:   H5Gobj.c
16
 *
17
 * Purpose:   Functions for abstract handling of objects in groups.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Gmodule.h" /* This source code file is part of the H5G module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"  /* Generic Functions      */
32
#include "H5Eprivate.h" /* Error handling       */
33
#include "H5Fprivate.h" /* File access        */
34
#include "H5Gpkg.h"     /* Groups         */
35
#include "H5Iprivate.h" /* IDs            */
36
#include "H5Lprivate.h" /* Links          */
37
#include "H5Pprivate.h" /* Property Lists     */
38
39
/****************/
40
/* Local Macros */
41
/****************/
42
43
/******************/
44
/* Local Typedefs */
45
/******************/
46
47
/* User data for object header iterator when converting link messages to dense
48
 * link storage
49
 */
50
typedef struct {
51
    H5F_t       *f;       /* Pointer to file for insertion */
52
    haddr_t      oh_addr; /* Address of the object header */
53
    H5O_linfo_t *linfo;   /* Pointer to link info */
54
} H5G_obj_oh_it_ud1_t;
55
56
/* User data for link iterator when converting dense link storage to link
57
 * messages
58
 */
59
typedef struct {
60
    H5O_link_t *lnk_table;   /* Array of links to convert */
61
    size_t      nlinks;      /* Number of links converted */
62
    size_t      alloc_links; /* Size of link table        */
63
} H5G_obj_lnk_it_ud1_t;
64
65
/* User data for symbol table iterator when converting old-format group to
66
 * a new-format group
67
 */
68
typedef struct {
69
    const H5O_loc_t *grp_oloc; /* Pointer to group for insertion */
70
} H5G_obj_stab_it_ud1_t;
71
72
/********************/
73
/* Package Typedefs */
74
/********************/
75
76
/********************/
77
/* Local Prototypes */
78
/********************/
79
static herr_t H5G__obj_compact_to_dense_cb(const void *_mesg, unsigned idx, void *_udata);
80
static herr_t H5G__obj_remove_update_linfo(const H5O_loc_t *oloc, H5O_linfo_t *linfo);
81
82
/*********************/
83
/* Package Variables */
84
/*********************/
85
86
/*****************************/
87
/* Library Private Variables */
88
/*****************************/
89
90
/*******************/
91
/* Local Variables */
92
/*******************/
93
94
/*-------------------------------------------------------------------------
95
 * Function:    H5G__obj_create
96
 *
97
 * Purpose:     Create an object header for a group and update object location info
98
 *
99
 * Return:      Non-negative on success/Negative on failure
100
 *
101
 *-------------------------------------------------------------------------
102
 */
103
herr_t
104
H5G__obj_create(H5F_t *f, H5G_obj_create_t *gcrt_info, H5O_loc_t *oloc /*out*/)
105
0
{
106
0
    H5P_genplist_t *gc_plist;            /* Group creation property list */
107
0
    H5O_ginfo_t     ginfo;               /* Group info */
108
0
    H5O_linfo_t     linfo;               /* Link info */
109
0
    H5O_pline_t     pline;               /* Pipeline */
110
0
    herr_t          ret_value = SUCCEED; /* Return value */
111
112
0
    FUNC_ENTER_PACKAGE
113
114
    /*
115
     * Check arguments.
116
     */
117
0
    assert(f);
118
0
    assert(oloc);
119
120
    /* Get the property list */
121
0
    if (NULL == (gc_plist = (H5P_genplist_t *)H5I_object(gcrt_info->gcpl_id)))
122
0
        HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "not a property list");
123
124
    /* Get the group info property */
125
0
    if (H5P_get(gc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0)
126
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get group info");
127
128
    /* Get the link info property */
129
0
    if (H5P_get(gc_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0)
130
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get group info");
131
132
    /* Get the pipeline property */
133
0
    if (H5P_peek(gc_plist, H5O_CRT_PIPELINE_NAME, &pline) < 0)
134
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't get group info");
135
136
    /* Call the "real" group creation routine now */
137
0
    if (H5G__obj_create_real(f, &ginfo, &linfo, &pline, gcrt_info, oloc) < 0)
138
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "unable to create group");
139
140
0
done:
141
0
    FUNC_LEAVE_NOAPI(ret_value)
142
0
} /* end H5G__obj_create() */
143
144
/*-------------------------------------------------------------------------
145
 * Function:    H5G__obj_create_real
146
 *
147
 * Purpose:     Create an object header for a group and update object location info
148
 *
149
 * Return:      Non-negative on success/Negative on failure
150
 *
151
 *-------------------------------------------------------------------------
152
 */
153
herr_t
154
H5G__obj_create_real(H5F_t *f, const H5O_ginfo_t *ginfo, const H5O_linfo_t *linfo, const H5O_pline_t *pline,
155
                     H5G_obj_create_t *gcrt_info, H5O_loc_t *oloc /*out*/)
156
0
{
157
0
    size_t hdr_size;                       /* Size of object header to request */
158
0
    bool   use_at_least_v18;               /* Flag indicating the new group format should be used */
159
0
    hid_t  gcpl_id   = gcrt_info->gcpl_id; /* Group creation property list ID */
160
0
    herr_t ret_value = SUCCEED;            /* Return value */
161
162
0
    FUNC_ENTER_PACKAGE
163
164
    /*
165
     * Check arguments.
166
     */
167
0
    assert(f);
168
0
    assert(ginfo);
169
0
    assert(linfo);
170
0
    assert(pline);
171
0
    assert(oloc);
172
173
    /* Check for invalid access request */
174
0
    if (0 == (H5F_INTENT(f) & H5F_ACC_RDWR))
175
0
        HGOTO_ERROR(H5E_CACHE, H5E_BADVALUE, FAIL, "no write intent on file");
176
177
    /* Check for using the latest version of the group format which is introduced in v18 */
178
    /* (add more checks for creating "new format" groups when needed) */
179
0
    if ((H5F_LOW_BOUND(f) >= H5F_LIBVER_V18) || linfo->track_corder || (pline && pline->nused))
180
0
        use_at_least_v18 = true;
181
0
    else
182
0
        use_at_least_v18 = false;
183
184
    /* Make certain that the creation order is being tracked if an index is
185
     *  going to be built on it.
186
     */
187
0
    if (linfo->index_corder && !linfo->track_corder)
188
0
        HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "must track creation order to create index for it");
189
190
    /* Check if we should be using the latest version of the group format */
191
0
    if (use_at_least_v18) {
192
0
        H5O_link_t lnk;              /* Temporary link message info for computing message size */
193
0
        char       null_char = '\0'; /* Character for creating null string */
194
0
        size_t     ginfo_size;       /* Size of the group info message */
195
0
        size_t     linfo_size;       /* Size of the link info message */
196
0
        size_t     pline_size = 0;   /* Size of the pipeline message */
197
0
        size_t     link_size;        /* Size of a link message */
198
199
        /* Calculate message size information, for creating group's object header */
200
0
        linfo_size = H5O_msg_size_f(f, gcpl_id, H5O_LINFO_ID, linfo, (size_t)0);
201
0
        assert(linfo_size);
202
203
0
        ginfo_size = H5O_msg_size_f(f, gcpl_id, H5O_GINFO_ID, ginfo, (size_t)0);
204
0
        assert(ginfo_size);
205
206
0
        if (pline && pline->nused) {
207
0
            pline_size = H5O_msg_size_f(f, gcpl_id, H5O_PLINE_ID, pline, (size_t)0);
208
0
            assert(pline_size);
209
0
        } /* end if */
210
211
0
        lnk.type         = H5L_TYPE_HARD;
212
0
        lnk.corder       = 0;
213
0
        lnk.corder_valid = linfo->track_corder;
214
0
        lnk.cset         = H5T_CSET_ASCII;
215
0
        lnk.name         = &null_char;
216
0
        link_size        = H5O_msg_size_f(f, gcpl_id, H5O_LINK_ID, &lnk, (size_t)ginfo->est_name_len);
217
0
        assert(link_size);
218
219
        /* Compute size of header to use for creation */
220
221
        /* Basic header size */
222
0
        hdr_size = linfo_size + ginfo_size + pline_size;
223
224
        /* If this is likely to be a compact group, add space for the link
225
         * messages, unless the size of the link messages is greater than
226
         * the largest allowable object header message size, since the size
227
         * of the link messages is the size of the NIL spacer message that
228
         * would have to be written out to reserve enough space to hold the
229
         * links if the group were left empty.
230
         */
231
0
        bool compact = ginfo->est_num_entries <= ginfo->max_compact;
232
0
        if (compact) {
233
234
0
            size_t size_of_links = ginfo->est_num_entries * link_size;
235
236
0
            if (size_of_links < H5O_MESG_MAX_SIZE)
237
0
                hdr_size += size_of_links;
238
0
        }
239
0
    } /* end if */
240
0
    else
241
0
        hdr_size = (size_t)(4 + 2 * H5F_SIZEOF_ADDR(f));
242
243
    /*
244
     * Create group's object header.  It has a zero link count
245
     * since nothing refers to it yet.  The link count will be
246
     * incremented if the object is added to the group directed graph.
247
     */
248
0
    if (H5O_create(f, hdr_size, (size_t)1, gcpl_id, oloc /*out*/) < 0)
249
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create header");
250
251
    /* Check for format of group to create */
252
0
    if (use_at_least_v18) {
253
0
        H5_GCC_CLANG_DIAG_OFF("cast-qual")
254
        /* Insert link info message */
255
0
        if (H5O_msg_create(oloc, H5O_LINFO_ID, 0, H5O_UPDATE_TIME, (void *)linfo) < 0)
256
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
257
258
        /* Insert group info message */
259
0
        if (H5O_msg_create(oloc, H5O_GINFO_ID, H5O_MSG_FLAG_CONSTANT, 0, (void *)ginfo) < 0)
260
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
261
262
        /* Insert pipeline message */
263
0
        if (pline && pline->nused)
264
0
            if (H5O_msg_create(oloc, H5O_PLINE_ID, H5O_MSG_FLAG_CONSTANT, 0, (void *)pline) < 0)
265
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
266
0
        H5_GCC_CLANG_DIAG_ON("cast-qual")
267
0
    } /* end if */
268
0
    else {
269
0
        H5O_stab_t stab; /* Symbol table message  */
270
271
        /* The group doesn't currently have a 'stab' message, go create one */
272
0
        if (H5G__stab_create(oloc, ginfo, &stab) < 0)
273
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create symbol table");
274
275
        /* Cache the symbol table information */
276
0
        gcrt_info->cache_type            = H5G_CACHED_STAB;
277
0
        gcrt_info->cache.stab.btree_addr = stab.btree_addr;
278
0
        gcrt_info->cache.stab.heap_addr  = stab.heap_addr;
279
0
    } /* end else */
280
281
0
done:
282
0
    FUNC_LEAVE_NOAPI(ret_value)
283
0
} /* end H5G__obj_create_real() */
284
285
/*-------------------------------------------------------------------------
286
 * Function:    H5G__obj_get_linfo
287
 *
288
 * Purpose:     Retrieves the "link info" message for an object.  Also
289
 *              sets the number of links correctly, if it isn't set up yet.
290
 *
291
 * Return:  Success:  true/false whether message was found & retrieved
292
 *              Failure:        FAIL if error occurred
293
 *
294
 *-------------------------------------------------------------------------
295
 */
296
htri_t
297
H5G__obj_get_linfo(const H5O_loc_t *grp_oloc, H5O_linfo_t *linfo)
298
363
{
299
363
    H5B2_t *bt2_name  = NULL; /* v2 B-tree handle for name index */
300
363
    htri_t  ret_value = FAIL; /* Return value */
301
302
363
    FUNC_ENTER_PACKAGE_TAG(grp_oloc->addr)
303
304
    /* check arguments */
305
363
    assert(grp_oloc);
306
363
    assert(linfo);
307
308
    /* Check for the group having a link info message */
309
363
    if ((ret_value = H5O_msg_exists(grp_oloc, H5O_LINFO_ID)) < 0)
310
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header");
311
363
    if (ret_value) {
312
        /* Retrieve the "link info" structure */
313
0
        if (NULL == H5O_msg_read(grp_oloc, H5O_LINFO_ID, linfo))
314
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "link info message not present");
315
316
        /* Check if we don't know how many links there are */
317
0
        if (linfo->nlinks == HSIZET_MAX) {
318
            /* Check if we are using "dense" link storage */
319
0
            if (H5_addr_defined(linfo->fheap_addr)) {
320
                /* Open the name index v2 B-tree */
321
0
                if (NULL == (bt2_name = H5B2_open(grp_oloc->file, linfo->name_bt2_addr, NULL)))
322
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for name index");
323
324
                /* Retrieve # of records in "name" B-tree */
325
                /* (should be same # of records in all indices) */
326
0
                if (H5B2_get_nrec(bt2_name, &linfo->nlinks) < 0)
327
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of records in index");
328
0
            } /* end if */
329
0
            else {
330
                /* Retrieve # of links from object header */
331
0
                if (H5O_get_nlinks(grp_oloc, &linfo->nlinks) < 0)
332
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't retrieve # of links for object");
333
0
            } /* end if */
334
0
        }     /* end if */
335
0
    }         /* end if */
336
337
363
done:
338
    /* Release resources */
339
363
    if (bt2_name && H5B2_close(bt2_name) < 0)
340
0
        HDONE_ERROR(H5E_SYM, H5E_CLOSEERROR, FAIL, "can't close v2 B-tree for name index");
341
342
363
    FUNC_LEAVE_NOAPI_TAG(ret_value)
343
363
} /* end H5G__obj_get_linfo() */
344
345
/*-------------------------------------------------------------------------
346
 * Function:  H5G__obj_compact_to_dense_cb
347
 *
348
 * Purpose: Callback routine for converting "compact" to "dense"
349
 *              link storage form.
350
 *
351
 * Return:  Non-negative on success/Negative on failure
352
 *
353
 *-------------------------------------------------------------------------
354
 */
355
static herr_t
356
H5G__obj_compact_to_dense_cb(const void *_mesg, unsigned H5_ATTR_UNUSED idx, void *_udata)
357
0
{
358
0
    const H5O_link_t    *lnk       = (const H5O_link_t *)_mesg;     /* Pointer to link */
359
0
    H5G_obj_oh_it_ud1_t *udata     = (H5G_obj_oh_it_ud1_t *)_udata; /* 'User data' passed in */
360
0
    herr_t               ret_value = H5_ITER_CONT;                  /* Return value */
361
362
0
    FUNC_ENTER_PACKAGE
363
364
    /* check arguments */
365
0
    assert(lnk);
366
0
    assert(udata);
367
368
    /* Insert link into dense link storage */
369
0
    if (H5G__dense_insert(udata->f, udata->linfo, lnk) < 0)
370
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert link into dense storage");
371
372
0
done:
373
0
    FUNC_LEAVE_NOAPI(ret_value)
374
0
} /* end H5G__obj_compact_to_dense_cb() */
375
376
/*-------------------------------------------------------------------------
377
 * Function:  H5G__obj_stab_to_new_cb
378
 *
379
 * Purpose: Callback routine for converting "symbol table" link storage to
380
 *              "new format" storage (either "compact" or "dense" storage).
381
 *
382
 * Return:  Non-negative on success/Negative on failure
383
 *
384
 *-------------------------------------------------------------------------
385
 */
386
static herr_t
387
H5G__obj_stab_to_new_cb(const H5O_link_t *lnk, void *_udata)
388
0
{
389
0
    H5G_obj_stab_it_ud1_t *udata     = (H5G_obj_stab_it_ud1_t *)_udata; /* 'User data' passed in */
390
0
    herr_t                 ret_value = H5_ITER_CONT;                    /* Return value */
391
392
0
    FUNC_ENTER_PACKAGE
393
394
    /* check arguments */
395
0
    assert(lnk);
396
0
    assert(udata);
397
398
    /* Insert link into group */
399
0
    H5_GCC_CLANG_DIAG_OFF("cast-qual")
400
0
    if (H5G_obj_insert(udata->grp_oloc, (H5O_link_t *)lnk, false, H5O_TYPE_UNKNOWN, NULL) < 0)
401
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, H5_ITER_ERROR, "can't insert link into group");
402
0
    H5_GCC_CLANG_DIAG_ON("cast-qual")
403
404
0
done:
405
0
    FUNC_LEAVE_NOAPI(ret_value)
406
0
} /* end H5G__obj_stab_to_new_cb() */
407
408
/*-------------------------------------------------------------------------
409
 * Function:  H5G_obj_insert
410
 *
411
 * Purpose: Insert a new symbol into the group described by GRP_OLOC.
412
 *    file F.  The name of the new symbol is OBJ_LNK->NAME and its
413
 *    symbol table entry is OBJ_LNK.  Increment the reference
414
 *              count for the object the link points if OBJ_LNK is a hard link
415
 *              and ADJ_LINK is true.
416
 *
417
 * Return:  Non-negative on success/Negative on failure
418
 *
419
 *-------------------------------------------------------------------------
420
 */
421
herr_t
422
H5G_obj_insert(const H5O_loc_t *grp_oloc, H5O_link_t *obj_lnk, bool adj_link, H5O_type_t obj_type,
423
               const void *crt_info)
424
0
{
425
0
    H5O_pline_t  tmp_pline;             /* Pipeline message */
426
0
    H5O_pline_t *pline = NULL;          /* Pointer to pipeline message */
427
0
    H5O_linfo_t  linfo;                 /* Link info message */
428
0
    htri_t       linfo_exists;          /* Whether the link info message exists */
429
0
    bool         use_old_format;        /* Whether to use 'old format' (symbol table) for insertions or not */
430
0
    bool         use_new_dense = false; /* Whether to use "dense" form of 'new format' group */
431
0
    herr_t       ret_value     = SUCCEED; /* Return value */
432
433
0
    FUNC_ENTER_NOAPI_TAG(grp_oloc->addr, FAIL)
434
435
    /* check arguments */
436
0
    assert(grp_oloc && grp_oloc->file);
437
0
    assert(obj_lnk);
438
439
    /* Check if we have information about the number of objects in this group */
440
    /* (by attempting to get the link info message for this group) */
441
0
    if ((linfo_exists = H5G__obj_get_linfo(grp_oloc, &linfo)) < 0)
442
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
443
0
    if (linfo_exists) {
444
0
        H5O_ginfo_t ginfo;         /* Group info message */
445
0
        size_t      link_msg_size; /* Size of new link message in the file */
446
447
        /* Using the new format for groups */
448
0
        use_old_format = false;
449
450
        /* Check for tracking creation order on this group's links */
451
0
        if (linfo.track_corder) {
452
            /* Set the creation order for the new link & indicate that it's valid */
453
0
            obj_lnk->corder       = linfo.max_corder;
454
0
            obj_lnk->corder_valid = true;
455
456
            /* Increment the max. creation order used in the group */
457
0
            linfo.max_corder++;
458
0
        } /* end if */
459
460
        /* Get the link's message size */
461
0
        if ((link_msg_size = H5O_msg_raw_size(grp_oloc->file, H5O_LINK_ID, false, obj_lnk)) == 0)
462
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTGETSIZE, FAIL, "can't get link size");
463
464
        /* Get the group info */
465
0
        if (NULL == H5O_msg_read(grp_oloc, H5O_GINFO_ID, &ginfo))
466
0
            HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info");
467
468
        /* If there's still a small enough number of links, use the 'link' message */
469
        /* (If the encoded form of the link is too large to fit into an object
470
         *  header message, convert to using dense link storage instead of link messages)
471
         */
472
0
        if (H5_addr_defined(linfo.fheap_addr))
473
0
            use_new_dense = true;
474
0
        else if (linfo.nlinks < ginfo.max_compact && link_msg_size < H5O_MESG_MAX_SIZE)
475
0
            use_new_dense = false;
476
0
        else {
477
0
            htri_t              pline_exists; /* Whether the pipeline message exists */
478
0
            H5G_obj_oh_it_ud1_t udata;        /* User data for iteration */
479
0
            H5O_mesg_operator_t op;           /* Message operator */
480
481
            /* Get the pipeline message, if it exists */
482
0
            if ((pline_exists = H5O_msg_exists(grp_oloc, H5O_PLINE_ID)) < 0)
483
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "unable to read object header");
484
0
            if (pline_exists) {
485
0
                if (NULL == H5O_msg_read(grp_oloc, H5O_PLINE_ID, &tmp_pline))
486
0
                    HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link pipeline");
487
0
                pline = &tmp_pline;
488
0
            } /* end if */
489
490
            /* The group doesn't currently have "dense" storage for links */
491
0
            if (H5G__dense_create(grp_oloc->file, &linfo, pline) < 0)
492
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create 'dense' form of new format group");
493
494
            /* Set up user data for object header message iteration */
495
0
            udata.f       = grp_oloc->file;
496
0
            udata.oh_addr = grp_oloc->addr;
497
0
            udata.linfo   = &linfo;
498
499
            /* Iterate over the 'link' messages, inserting them into the dense link storage  */
500
0
            op.op_type  = H5O_MESG_OP_APP;
501
0
            op.u.app_op = H5G__obj_compact_to_dense_cb;
502
0
            if (H5O_msg_iterate(grp_oloc, H5O_LINK_ID, &op, &udata) < 0)
503
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "error iterating over links");
504
505
            /* Remove all the 'link' messages */
506
0
            if (H5O_msg_remove(grp_oloc, H5O_LINK_ID, H5O_ALL, false) < 0)
507
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete link messages");
508
509
0
            use_new_dense = true;
510
0
        } /* end else */
511
0
    }     /* end if */
512
0
    else {
513
        /* Check for new-style link information */
514
0
        if (obj_lnk->cset != H5T_CSET_ASCII || obj_lnk->type > H5L_TYPE_BUILTIN_MAX) {
515
0
            H5O_linfo_t           new_linfo = H5G_CRT_LINK_INFO_DEF;  /* Link information */
516
0
            H5O_ginfo_t           new_ginfo = H5G_CRT_GROUP_INFO_DEF; /* Group information */
517
0
            H5G_obj_stab_it_ud1_t udata;                              /* User data for iteration */
518
519
            /* Convert group to "new format" group, in order to hold the information */
520
521
            /* Insert link info message */
522
0
            if (H5O_msg_create(grp_oloc, H5O_LINFO_ID, 0, 0, &new_linfo) < 0)
523
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
524
525
            /* Insert group info message */
526
0
            if (H5O_msg_create(grp_oloc, H5O_GINFO_ID, H5O_MSG_FLAG_CONSTANT, H5O_UPDATE_TIME, &new_ginfo) <
527
0
                0)
528
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
529
530
            /* Set up user data for iteration */
531
0
            udata.grp_oloc = grp_oloc;
532
533
            /* Iterate through all links in "old format" group and insert them into new format */
534
0
            if (H5G__stab_iterate(grp_oloc, H5_ITER_NATIVE, (hsize_t)0, NULL, H5G__obj_stab_to_new_cb,
535
0
                                  &udata) < 0)
536
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over old format links");
537
538
            /* Remove the symbol table message from the group */
539
0
            if (H5O_msg_remove(grp_oloc, H5O_STAB_ID, 0, false) < 0)
540
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete old format link storage");
541
542
            /* Recursively call this routine to insert the new link, since the
543
             *  group is in the "new format" now and the link info should be
544
             *  set up, etc.
545
             */
546
0
            if (H5G_obj_insert(grp_oloc, obj_lnk, adj_link, obj_type, crt_info) < 0)
547
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert link into group");
548
549
            /* Done with insertion now */
550
0
            HGOTO_DONE(SUCCEED);
551
0
        } /* end if */
552
0
        else
553
0
            use_old_format = true;
554
0
    } /* end if */
555
556
    /* Insert into symbol table or "dense" storage */
557
0
    if (use_old_format) {
558
        /* Insert into symbol table */
559
0
        if (H5G__stab_insert(grp_oloc, obj_lnk, obj_type, crt_info) < 0)
560
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert entry into symbol table");
561
0
    } /* end if */
562
0
    else {
563
0
        if (use_new_dense) {
564
            /* Insert into dense link storage */
565
0
            if (H5G__dense_insert(grp_oloc->file, &linfo, obj_lnk) < 0)
566
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert link into dense storage");
567
0
        } /* end if */
568
0
        else {
569
            /* Insert with link message */
570
0
            if (H5G__compact_insert(grp_oloc, obj_lnk) < 0)
571
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert link as link message");
572
0
        } /* end else */
573
0
    }     /* end else */
574
575
    /* Increment the number of objects in this group */
576
0
    if (!use_old_format) {
577
0
        linfo.nlinks++;
578
0
        if (H5O_msg_write(grp_oloc, H5O_LINFO_ID, 0, H5O_UPDATE_TIME, &linfo) < 0)
579
0
            HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update link info message");
580
0
    } /* end if */
581
582
    /* Increment link count on object, if requested and it's a hard link */
583
0
    if (adj_link && obj_lnk->type == H5L_TYPE_HARD) {
584
0
        H5O_loc_t obj_oloc; /* Object location */
585
0
        H5O_loc_reset(&obj_oloc);
586
587
        /* Create temporary object location */
588
0
        obj_oloc.file = grp_oloc->file;
589
0
        obj_oloc.addr = obj_lnk->u.hard.addr;
590
591
        /* Increment reference count for object */
592
0
        if (H5O_link(&obj_oloc, 1) < 0)
593
0
            HGOTO_ERROR(H5E_SYM, H5E_LINKCOUNT, FAIL, "unable to increment hard link count");
594
0
    } /* end if */
595
596
0
done:
597
    /* Free any space used by the pipeline message */
598
0
    if (pline && H5O_msg_reset(H5O_PLINE_ID, pline) < 0)
599
0
        HDONE_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "can't release pipeline");
600
601
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
602
0
} /* end H5G_obj_insert() */
603
604
/*-------------------------------------------------------------------------
605
 * Function:  H5G__obj_iterate
606
 *
607
 * Purpose:     Private function for H5Giterate.
608
 *              Iterates over objects in a group
609
 *
610
 * Return:  Success:        Non-negative
611
 *
612
 *    Failure:  Negative
613
 *
614
 *-------------------------------------------------------------------------
615
 */
616
herr_t
617
H5G__obj_iterate(const H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t skip,
618
                 hsize_t *last_lnk, H5G_lib_iterate_t op, void *op_data)
619
76
{
620
76
    H5O_linfo_t linfo;            /* Link info message */
621
76
    htri_t      linfo_exists;     /* Whether the link info message exists */
622
76
    herr_t      ret_value = FAIL; /* Return value */
623
624
76
    FUNC_ENTER_PACKAGE_TAG(grp_oloc->addr)
625
626
    /* Sanity check */
627
76
    assert(grp_oloc);
628
76
    assert(op);
629
630
    /* Attempt to get the link info for this group */
631
76
    if ((linfo_exists = H5G__obj_get_linfo(grp_oloc, &linfo)) < 0)
632
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
633
76
    if (linfo_exists) {
634
        /* Check for going out of bounds */
635
0
        if (skip > 0 && (size_t)skip >= linfo.nlinks)
636
0
            HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "index out of bound");
637
638
        /* Check for creation order tracking, if creation order index lookup requested */
639
0
        if (idx_type == H5_INDEX_CRT_ORDER) {
640
            /* Check if creation order is tracked */
641
0
            if (!linfo.track_corder)
642
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "creation order not tracked for links in group");
643
0
        } /* end if */
644
645
0
        if (H5_addr_defined(linfo.fheap_addr)) {
646
            /* Iterate over the links in the group, building a table of the link messages */
647
0
            if ((ret_value = H5G__dense_iterate(grp_oloc->file, &linfo, idx_type, order, skip, last_lnk, op,
648
0
                                                op_data)) < 0)
649
0
                HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over dense links");
650
0
        } /* end if */
651
0
        else {
652
            /* Get the object's name from the link messages */
653
0
            if ((ret_value = H5G__compact_iterate(grp_oloc, &linfo, idx_type, order, skip, last_lnk, op,
654
0
                                                  op_data)) < 0)
655
0
                HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over compact links");
656
0
        } /* end else */
657
0
    }     /* end if */
658
76
    else {
659
        /* Can only perform name lookups on groups with symbol tables */
660
76
        if (idx_type != H5_INDEX_NAME)
661
0
            HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query");
662
663
        /* Iterate over symbol table */
664
76
        if ((ret_value = H5G__stab_iterate(grp_oloc, order, skip, last_lnk, op, op_data)) < 0)
665
50
            HGOTO_ERROR(H5E_SYM, H5E_BADITER, FAIL, "can't iterate over symbol table");
666
76
    } /* end else */
667
668
76
done:
669
76
    FUNC_LEAVE_NOAPI_TAG(ret_value)
670
76
} /* end H5G__obj_iterate() */
671
672
/*-------------------------------------------------------------------------
673
 * Function:  H5G__obj_info
674
 *
675
 * Purpose: Retrieve information about a group
676
 *
677
 * Return:  Non-negative on success/Negative on failure
678
 *
679
 *-------------------------------------------------------------------------
680
 */
681
herr_t
682
H5G__obj_info(const H5O_loc_t *oloc, H5G_info_t *grp_info)
683
7
{
684
7
    H5G_t      *grp = NULL;          /* Group to query */
685
7
    H5G_loc_t   grp_loc;             /* Entry of group to be queried */
686
7
    H5G_name_t  grp_path;            /* Group hier. path */
687
7
    H5O_loc_t   grp_oloc;            /* Group object location */
688
7
    H5O_linfo_t linfo;               /* Link info message */
689
7
    htri_t      linfo_exists;        /* Whether the link info message exists */
690
7
    herr_t      ret_value = SUCCEED; /* Return value */
691
692
7
    FUNC_ENTER_PACKAGE
693
694
    /* Sanity check */
695
7
    assert(oloc);
696
7
    assert(grp_info);
697
698
    /* Set up group location to fill in */
699
7
    grp_loc.oloc = &grp_oloc;
700
7
    grp_loc.path = &grp_path;
701
7
    H5G_loc_reset(&grp_loc);
702
703
    /* Deep copy (duplicate) of the group location object */
704
7
    if (H5O_loc_copy_deep(&grp_oloc, oloc) < 0)
705
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "can't copy object location");
706
707
    /* Open the group */
708
7
    if (NULL == (grp = H5G_open(&grp_loc)))
709
0
        HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "mount point not found");
710
711
    /* Get information from the group */
712
7
    grp_info->mounted = H5G_MOUNTED(grp);
713
714
    /* Attempt to get the link info for this group */
715
7
    if ((linfo_exists = H5G__obj_get_linfo(oloc, &linfo)) < 0)
716
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
717
7
    if (linfo_exists) {
718
        /* Retrieve the information about the links */
719
0
        grp_info->nlinks     = linfo.nlinks;
720
0
        grp_info->max_corder = linfo.max_corder;
721
722
        /* Check if the group is using compact or dense storage for its links */
723
0
        if (H5_addr_defined(linfo.fheap_addr))
724
0
            grp_info->storage_type = H5G_STORAGE_TYPE_DENSE;
725
0
        else
726
0
            grp_info->storage_type = H5G_STORAGE_TYPE_COMPACT;
727
0
    } /* end if */
728
7
    else {
729
        /* Get the number of objects in this group by iterating over symbol table */
730
7
        if (H5G__stab_count(oloc, &grp_info->nlinks) < 0)
731
1
            HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "can't count objects");
732
733
        /* Set the other information about the group */
734
6
        grp_info->storage_type = H5G_STORAGE_TYPE_SYMBOL_TABLE;
735
6
        grp_info->max_corder   = 0;
736
6
    } /* end else */
737
738
7
done:
739
    /* Clean up resources */
740
7
    if (grp && H5G_close(grp) < 0)
741
0
        HDONE_ERROR(H5E_SYM, H5E_CANTCLOSEOBJ, FAIL, "unable to close queried group");
742
743
7
    FUNC_LEAVE_NOAPI(ret_value)
744
7
} /* end H5G__obj_info() */
745
746
/*-------------------------------------------------------------------------
747
 * Function:  H5G_obj_get_name_by_idx
748
 *
749
 * Purpose:     Returns the name of link in a group by giving index.
750
 *
751
 * Return:  Success:        Non-negative, length of name
752
 *    Failure:  Negative
753
 *
754
 *-------------------------------------------------------------------------
755
 */
756
herr_t
757
H5G_obj_get_name_by_idx(const H5O_loc_t *oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
758
                        char *name, size_t name_size, size_t *name_len)
759
138
{
760
138
    H5O_linfo_t linfo;               /* Link info message */
761
138
    htri_t      linfo_exists;        /* Whether the link info message exists */
762
138
    herr_t      ret_value = SUCCEED; /* Return value */
763
764
138
    FUNC_ENTER_NOAPI_TAG(oloc->addr, FAIL)
765
766
    /* Sanity check */
767
138
    assert(oloc && oloc->file);
768
769
    /* Attempt to get the link info for this group */
770
138
    if ((linfo_exists = H5G__obj_get_linfo(oloc, &linfo)) < 0)
771
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
772
138
    if (linfo_exists) {
773
        /* Check for creation order tracking, if creation order index lookup requested */
774
0
        if (idx_type == H5_INDEX_CRT_ORDER)
775
            /* Check if creation order is tracked */
776
0
            if (!linfo.track_corder)
777
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "creation order not tracked for links in group");
778
779
        /* Check for dense link storage */
780
0
        if (H5_addr_defined(linfo.fheap_addr)) {
781
            /* Get the object's name from the dense link storage */
782
0
            if (H5G__dense_get_name_by_idx(oloc->file, &linfo, idx_type, order, n, name, name_size,
783
0
                                           name_len) < 0)
784
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate name");
785
0
        } /* end if */
786
0
        else {
787
            /* Get the object's name from the link messages */
788
0
            if (H5G__compact_get_name_by_idx(oloc, &linfo, idx_type, order, n, name, name_size, name_len) < 0)
789
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate name");
790
0
        } /* end else */
791
0
    }     /* end if */
792
138
    else {
793
        /* Can only perform name lookups on groups with symbol tables */
794
138
        if (idx_type != H5_INDEX_NAME)
795
0
            HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query");
796
797
        /* Get the object's name from the symbol table */
798
138
        if (H5G__stab_get_name_by_idx(oloc, order, n, name, name_size, name_len) < 0)
799
2
            HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate name");
800
138
    } /* end else */
801
802
138
done:
803
138
    FUNC_LEAVE_NOAPI_TAG(ret_value)
804
138
} /* end H5G_obj_get_name_by_idx() */
805
806
/*-------------------------------------------------------------------------
807
 * Function:  H5G__obj_remove_update_linfo
808
 *
809
 * Purpose:     Update the link info after removing a link from a group
810
 *
811
 * Return:  Success:        Non-negative
812
 *    Failure:  Negative
813
 *
814
 *-------------------------------------------------------------------------
815
 */
816
static herr_t
817
H5G__obj_remove_update_linfo(const H5O_loc_t *oloc, H5O_linfo_t *linfo)
818
0
{
819
0
    herr_t ret_value = SUCCEED; /* Return value */
820
821
0
    FUNC_ENTER_PACKAGE
822
823
    /* Sanity check */
824
0
    assert(oloc);
825
0
    assert(linfo);
826
827
    /* Decrement # of links in group */
828
0
    linfo->nlinks--;
829
830
    /* Reset the creation order min/max if there's no more links in group */
831
0
    if (linfo->nlinks == 0)
832
0
        linfo->max_corder = 0;
833
834
    /* Check for transitioning out of dense storage, if we are using it */
835
0
    if (H5_addr_defined(linfo->fheap_addr)) {
836
        /* Check if there's no more links */
837
0
        if (linfo->nlinks == 0) {
838
            /* Delete the dense storage */
839
0
            if (H5G__dense_delete(oloc->file, linfo, false) < 0)
840
0
                HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage");
841
0
        } /* end if */
842
        /* Check for switching back to compact storage */
843
0
        else {
844
0
            H5O_ginfo_t ginfo; /* Group info message            */
845
846
            /* Get the group info */
847
0
            if (NULL == H5O_msg_read(oloc, H5O_GINFO_ID, &ginfo))
848
0
                HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get group info");
849
850
            /* Check if we should switch from dense storage back to link messages */
851
0
            if (linfo->nlinks < ginfo.min_dense) {
852
0
                struct H5O_t    *oh = NULL;          /* Pointer to group's object header */
853
0
                H5G_link_table_t ltable;             /* Table of links */
854
0
                bool             can_convert = true; /* Whether converting to link messages is possible */
855
0
                size_t           u;                  /* Local index */
856
857
                /* Build the table of links for this group */
858
0
                if (H5G__dense_build_table(oloc->file, linfo, H5_INDEX_NAME, H5_ITER_NATIVE, &ltable) < 0)
859
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links");
860
861
                /* Pin the object header */
862
0
                if (NULL == (oh = H5O_pin(oloc)))
863
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTPIN, FAIL, "unable to pin group object header");
864
865
                /* Inspect links in table for ones that can't be converted back
866
                 * into link message form (currently only links which can't fit
867
                 * into an object header message)
868
                 */
869
0
                for (u = 0; u < linfo->nlinks; u++)
870
0
                    if (H5O_msg_size_oh(oloc->file, oh, H5O_LINK_ID, &(ltable.lnks[u]), (size_t)0) >=
871
0
                        H5O_MESG_MAX_SIZE) {
872
0
                        can_convert = false;
873
0
                        break;
874
0
                    } /* end if */
875
876
                /* If ok, insert links as link messages */
877
0
                if (can_convert) {
878
                    /* Insert link messages into group */
879
0
                    for (u = 0; u < linfo->nlinks; u++)
880
0
                        if (H5O_msg_append_oh(oloc->file, oh, H5O_LINK_ID, 0, H5O_UPDATE_TIME,
881
0
                                              &(ltable.lnks[u])) < 0) {
882
                            /* Release object header */
883
0
                            if (H5O_unpin(oh) < 0)
884
0
                                HDONE_ERROR(H5E_SYM, H5E_CANTUNPIN, FAIL,
885
0
                                            "unable to unpin group object header");
886
887
0
                            HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create message");
888
0
                        } /* end if */
889
890
                    /* Remove the dense storage */
891
0
                    if (H5G__dense_delete(oloc->file, linfo, false) < 0)
892
0
                        HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete dense link storage");
893
0
                } /* end if */
894
895
                /* Release object header */
896
0
                if (H5O_unpin(oh) < 0)
897
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTUNPIN, FAIL, "unable to unpin group object header");
898
899
                /* Free link table information */
900
0
                if (H5G__link_release_table(&ltable) < 0)
901
0
                    HGOTO_ERROR(H5E_SYM, H5E_CANTFREE, FAIL, "unable to release link table");
902
0
            } /* end if */
903
0
        }     /* end else */
904
0
    }         /* end if */
905
906
    /* Update link info in the object header */
907
0
    if (H5O_msg_write(oloc, H5O_LINFO_ID, 0, H5O_UPDATE_TIME, linfo) < 0)
908
0
        HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update link info message");
909
910
0
done:
911
0
    FUNC_LEAVE_NOAPI(ret_value)
912
0
} /* end H5G__obj_remove_update_linfo() */
913
914
/*-------------------------------------------------------------------------
915
 * Function:  H5G_obj_remove
916
 *
917
 * Purpose:     Remove a link from a group.
918
 *
919
 * Return:  Success:        Non-negative
920
 *    Failure:  Negative
921
 *
922
 *-------------------------------------------------------------------------
923
 */
924
herr_t
925
H5G_obj_remove(const H5O_loc_t *oloc, H5RS_str_t *grp_full_path_r, const char *name)
926
0
{
927
0
    H5O_linfo_t linfo;               /* Link info message            */
928
0
    htri_t      linfo_exists;        /* Whether the link info message exists */
929
0
    bool        use_old_format;      /* Whether to use 'old format' (symbol table) for deletion or not */
930
0
    herr_t      ret_value = SUCCEED; /* Return value */
931
932
0
    FUNC_ENTER_NOAPI_TAG(oloc->addr, FAIL)
933
934
    /* Sanity check */
935
0
    assert(oloc);
936
0
    assert(name && *name);
937
938
    /* Attempt to get the link info for this group */
939
0
    if ((linfo_exists = H5G__obj_get_linfo(oloc, &linfo)) < 0)
940
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
941
0
    if (linfo_exists) {
942
        /* Using the new format for groups */
943
0
        use_old_format = false;
944
945
        /* Check for dense or compact storage */
946
0
        if (H5_addr_defined(linfo.fheap_addr)) {
947
            /* Remove object from the dense link storage */
948
0
            if (H5G__dense_remove(oloc->file, &linfo, grp_full_path_r, name) < 0)
949
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object");
950
0
        } /* end if */
951
0
        else
952
            /* Remove object from the link messages */
953
0
            if (H5G__compact_remove(oloc, grp_full_path_r, name) < 0)
954
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object");
955
0
    } /* end if */
956
0
    else {
957
        /* Using the old format for groups */
958
0
        use_old_format = true;
959
960
        /* Remove object from the symbol table */
961
0
        if (H5G__stab_remove(oloc, grp_full_path_r, name) < 0)
962
0
            HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object");
963
0
    } /* end else */
964
965
    /* Update link info for a new-style group */
966
0
    if (!use_old_format)
967
0
        if (H5G__obj_remove_update_linfo(oloc, &linfo) < 0)
968
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTUPDATE, FAIL, "unable to update link info");
969
970
0
done:
971
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
972
0
} /* end H5G_obj_remove() */
973
974
/*-------------------------------------------------------------------------
975
 * Function:  H5G_obj_remove_by_idx
976
 *
977
 * Purpose:     Remove a link from a group, according to the order within an index.
978
 *
979
 * Return:  Success:        Non-negative
980
 *    Failure:  Negative
981
 *
982
 *-------------------------------------------------------------------------
983
 */
984
herr_t
985
H5G_obj_remove_by_idx(const H5O_loc_t *grp_oloc, H5RS_str_t *grp_full_path_r, H5_index_t idx_type,
986
                      H5_iter_order_t order, hsize_t n)
987
0
{
988
0
    H5O_linfo_t linfo;               /* Link info message            */
989
0
    htri_t      linfo_exists;        /* Whether the link info message exists */
990
0
    bool        use_old_format;      /* Whether to use 'old format' (symbol table) for deletion or not */
991
0
    herr_t      ret_value = SUCCEED; /* Return value */
992
993
0
    FUNC_ENTER_NOAPI(FAIL)
994
995
    /* Sanity check */
996
0
    assert(grp_oloc && grp_oloc->file);
997
998
    /* Attempt to get the link info for this group */
999
0
    if ((linfo_exists = H5G__obj_get_linfo(grp_oloc, &linfo)) < 0)
1000
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
1001
0
    if (linfo_exists) {
1002
        /* Check for creation order tracking, if creation order index lookup requested */
1003
0
        if (idx_type == H5_INDEX_CRT_ORDER) {
1004
            /* Check if creation order is tracked */
1005
0
            if (!linfo.track_corder)
1006
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "creation order not tracked for links in group");
1007
0
        } /* end if */
1008
1009
        /* Using the new format for groups */
1010
0
        use_old_format = false;
1011
1012
        /* Check for dense or compact storage */
1013
0
        if (H5_addr_defined(linfo.fheap_addr)) {
1014
            /* Remove object from the dense link storage */
1015
0
            if (H5G__dense_remove_by_idx(grp_oloc->file, &linfo, grp_full_path_r, idx_type, order, n) < 0)
1016
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object");
1017
0
        } /* end if */
1018
0
        else {
1019
            /* Remove object from compact link storage */
1020
0
            if (H5G__compact_remove_by_idx(grp_oloc, &linfo, grp_full_path_r, idx_type, order, n) < 0)
1021
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object");
1022
0
        } /* end else */
1023
0
    }     /* end if */
1024
0
    else {
1025
        /* Can only perform name lookups on groups with symbol tables */
1026
0
        if (idx_type != H5_INDEX_NAME)
1027
0
            HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query");
1028
1029
        /* Using the old format for groups */
1030
0
        use_old_format = true;
1031
1032
        /* Remove object from the symbol table */
1033
0
        if (H5G__stab_remove_by_idx(grp_oloc, grp_full_path_r, order, n) < 0)
1034
0
            HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't remove object");
1035
0
    } /* end else */
1036
1037
    /* Update link info for a new-style group */
1038
0
    if (!use_old_format)
1039
0
        if (H5G__obj_remove_update_linfo(grp_oloc, &linfo) < 0)
1040
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTUPDATE, FAIL, "unable to update link info");
1041
1042
0
done:
1043
0
    FUNC_LEAVE_NOAPI(ret_value)
1044
0
} /* end H5G_obj_remove() */
1045
1046
/*-------------------------------------------------------------------------
1047
 * Function:  H5G__obj_lookup
1048
 *
1049
 * Purpose: Look up a link in a group, using the name as the key.
1050
 *
1051
 * Return:  Non-negative on success/Negative on failure
1052
 *
1053
 *-------------------------------------------------------------------------
1054
 */
1055
herr_t
1056
H5G__obj_lookup(const H5O_loc_t *grp_oloc, const char *name, bool *found, H5O_link_t *lnk)
1057
142
{
1058
142
    H5O_linfo_t linfo;               /* Link info message */
1059
142
    htri_t      linfo_exists;        /* Whether the link info message exists */
1060
142
    herr_t      ret_value = SUCCEED; /* Return value */
1061
1062
142
    FUNC_ENTER_PACKAGE_TAG(grp_oloc->addr)
1063
1064
    /* check arguments */
1065
142
    assert(grp_oloc && grp_oloc->file);
1066
142
    assert(name && *name);
1067
1068
    /* Attempt to get the link info message for this group */
1069
142
    if ((linfo_exists = H5G__obj_get_linfo(grp_oloc, &linfo)) < 0)
1070
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
1071
142
    if (linfo_exists) {
1072
        /* Check for dense link storage */
1073
0
        if (H5_addr_defined(linfo.fheap_addr)) {
1074
            /* Get the object's info from the dense link storage */
1075
0
            if (H5G__dense_lookup(grp_oloc->file, &linfo, name, found, lnk) < 0)
1076
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object");
1077
0
        } /* end if */
1078
0
        else {
1079
            /* Get the object's info from the link messages */
1080
0
            if (H5G__compact_lookup(grp_oloc, name, found, lnk) < 0)
1081
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object");
1082
0
        } /* end else */
1083
0
    }     /* end if */
1084
142
    else
1085
        /* Get the object's info from the symbol table */
1086
142
        if (H5G__stab_lookup(grp_oloc, name, found, lnk) < 0)
1087
0
            HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object");
1088
1089
142
done:
1090
142
    FUNC_LEAVE_NOAPI_TAG(ret_value)
1091
142
} /* end H5G__obj_lookup() */
1092
1093
/*-------------------------------------------------------------------------
1094
 * Function:  H5G_obj_lookup_by_idx
1095
 *
1096
 * Purpose: Look up link info in a group, according to an order within an
1097
 *              index.
1098
 *
1099
 * Return:  Non-negative on success/Negative on failure
1100
 *
1101
 *-------------------------------------------------------------------------
1102
 */
1103
herr_t
1104
H5G_obj_lookup_by_idx(const H5O_loc_t *grp_oloc, H5_index_t idx_type, H5_iter_order_t order, hsize_t n,
1105
                      H5O_link_t *lnk)
1106
0
{
1107
0
    H5O_linfo_t linfo;               /* Link info message */
1108
0
    htri_t      linfo_exists;        /* Whether the link info message exists */
1109
0
    herr_t      ret_value = SUCCEED; /* Return value */
1110
1111
0
    FUNC_ENTER_NOAPI_TAG(grp_oloc->addr, FAIL)
1112
1113
    /* check arguments */
1114
0
    assert(grp_oloc && grp_oloc->file);
1115
1116
    /* Attempt to get the link info message for this group */
1117
0
    if ((linfo_exists = H5G__obj_get_linfo(grp_oloc, &linfo)) < 0)
1118
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check for link info message");
1119
0
    if (linfo_exists) {
1120
        /* Check for creation order tracking, if creation order index lookup requested */
1121
0
        if (idx_type == H5_INDEX_CRT_ORDER) {
1122
            /* Check if creation order is tracked */
1123
0
            if (!linfo.track_corder)
1124
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "creation order not tracked for links in group");
1125
0
        } /* end if */
1126
1127
        /* Check for dense link storage */
1128
0
        if (H5_addr_defined(linfo.fheap_addr)) {
1129
            /* Get the link from the dense storage */
1130
0
            if (H5G__dense_lookup_by_idx(grp_oloc->file, &linfo, idx_type, order, n, lnk) < 0)
1131
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object");
1132
0
        } /* end if */
1133
0
        else {
1134
            /* Get the link from the link messages */
1135
0
            if (H5G__compact_lookup_by_idx(grp_oloc, &linfo, idx_type, order, n, lnk) < 0)
1136
0
                HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object");
1137
0
        } /* end else */
1138
0
    }     /* end if */
1139
0
    else {
1140
        /* Can only perform name lookups on groups with symbol tables */
1141
0
        if (idx_type != H5_INDEX_NAME)
1142
0
            HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "no creation order index to query");
1143
1144
        /* Get the object's info from the symbol table */
1145
0
        if (H5G__stab_lookup_by_idx(grp_oloc, order, n, lnk) < 0)
1146
0
            HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "can't locate object");
1147
0
    } /* end else */
1148
1149
0
done:
1150
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
1151
0
} /* end H5G_obj_lookup_by_idx() */