Coverage Report

Created: 2025-08-03 06:26

/src/hdf5/src/H5EAhdr.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:   H5EAhdr.c
16
 *
17
 * Purpose:   Array header routines for extensible arrays.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/**********************/
23
/* Module Declaration */
24
/**********************/
25
26
#include "H5EAmodule.h" /* This source code file is part of the H5EA 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 "H5EApkg.h"     /* Extensible Arrays     */
38
#include "H5FLprivate.h" /* Free Lists                               */
39
#include "H5MFprivate.h" /* File memory management    */
40
#include "H5MMprivate.h" /* Memory management     */
41
#include "H5VMprivate.h" /* Vectors and arrays      */
42
43
/****************/
44
/* Local Macros */
45
/****************/
46
47
#ifndef NDEBUG
48
/* Max. # of bits for max. nelmts index */
49
#define H5EA_MAX_NELMTS_IDX_MAX 64
50
#endif /* NDEBUG */
51
52
/* # of elements in a data block for a particular super block */
53
0
#define H5EA_SBLK_DBLK_NELMTS(s, m) (size_t) H5_EXP2(((s) + 1) / 2) * (m)
54
55
/******************/
56
/* Local Typedefs */
57
/******************/
58
59
/* Alias for pointer to factory, for use when allocating sequences of them */
60
typedef H5FL_fac_head_t *H5FL_fac_head_ptr_t;
61
62
/********************/
63
/* Package Typedefs */
64
/********************/
65
66
/********************/
67
/* Local Prototypes */
68
/********************/
69
70
/*********************/
71
/* Package Variables */
72
/*********************/
73
74
/*****************************/
75
/* Library Private Variables */
76
/*****************************/
77
78
/*******************/
79
/* Local Variables */
80
/*******************/
81
82
/* Declare a free list to manage the H5EA_hdr_t struct */
83
H5FL_DEFINE_STATIC(H5EA_hdr_t);
84
85
/* Declare a free list to manage the H5FL_fac_head_ptr_t sequence information */
86
H5FL_SEQ_DEFINE_STATIC(H5FL_fac_head_ptr_t);
87
88
/* Declare a free list to manage the H5EA_sblk_info_t sequence information */
89
H5FL_SEQ_DEFINE_STATIC(H5EA_sblk_info_t);
90
91
/*-------------------------------------------------------------------------
92
 * Function:  H5EA__hdr_alloc
93
 *
94
 * Purpose: Allocate shared extensible array header
95
 *
96
 * Return:  Non-negative on success/Negative on failure
97
 *
98
 *-------------------------------------------------------------------------
99
 */
100
H5EA_hdr_t *
101
H5EA__hdr_alloc(H5F_t *f)
102
0
{
103
0
    H5EA_hdr_t *hdr       = NULL; /* Shared extensible array header */
104
0
    H5EA_hdr_t *ret_value = NULL;
105
106
0
    FUNC_ENTER_PACKAGE
107
108
    /* Check arguments */
109
0
    assert(f);
110
111
    /* Allocate space for the shared information */
112
0
    if (NULL == (hdr = H5FL_CALLOC(H5EA_hdr_t)))
113
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
114
0
                    "memory allocation failed for extensible array shared header");
115
116
    /* Set non-zero internal fields */
117
0
    hdr->addr = HADDR_UNDEF;
118
119
    /* Set the internal parameters for the array */
120
0
    hdr->f           = f;
121
0
    hdr->swmr_write  = (H5F_INTENT(f) & H5F_ACC_SWMR_WRITE) > 0;
122
0
    hdr->sizeof_addr = H5F_SIZEOF_ADDR(f);
123
0
    hdr->sizeof_size = H5F_SIZEOF_SIZE(f);
124
125
    /* Set the return value */
126
0
    ret_value = hdr;
127
128
0
done:
129
0
    if (!ret_value)
130
0
        if (hdr && H5EA__hdr_dest(hdr) < 0)
131
0
            HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, NULL, "unable to destroy extensible array header");
132
133
0
    FUNC_LEAVE_NOAPI(ret_value)
