Coverage Report

Created: 2025-08-03 06:26

/src/hdf5/src/H5Gbtree2.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 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:   H5Gbtree2.c
16
 *
17
 * Purpose:   v2 B-tree callbacks for indexing fields on links
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 "H5Gpkg.h"      /* Groups          */
34
#include "H5MMprivate.h" /* Memory management     */
35
36
/****************/
37
/* Local Macros */
38
/****************/
39
40
/******************/
41
/* Local Typedefs */
42
/******************/
43
44
/*
45
 * Data exchange structure for dense link storage.  This structure is
46
 * passed through the fractal heap layer to compare links.
47
 */
48
typedef struct H5G_fh_ud_cmp_t {
49
    /* downward */
50
    H5F_t       *f;             /* Pointer to file that fractal heap is in */
51
    const char  *name;          /* Name of link to compare           */
52
    H5B2_found_t found_op;      /* Callback when correct link is found */
53
    void        *found_op_data; /* Callback data when correct link is found */
54
55
    /* upward */
56
    int cmp; /* Comparison of two link names      */
57
} H5G_fh_ud_cmp_t;
58
59
/********************/
60
/* Package Typedefs */
61
/********************/
62
63
/********************/
64
/* Local Prototypes */
65
/********************/
66
67
/* v2 B-tree function callbacks */
68
69
/* v2 B-tree driver callbacks for 'creation order' index */
70
static herr_t H5G__dense_btree2_corder_store(void *native, const void *udata);
71
static herr_t H5G__dense_btree2_corder_compare(const void *rec1, const void *rec2, int *result);
72
static herr_t H5G__dense_btree2_corder_encode(uint8_t *raw, const void *native, void *ctx);
73
static herr_t H5G__dense_btree2_corder_decode(const uint8_t *raw, void *native, void *ctx);
74
static herr_t H5G__dense_btree2_corder_debug(FILE *stream, int indent, int fwidth, const void *record,
75
                                             const void *_udata);
76
77
/* v2 B-tree driver callbacks for 'name' index */
78
static herr_t H5G__dense_btree2_name_store(void *native, const void *udata);
79
static herr_t H5G__dense_btree2_name_compare(const void *rec1, const void *rec2, int *result);
80
static herr_t H5G__dense_btree2_name_encode(uint8_t *raw, const void *native, void *ctx);
81
static herr_t H5G__dense_btree2_name_decode(const uint8_t *raw, void *native, void *ctx);
82
static herr_t H5G__dense_btree2_name_debug(FILE *stream, int indent, int fwidth, const void *record,
83
                                           const void *_udata);
84
85
/* Fractal heap function callbacks */
86
static herr_t H5G__dense_fh_name_cmp(const void *obj, size_t obj_len, void *op_data);
87
88
/*********************/
89
/* Package Variables */
90
/*********************/
91
/* v2 B-tree class for indexing 'name' field of links */
92
const H5B2_class_t H5G_BT2_NAME[1] = {{
93
    /* B-tree class information */
94
    H5B2_GRP_DENSE_NAME_ID,           /* Type of B-tree */
95
    "H5B2_GRP_DENSE_NAME_ID",         /* Name of B-tree class */
96
    sizeof(H5G_dense_bt2_name_rec_t), /* Size of native record */
97
    NULL,                             /* Create client callback context */
98
    NULL,                             /* Destroy client callback context */
99
    H5G__dense_btree2_name_store,     /* Record storage callback */
100
    H5G__dense_btree2_name_compare,   /* Record comparison callback */
101
    H5G__dense_btree2_name_encode,    /* Record encoding callback */
102
    H5G__dense_btree2_name_decode,    /* Record decoding callback */
103
    H5G__dense_btree2_name_debug      /* Record debugging callback */
104
}};
105
106
/* v2 B-tree class for indexing 'creation order' field of links */
107
const H5B2_class_t H5G_BT2_CORDER[1] = {{
108
    /* B-tree class information */
109
    H5B2_GRP_DENSE_CORDER_ID,           /* Type of B-tree */
110
    "H5B2_GRP_DENSE_CORDER_ID",         /* Name of B-tree class */
111
    sizeof(H5G_dense_bt2_corder_rec_t), /* Size of native record */
112
    NULL,                               /* Create client callback context */
113
    NULL,                               /* Destroy client callback context */
114
    H5G__dense_btree2_corder_store,     /* Record storage callback */
115
    H5G__dense_btree2_corder_compare,   /* Record comparison callback */
116
    H5G__dense_btree2_corder_encode,    /* Record encoding callback */
117
    H5G__dense_btree2_corder_decode,    /* Record decoding callback */
118
    H5G__dense_btree2_corder_debug      /* Record debugging callback */
119
}};
120
121
/*****************************/
122
/* Library Private Variables */
123
/*****************************/
124
125
/*******************/
126
/* Local Variables */
127
/*******************/
128
129
/*-------------------------------------------------------------------------
130
 * Function:  H5G__dense_fh_name_cmp
131
 *
132
 * Purpose: Compares the name of a link in a fractal heap to another
133
 *              name
134
 *
135
 * Return:  SUCCEED/FAIL
136
 *
137
 *-------------------------------------------------------------------------
138
 */
