Coverage Report

Created: 2026-08-13 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Fcwfs.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
 * Purpose: Each file has a small cache of global heap collections called
15
 *    the CWFS list and recently accessed collections with free
16
 *    space appear on this list.  As collections are accessed the
17
 *    collection is moved toward the front of the list.  New
18
 *    collections are added to the front of the list while old
19
 *    collections are added to the end of the list.
20
 *
21
 *    The collection model reduces the overhead which would be
22
 *    incurred if the global heap were a single object, and the
23
 *    CWFS list allows the library to cheaply choose a collection
24
 *    for a new object based on object size, amount of free space
25
 *    in the collection, and temporal locality.
26
 */
27
28
/****************/
29
/* Module Setup */
30
/****************/
31
32
#include "H5Fmodule.h" /* This source code file is part of the H5F module */
33
34
/***********/
35
/* Headers */
36
/***********/
37
#include "H5private.h"   /* Generic Functions     */
38
#include "H5Eprivate.h"  /* Error handling        */
39
#include "H5Fpkg.h"      /* File access       */
40
#include "H5HGprivate.h" /* Global heaps        */
41
#include "H5MFprivate.h" /* File memory management    */
42
#include "H5MMprivate.h" /* Memory management     */
43
44
/****************/
45
/* Local Macros */
46
/****************/
47
48
/*
49
 * Maximum length of the CWFS list, the list of remembered collections that
50
 * have free space.
51
 */
52
0
#define H5F_NCWFS 16
53
54
/******************/
55
/* Local Typedefs */
56
/******************/
57
58
/********************/
59
/* Package Typedefs */
60
/********************/
61
62
/********************/
63
/* Local Prototypes */
64
/********************/
65
66
/*********************/
67
/* Package Variables */
68
/*********************/
69
70
/*****************************/
71
/* Library Private Variables */
72
/*****************************/
73
74
/*******************/
75
/* Local Variables */
76
/*******************/
77
78
/*-------------------------------------------------------------------------
79
 * Function:  H5F_cwfs_add
80
 *
81
 * Purpose: Add a global heap collection to the CWFS for a file.
82
 *
83
 * Return:  Success:  Non-negative
84
 *    Failure:  Negative
85
 *
86
 *-------------------------------------------------------------------------
87
 */
88
herr_t
89
H5F_cwfs_add(H5F_t *f, H5HG_heap_t *heap)
90
0
{
91
0
    herr_t ret_value = SUCCEED; /* Return value */
92
93
0
    FUNC_ENTER_NOAPI(FAIL)
94
95
    /* Check args */
96
0
    assert(f);
97
0
    assert(f->shared);
98
0
    assert(heap);
99
100
    /*
101
     * Add the new heap to the CWFS list, removing some other entry if
102
     * necessary to make room. We remove the right-most entry that has less
103
     * free space than this heap.
104
     */
105
0
    if (NULL == f->shared->cwfs) {
106
0
        if (NULL == (f->shared->cwfs = (H5HG_heap_t **)H5MM_malloc(H5F_NCWFS * sizeof(H5HG_heap_t *))))
107
0
            HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, FAIL, "can't allocate CWFS for file");
108
0
        f->shared->cwfs[0] = heap;
109
0
        f->shared->ncwfs   = 1;
110
0
    }
111
0
    else if (H5F_NCWFS == f->shared->ncwfs) {
112
0
        int i; /* Local index variable */
113
114
0
        for (i = H5F_NCWFS - 1; i >= 0; --i)
115
0
            if (H5HG_FREE_SIZE(f->shared->cwfs[i]) < H5HG_FREE_SIZE(heap)) {
116
0
                memmove(f->shared->cwfs + 1, f->shared->cwfs, (size_t)i * sizeof(H5HG_heap_t *));
117
0
                f->shared->cwfs[0] = heap;
118
0
                break;
119
0
            } /* end if */
120
0
    }