134
0
} /* end H5EA__hdr_alloc() */
135
136
/*-------------------------------------------------------------------------
137
 * Function:  H5EA__hdr_init
138
 *
139
 * Purpose: Compute useful information for extensible array, based on
140
 *              "creation" information.
141
 *
142
 * Notes: The equations for variables below are based on this information:
143
 *
144
 *  <sblk idx>  <# of dblks>  <size of dblks>       Range of elements in sblk
145
 *  ==========  ============  ===============       =========================
146
 *        0          1         1 * <dblk min elmts>   0 * <dblk min elmts> <->   1 * <dblk min elmts> - 1
147
 *        1          1         2 * <dblk min elmts>   1 * <dblk min elmts> <->   3 * <dblk min elmts> - 1
148
 *        2          2         2 * <dblk min elmts>   3 * <dblk min elmts> <->   7 * <dblk min elmts> - 1
149
 *        3          2         4 * <dblk min elmts>   7 * <dblk min elmts> <->  15 * <dblk min elmts> - 1
150
 *        4          4         4 * <dblk min elmts>  15 * <dblk min elmts> <->  31 * <dblk min elmts> - 1
151
 *        5          4         8 * <dblk min elmts>  31 * <dblk min elmts> <->  63 * <dblk min elmts> - 1
152
 *        6          8         8 * <dblk min elmts>  63 * <dblk min elmts> <-> 127 * <dblk min elmts> - 1
153
 *        7          8        16 * <dblk min elmts> 127 * <dblk min elmts> <-> 255 * <dblk min elmts> - 1
154
 *        .          .         . * <dblk min elmts>   . * <dblk min elmts> <->   . * <dblk min elmts> - 1
155
 *        .          .         . * <dblk min elmts>   . * <dblk min elmts> <->   . * <dblk min elmts> - 1
156
 *        .          .         . * <dblk min elmts>   . * <dblk min elmts> <->   . * <dblk min elmts> - 1
157
 *
158
 *  Therefore:
159
 *    <sblk idx>(<elmt idx>) = lg2((<elmt idx> / <dblk min elmts>) + 1)
160
 *    <# of dblks>(<sblk idx>) = 2 ^ (<sblk idx> / 2)
161
 *    <size of dblk>(<sblk idx>) = 2 ^ ((<sblk idx> + 1) / 2)
162
 *    <total # of sblks>(<max. # of elmts>) = 1 + (lg2(<max. # of elmts>) - lg2(<dblk min_elmts>))
163
 *
164
 * Return:  Non-negative on success/Negative on failure
165
 *
166
 *-------------------------------------------------------------------------
167
 */
168
herr_t
169
H5EA__hdr_init(H5EA_hdr_t *hdr, void *ctx_udata)
170
0
{
171
0
    hsize_t start_idx;  /* First element index for each super block */
172
0
    hsize_t start_dblk; /* First data block index for each super block */
173
0
    size_t  u;          /* Local index variable */
174
0
    herr_t  ret_value = SUCCEED;
175
176
0
    FUNC_ENTER_PACKAGE
177
178
    /* Sanity check */
179
0
    assert(hdr);
180
0
    assert(hdr->cparam.max_nelmts_bits);
181
0
    assert(hdr->cparam.data_blk_min_elmts);
182
0
    assert(hdr->cparam.sup_blk_min_data_ptrs);
183
184
    /* Compute general information */
185
0
    hdr->nsblks           = 1 + (hdr->cparam.max_nelmts_bits - H5VM_log2_of2(hdr->cparam.data_blk_min_elmts));
186
0
    hdr->dblk_page_nelmts = (size_t)1 << hdr->cparam.max_dblk_page_nelmts_bits;
187
0
    hdr->arr_off_size     = (unsigned char)H5EA_SIZEOF_OFFSET_BITS(hdr->cparam.max_nelmts_bits);
188
189
    /* Allocate information for each super block */
190
0
    if (NULL == (hdr->sblk_info = H5FL_SEQ_MALLOC(H5EA_sblk_info_t, hdr->nsblks)))
191
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, FAIL, "memory allocation failed for super block info array");
192
193
    /* Compute information about each super block */
194
0
    start_idx  = 0;
195
0
    start_dblk = 0;
196
0
    for (u = 0; u < hdr->nsblks; u++) {
197
0
        hdr->sblk_info[u].ndblks      = (size_t)H5_EXP2(u / 2);
198
0
        hdr->sblk_info[u].dblk_nelmts = H5EA_SBLK_DBLK_NELMTS(u, hdr->cparam.data_blk_min_elmts);
199
0
        hdr->sblk_info[u].start_idx   = start_idx;
200
0
        hdr->sblk_info[u].start_dblk  = start_dblk;
201
202
        /* Advance starting indices for next super block */
203
0
        start_idx += (hsize_t)hdr->sblk_info[u].ndblks * (hsize_t)hdr->sblk_info[u].dblk_nelmts;
204
0
        start_dblk += (hsize_t)hdr->sblk_info[u].ndblks;
205
0
    }
