Coverage Report

Created: 2026-02-26 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5FAhdr.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:     H5FAhdr.c
16
 *
17
 * Purpose:     Array header routines for Fixed Array.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/**********************/
23
/* Module Declaration */
24
/**********************/
25
26
#include "H5FAmodule.h" /* This source code file is part of the H5FA module */
27
28
/***********************/
29
/* Other Packages Used */
30
/***********************/
31
32
/***********/
33
/* Headers */
34
/***********/
35
#include "H5private.h"   /* Generic Functions                            */
36
#include "H5Eprivate.h"  /* Error handling                               */
37
#include "H5FApkg.h"     /* Fixed Arrays                                 */
38
#include "H5FLprivate.h" /* Free Lists                               */
39
#include "H5MFprivate.h" /* File memory management                       */
40
#include "H5MMprivate.h" /* Memory management                            */
41
42
/****************/
43
/* Local Macros */
44
/****************/
45
46
/******************/
47
/* Local Typedefs */
48
/******************/
49
50
/********************/
51
/* Package Typedefs */
52
/********************/
53
54
/********************/
55
/* Local Prototypes */
56
/********************/
57
58
/*********************/
59
/* Package Variables */
60
/*********************/
61
62
/*****************************/
63
/* Library Private Variables */
64
/*****************************/
65
66
/*******************/
67
/* Local Variables */
68
/*******************/
69
70
/* Declare a free list to manage the H5FA_hdr_t struct */
71
H5FL_DEFINE_STATIC(H5FA_hdr_t);
72
73
/*-------------------------------------------------------------------------
74
 * Function:    H5FA__hdr_alloc
75
 *
76
 * Purpose:     Allocate shared Fixed Array header
77
 *
78
 * Return:      SUCCEED/FAIL
79
 *
80
 *-------------------------------------------------------------------------
81
 */
82
H5FA_hdr_t *
83
H5FA__hdr_alloc(H5F_t *f)
84
0
{
85
0
    H5FA_hdr_t *hdr       = NULL; /* Shared Fixed Array header */
86
0
    H5FA_hdr_t *ret_value = NULL;
87
88
0
    FUNC_ENTER_PACKAGE
89
90
    /* Check arguments */
91
0
    assert(f);
92
93
    /* Allocate space for the shared information */
94
0
    if (NULL == (hdr = H5FL_CALLOC(H5FA_hdr_t)))
95
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTALLOC, NULL,
96
0
                    "memory allocation failed for Fixed Array shared header");
97
98
    /* Set non-zero internal fields */
99
0
    hdr->addr = HADDR_UNDEF;
100
101
    /* Set the internal parameters for the array */
102
0
    hdr->f           = f;
103
0
    hdr->swmr_write  = (H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) > 0;
104
0
    hdr->sizeof_addr = H5F_SIZEOF_ADDR(f);
105
0
    hdr->sizeof_size = H5F_SIZEOF_SIZE(f);
106
107
    /* Set the return value */
108
0
    ret_value = hdr;
109
110
0
done:
111
0
    if (!ret_value)
112
0
        if (hdr && H5FA__hdr_dest(hdr) < 0)
113
0
            HDONE_ERROR(H5E_FARRAY, H5E_CANTFREE, NULL, "unable to destroy fixed array header");
114
0
    FUNC_LEAVE_NOAPI(ret_value)
115
0
} /* end H5FA__hdr_alloc() */
116
117
/*-------------------------------------------------------------------------
118
 * Function:    H5FA__hdr_init
119
 *
120
 * Purpose:     Initialize shared fixed array header
121
 *
122
 * Return:      SUCCEED/FAIL
123
 *
124
 *-------------------------------------------------------------------------
125
 */
126
herr_t
127
H5FA__hdr_init(H5FA_hdr_t *hdr, void *ctx_udata)
128
0
{
129
0
    herr_t ret_value = SUCCEED;
130
131
0
    FUNC_ENTER_PACKAGE
132
133
    /* Check arguments */
134
0
    assert(hdr);
135
136
    /* Set size of header on disk (locally and in statistics) */
137
0
    hdr->stats.hdr_size = hdr->size = H5FA_HEADER_SIZE_HDR(hdr);
138
139
    /* Set number of elements for Fixed Array in statistics */
140
0
    hdr->stats.nelmts = hdr->cparam.nelmts;
141
142
    /* Create the callback context, if there's one */
143
0
    if (hdr->cparam.cls->crt_context)
144
0
        if (NULL == (hdr->cb_ctx = (*hdr->cparam.cls->crt_context)(ctx_udata)))
145
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTCREATE, FAIL,
146
0
                        "unable to create fixed array client callback context");
