Coverage Report

Created: 2026-06-09 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5HLdblk.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:     H5HLdblk.c
16
 *
17
 * Purpose:     Data block routines for local heaps.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5HLmodule.h" /* This source code file is part of the H5HL module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions            */
32
#include "H5Eprivate.h"  /* Error handling               */
33
#include "H5FLprivate.h" /* Free lists                   */
34
#include "H5HLpkg.h"     /* Local Heaps                  */
35
#include "H5MFprivate.h" /* File memory management       */
36
37
/****************/
38
/* Local Macros */
39
/****************/
40
41
/******************/
42
/* Local Typedefs */
43
/******************/
44
45
/********************/
46
/* Package Typedefs */
47
/********************/
48
49
/********************/
50
/* Local Prototypes */
51
/********************/
52
53
/*********************/
54
/* Package Variables */
55
/*********************/
56
57
/*****************************/
58
/* Library Private Variables */
59
/*****************************/
60
61
/*******************/
62
/* Local Variables */
63
/*******************/
64
65
/* Declare a free list to manage the H5HL_dblk_t struct */
66
H5FL_DEFINE_STATIC(H5HL_dblk_t);
67
68
/*-------------------------------------------------------------------------
69
 * Function:    H5HL__dblk_new
70
 *
71
 * Purpose:     Create a new local heap data block object
72
 *
73
 * Return:      Success:    non-NULL pointer to new local heap data block
74
 *              Failure:    NULL
75
 *
76
 *-------------------------------------------------------------------------
77
 */
78
H5HL_dblk_t *
79
H5HL__dblk_new(H5HL_t *heap)
80
0
{
81
0
    H5HL_dblk_t *dblk      = NULL; /* New local heap data block */
82
0
    H5HL_dblk_t *ret_value = NULL;
83
84
0
    FUNC_ENTER_PACKAGE
85
86
    /* check arguments */
87
0
    assert(heap);
88
89
    /* Allocate new local heap data block */
90
0
    if (NULL == (dblk = H5FL_CALLOC(H5HL_dblk_t)))
91
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed for local heap data block");
92
93
    /* Increment ref. count on heap data structure */
94
0
    if (FAIL == H5HL__inc_rc(heap))
95
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment heap ref. count");
96
97
    /* Link the heap & the data block */
98
0
    dblk->heap = heap;
99
0
    heap->dblk = dblk;
100
101
    /* Set the return value */
102
0
    ret_value = dblk;
103
104
0
done:
105
    /* Ensure that the data block memory is deallocated on errors */
106
0
    if (!ret_value && dblk != NULL)
107
        /* H5FL_FREE always returns NULL so we can't check for errors */
108
0
        dblk = H5FL_FREE(H5HL_dblk_t, dblk);
109
110
0
    FUNC_LEAVE_NOAPI(ret_value)
111
0
} /* end H5HL__dblk_new() */
112
113
/*-------------------------------------------------------------------------
114
 * Function:    H5HL__dblk_dest
115
 *
116
 * Purpose:     Destroy a local heap data block object
117
 *
118
 * Return:      SUCCEED/FAIL
119
 *
120
 *-------------------------------------------------------------------------
121
 */
122
herr_t
123
H5HL__dblk_dest(H5HL_dblk_t *dblk)
124
0
{
125
0
    herr_t ret_value = SUCCEED;
126
127
0
    FUNC_ENTER_PACKAGE
128
129
    /* check arguments */
130
0
    assert(dblk);
131
132
    /* Check if data block was initialized */
133
0
    if (dblk->heap) {
134
        /* Unlink data block from heap */
135
0
        dblk->heap->dblk = NULL;
136
137
        /* Decrement ref. count on heap data structure */
138
0
        if (FAIL == H5HL__dec_rc(dblk->heap))
139
0
            HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement heap ref. count");
140
141
        /* Unlink heap from data block */
142
0
        dblk->heap = NULL;
143
0
    }
144
145
0
done:
146
    /* Free local heap data block */
147
    /* H5FL_FREE always returns NULL so we can't check for errors */
148
0
    dblk = H5FL_FREE(H5HL_dblk_t, dblk);
149
150
0
    FUNC_LEAVE_NOAPI(ret_value)
151
0
} /* end H5HL__dblk_dest() */
152
153
/*-------------------------------------------------------------------------
154
 * Function:    H5HL__dblk_realloc
155
 *
156
 * Purpose:     Reallocate data block for heap
157
 *
158
 * Return:      SUCCEED/FAIL
159
 *
160
 *-------------------------------------------------------------------------
161
 */