206
207
    /* Set size of header on disk (locally and in statistics) */
208
0
    hdr->stats.computed.hdr_size = hdr->size = H5EA_HEADER_SIZE_HDR(hdr);
209
210
    /* Create the callback context, if there's one */
211
0
    if (hdr->cparam.cls->crt_context) {
212
0
        if (NULL == (hdr->cb_ctx = (*hdr->cparam.cls->crt_context)(ctx_udata)))
213
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTCREATE, FAIL,
214
0
                        "unable to create extensible array client callback context");
215
0
    }
216
217
0
done:
218
0
    FUNC_LEAVE_NOAPI(ret_value)
219
0
} /* end H5EA__hdr_init() */
220
221
/*-------------------------------------------------------------------------
222
 * Function:  H5EA__hdr_alloc_elmts
223
 *
224
 * Purpose: Allocate extensible array data block elements
225
 *
226
 * Return:  Non-NULL pointer to buffer for elements on success/NULL on failure
227
 *
228
 *-------------------------------------------------------------------------
229
 */
230
void *
231
H5EA__hdr_alloc_elmts(H5EA_hdr_t *hdr, size_t nelmts)
232
0
{
233
0
    void    *elmts = NULL; /* Element buffer allocated */
234
0
    unsigned idx;          /* Index of element buffer factory in header */
235
0
    void    *ret_value = NULL;
236
237
0
    FUNC_ENTER_PACKAGE
238
239
    /* Check arguments */
240
0
    assert(hdr);
241
0
    assert(nelmts > 0);
242
243
    /* Compute the index of the element buffer factory */
244
0
    H5_CHECK_OVERFLOW(nelmts, /*From:*/ size_t, /*To:*/ uint32_t);
245
0
    idx = H5VM_log2_of2((uint32_t)nelmts) - H5VM_log2_of2((uint32_t)hdr->cparam.data_blk_min_elmts);
246
247
    /* Check for needing to increase size of array of factories */
248
0
    if (idx >= hdr->elmt_fac.nalloc) {
249
0
        H5FL_fac_head_t **new_fac; /* New array of element factories */
250
0
        size_t            new_nalloc =
251
0
            MAX3(1, (idx + 1), (2 * hdr->elmt_fac.nalloc)); /* New number of factories allocated */
252
253
        /* Re-allocate array of element factories */
254
0
        if (NULL == (new_fac = H5FL_SEQ_REALLOC(H5FL_fac_head_ptr_t, hdr->elmt_fac.fac, new_nalloc)))
255
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
256
0
                        "memory allocation failed for data block data element buffer factory array");
257
258
        /* Zero out new elements allocated */
259
0
        memset(new_fac + hdr->elmt_fac.nalloc, 0,
260
0
               (new_nalloc - hdr->elmt_fac.nalloc) * sizeof(H5FL_fac_head_ptr_t));
261
262
        /* Update information about element factories in header */
263
0
        hdr->elmt_fac.nalloc = new_nalloc;
264
0
        hdr->elmt_fac.fac    = new_fac;
265
0
    } /* end if */
266
267
    /* Check for un-initialized factory at index */
268
0
    if (NULL == hdr->elmt_fac.fac[idx]) {
269
0
        if (NULL == (hdr->elmt_fac.fac[idx] = H5FL_fac_init(nelmts * (size_t)hdr->cparam.cls->nat_elmt_size)))
270
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTINIT, NULL,
271
0
                        "can't create data block data element buffer factory");
272
0
    } /* end if */
273
274
    /* Allocate buffer for elements in index block */
275
0
    if (NULL == (elmts = H5FL_FAC_MALLOC(hdr->elmt_fac.fac[idx])))
276
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
277
0
                    "memory allocation failed for data block data element buffer");
278
279
    /* Set the return value */
280
0
    ret_value = elmts;
281
282
0
done:
283
0
    if (!ret_value)
284
0
        if (elmts)
285
0
            elmts = H5FL_FAC_FREE(hdr->elmt_fac.fac[idx], elmts);
286
287
0
    FUNC_LEAVE_NOAPI(ret_value)