147
148
0
done:
149
0
    FUNC_LEAVE_NOAPI(ret_value)
150
0
} /* end H5FA__hdr_init() */
151
152
/*-------------------------------------------------------------------------
153
 * Function:    H5FA__hdr_create
154
 *
155
 * Purpose:     Creates a new Fixed Array header in the file
156
 *
157
 * Return:      Success:    Address of new header in the file
158
 *              Failure:    HADDR_UNDEF
159
 *
160
 *-------------------------------------------------------------------------
161
 */
162
haddr_t
163
H5FA__hdr_create(H5F_t *f, const H5FA_create_t *cparam, void *ctx_udata)
164
0
{
165
0
    H5FA_hdr_t *hdr       = NULL;  /* Fixed array header */
166
0
    bool        inserted  = false; /* Whether the header was inserted into cache */
167
0
    haddr_t     ret_value = HADDR_UNDEF;
168
169
0
    FUNC_ENTER_PACKAGE
170
171
    /* Check arguments */
172
0
    assert(f);
173
0
    assert(cparam);
174
175
#ifndef NDEBUG
176
    {
177
        /* Check for valid parameters */
178
        if (cparam->raw_elmt_size == 0)
179
            HGOTO_ERROR(H5E_FARRAY, H5E_BADVALUE, HADDR_UNDEF, "element size must be greater than zero");
180
        if (cparam->max_dblk_page_nelmts_bits == 0)
181
            HGOTO_ERROR(H5E_FARRAY, H5E_BADVALUE, HADDR_UNDEF,
182
                        "max. # of elements bits must be greater than zero");
183
        if (cparam->nelmts == 0)
184
            HGOTO_ERROR(H5E_FARRAY, H5E_BADVALUE, HADDR_UNDEF, "# of elements must be greater than zero");
185
    }
186
#endif /* NDEBUG */
187
188
    /* Allocate space for the shared information */
189
0
    if (NULL == (hdr = H5FA__hdr_alloc(f)))
190
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTALLOC, HADDR_UNDEF,
191
0
                    "memory allocation failed for Fixed Array shared header");
192
193
0
    hdr->dblk_addr = HADDR_UNDEF;
194
195
    /* Set the creation parameters for the array */
196
0
    H5MM_memcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
197
198
    /* Finish initializing fixed array header */
199
0
    if (H5FA__hdr_init(hdr, ctx_udata) < 0)
200
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTINIT, HADDR_UNDEF, "initialization failed for fixed array header");
201
202
    /* Allocate space for the header on disk */
203
0
    if (HADDR_UNDEF == (hdr->addr = H5MF_alloc(f, H5FD_MEM_FARRAY_HDR, (hsize_t)hdr->size)))
204
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTALLOC, HADDR_UNDEF, "file allocation failed for Fixed Array header");
205
206
    /* Create 'top' proxy for fixed array entries */
207
0
    if (hdr->swmr_write)
208
0
        if (NULL == (hdr->top_proxy = H5AC_proxy_entry_create()))
209
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTCREATE, HADDR_UNDEF, "can't create fixed array entry proxy");
210
211
    /* Cache the new Fixed Array header */
212
0
    if (H5AC_insert_entry(f, H5AC_FARRAY_HDR, hdr->addr, hdr, H5AC__NO_FLAGS_SET) < 0)
213
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTINSERT, HADDR_UNDEF, "can't add fixed array header to cache");
214
0
    inserted = true;
215
216
    /* Add header as child of 'top' proxy */
217
0
    if (hdr->top_proxy)
218
0
        if (H5AC_proxy_entry_add_child(hdr->top_proxy, f, hdr) < 0)
219
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTSET, HADDR_UNDEF,
220
0
                        "unable to add fixed array entry as child of array proxy");
221
222
    /* Set address of array header to return */
223
0
    ret_value = hdr->addr;
224
225
0
done:
226
0
    if (!H5_addr_defined(ret_value))
