Coverage Report

Created: 2026-10-17 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Bdbg.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:         H5Bdbg.c
16
 *
17
 * Purpose:         Debugging routines for B-link tree package
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5Bmodule.h" /* This source code file is part of the H5B module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions            */
32
#include "H5Bpkg.h"      /* B-link trees                 */
33
#include "H5Eprivate.h"  /* Error handling               */
34
#include "H5MMprivate.h" /* Memory management            */
35
36
/*-------------------------------------------------------------------------
37
 * Function:    H5B_debug
38
 *
39
 * Purpose:     Prints debugging info about a B-tree
40
 *
41
 * Return:      Non-negative on success/Negative on failure
42
 *-------------------------------------------------------------------------
43
 */
44
herr_t
45
H5B_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth, const H5B_class_t *type, void *udata)
46
0
{
47
0
    H5B_t         *bt = NULL;
48
0
    H5UC_t        *rc_shared;           /* Ref-counted shared info */
49
0
    H5B_shared_t  *shared;              /* Pointer to shared B-tree info */
50
0
    H5B_cache_ud_t cache_udata;         /* User-data for metadata cache callback */
51
0
    unsigned       u;                   /* Local index variable */
52
0
    herr_t         ret_value = SUCCEED; /* Return value */
53
54
0
    FUNC_ENTER_NOAPI(FAIL)
55
56
    /* Check arguments */
57
0
    assert(f);
58
0
    assert(H5_addr_defined(addr));
59
0
    assert(stream);
60
0
    assert(indent >= 0);
61
0
    assert(fwidth >= 0);
62
0
    assert(type);
63
64
    /* Currently does not support SWMR access */
65
0
    assert(!(H5F_INTENT(f) & H5F_ACC_SWMR_WRITE));
66
67
    /* Get shared info for B-tree */
68
0
    if (NULL == (rc_shared = (type->get_shared)(f, udata)))
69
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's shared ref. count object");
70
0
    shared = (H5B_shared_t *)H5UC_GET_OBJ(rc_shared);
71
0
    assert(shared);
72
73
    /*
74
     * Load the tree node.
75
     */
76
0
    cache_udata.f         = f;
77
0
    cache_udata.type      = type;
78
0
    cache_udata.rc_shared = rc_shared;
79
0
    if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
80
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree node");
81
82
    /*
83
     * Print the values.
84
     */
85
0
    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Tree type ID:",
86
0
            ((shared->type->id) == H5B_SNODE_ID
87
0
                 ? "H5B_SNODE_ID"
88
0
                 : ((shared->type->id) == H5B_CHUNK_ID ? "H5B_CHUNK_ID" : "Unknown!")));
89
0
    fprintf(stream, "%*s%-*s %zu\n", indent, "", fwidth, "Size of node:", shared->sizeof_rnode);
90
0
    fprintf(stream, "%*s%-*s %zu\n", indent, "", fwidth, "Size of raw (disk) key:", shared->sizeof_rkey);
91
0
    fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
92
0
            "Dirty flag:", bt->cache_info.is_dirty ? "True" : "False");
93
0
    fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Level:", bt->level);
94
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Address of left sibling:", bt->left);
95
0
    fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent, "", fwidth, "Address of right sibling:", bt->right);
96
0
    fprintf(stream, "%*s%-*s %u (%u)\n", indent, "", fwidth, "Number of children (max):", bt->nchildren,
97
0
            shared->two_k);
98
99
    /*
100
     * Print the child addresses
101
     */
102
0
    for (u = 0; u < bt->nchildren; u++) {
103
0
        fprintf(stream, "%*sChild %d...\n", indent, "", u);
104
0
        fprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent + 3, "", MAX(3, fwidth) - 3,
105
0
                "Address:", bt->child[u]);
106
107
        /* If there is a key debugging routine, use it to display the left & right keys */
108
0
        if (type->debug_key) {
109
            /* Decode the 'left' key & print it */
110
0
            fprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(3, fwidth) - 3, "Left Key:");
111
0
            assert(H5B_NKEY(bt, shared, u));
112
0
            (void)(type->debug_key)(stream, indent + 6, MAX(6, fwidth) - 6, H5B_NKEY(bt, shared, u), udata);
113
114
            /* Decode the 'right' key & print it */
115
0
            fprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(3, fwidth) - 3, "Right Key:");
116
0
            assert(H5B_NKEY(bt, shared, u + 1));
117
0
            (void)(type->debug_key)(stream, indent + 6, MAX(6, fwidth) - 6, H5B_NKEY(bt, shared, u + 1),
118
0
                                    udata);
119
0
        } /* end if */
120
0
    }     /* end for */