288
0
} /* end H5EA__hdr_alloc_elmts() */
289
290
/*-------------------------------------------------------------------------
291
 * Function:  H5EA__hdr_free_elmts
292
 *
293
 * Purpose: Free extensible array data block elements
294
 *
295
 * Return:  SUCCEED/FAIL
296
 *
297
 *-------------------------------------------------------------------------
298
 */
299
herr_t
300
H5EA__hdr_free_elmts(H5EA_hdr_t *hdr, size_t nelmts, void *elmts)
301
0
{
302
0
    unsigned idx; /* Index of element buffer factory in header */
303
304
0
    FUNC_ENTER_PACKAGE_NOERR
305
306
    /* Check arguments */
307
0
    assert(hdr);
308
0
    assert(nelmts > 0);
309
0
    assert(elmts);
310
311
    /* Compute the index of the element buffer factory */
312
0
    H5_CHECK_OVERFLOW(nelmts, /*From:*/ size_t, /*To:*/ uint32_t);
313
0
    idx = H5VM_log2_of2((uint32_t)nelmts) - H5VM_log2_of2((uint32_t)hdr->cparam.data_blk_min_elmts);
314
315
    /* Free buffer for elements in index block */
316
0
    assert(idx < hdr->elmt_fac.nalloc);
317
0
    assert(hdr->elmt_fac.fac[idx]);
318
0
    elmts = H5FL_FAC_FREE(hdr->elmt_fac.fac[idx], elmts);
319
320
0
    FUNC_LEAVE_NOAPI(SUCCEED)
321
0
} /* end H5EA__hdr_free_elmts() */
322
323
/*-------------------------------------------------------------------------
324
 * Function:  H5EA__hdr_create
325
 *
326
 * Purpose: Creates a new extensible array header in the file
327
 *
328
 * Return:      Success:    Address of new header in the file
329
 *              Failure:    HADDR_UNDEF
330
 *
331
 *-------------------------------------------------------------------------
332
 */
333
haddr_t
334
H5EA__hdr_create(H5F_t *f, const H5EA_create_t *cparam, void *ctx_udata)
335
0
{
336
0
    H5EA_hdr_t *hdr       = NULL;  /* Extensible array header */
337
0
    bool        inserted  = false; /* Whether the header was inserted into cache */
338
0
    haddr_t     ret_value = HADDR_UNDEF;
339
340
0
    FUNC_ENTER_PACKAGE
341
342
    /* Check arguments */
343
0
    assert(f);
344
0
    assert(cparam);
345
346
#ifndef NDEBUG
347
    {
348
        unsigned sblk_idx;         /* Super block index for first "actual" super block */
349
        size_t   dblk_nelmts;      /* Number of data block elements */
350
        size_t   dblk_page_nelmts; /* Number of elements in a data block page */
351
352
        /* Check for valid parameters */
353
        if (cparam->raw_elmt_size == 0)
354
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF, "element size must be greater than zero");
355
        if (cparam->max_nelmts_bits == 0)
356
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
357
                        "max. # of elements bits must be greater than zero");
358
        if (cparam->max_nelmts_bits > H5EA_MAX_NELMTS_IDX_MAX)
359
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF, "max. # of elements bits must be <= %u",
360
                        (unsigned)H5EA_MAX_NELMTS_IDX_MAX);
361
        if (cparam->sup_blk_min_data_ptrs < 2)
362
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
363
                        "min # of data block pointers in super block must be >= two");
364
        if (!POWER_OF_TWO(cparam->sup_blk_min_data_ptrs))
365
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
366
                        "min # of data block pointers in super block must be power of two");
367
        if (!POWER_OF_TWO(cparam->data_blk_min_elmts))
368
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
369
                        "min # of elements per data block must be power of two");
370
        dblk_page_nelmts = (size_t)1 << cparam->max_dblk_page_nelmts_bits;
371
        if (dblk_page_nelmts < cparam->idx_blk_elmts)
372
            HGOTO_ERROR(
373
                H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
374
                "# of elements per data block page must be greater than # of elements in index block");
375
376
        /* Compute the number of elements in data blocks for first actual super block */
377
        sblk_idx    = H5EA_SBLK_FIRST_IDX(cparam->sup_blk_min_data_ptrs);
378
        dblk_nelmts = H5EA_SBLK_DBLK_NELMTS(sblk_idx, cparam->data_blk_min_elmts);