227
0
        if (hdr) {
228
            /* Remove from cache, if inserted */
229
0
            if (inserted)
230
0
                if (H5AC_remove_entry(hdr) < 0)
231
0
                    HDONE_ERROR(H5E_FARRAY, H5E_CANTREMOVE, HADDR_UNDEF,
232
0
                                "unable to remove fixed array header from cache");
233
234
            /* Release header's disk space */
235
0
            if (H5_addr_defined(hdr->addr) &&
236
0
                H5MF_xfree(f, H5FD_MEM_FARRAY_HDR, hdr->addr, (hsize_t)hdr->size) < 0)
237
0
                HDONE_ERROR(H5E_FARRAY, H5E_CANTFREE, HADDR_UNDEF, "unable to free Fixed Array header");
238
239
            /* Destroy header */
240
0
            if (H5FA__hdr_dest(hdr) < 0)
241
0
                HDONE_ERROR(H5E_FARRAY, H5E_CANTFREE, HADDR_UNDEF, "unable to destroy Fixed Array header");
242
0
        }
243
244
0
    FUNC_LEAVE_NOAPI(ret_value)
245
0
} /* end H5FA__hdr_create() */
246
247
/*-------------------------------------------------------------------------
248
 * Function:    H5FA__hdr_incr
249
 *
250
 * Purpose:     Increment component reference count on shared array header
251
 *
252
 * Return:      SUCCEED/FAIL
253
 *
254
 *-------------------------------------------------------------------------
255
 */
256
herr_t
257
H5FA__hdr_incr(H5FA_hdr_t *hdr)
258
0
{
259
0
    herr_t ret_value = SUCCEED;
260
261
0
    FUNC_ENTER_PACKAGE
262
263
    /* Sanity check */
264
0
    assert(hdr);
265
266
    /* Mark header as un-evictable when something is depending on it */
267
0
    if (hdr->rc == 0)
268
0
        if (H5AC_pin_protected_entry(hdr) < 0)
269
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTPIN, FAIL, "unable to pin fixed array header");
270
271
    /* Increment reference count on shared header */
272
0
    hdr->rc++;
273
274
0
done:
275
0
    FUNC_LEAVE_NOAPI(ret_value)
276
0
} /* end H5FA__hdr_incr() */
277
278
/*-------------------------------------------------------------------------
279
 * Function:    H5FA__hdr_decr
280
 *
281
 * Purpose:     Decrement component reference count on shared array header
282
 *
283
 * Return:      SUCCEED/FAIL
284
 *
285
 *-------------------------------------------------------------------------
286
 */
287
herr_t
288
H5FA__hdr_decr(H5FA_hdr_t *hdr)
289
0
{
290
0
    herr_t ret_value = SUCCEED;
291
292
0
    FUNC_ENTER_PACKAGE
293
294
    /* Sanity check */
295
0
    assert(hdr);
296
0
    assert(hdr->rc);
297
298
    /* Decrement reference count on shared header */
299
0
    hdr->rc--;
300
301
    /* Mark header as evictable again when nothing depend on it */
302
0
    if (hdr->rc == 0) {
303
0
        assert(hdr->file_rc == 0);
304
0
        if (H5AC_unpin_entry(hdr) < 0)
305
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTUNPIN, FAIL, "unable to unpin fixed array header");
306
0
    }
307
308
0
done:
309
0
    FUNC_LEAVE_NOAPI(ret_value)
310
0
} /* end H5FA__hdr_decr() */
311
312
/*-------------------------------------------------------------------------
313
 * Function:    H5FA__hdr_fuse_incr
314
 *
315
 * Purpose:     Increment file reference count on shared array header
316
 *
317
 * Return:      SUCCEED/FAIL
318
 *
319
 *-------------------------------------------------------------------------
320
 */
321
herr_t
322
H5FA__hdr_fuse_incr(H5FA_hdr_t *hdr)
323
0
{
324
0
    FUNC_ENTER_PACKAGE_NOERR
325
326
    /* Sanity check */
327
0
    assert(hdr);
328
329
    /* Increment file reference count on shared header */
330
0
    hdr->file_rc++;
331
332
0
    FUNC_LEAVE_NOAPI(SUCCEED)
333
0
} /* end H5FA__hdr_fuse_incr() */
334
335
/*-------------------------------------------------------------------------
336
 * Function:    H5FA__hdr_fuse_decr
337
 *
338
 * Purpose:     Decrement file reference count on shared array header
339
 *
340
 * Return:      Success:    The reference count of the header
341
 *              Failure:    Can't fail
342
 *
343
 *-------------------------------------------------------------------------
344
 */