162
herr_t
163
H5HL__dblk_realloc(H5F_t *f, H5HL_t *heap, size_t new_heap_size)
164
0
{
165
0
    H5HL_dblk_t *dblk;          /* Local heap data block */
166
0
    haddr_t      old_addr;      /* Old location of heap data block */
167
0
    haddr_t      new_addr;      /* New location of heap data block */
168
0
    size_t       old_heap_size; /* Old size of heap data block */
169
0
    herr_t       ret_value = SUCCEED;
170
171
0
    FUNC_ENTER_PACKAGE
172
173
    /* Check arguments */
174
0
    assert(heap);
175
0
    assert(new_heap_size > 0);
176
177
    /* Release old space on disk */
178
0
    old_addr      = heap->dblk_addr;
179
0
    old_heap_size = heap->dblk_size;
180
0
    H5_CHECK_OVERFLOW(old_heap_size, size_t, hsize_t);
181
0
    if (FAIL == H5MF_xfree(f, H5FD_MEM_LHEAP, old_addr, (hsize_t)old_heap_size))
182
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't free old local heap data");
183
184
    /* Allocate new space on disk */
185
0
    H5_CHECK_OVERFLOW(new_heap_size, size_t, hsize_t);
186
0
    if (HADDR_UNDEF == (new_addr = H5MF_alloc(f, H5FD_MEM_LHEAP, (hsize_t)new_heap_size)))
187
0
        HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate file space for local heap");
188
189
    /* Update heap info*/
190
0
    heap->dblk_addr = new_addr;
191
0
    heap->dblk_size = new_heap_size;
192
193
    /* Check if heap data block actually moved in the file */
194
0
    if (H5_addr_eq(old_addr, new_addr)) {
195
        /* Check if heap data block is contiguous w/prefix */
196
0
        if (heap->single_cache_obj) {
197
            /* Sanity check */
198
0
            assert(H5_addr_eq(heap->prfx_addr + heap->prfx_size, old_addr));
199
0
            assert(heap->prfx);
200
201
            /* Resize the heap prefix in the cache */
202
0
            if (FAIL == H5AC_resize_entry(heap->prfx, (size_t)(heap->prfx_size + new_heap_size)))
203
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap in cache");
204
0
        }
205
0
        else {
206
            /* Sanity check */
207
0
            assert(H5_addr_ne(heap->prfx_addr + heap->prfx_size, old_addr));
208
0
            assert(heap->dblk);
209
210
            /* Resize the heap data block in the cache */
211
0
            if (H5AC_resize_entry(heap->dblk, (size_t)new_heap_size) < 0)
212
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap (data block) in cache");
213
0
        }
214
0
    }
215
0
    else {
216
        /* Check if heap data block was contiguous w/prefix previously */
217
0
        if (heap->single_cache_obj) {
218
            /* Create new heap data block */
219
0
            if (NULL == (dblk = H5HL__dblk_new(heap)))
220
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "unable to allocate local heap data block");
221
222
            /* Resize current heap prefix */
223
0
            heap->prfx_size = H5HL_SIZEOF_HDR(f);
224
0
            if (FAIL == H5AC_resize_entry(heap->prfx, (size_t)heap->prfx_size))
225
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap prefix in cache");
226
227
            /* Insert data block into cache (pinned) */
228
0
            if (FAIL == H5AC_insert_entry(f, H5AC_LHEAP_DBLK, new_addr, dblk, H5AC__PIN_ENTRY_FLAG))
229
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to cache local heap data block");
230
231
0
            dblk = NULL;
232
233
            /* Reset 'single cache object' flag */
234
0
            heap->single_cache_obj = false;
235
0
        }
236
0
        else {
237
            /* Resize the heap data block in the cache */
238
            /* (ignore [unlikely] case where heap data block ends up
239
             *      contiguous w/heap prefix again.
240
             */
241
0
            if (FAIL == H5AC_resize_entry(heap->dblk, (size_t)new_heap_size))
242
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL, "unable to resize heap data block in cache");
243
244
            /* Relocate the heap data block in the cache */
245
0
            if (FAIL == H5AC_move_entry(f, H5AC_LHEAP_DBLK, old_addr, new_addr))
246
0
                HGOTO_ERROR(H5E_HEAP, H5E_CANTMOVE, FAIL, "unable to move heap data block in cache");
247
0
        }
248
0
    }
249
250
0
done:
251
    /* Restore old heap address & size on errors */
252
0
    if (FAIL == ret_value) {
253
0
        heap->dblk_addr = old_addr;
254
0
        heap->dblk_size = old_heap_size;
255
0
    }
256
0
    FUNC_LEAVE_NOAPI(ret_value)
257
0
} /* end H5HL__dblk_realloc() */