379
        if (dblk_page_nelmts < dblk_nelmts)
380
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
381
                        "max. # of elements per data block page bits must be > # of elements in "
382
                        "first data block from super block");
383
384
        if (cparam->max_dblk_page_nelmts_bits > cparam->max_nelmts_bits)
385
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, HADDR_UNDEF,
386
                        "max. # of elements per data block page bits must be <= max. # of elements bits");
387
    }
388
#endif /* NDEBUG */
389
390
    /* Allocate space for the shared information */
391
0
    if (NULL == (hdr = H5EA__hdr_alloc(f)))
392
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, HADDR_UNDEF,
393
0
                    "memory allocation failed for extensible array shared header");
394
395
    /* Set the internal parameters for the array */
396
0
    hdr->idx_blk_addr = HADDR_UNDEF;
397
398
    /* Set the creation parameters for the array */
399
0
    H5MM_memcpy(&hdr->cparam, cparam, sizeof(hdr->cparam));
400
401
    /* Finish initializing extensible array header */
402
0
    if (H5EA__hdr_init(hdr, ctx_udata) < 0)
403
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTINIT, HADDR_UNDEF,
404
0
                    "initialization failed for extensible array header");
405
406
    /* Allocate space for the header on disk */
407
0
    if (HADDR_UNDEF == (hdr->addr = H5MF_alloc(f, H5FD_MEM_EARRAY_HDR, (hsize_t)hdr->size)))
408
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, HADDR_UNDEF,
409
0
                    "file allocation failed for extensible array header");
410
411
    /* Create 'top' proxy for extensible array entries */
412
0
    if (hdr->swmr_write)
413
0
        if (NULL == (hdr->top_proxy = H5AC_proxy_entry_create()))
414
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTCREATE, HADDR_UNDEF, "can't create extensible array entry proxy");
415
416
    /* Cache the new extensible array header */
417
0
    if (H5AC_insert_entry(f, H5AC_EARRAY_HDR, hdr->addr, hdr, H5AC__NO_FLAGS_SET) < 0)
418
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTINSERT, HADDR_UNDEF, "can't add extensible array header to cache");
419
0
    inserted = true;
420
421
    /* Add header as child of 'top' proxy */
422
0
    if (hdr->top_proxy)
423
0
        if (H5AC_proxy_entry_add_child(hdr->top_proxy, f, hdr) < 0)
424
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTSET, HADDR_UNDEF,
425
0
                        "unable to add extensible array entry as child of array proxy");
426
427
    /* Set address of array header to return */
428
0
    ret_value = hdr->addr;
429
430
0
done:
431
0
    if (!H5_addr_defined(ret_value))
432
0
        if (hdr) {
433
            /* Remove from cache, if inserted */
434
0
            if (inserted)
435
0
                if (H5AC_remove_entry(hdr) < 0)
436
0
                    HDONE_ERROR(H5E_EARRAY, H5E_CANTREMOVE, HADDR_UNDEF,
437
0
                                "unable to remove extensible array header from cache");
438
439
            /* Release header's disk space */
440
0
            if (H5_addr_defined(hdr->addr) &&
441
0
                H5MF_xfree(f, H5FD_MEM_EARRAY_HDR, hdr->addr, (hsize_t)hdr->size) < 0)
442
0
                HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, HADDR_UNDEF, "unable to free extensible array header");
443
444
            /* Destroy header */
445
0
            if (H5EA__hdr_dest(hdr) < 0)
446
0
                HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, HADDR_UNDEF,
447
0
                            "unable to destroy extensible array header");
448
0
        } /* end if */
449
450
0
    FUNC_LEAVE_NOAPI(ret_value)
451
0
} /* end H5EA__hdr_create() */
452
453
/*-------------------------------------------------------------------------
454
 * Function:  H5EA__hdr_incr
455
 *
456
 * Purpose: Increment component reference count on shared array header
457
 *
458
 * Return:  Non-negative on success/Negative on failure
459
 *
460
 *-------------------------------------------------------------------------
461
 */
462
herr_t
463
H5EA__hdr_incr(H5EA_hdr_t *hdr)
464
0
{
465
0
    herr_t ret_value = SUCCEED;
466
467
0
    FUNC_ENTER_PACKAGE
468
469
    /* Sanity check */
470
0
    assert(hdr);
471
472
    /* Mark header as un-evictable when something is depending on it */
473
0
    if (hdr->rc == 0)
474
0
        if (H5AC_pin_protected_entry(hdr) < 0)
475
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTPIN, FAIL, "unable to pin extensible array header");
476
477
    /* Increment reference count on shared header */