345
size_t
346
H5FA__hdr_fuse_decr(H5FA_hdr_t *hdr)
347
0
{
348
0
    size_t ret_value = 0;
349
350
0
    FUNC_ENTER_PACKAGE_NOERR
351
352
    /* Sanity check */
353
0
    assert(hdr);
354
0
    assert(hdr->file_rc);
355
356
    /* Decrement file reference count on shared header */
357
0
    hdr->file_rc--;
358
359
    /* Set return value */
360
0
    ret_value = hdr->file_rc;
361
362
0
    FUNC_LEAVE_NOAPI(ret_value)
363
0
} /* end H5FA__hdr_fuse_decr() */
364
365
/*-------------------------------------------------------------------------
366
 * Function:    H5FA__hdr_modified
367
 *
368
 * Purpose:     Mark a fixed array as modified
369
 *
370
 * Return:      SUCCEED/FAIL
371
 *
372
 *-------------------------------------------------------------------------
373
 */
374
herr_t
375
H5FA__hdr_modified(H5FA_hdr_t *hdr)
376
0
{
377
0
    herr_t ret_value = SUCCEED;
378
379
0
    FUNC_ENTER_PACKAGE
380
381
    /* Sanity check */
382
0
    assert(hdr);
383
384
    /* Mark header as dirty in cache */
385
0
    if (H5AC_mark_entry_dirty(hdr) < 0)
386
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTMARKDIRTY, FAIL, "unable to mark fixed array header as dirty");
387
388
0
done:
389
0
    FUNC_LEAVE_NOAPI(ret_value)
390
0
} /* end H5FA__hdr_modified() */
391
392
/*-------------------------------------------------------------------------
393
 * Function:  H5FA__hdr_protect
394
 *
395
 * Purpose: Convenience wrapper around protecting fixed array header
396
 *
397
 * Return:  Non-NULL pointer to header on success/NULL on failure
398
 *
399
 *-------------------------------------------------------------------------
400
 */
401
H5FA_hdr_t *
402
H5FA__hdr_protect(H5F_t *f, haddr_t fa_addr, void *ctx_udata, unsigned flags)
403
0
{
404
0
    H5FA_hdr_t         *hdr;   /* Fixed array header */
405
0
    H5FA_hdr_cache_ud_t udata; /* User data for cache callbacks */
406
0
    H5FA_hdr_t         *ret_value = NULL;
407
408
0
    FUNC_ENTER_PACKAGE
409
410
    /* Sanity check */
411
0
    assert(f);
412
0
    assert(H5_addr_defined(fa_addr));
413
414
    /* only the H5AC__READ_ONLY_FLAG is permitted */
415
0
    assert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
416
417
    /* Set up user data for cache callbacks */
418
0
    udata.f         = f;
419
0
    udata.addr      = fa_addr;
420
0
    udata.ctx_udata = ctx_udata;
421
422
    /* Protect the header */
423
0
    if (NULL == (hdr = (H5FA_hdr_t *)H5AC_protect(f, H5AC_FARRAY_HDR, fa_addr, &udata, flags)))
424
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTPROTECT, NULL, "unable to protect fixed array header, address = %llu",
425
0
                    (unsigned long long)fa_addr);
426
0
    hdr->f = f; /* (Must be set again here, in case the header was already in the cache -QAK) */
427
428
    /* Create top proxy, if it doesn't exist */
429
0
    if (hdr->swmr_write && NULL == hdr->top_proxy) {
430
        /* Create 'top' proxy for fixed array entries */
431
0
        if (NULL == (hdr->top_proxy = H5AC_proxy_entry_create()))
432
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTCREATE, NULL, "can't create fixed array entry proxy");
433
434
        /* Add header as child of 'top' proxy */
435
0
        if (H5AC_proxy_entry_add_child(hdr->top_proxy, f, hdr) < 0)
436
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTSET, NULL,
437
0
                        "unable to add fixed array entry as child of array proxy");
438
0
    }
439
440
    /* Set return value */
441
0
    ret_value = hdr;
442
443
0
done:
444
0
    FUNC_LEAVE_NOAPI(ret_value)
445
0
} /* end H5FA__hdr_protect() */
446
447
/*-------------------------------------------------------------------------
448
 * Function:  H5FA__hdr_unprotect
449
 *
450
 * Purpose: Convenience wrapper around unprotecting fixed array header
451
 *
452
 * Return:  Non-negative on success/Negative on failure
453
 *
454
 *-------------------------------------------------------------------------
455
 */
456
herr_t
457
H5FA__hdr_unprotect(H5FA_hdr_t *hdr, unsigned cache_flags)
458
0
{
459
0
    herr_t ret_value = SUCCEED;
460
461
0
    FUNC_ENTER_PACKAGE
462
463
    /* Sanity check */
464
0
    assert(hdr);
465
466
    /* Unprotect the header */
467
0
    if (H5AC_unprotect(hdr->f, H5AC_FARRAY_HDR, hdr->addr, hdr, cache_flags) < 0)
468
0
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTUNPROTECT, FAIL,
469
0
                    "unable to unprotect fixed array hdr, address = %llu", (unsigned long long)hdr->addr);