121
0
    else {
122
0
        memmove(f->shared->cwfs + 1, f->shared->cwfs, f->shared->ncwfs * sizeof(H5HG_heap_t *));
123
0
        f->shared->cwfs[0] = heap;
124
0
        f->shared->ncwfs += 1;
125
0
    } /* end else */
126
127
0
done:
128
0
    FUNC_LEAVE_NOAPI(ret_value)
129
0
} /* H5F_cwfs_add() */
130
131
/*-------------------------------------------------------------------------
132
 * Function:  H5F_cwfs_find_free_heap
133
 *
134
 * Purpose: Find a global heap collection with free space for storing
135
 *    a new object.
136
 *
137
 * Return:  Success:  Non-negative
138
 *    Failure:  Negative
139
 *
140
 *-------------------------------------------------------------------------
141
 */
142
herr_t
143
H5F_cwfs_find_free_heap(H5F_t *f, size_t need, haddr_t *addr)
144
0
{
145
0
    unsigned cwfsno;              /* Local index for iterating over collections */
146
0
    bool     found     = false;   /* Flag to indicate a heap with enough space was found */
147
0
    herr_t   ret_value = SUCCEED; /* Return value */
148
149
0
    FUNC_ENTER_NOAPI(FAIL)
150
151
    /* Check args */
152
0
    assert(f);
153
0
    assert(f->shared);
154
0
    assert(addr);
155
156
    /* Note that we don't have metadata cache locks on the entries in
157
     * f->shared->cwfs.
158
     *
159
     * In the current situation, this doesn't matter, as we are single
160
     * threaded, and as best I can tell, entries are added to and deleted
161
     * from f->shared->cwfs as they are added to and deleted from the
162
     * metadata cache.
163
     *
164
     * To be proper, we should either lock each entry in f->shared->cwfs
165
     * as we examine it, or lock the whole array.  However, at present
166
     * I don't see the point as there will be significant overhead,
167
     * and protecting and unprotecting all the collections in the global
168
     * heap on a regular basis will skew the replacement policy.
169
     *
170
     *                                        JRM - 5/24/04
171
     */
172
0
    for (cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++)
173
0
        if (H5HG_FREE_SIZE(f->shared->cwfs[cwfsno]) >= need) {
174
0
            *addr = H5HG_ADDR(f->shared->cwfs[cwfsno]);
175
0
            found = true;
176
0
            break;
177
0
        } /* end if */
178
179
    /*
180
     * If we didn't find any collection with enough free space the check if
181
     * we can extend any of the collections to make enough room.
182
     */
183
0
    if (!found) {
184
0
        size_t new_need;
185
186
0
        for (cwfsno = 0; cwfsno < f->shared->ncwfs; cwfsno++) {
187
0
            new_need = need;
188
0
            new_need -= H5HG_FREE_SIZE(f->shared->cwfs[cwfsno]);
189
0
            new_need = MAX(H5HG_SIZE(f->shared->cwfs[cwfsno]), new_need);
190
191
0
            if ((H5HG_SIZE(f->shared->cwfs[cwfsno]) + new_need) <= H5HG_MAXSIZE) {
192
0
                htri_t was_extended; /* Whether the heap was extended */
193
194
0
                was_extended =
195
0
                    H5MF_try_extend(f, H5FD_MEM_GHEAP, H5HG_ADDR(f->shared->cwfs[cwfsno]),
196
0
                                    (hsize_t)H5HG_SIZE(f->shared->cwfs[cwfsno]), (hsize_t)new_need);
197
0
                if (was_extended < 0)
198
0
                    HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "error trying to extend heap");
199
0
                else if (was_extended == true) {
200
0
                    if (H5HG_extend(f, H5HG_ADDR(f->shared->cwfs[cwfsno]), new_need) < 0)
201
0
                        HGOTO_ERROR(H5E_HEAP, H5E_CANTRESIZE, FAIL,
202
0
                                    "unable to extend global heap collection");
203
0
                    *addr = H5HG_ADDR(f->shared->cwfs[cwfsno]);
204
0
                    found = true;
205
0
                    break;
206
0
                } /* end if */
207
0
            }     /* end if */
208
0
        }         /* end for */
209
0
    }             /* end if */