478
0
    hdr->rc++;
479
480
0
done:
481
0
    FUNC_LEAVE_NOAPI(ret_value)
482
0
} /* end H5EA__hdr_incr() */
483
484
/*-------------------------------------------------------------------------
485
 * Function:  H5EA__hdr_decr
486
 *
487
 * Purpose: Decrement component reference count on shared array header
488
 *
489
 * Return:  Non-negative on success/Negative on failure
490
 *
491
 *-------------------------------------------------------------------------
492
 */
493
herr_t
494
H5EA__hdr_decr(H5EA_hdr_t *hdr)
495
0
{
496
0
    herr_t ret_value = SUCCEED;
497
498
0
    FUNC_ENTER_PACKAGE
499
500
    /* Sanity check */
501
0
    assert(hdr);
502
0
    assert(hdr->rc);
503
504
    /* Decrement reference count on shared header */
505
0
    hdr->rc--;
506
507
    /* Mark header as evictable again when nothing depend on it */
508
0
    if (hdr->rc == 0) {
509
0
        assert(hdr->file_rc == 0);
510
0
        if (H5AC_unpin_entry(hdr) < 0)
511
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNPIN, FAIL, "unable to unpin extensible array header");
512
0
    }
513
514
0
done:
515
0
    FUNC_LEAVE_NOAPI(ret_value)
516
0
} /* end H5EA__hdr_decr() */
517
518
/*-------------------------------------------------------------------------
519
 * Function:  H5EA__hdr_fuse_incr
520
 *
521
 * Purpose: Increment file reference count on shared array header
522
 *
523
 * Return:  Non-negative on success/Negative on failure
524
 *
525
 *-------------------------------------------------------------------------
526
 */
527
herr_t
528
H5EA__hdr_fuse_incr(H5EA_hdr_t *hdr)
529
0
{
530
0
    FUNC_ENTER_PACKAGE_NOERR
531
532
    /* Sanity check */
533
0
    assert(hdr);
534
535
    /* Increment file reference count on shared header */
536
0
    hdr->file_rc++;
537
538
0
    FUNC_LEAVE_NOAPI(SUCCEED)
539
0
} /* end H5EA__hdr_fuse_incr() */
540
541
/*-------------------------------------------------------------------------
542
 * Function:  H5EA__hdr_fuse_decr
543
 *
544
 * Purpose: Decrement file reference count on shared array header
545
 *
546
 * Return:      Success:    The reference count of the header
547
 *              Failure:    Can't fail
548
 *
549
 *-------------------------------------------------------------------------
550
 */
551
size_t
552
H5EA__hdr_fuse_decr(H5EA_hdr_t *hdr)
553
0
{
554
0
    size_t ret_value = 0;
555
556
0
    FUNC_ENTER_PACKAGE_NOERR
557
558
    /* Sanity check */
559
0
    assert(hdr);
560
0
    assert(hdr->file_rc);
561
562
    /* Decrement file reference count on shared header */
563
0
    hdr->file_rc--;
564
565
    /* Set return value */
566
0
    ret_value = hdr->file_rc;
567
568
0
    FUNC_LEAVE_NOAPI(ret_value)
569
0
} /* end H5EA__hdr_fuse_decr() */
570
571
/*-------------------------------------------------------------------------
572
 * Function:  H5EA__hdr_modified
573
 *
574
 * Purpose: Mark an extensible array as modified
575
 *
576
 * Return:  SUCCEED/FAIL
577
 *
578
 *-------------------------------------------------------------------------
579
 */
580
herr_t
581
H5EA__hdr_modified(H5EA_hdr_t *hdr)
582
0
{
583
0
    herr_t ret_value = SUCCEED;
584
585
0
    FUNC_ENTER_PACKAGE
586
587
    /* Sanity check */
588
0
    assert(hdr);
589
0
    assert(hdr->f);
590
591
    /* Mark header as dirty in cache */
592
0
    if (H5AC_mark_entry_dirty(hdr) < 0)
593
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTMARKDIRTY, FAIL, "unable to mark extensible array header as dirty");
594
595
0
done:
596
0
    FUNC_LEAVE_NOAPI(ret_value)