470
471
0
done:
472
0
    FUNC_LEAVE_NOAPI(ret_value)
473
0
} /* end H5FA__hdr_unprotect() */
474
475
/*-------------------------------------------------------------------------
476
 * Function:  H5FA__hdr_delete
477
 *
478
 * Purpose:     Delete a fixed array, starting with the header
479
 *
480
 * Return:      SUCCEED/FAIL
481
 *
482
 *-------------------------------------------------------------------------
483
 */
484
herr_t
485
H5FA__hdr_delete(H5FA_hdr_t *hdr)
486
0
{
487
0
    unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting header */
488
0
    herr_t   ret_value   = SUCCEED;
489
490
0
    FUNC_ENTER_PACKAGE
491
492
    /* Sanity check */
493
0
    assert(hdr);
494
0
    assert(!hdr->file_rc);
495
496
#ifndef NDEBUG
497
498
    unsigned hdr_status = 0; /* Array header's status in the metadata cache */
499
500
    /* Check the array header's status in the metadata cache */
501
    if (H5AC_get_entry_status(hdr->f, hdr->addr, &hdr_status) < 0)
502
        HGOTO_ERROR(H5E_FARRAY, H5E_CANTGET, FAIL, "unable to check metadata cache status for array header");
503
504
    /* Sanity checks on array header */
505
    assert(hdr_status & H5AC_ES__IN_CACHE);
506
    assert(hdr_status & H5AC_ES__IS_PROTECTED);
507
508
#endif /* NDEBUG */
509
510
    /* Check for Fixed Array Data block */
511
0
    if (H5_addr_defined(hdr->dblk_addr)) {
512
        /* Delete Fixed Array Data block */
513
0
        if (H5FA__dblock_delete(hdr, hdr->dblk_addr) < 0)
514
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTDELETE, FAIL, "unable to delete fixed array data block");
515
0
    }
516
517
    /* Set flags to finish deleting header on unprotect */
518
0
    cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
519
520
0
done:
521
    /* Unprotect the header, deleting it if an error hasn't occurred */
522
0
    if (H5AC_unprotect(hdr->f, H5AC_FARRAY_HDR, hdr->addr, hdr, cache_flags) < 0)
523
0
        HDONE_ERROR(H5E_FARRAY, H5E_CANTUNPROTECT, FAIL, "unable to release fixed array header");
524
525
0
    FUNC_LEAVE_NOAPI(ret_value)
526
0
} /* end H5FA__hdr_delete() */
527
528
/*-------------------------------------------------------------------------
529
 * Function:    H5FA__hdr_dest
530
 *
531
 * Purpose:     Destroys a fixed array header in memory.
532
 *
533
 * Return:      SUCCEED/FAIL
534
 *
535
 *-------------------------------------------------------------------------
536
 */
537
herr_t
538
H5FA__hdr_dest(H5FA_hdr_t *hdr)
539
0
{
540
0
    herr_t ret_value = SUCCEED;
541
542
0
    FUNC_ENTER_PACKAGE
543
544
    /* Check arguments */
545
0
    assert(hdr);
546
0
    assert(hdr->rc == 0);
547
548
    /* Destroy the callback context */
549
0
    if (hdr->cb_ctx) {
550
0
        if ((*hdr->cparam.cls->dst_context)(hdr->cb_ctx) < 0)
551
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTRELEASE, FAIL,
552
0
                        "unable to destroy fixed array client callback context");
553
0
    }
554
0
    hdr->cb_ctx = NULL;
555
556
    /* Destroy the 'top' proxy */
557
0
    if (hdr->top_proxy) {
558
0
        if (H5AC_proxy_entry_dest(hdr->top_proxy) < 0)
559
0
            HGOTO_ERROR(H5E_FARRAY, H5E_CANTRELEASE, FAIL, "unable to destroy fixed array 'top' proxy");
560
0
        hdr->top_proxy = NULL;
561
0
    }
562
563
    /* Free the shared info itself */
564
0
    hdr = H5FL_FREE(H5FA_hdr_t, hdr);
565
566
0
done:
567
0
    FUNC_LEAVE_NOAPI(ret_value)
568
0
} /* end H5FA__hdr_dest() */