121
122
0
done:
123
0
    if (bt && H5AC_unprotect(f, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
124
0
        HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node");
125
126
0
    FUNC_LEAVE_NOAPI(ret_value)
127
0
} /* end H5B_debug() */
128
129
/*-------------------------------------------------------------------------
130
 * Function:    H5B__verify_structure
131
 *
132
 * Purpose:     Verifies that the tree is structured correctly
133
 *
134
 * Return:      SUCCEED/FAIL
135
 *-------------------------------------------------------------------------
136
 */
137
herr_t
138
H5B__verify_structure(H5F_t *f, haddr_t addr, const H5B_class_t *type, void *udata)
139
0
{
140
0
    H5B_t         *bt = NULL;
141
0
    H5UC_t        *rc_shared;   /* Ref-counted shared info */
142
0
    H5B_shared_t  *shared;      /* Pointer to shared B-tree info */
143
0
    H5B_cache_ud_t cache_udata; /* User-data for metadata cache callback */
144
0
    int            cmp;
145
0
    herr_t         ret_value = SUCCEED; /* Return value */
146
147
    /* A queue of child data */
148
0
    struct child_t {
149
0
        haddr_t         addr;
150
0
        unsigned        level;
151
0
        struct child_t *next;
152
0
    } *head = NULL, *tail = NULL, *prev = NULL, *cur = NULL, *tmp = NULL;
153
154
0
    FUNC_ENTER_PACKAGE
155
156
    /* Get shared info for B-tree */
157
0
    if (NULL == (rc_shared = (type->get_shared)(f, udata)))
158
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's shared ref. count object");
159
0
    if (NULL == (shared = (H5B_shared_t *)H5UC_GET_OBJ(rc_shared)))
160
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't retrieve B-tree's ref counted shared info");
161
162
    /* Initialize the queue */
163
0
    cache_udata.f         = f;
164
0
    cache_udata.type      = type;
165
0
    cache_udata.rc_shared = rc_shared;
166
167
0
    if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
168
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "can't protect B-tree node");
169
170
0
    if (NULL == (shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared)))
171
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL, "can't get B-tree shared data");
172
173
0
    if (NULL == (cur = (struct child_t *)H5MM_calloc(sizeof(struct child_t))))
174
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "can't allocate memory for queue");
175
176
0
    cur->addr  = addr;
177
0
    cur->level = bt->level;
178
0
    head = tail = cur;
179
180
0
    if (H5AC_unprotect(f, H5AC_BT, addr, bt, H5AC__NO_FLAGS_SET) < 0)
181
0
        HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "can't unprotect B-tree node");
182
183
0
    bt = NULL; /* Make certain future references will be caught */
184
185
    /* Do a breadth-first search of the tree.  New nodes are added to the end
186
     * of the queue as the `cur' pointer is advanced toward the end.  We don't
187
     * remove any nodes from the queue because we need them in the uniqueness
188
     * test.
189
     */
190
0
    while (cur) {
191
0
        if (NULL == (bt = (H5B_t *)H5AC_protect(f, H5AC_BT, cur->addr, &cache_udata, H5AC__READ_ONLY_FLAG)))
192
0
            HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "can't protect B-tree node");
193
194
        /* Check node header */
195
0
        if (bt->level != cur->level)
196
0
            HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "B-tree level incorrect");
197
198
0
        if (cur->next && cur->next->level == bt->level) {
199
0
            if (!H5_addr_eq(bt->right, cur->next->addr))
200
0
                HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "right address should not equal next");
201
0
        }
202
0
        else {
203
0
            if (H5_addr_defined(bt->right))
204
0
                HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "bt->right should be HADDR_UNDEF");
205
0
        }
206
207
0
        if (prev && prev->level == bt->level) {
208
0
            if (!H5_addr_eq(bt->left, prev->addr))
209
0
                HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "left address should not equal previous");
210
0
        }
211
0
        else {
212
0
            if (H5_addr_defined(bt->left))
213
0
                HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "bt->left should be HADDR_UNDEF");
214
0
        }
215
216
0
        if (cur->level > 0) {
217
0
            for (unsigned u = 0; u < bt->nchildren; u++) {
218
                /* Check that child nodes haven't already been seen.  If they
219
                 * have then the tree has a cycle.
220
                 */
221
0
                for (tmp = head; tmp; tmp = tmp->next)
222
0
                    if (!H5_addr_ne(tmp->addr, bt->child[u]))
223
0
                        HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "cycle detected in tree");
224
225
                /* Add the child node to the end of the queue */
226
0
                if (NULL == (tmp = (struct child_t *)H5MM_calloc(sizeof(struct child_t))))
227
0
                    HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "can't allocate memory for child node");
228
229
0
                tmp->addr  = bt->child[u];
230
0
                tmp->level = bt->level - 1;
231
0
                tail->next = tmp;
232
0
                tail       = tmp;
233
234
                /* Check that the keys are monotonically increasing */
235
0
                cmp = (type->cmp2)(H5B_NKEY(bt, shared, u), udata, H5B_NKEY(bt, shared, u + 1));
236
0
                if (cmp >= 0)
237
0
                    HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, FAIL, "keys not monotonically increasing");
238
0
            }
239
0
        }
240
241
        /* Release node */
242
0
        if (H5AC_unprotect(f, H5AC_BT, cur->addr, bt, H5AC__NO_FLAGS_SET) < 0)
243
0
            HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "can't unprotect B-tree node");
244
245
0
        bt = NULL; /* Make certain future references will be caught */
246
247
        /* Advance current location in queue */
248
0
        prev = cur;
249
0
        cur  = cur->next;
250
0
    }
251
252
    /* Free all entries from queue */
253
0
    while (head) {
254
0
        tmp = head->next;
255
0
        H5MM_xfree(head);
256
0
        head = tmp;
257
0
    }
258
259
0
done:
260
0
    FUNC_LEAVE_NOAPI(ret_value)
261
0
} /* end H5B__verify_structure() */