139
static herr_t
140
H5G__dense_fh_name_cmp(const void *obj, size_t obj_len, void *_udata)
141
0
{
142
0
    H5G_fh_ud_cmp_t *udata = (H5G_fh_ud_cmp_t *)_udata; /* User data for 'op' callback */
143
0
    H5O_link_t      *lnk;                               /* Pointer to link created from heap object */
144
0
    herr_t           ret_value = SUCCEED;               /* Return value */
145
146
0
    FUNC_ENTER_PACKAGE
147
148
    /* Decode link information */
149
0
    if (NULL == (lnk = (H5O_link_t *)H5O_msg_decode(udata->f, NULL, H5O_LINK_ID, obj_len,
150
0
                                                    (const unsigned char *)obj)))
151
0
        HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode link");
152
153
    /* Compare the string values */
154
0
    udata->cmp = strcmp(udata->name, lnk->name);
155
156
    /* Check for correct link & callback to make */
157
0
    if (udata->cmp == 0 && udata->found_op) {
158
0
        if ((udata->found_op)(lnk, udata->found_op_data) < 0)
159
0
            HGOTO_ERROR(H5E_SYM, H5E_CANTOPERATE, FAIL, "link found callback failed");
160
0
    } /* end if */
161
162
    /* Release the space allocated for the link */
163
0
    H5O_msg_free(H5O_LINK_ID, lnk);
164
165
0
done:
166
0
    FUNC_LEAVE_NOAPI(ret_value)
167
0
} /* end H5G__dense_fh_name_cmp() */
168
169
/*-------------------------------------------------------------------------
170
 * Function:  H5G__dense_btree2_name_store
171
 *
172
 * Purpose: Store user information into native record for v2 B-tree
173
 *
174
 * Return:  Success:  non-negative
175
 *    Failure:  negative
176
 *
177
 *-------------------------------------------------------------------------
178
 */