210
211
0
    if (found) {
212
        /* Move the collection forward in the CWFS list, if it's not
213
         * already at the front
214
         */
215
0
        if (cwfsno > 0) {
216
0
            H5HG_heap_t *tmp = f->shared->cwfs[cwfsno];
217
218
0
            f->shared->cwfs[cwfsno]     = f->shared->cwfs[cwfsno - 1];
219
0
            f->shared->cwfs[cwfsno - 1] = tmp;
220
0
        } /* end if */
221
0
    }     /* end if */
222
223
0
done:
224
0
    FUNC_LEAVE_NOAPI(ret_value)
225
0
} /* H5F_cwfs_find_free_heap() */
226
227
/*-------------------------------------------------------------------------
228
 * Function:  H5F_cwfs_advance_heap
229
 *
230
 * Purpose: Advance a heap in the CWFS
231
 *
232
 * Return:  Success:  Non-negative
233
 *    Failure:  Negative
234
 *
235
 *-------------------------------------------------------------------------
236
 */
237
herr_t
238
H5F_cwfs_advance_heap(H5F_t *f, H5HG_heap_t *heap, bool add_heap)
239
0
{
240
0
    unsigned u;                   /* Local index variable */
241
0
    herr_t   ret_value = SUCCEED; /* Return value */
242
243
0
    FUNC_ENTER_NOAPI(FAIL)
244
245
    /* Check args */
246
0
    assert(f);
247
0
    assert(f->shared);
248
0
    assert(heap);
249
250
0
    for (u = 0; u < f->shared->ncwfs; u++)
251
0
        if (f->shared->cwfs[u] == heap) {
252
0
            if (u) {
253
0
                f->shared->cwfs[u]     = f->shared->cwfs[u - 1];
254
0
                f->shared->cwfs[u - 1] = heap;
255
0
            } /* end if */
256
0
            break;
257
0
        } /* end if */
258
0
    if (add_heap && u >= f->shared->ncwfs) {
259
0
        f->shared->ncwfs                      = MIN(f->shared->ncwfs + 1, H5F_NCWFS);
260
0
        f->shared->cwfs[f->shared->ncwfs - 1] = heap;
261
0
    } /* end if */
262
263
0
done:
264
0
    FUNC_LEAVE_NOAPI(ret_value)
265
0
} /* H5F_cwfs_advance_heap() */
266
267
/*-------------------------------------------------------------------------
268
 * Function:  H5F_cwfs_remove_heap
269
 *
270
 * Purpose: Remove a heap from the CWFS
271
 *
272
 * Return:  Success:  Non-negative
273
 *    Failure:  Negative
274
 *
275
 *-------------------------------------------------------------------------
276
 */
277
herr_t
278
H5F_cwfs_remove_heap(H5F_shared_t *shared, H5HG_heap_t *heap)
279
0
{
280
0
    unsigned u;                   /* Local index variable */
281
0
    herr_t   ret_value = SUCCEED; /* Return value */
282
283
0
    FUNC_ENTER_NOAPI(FAIL)
284
285
    /* Check args */
286
0
    assert(shared);
287
0
    assert(heap);
288
289
    /* Remove the heap from the CWFS list */
290
0
    for (u = 0; u < shared->ncwfs; u++) {
291
0
        if (shared->cwfs[u] == heap) {
292
0
            shared->ncwfs -= 1;
293
0
            memmove(shared->cwfs + u, shared->cwfs + u + 1, (shared->ncwfs - u) * sizeof(H5HG_heap_t *));
294
0
            break;
295
0
        } /* end if */
296
0
    }     /* end for */
297
298
0
done:
299
0
    FUNC_LEAVE_NOAPI(ret_value)
300
0
} /* H5F_cwfs_remove_heap() */