597
0
} /* end H5EA__hdr_modified() */
598
599
/*-------------------------------------------------------------------------
600
 * Function:  H5EA__hdr_protect
601
 *
602
 * Purpose: Convenience wrapper around protecting extensible array header
603
 *
604
 * Return:  Non-NULL pointer to header on success/NULL on failure
605
 *
606
 *-------------------------------------------------------------------------
607
 */
608
H5EA_hdr_t *
609
H5EA__hdr_protect(H5F_t *f, haddr_t ea_addr, void *ctx_udata, unsigned flags)
610
0
{
611
0
    H5EA_hdr_t         *hdr;   /* Extensible array header */
612
0
    H5EA_hdr_cache_ud_t udata; /* User data for cache callbacks */
613
0
    H5EA_hdr_t         *ret_value = NULL;
614
615
0
    FUNC_ENTER_PACKAGE
616
617
    /* Sanity check */
618
0
    assert(f);
619
0
    assert(H5_addr_defined(ea_addr));
620
621
    /* only the H5AC__READ_ONLY_FLAG may appear in flags */
622
0
    assert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
623
624
    /* Set up user data for cache callbacks */
625
0
    udata.f         = f;
626
0
    udata.addr      = ea_addr;
627
0
    udata.ctx_udata = ctx_udata;
628
629
    /* Protect the header */
630
0
    if (NULL == (hdr = (H5EA_hdr_t *)H5AC_protect(f, H5AC_EARRAY_HDR, ea_addr, &udata, flags)))
631
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTPROTECT, NULL,
632
0
                    "unable to protect extensible array header, address = %llu", (unsigned long long)ea_addr);
633
0
    hdr->f = f; /* (Must be set again here, in case the header was already in the cache -QAK) */
634
635
    /* Create top proxy, if it doesn't exist */
636
0
    if (hdr->swmr_write && NULL == hdr->top_proxy) {
637
        /* Create 'top' proxy for extensible array entries */
638
0
        if (NULL == (hdr->top_proxy = H5AC_proxy_entry_create()))
639
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTCREATE, NULL, "can't create extensible array entry proxy");
640
641
        /* Add header as child of 'top' proxy */
642
0
        if (H5AC_proxy_entry_add_child(hdr->top_proxy, f, hdr) < 0)
643
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTSET, NULL,
644
0
                        "unable to add extensible array entry as child of array proxy");
645
0
    } /* end if */
646
647
    /* Set return value */
648
0
    ret_value = hdr;
649
650
0
done:
651
0
    FUNC_LEAVE_NOAPI(ret_value)
652
0
} /* end H5EA__hdr_protect() */
653
654
/*-------------------------------------------------------------------------
655
 * Function:  H5EA__hdr_unprotect
656
 *
657
 * Purpose: Convenience wrapper around unprotecting extensible array header
658
 *
659
 * Return:  Non-negative on success/Negative on failure
660
 *
661
 *-------------------------------------------------------------------------
662
 */
663
herr_t
664
H5EA__hdr_unprotect(H5EA_hdr_t *hdr, unsigned cache_flags)
665
0
{
666
0
    herr_t ret_value = SUCCEED;
667
668
0
    FUNC_ENTER_PACKAGE
669
670
    /* Sanity check */
671
0
    assert(hdr);
672
673
    /* Unprotect the header */
674
0
    if (H5AC_unprotect(hdr->f, H5AC_EARRAY_HDR, hdr->addr, hdr, cache_flags) < 0)
675
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNPROTECT, FAIL,
676
0
                    "unable to unprotect extensible array hdr, address = %llu",
677
0
                    (unsigned long long)hdr->addr);
678
679
0
done:
680
0
    FUNC_LEAVE_NOAPI(ret_value)
681
0
} /* end H5EA__hdr_unprotect() */
682
683
/*-------------------------------------------------------------------------
684
 * Function:  H5EA__hdr_delete
685
 *
686
 * Purpose: Delete an extensible array, starting with the header
687
 *
688
 * Return:  SUCCEED/FAIL
689
 *
690
 *-------------------------------------------------------------------------
691
 */
692
herr_t
693
H5EA__hdr_delete(H5EA_hdr_t *hdr)
694
0
{
695
0
    unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting header */
696
0
    herr_t   ret_value   = SUCCEED;
697
698
0
    FUNC_ENTER_PACKAGE
699
700
    /* Sanity check */
701
0
    assert(hdr);
702
0
    assert(!hdr->file_rc);
703
704
#ifndef NDEBUG
705
    unsigned hdr_status = 0; /* Array header's status in the metadata cache */
706
707
    /* Check the array header's status in the metadata cache */
708
    if (H5AC_get_entry_status(hdr->f, hdr->addr, &hdr_status) < 0)
709
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTGET, FAIL, "unable to check metadata cache status for array header");
710
711
    /* Sanity checks on array header */