179
static herr_t
180
H5G__dense_btree2_name_store(void *_nrecord, const void *_udata)
181
0
{
182
0
    const H5G_bt2_ud_ins_t   *udata   = (const H5G_bt2_ud_ins_t *)_udata;
183
0
    H5G_dense_bt2_name_rec_t *nrecord = (H5G_dense_bt2_name_rec_t *)_nrecord;
184
185
0
    FUNC_ENTER_PACKAGE_NOERR
186
187
    /* Copy user information info native record */
188
0
    nrecord->hash = udata->common.name_hash;
189
0
    H5MM_memcpy(nrecord->id, udata->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
190
191
0
    FUNC_LEAVE_NOAPI(SUCCEED)
192
0
} /* H5G__dense_btree2_name_store() */
193
194
/*-------------------------------------------------------------------------
195
 * Function:  H5G__dense_btree2_name_compare
196
 *
197
 * Purpose: Compare two native information records, according to some key
198
 *
199
 * Return:  <0 if rec1 < rec2
200
 *              =0 if rec1 == rec2
201
 *              >0 if rec1 > rec2
202
 *
203
 *-------------------------------------------------------------------------
204
 */
205
static herr_t
206
H5G__dense_btree2_name_compare(const void *_bt2_udata, const void *_bt2_rec, int *result)
207
0
{
208
0
    const H5G_bt2_ud_common_t      *bt2_udata = (const H5G_bt2_ud_common_t *)_bt2_udata;
209
0
    const H5G_dense_bt2_name_rec_t *bt2_rec   = (const H5G_dense_bt2_name_rec_t *)_bt2_rec;
210
0
    herr_t                          ret_value = SUCCEED; /* Return value */
211
212
0
    FUNC_ENTER_PACKAGE
213
214
    /* Sanity check */
215
0
    assert(bt2_udata);
216
0
    assert(bt2_rec);
217
218
    /* Check hash value */
219
0
    if (bt2_udata->name_hash < bt2_rec->hash)
220
0
        *result = (-1);
221
0
    else if (bt2_udata->name_hash > bt2_rec->hash)
222
0
        *result = 1;
223
0
    else {
224
0
        H5G_fh_ud_cmp_t fh_udata; /* User data for fractal heap 'op' callback */
225
226
        /* Sanity check */
227
0
        assert(bt2_udata->name_hash == bt2_rec->hash);
228
229
        /* Prepare user data for callback */
230
        /* down */
231
0
        fh_udata.f             = bt2_udata->f;
232
0
        fh_udata.name          = bt2_udata->name;
233
0
        fh_udata.found_op      = bt2_udata->found_op;
234
0
        fh_udata.found_op_data = bt2_udata->found_op_data;
235
236
        /* up */
237
0
        fh_udata.cmp = 0;
238
239
        /* Check if the user's link and the B-tree's link have the same name */
240
0
        if (H5HF_op(bt2_udata->fheap, bt2_rec->id, H5G__dense_fh_name_cmp, &fh_udata) < 0)
241
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records");
242
243
        /* Callback will set comparison value */
244
0
        *result = fh_udata.cmp;
245
0
    } /* end else */
246
247
0
done:
248
0
    FUNC_LEAVE_NOAPI(ret_value)
249
0
} /* H5G__dense_btree2_name_compare() */
250
251
/*-------------------------------------------------------------------------
252
 * Function:  H5G__dense_btree2_name_encode
253
 *
254
 * Purpose: Encode native information into raw form for storing on disk
255
 *
256
 * Return:  Success:  non-negative
257
 *    Failure:  negative
258
 *
259
 *-------------------------------------------------------------------------
260
 */
261
static herr_t
262
H5G__dense_btree2_name_encode(uint8_t *raw, const void *_nrecord, void H5_ATTR_UNUSED *ctx)
263
0
{
264
0
    const H5G_dense_bt2_name_rec_t *nrecord = (const H5G_dense_bt2_name_rec_t *)_nrecord;
265
266
0
    FUNC_ENTER_PACKAGE_NOERR
267
268
    /* Encode the record's fields */
269
0
    UINT32ENCODE(raw, nrecord->hash);
270
0
    H5MM_memcpy(raw, nrecord->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
271
272
0
    FUNC_LEAVE_NOAPI(SUCCEED)
273
0
} /* H5G__dense_btree2_name_encode() */
274
275
/*-------------------------------------------------------------------------
276
 * Function:  H5G__dense_btree2_name_decode
277
 *
278
 * Purpose: Decode raw disk form of record into native form
279
 *
280
 * Return:  Success:  non-negative
281
 *    Failure:  negative
282
 *
283
 *-------------------------------------------------------------------------
284
 */
285
static herr_t
286
H5G__dense_btree2_name_decode(const uint8_t *raw, void *_nrecord, void H5_ATTR_UNUSED *ctx)
287
0
{
288
0
    H5G_dense_bt2_name_rec_t *nrecord = (H5G_dense_bt2_name_rec_t *)_nrecord;
289
290
0
    FUNC_ENTER_PACKAGE_NOERR
291
292
    /* Decode the record's fields */
293
0
    UINT32DECODE(raw, nrecord->hash);
294
0
    H5MM_memcpy(nrecord->id, raw, (size_t)H5G_DENSE_FHEAP_ID_LEN);
295
296
0
    FUNC_LEAVE_NOAPI(SUCCEED)
297
0
} /* H5G__dense_btree2_name_decode() */
298
299
/*-------------------------------------------------------------------------
300
 * Function:  H5G__dense_btree2_name_debug
301
 *
302
 * Purpose: Debug native form of record
303
 *
304
 * Return:  Success:  non-negative
305
 *    Failure:  negative
306
 *
307
 *-------------------------------------------------------------------------
308
 */
309
static herr_t
310
H5G__dense_btree2_name_debug(FILE *stream, int indent, int fwidth, const void *_nrecord,
311
                             const void H5_ATTR_UNUSED *_udata)
312
0
{
313
0
    const H5G_dense_bt2_name_rec_t *nrecord = (const H5G_dense_bt2_name_rec_t *)_nrecord;
314
0
    unsigned                        u; /* Local index variable */
315
316
0
    FUNC_ENTER_PACKAGE_NOERR
317
318
0
    fprintf(stream, "%*s%-*s {%x, ", indent, "", fwidth, "Record:", (unsigned)nrecord->hash);
319
0
    for (u = 0; u < H5G_DENSE_FHEAP_ID_LEN; u++)
320
0
        fprintf(stderr, "%02x%s", nrecord->id[u], (u < (H5G_DENSE_FHEAP_ID_LEN - 1) ? " " : "}\n"));
321
322
0
    FUNC_LEAVE_NOAPI(SUCCEED)
323
0
} /* H5G__dense_btree2_name_debug() */
324
325
/*-------------------------------------------------------------------------
326
 * Function:  H5G__dense_btree2_corder_store
327
 *
328
 * Purpose: Store user information into native record for v2 B-tree
329
 *
330
 * Return:  Success:  non-negative
331
 *    Failure:  negative
332
 *
333
 *-------------------------------------------------------------------------
334
 */
335
static herr_t
336
H5G__dense_btree2_corder_store(void *_nrecord, const void *_udata)
337
0
{
338
0
    const H5G_bt2_ud_ins_t     *udata   = (const H5G_bt2_ud_ins_t *)_udata;
339
0
    H5G_dense_bt2_corder_rec_t *nrecord = (H5G_dense_bt2_corder_rec_t *)_nrecord;
340
341
0
    FUNC_ENTER_PACKAGE_NOERR
342
343
    /* Copy user information info native record */
344
0
    nrecord->corder = udata->common.corder;
345
0
    H5MM_memcpy(nrecord->id, udata->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
346
347
0
    FUNC_LEAVE_NOAPI(SUCCEED)
348
0
} /* H5G__dense_btree2_corder_store() */
349
350
/*-------------------------------------------------------------------------
351
 * Function:  H5G__dense_btree2_corder_compare
352
 *
353
 * Purpose: Compare two native information records, according to some key
354
 *
355
 * Return:  <0 if rec1 < rec2
356
 *              =0 if rec1 == rec2
357
 *              >0 if rec1 > rec2
358
 *
359
 *-------------------------------------------------------------------------
360
 */
361
static herr_t
362
H5G__dense_btree2_corder_compare(const void *_bt2_udata, const void *_bt2_rec, int *result)
363
0
{
364
0
    const H5G_bt2_ud_common_t        *bt2_udata = (const H5G_bt2_ud_common_t *)_bt2_udata;
365
0
    const H5G_dense_bt2_corder_rec_t *bt2_rec   = (const H5G_dense_bt2_corder_rec_t *)_bt2_rec;
366
367
0
    FUNC_ENTER_PACKAGE_NOERR
368
369
    /* Sanity check */
370
0
    assert(bt2_udata);
371
0
    assert(bt2_rec);
372
373
    /* Check creation order value */
374
0
    if (bt2_udata->corder < bt2_rec->corder)
375
0
        *result = -1;
376
0
    else if (bt2_udata->corder > bt2_rec->corder)
377
0
        *result = 1;
378
0
    else
379
0
        *result = 0;
380
381
0
    FUNC_LEAVE_NOAPI(SUCCEED)
382
0
} /* H5G__dense_btree2_corder_compare() */
383
384
/*-------------------------------------------------------------------------
385
 * Function:  H5G__dense_btree2_corder_encode
386
 *
387
 * Purpose: Encode native information into raw form for storing on disk
388
 *
389
 * Return:  Success:  non-negative
390
 *    Failure:  negative
391
 *
392
 *-------------------------------------------------------------------------
393
 */
394
static herr_t
395
H5G__dense_btree2_corder_encode(uint8_t *raw, const void *_nrecord, void H5_ATTR_UNUSED *ctx)
396
0
{
397
0
    const H5G_dense_bt2_corder_rec_t *nrecord = (const H5G_dense_bt2_corder_rec_t *)_nrecord;
398
399
0
    FUNC_ENTER_PACKAGE_NOERR
400
401
    /* Encode the record's fields */
402
0
    INT64ENCODE(raw, nrecord->corder);
403
0
    H5MM_memcpy(raw, nrecord->id, (size_t)H5G_DENSE_FHEAP_ID_LEN);
404
405
0
    FUNC_LEAVE_NOAPI(SUCCEED)
406
0
} /* H5G__dense_btree2_corder_encode() */
407
408
/*-------------------------------------------------------------------------
409
 * Function:  H5G__dense_btree2_corder_decode
410
 *
411
 * Purpose: Decode raw disk form of record into native form
412
 *
413
 * Return:  Success:  non-negative
414
 *    Failure:  negative
415
 *
416
 *-------------------------------------------------------------------------
417
 */
418
static herr_t
419
H5G__dense_btree2_corder_decode(const uint8_t *raw, void *_nrecord, void H5_ATTR_UNUSED *ctx)
420
0
{
421
0
    H5G_dense_bt2_corder_rec_t *nrecord = (H5G_dense_bt2_corder_rec_t *)_nrecord;
422
423
0
    FUNC_ENTER_PACKAGE_NOERR
424
425
    /* Decode the record's fields */
426
0
    INT64DECODE(raw, nrecord->corder);
427
0
    H5MM_memcpy(nrecord->id, raw, (size_t)H5G_DENSE_FHEAP_ID_LEN);
428
429
0
    FUNC_LEAVE_NOAPI(SUCCEED)
430
0
} /* H5G__dense_btree2_corder_decode() */
431
432
/*-------------------------------------------------------------------------
433
 * Function:  H5G__dense_btree2_corder_debug
434
 *
435
 * Purpose: Debug native form of record
436
 *
437
 * Return:  Success:  non-negative
438
 *    Failure:  negative
439
 *
440
 *-------------------------------------------------------------------------
441
 */
442
static herr_t
443
H5G__dense_btree2_corder_debug(FILE *stream, int indent, int fwidth, const void *_nrecord,
444
                               const void H5_ATTR_UNUSED *_udata)
445
0
{
446
0
    const H5G_dense_bt2_corder_rec_t *nrecord = (const H5G_dense_bt2_corder_rec_t *)_nrecord;
447
0
    unsigned                          u; /* Local index variable */
448
449
0
    FUNC_ENTER_PACKAGE_NOERR
450
451
0
    fprintf(stream, "%*s%-*s {%llu, ", indent, "", fwidth, "Record:", (unsigned long long)nrecord->corder);
452
0
    for (u = 0; u < H5G_DENSE_FHEAP_ID_LEN; u++)
453
0
        fprintf(stderr, "%02x%s", nrecord->id[u], (u < (H5G_DENSE_FHEAP_ID_LEN - 1) ? " " : "}\n"));
454
455
0
    FUNC_LEAVE_NOAPI(SUCCEED)
456
0
} /* H5G__dense_btree2_corder_debug() */