712
    assert(hdr_status & H5AC_ES__IN_CACHE);
713
    assert(hdr_status & H5AC_ES__IS_PROTECTED);
714
#endif /* NDEBUG */
715
716
    /* Check for index block */
717
0
    if (H5_addr_defined(hdr->idx_blk_addr)) {
718
        /* Delete index block */
719
0
        if (H5EA__iblock_delete(hdr) < 0)
720
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTDELETE, FAIL, "unable to delete extensible array index block");
721
0
    } /* end if */
722
723
    /* Set flags to finish deleting header on unprotect */
724
0
    cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
725
726
0
done:
727
728
    /* Unprotect the header, deleting it if an error hasn't occurred */
729
0
    if (H5EA__hdr_unprotect(hdr, cache_flags) < 0)
730
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNPROTECT, FAIL, "unable to release extensible array header");
731
732
0
    FUNC_LEAVE_NOAPI(ret_value)
733
0
} /* end H5EA__hdr_delete() */
734
735
/*-------------------------------------------------------------------------
736
 * Function:  H5EA__hdr_dest
737
 *
738
 * Purpose: Destroys an extensible array header in memory.
739
 *
740
 * Return:  Non-negative on success/Negative on failure
741
 *
742
 *-------------------------------------------------------------------------
743
 */
744
herr_t
745
H5EA__hdr_dest(H5EA_hdr_t *hdr)
746
0
{
747
0
    herr_t ret_value = SUCCEED;
748
749
0
    FUNC_ENTER_PACKAGE
750
751
    /* Check arguments */
752
0
    assert(hdr);
753
0
    assert(hdr->rc == 0);
754
755
    /* Destroy the callback context */
756
0
    if (hdr->cb_ctx) {
757
0
        if ((*hdr->cparam.cls->dst_context)(hdr->cb_ctx) < 0)
758
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTRELEASE, FAIL,
759
0
                        "unable to destroy extensible array client callback context");
760
0
    } /* end if */
761
0
    hdr->cb_ctx = NULL;
762
763
    /* Check for data block element buffer factory info to free */
764
0
    if (hdr->elmt_fac.fac) {
765
0
        unsigned u; /* Local index variable */
766
767
        /* Sanity check */
768
0
        assert(hdr->elmt_fac.nalloc > 0);
769
770
        /* Iterate over factories, shutting them down */
771
0
        for (u = 0; u < hdr->elmt_fac.nalloc; u++) {
772
            /* Check if this factory has been initialized */
773
0
            if (hdr->elmt_fac.fac[u]) {
774
0
                if (H5FL_fac_term(hdr->elmt_fac.fac[u]) < 0)
775
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTRELEASE, FAIL,
776
0
                                "unable to destroy extensible array header factory");
777
0
                hdr->elmt_fac.fac[u] = NULL;
778
0
            } /* end if */
779
0
        }     /* end for */
780
781
        /* Free factory array */
782
0
        hdr->elmt_fac.fac = (H5FL_fac_head_t **)H5FL_SEQ_FREE(H5FL_fac_head_ptr_t, hdr->elmt_fac.fac);
783
0
    } /* end if */
784
785
    /* Free the super block info array */
786
0
    if (hdr->sblk_info)
787
0
        hdr->sblk_info = (H5EA_sblk_info_t *)H5FL_SEQ_FREE(H5EA_sblk_info_t, hdr->sblk_info);
788
789
    /* Destroy the 'top' proxy */
790
0
    if (hdr->top_proxy) {
791
0
        if (H5AC_proxy_entry_dest(hdr->top_proxy) < 0)
792
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTRELEASE, FAIL, "unable to destroy extensible array 'top' proxy");
793
0
        hdr->top_proxy = NULL;
794
0
    } /* end if */
795
796
    /* Free the shared info itself */
797
0
    hdr = H5FL_FREE(H5EA_hdr_t, hdr);
798
799
0
done:
800
0
    FUNC_LEAVE_NOAPI(ret_value)
801
0
} /* end H5EA__hdr_dest() */