Coverage Report

Created: 2025-11-11 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5EAcache.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:   H5EAcache.c
16
 *
17
 * Purpose:   Implement extensible array metadata cache methods.
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 "H5MMprivate.h" /* Memory management     */
39
40
/****************/
41
/* Local Macros */
42
/****************/
43
44
/* Fractal heap format version #'s */
45
0
#define H5EA_HDR_VERSION    0 /* Header */
46
0
#define H5EA_IBLOCK_VERSION 0 /* Index block */
47
0
#define H5EA_SBLOCK_VERSION 0 /* Super block */
48
0
#define H5EA_DBLOCK_VERSION 0 /* Data block */
49
50
/******************/
51
/* Local Typedefs */
52
/******************/
53
54
/********************/
55
/* Package Typedefs */
56
/********************/
57
58
/********************/
59
/* Local Prototypes */
60
/********************/
61
62
/* Metadata cache (H5AC) callbacks */
63
static herr_t H5EA__cache_hdr_get_initial_load_size(void *udata, size_t *image_len);
64
static htri_t H5EA__cache_hdr_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
65
static void  *H5EA__cache_hdr_deserialize(const void *image, size_t len, void *udata, bool *dirty);
66
static herr_t H5EA__cache_hdr_image_len(const void *thing, size_t *image_len);
67
static herr_t H5EA__cache_hdr_serialize(const H5F_t *f, void *image, size_t len, void *thing);
68
static herr_t H5EA__cache_hdr_notify(H5AC_notify_action_t action, void *thing);
69
static herr_t H5EA__cache_hdr_free_icr(void *thing);
70
71
static herr_t H5EA__cache_iblock_get_initial_load_size(void *udata, size_t *image_len);
72
static htri_t H5EA__cache_iblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
73
static void  *H5EA__cache_iblock_deserialize(const void *image, size_t len, void *udata, bool *dirty);
74
static herr_t H5EA__cache_iblock_image_len(const void *thing, size_t *image_len);
75
static herr_t H5EA__cache_iblock_serialize(const H5F_t *f, void *image, size_t len, void *thing);
76
static herr_t H5EA__cache_iblock_notify(H5AC_notify_action_t action, void *thing);
77
static herr_t H5EA__cache_iblock_free_icr(void *thing);
78
79
static herr_t H5EA__cache_sblock_get_initial_load_size(void *udata, size_t *image_len);
80
static htri_t H5EA__cache_sblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
81
static void  *H5EA__cache_sblock_deserialize(const void *image, size_t len, void *udata, bool *dirty);
82
static herr_t H5EA__cache_sblock_image_len(const void *thing, size_t *image_len);
83
static herr_t H5EA__cache_sblock_serialize(const H5F_t *f, void *image, size_t len, void *thing);
84
static herr_t H5EA__cache_sblock_notify(H5AC_notify_action_t action, void *thing);
85
static herr_t H5EA__cache_sblock_free_icr(void *thing);
86
87
static herr_t H5EA__cache_dblock_get_initial_load_size(void *udata, size_t *image_len);
88
static htri_t H5EA__cache_dblock_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
89
static void  *H5EA__cache_dblock_deserialize(const void *image, size_t len, void *udata, bool *dirty);
90
static herr_t H5EA__cache_dblock_image_len(const void *thing, size_t *image_len);
91
static herr_t H5EA__cache_dblock_serialize(const H5F_t *f, void *image, size_t len, void *thing);
92
static herr_t H5EA__cache_dblock_notify(H5AC_notify_action_t action, void *thing);
93
static herr_t H5EA__cache_dblock_free_icr(void *thing);
94
static herr_t H5EA__cache_dblock_fsf_size(const void *thing, hsize_t *fsf_size);
95
96
static herr_t H5EA__cache_dblk_page_get_initial_load_size(void *udata, size_t *image_len);
97
static htri_t H5EA__cache_dblk_page_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
98
static void  *H5EA__cache_dblk_page_deserialize(const void *image, size_t len, void *udata, bool *dirty);
99
static herr_t H5EA__cache_dblk_page_image_len(const void *thing, size_t *image_len);
100
static herr_t H5EA__cache_dblk_page_serialize(const H5F_t *f, void *image, size_t len, void *thing);
101
static herr_t H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, void *thing);
102
static herr_t H5EA__cache_dblk_page_free_icr(void *thing);
103
104
/*********************/
105
/* Package Variables */
106
/*********************/
107
108
/* H5EA header inherits cache-like properties from H5AC */
109
const H5AC_class_t H5AC_EARRAY_HDR[1] = {{
110
    H5AC_EARRAY_HDR_ID,                    /* Metadata client ID */
111
    "Extensible Array Header",             /* Metadata client name (for debugging) */
112
    H5FD_MEM_EARRAY_HDR,                   /* File space memory type for client */
113
    H5AC__CLASS_NO_FLAGS_SET,              /* Client class behavior flags */
114
    H5EA__cache_hdr_get_initial_load_size, /* 'get_initial_load_size' callback */
115
    NULL,                                  /* 'get_final_load_size' callback */
116
    H5EA__cache_hdr_verify_chksum,         /* 'verify_chksum' callback */
117
    H5EA__cache_hdr_deserialize,           /* 'deserialize' callback */
118
    H5EA__cache_hdr_image_len,             /* 'image_len' callback */
119
    NULL,                                  /* 'pre_serialize' callback */
120
    H5EA__cache_hdr_serialize,             /* 'serialize' callback */
121
    H5EA__cache_hdr_notify,                /* 'notify' callback */
122
    H5EA__cache_hdr_free_icr,              /* 'free_icr' callback */
123
    NULL,                                  /* 'fsf_size' callback */
124
}};
125
126
/* H5EA index block inherits cache-like properties from H5AC */
127
const H5AC_class_t H5AC_EARRAY_IBLOCK[1] = {{
128
    H5AC_EARRAY_IBLOCK_ID,                    /* Metadata client ID */
129
    "Extensible Array Index Block",           /* Metadata client name (for debugging) */
130
    H5FD_MEM_EARRAY_IBLOCK,                   /* File space memory type for client */
131
    H5AC__CLASS_NO_FLAGS_SET,                 /* Client class behavior flags */
132
    H5EA__cache_iblock_get_initial_load_size, /* 'get_initial_load_size' callback */
133
    NULL,                                     /* 'get_final_load_size' callback */
134
    H5EA__cache_iblock_verify_chksum,         /* 'verify_chksum' callback */
135
    H5EA__cache_iblock_deserialize,           /* 'deserialize' callback */
136
    H5EA__cache_iblock_image_len,             /* 'image_len' callback */
137
    NULL,                                     /* 'pre_serialize' callback */
138
    H5EA__cache_iblock_serialize,             /* 'serialize' callback */
139
    H5EA__cache_iblock_notify,                /* 'notify' callback */
140
    H5EA__cache_iblock_free_icr,              /* 'free_icr' callback */
141
    NULL,                                     /* 'fsf_size' callback */
142
}};
143
144
/* H5EA super block inherits cache-like properties from H5AC */
145
const H5AC_class_t H5AC_EARRAY_SBLOCK[1] = {{
146
    H5AC_EARRAY_SBLOCK_ID,                    /* Metadata client ID */
147
    "Extensible Array Super Block",           /* Metadata client name (for debugging) */
148
    H5FD_MEM_EARRAY_SBLOCK,                   /* File space memory type for client */
149
    H5AC__CLASS_NO_FLAGS_SET,                 /* Client class behavior flags */
150
    H5EA__cache_sblock_get_initial_load_size, /* 'get_initial_load_size' callback */
151
    NULL,                                     /* 'get_final_load_size' callback */
152
    H5EA__cache_sblock_verify_chksum,         /* 'verify_chksum' callback */
153
    H5EA__cache_sblock_deserialize,           /* 'deserialize' callback */
154
    H5EA__cache_sblock_image_len,             /* 'image_len' callback */
155
    NULL,                                     /* 'pre_serialize' callback */
156
    H5EA__cache_sblock_serialize,             /* 'serialize' callback */
157
    H5EA__cache_sblock_notify,                /* 'notify' callback */
158
    H5EA__cache_sblock_free_icr,              /* 'free_icr' callback */
159
    NULL,                                     /* 'fsf_size' callback */
160
}};
161
162
/* H5EA data block inherits cache-like properties from H5AC */
163
const H5AC_class_t H5AC_EARRAY_DBLOCK[1] = {{
164
    H5AC_EARRAY_DBLOCK_ID,                    /* Metadata client ID */
165
    "Extensible Array Data Block",            /* Metadata client name (for debugging) */
166
    H5FD_MEM_EARRAY_DBLOCK,                   /* File space memory type for client */
167
    H5AC__CLASS_NO_FLAGS_SET,                 /* Client class behavior flags */
168
    H5EA__cache_dblock_get_initial_load_size, /* 'get_initial_load_size' callback */
169
    NULL,                                     /* 'get_final_load_size' callback */
170
    H5EA__cache_dblock_verify_chksum,         /* 'verify_chksum' callback */
171
    H5EA__cache_dblock_deserialize,           /* 'deserialize' callback */
172
    H5EA__cache_dblock_image_len,             /* 'image_len' callback */
173
    NULL,                                     /* 'pre_serialize' callback */
174
    H5EA__cache_dblock_serialize,             /* 'serialize' callback */
175
    H5EA__cache_dblock_notify,                /* 'notify' callback */
176
    H5EA__cache_dblock_free_icr,              /* 'free_icr' callback */
177
    H5EA__cache_dblock_fsf_size,              /* 'fsf_size' callback */
178
}};
179
180
/* H5EA data block page inherits cache-like properties from H5AC */
181
const H5AC_class_t H5AC_EARRAY_DBLK_PAGE[1] = {{
182
    H5AC_EARRAY_DBLK_PAGE_ID,                    /* Metadata client ID */
183
    "Extensible Array Data Block Page",          /* Metadata client name (for debugging) */
184
    H5FD_MEM_EARRAY_DBLK_PAGE,                   /* File space memory type for client */
185
    H5AC__CLASS_NO_FLAGS_SET,                    /* Client class behavior flags */
186
    H5EA__cache_dblk_page_get_initial_load_size, /* 'get_initial_load_size' callback */
187
    NULL,                                        /* 'get_final_load_size' callback */
188
    H5EA__cache_dblk_page_verify_chksum,         /* 'verify_chksum' callback */
189
    H5EA__cache_dblk_page_deserialize,           /* 'deserialize' callback */
190
    H5EA__cache_dblk_page_image_len,             /* 'image_len' callback */
191
    NULL,                                        /* 'pre_serialize' callback */
192
    H5EA__cache_dblk_page_serialize,             /* 'serialize' callback */
193
    H5EA__cache_dblk_page_notify,                /* 'notify' callback */
194
    H5EA__cache_dblk_page_free_icr,              /* 'free_icr' callback */
195
    NULL,                                        /* 'fsf_size' callback */
196
}};
197
198
/*****************************/
199
/* Library Private Variables */
200
/*****************************/
201
202
/*******************/
203
/* Local Variables */
204
/*******************/
205
206
/*-------------------------------------------------------------------------
207
 * Function:    H5EA__cache_hdr_get_initial_load_size
208
 *
209
 * Purpose:     Compute the size of the data structure on disk.
210
 *
211
 * Return:      Non-negative on success/Negative on failure
212
 *
213
 *-------------------------------------------------------------------------
214
 */
215
static herr_t
216
H5EA__cache_hdr_get_initial_load_size(void *_udata, size_t *image_len)
217
0
{
218
0
    H5EA_hdr_cache_ud_t *udata = (H5EA_hdr_cache_ud_t *)_udata; /* User data for callback */
219
220
0
    FUNC_ENTER_PACKAGE_NOERR
221
222
    /* Check arguments */
223
0
    assert(udata);
224
0
    assert(udata->f);
225
0
    assert(image_len);
226
227
    /* Set the image length size */
228
0
    *image_len = (size_t)H5EA_HEADER_SIZE_FILE(udata->f);
229
230
0
    FUNC_LEAVE_NOAPI(SUCCEED)
231
0
} /* end H5EA__cache_hdr_get_initial_load_size() */
232
233
/*-------------------------------------------------------------------------
234
 * Function:  H5EA__cache_hdr_verify_chksum
235
 *
236
 * Purpose:     Verify the computed checksum of the data structure is the
237
 *              same as the stored chksum.
238
 *
239
 * Return:      Success:        true/false
240
 *              Failure:        Negative
241
 *
242
 *-------------------------------------------------------------------------
243
 */
244
static htri_t
245
H5EA__cache_hdr_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
246
0
{
247
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
248
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
249
0
    uint32_t       computed_chksum;                 /* Computed metadata checksum value */
250
0
    htri_t         ret_value = true;
251
252
0
    FUNC_ENTER_PACKAGE
253
254
    /* Check arguments */
255
0
    assert(image);
256
257
    /* Get stored and computed checksums */
258
0
    if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
259
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, FAIL, "can't get checksums");
260
261
0
    if (stored_chksum != computed_chksum)
262
0
        ret_value = false;
263
264
0
done:
265
0
    FUNC_LEAVE_NOAPI(ret_value)
266
0
} /* end H5EA__cache_hdr_verify_chksum() */
267
268
/*-------------------------------------------------------------------------
269
 * Function:  H5EA__cache_hdr_deserialize
270
 *
271
 * Purpose: Loads a data structure from the disk.
272
 *
273
 * Return:  Success:  Pointer to a new B-tree.
274
 *    Failure:  NULL
275
 *
276
 *-------------------------------------------------------------------------
277
 */
278
static void *
279
H5EA__cache_hdr_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty)
280
0
{
281
0
    H5EA_cls_id_t        id;           /* ID of extensible array class, as found in file */
282
0
    H5EA_hdr_t          *hdr   = NULL; /* Extensible array info */
283
0
    H5EA_hdr_cache_ud_t *udata = (H5EA_hdr_cache_ud_t *)_udata;
284
0
    const uint8_t       *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
285
0
    uint32_t             stored_chksum;                   /* Stored metadata checksum value */
286
0
    void                *ret_value = NULL;
287
288
0
    FUNC_ENTER_PACKAGE
289
290
    /* Check arguments */
291
0
    assert(image);
292
0
    assert(udata);
293
0
    assert(udata->f);
294
0
    assert(H5_addr_defined(udata->addr));
295
296
    /* Allocate space for the extensible array data structure */
297
0
    if (NULL == (hdr = H5EA__hdr_alloc(udata->f)))
298
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
299
0
                    "memory allocation failed for extensible array shared header");
300
301
    /* Set the extensible array header's address */
302
0
    hdr->addr = udata->addr;
303
304
    /* Magic number */
305
0
    if (memcmp(image, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
306
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array header signature");
307
0
    image += H5_SIZEOF_MAGIC;
308
309
    /* Version */
310
0
    if (*image++ != H5EA_HDR_VERSION)
311
0
        HGOTO_ERROR(H5E_EARRAY, H5E_VERSION, NULL, "wrong extensible array header version");
312
313
    /* Extensible array class */
314
0
    id = (H5EA_cls_id_t)*image++;
315
0
    if (id >= H5EA_NUM_CLS_ID)
316
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADTYPE, NULL, "incorrect extensible array class");
317
0
    hdr->cparam.cls = H5EA_client_class_g[id];
318
319
    /* General array creation/configuration information */
320
0
    hdr->cparam.raw_elmt_size = *image++; /* Element size in file (in bytes) */
321
0
    hdr->cparam.max_nelmts_bits =
322
0
        *image++; /* Log2(Max. # of elements in array) - i.e. # of bits needed to store max. # of elements */
323
0
    hdr->cparam.idx_blk_elmts         = *image++; /* # of elements to store in index block */
324
0
    hdr->cparam.data_blk_min_elmts    = *image++; /* Min. # of elements per data block */
325
0
    hdr->cparam.sup_blk_min_data_ptrs = *image++; /* Min. # of data block pointers for a super block */
326
0
    hdr->cparam.max_dblk_page_nelmts_bits =
327
0
        *image++; /* Log2(Max. # of elements in data block page) - i.e. # of bits needed to store max. # of
328
                     elements in data block page */
329
330
    /* Array statistics */
331
0
    hdr->stats.computed.hdr_size = len;                                   /* Size of header in file */
332
0
    H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.nsuper_blks);    /* Number of super blocks created */
333
0
    H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.super_blk_size); /* Size of super blocks created */
334
0
    H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.ndata_blks);     /* Number of data blocks created */
335
0
    H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.data_blk_size);  /* Size of data blocks created */
336
0
    H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.max_idx_set);    /* Max. index set (+1) */
337
0
    H5F_DECODE_LENGTH(udata->f, image, hdr->stats.stored.nelmts);         /* Number of elements 'realized' */
338
339
    /* Internal information */
340
0
    H5F_addr_decode(udata->f, &image, &hdr->idx_blk_addr); /* Address of index block */
341
342
    /* Index block statistics */
343
0
    if (H5_addr_defined(hdr->idx_blk_addr)) {
344
0
        H5EA_iblock_t iblock; /* Fake index block for computing size */
345
346
        /* Set index block count for file */
347
0
        hdr->stats.computed.nindex_blks = 1;
348
349
        /* Set up fake index block for computing size on disk */
350
0
        iblock.hdr         = hdr;
351
0
        iblock.nsblks      = H5EA_SBLK_FIRST_IDX(hdr->cparam.sup_blk_min_data_ptrs);
352
0
        iblock.ndblk_addrs = 2 * ((size_t)hdr->cparam.sup_blk_min_data_ptrs - 1);
353
0
        iblock.nsblk_addrs = hdr->nsblks - iblock.nsblks;
354
355
        /* Compute size of index block in file */
356
0
        hdr->stats.computed.index_blk_size = H5EA_IBLOCK_SIZE(&iblock);
357
0
    } /* end if */
358
0
    else {
359
0
        hdr->stats.computed.nindex_blks    = 0; /* Number of index blocks in file */
360
0
        hdr->stats.computed.index_blk_size = 0; /* Size of index blocks in file */
361
0
    }                                           /* end else */
362
363
    /* Sanity check */
364
    /* (allow for checksum not decoded yet) */
365
0
    assert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
366
367
    /* checksum verification already done in verify_chksum cb */
368
369
    /* Metadata checksum */
370
0
    UINT32DECODE(image, stored_chksum);
371
372
    /* Sanity check */
373
0
    assert((size_t)(image - (const uint8_t *)_image) == len);
374
375
    /* Finish initializing extensible array header */
376
0
    if (H5EA__hdr_init(hdr, udata->ctx_udata) < 0)
377
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTINIT, NULL, "initialization failed for extensible array header");
378
0
    assert(hdr->size == len);
379
380
    /* Set return value */
381
0
    ret_value = hdr;
382
383
0
done:
384
    /* Release resources */
385
0
    if (!ret_value)
386
0
        if (hdr && H5EA__hdr_dest(hdr) < 0)
387
0
            HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, NULL, "unable to destroy extensible array header");
388
389
0
    FUNC_LEAVE_NOAPI(ret_value)
390
0
} /* end H5EA__cache_hdr_deserialize() */
391
392
/*-------------------------------------------------------------------------
393
 * Function:    H5EA__cache_hdr_image_len
394
 *
395
 * Purpose:     Compute the size of the data structure on disk.
396
 *
397
 * Return:      Non-negative on success/Negative on failure
398
 *
399
 *-------------------------------------------------------------------------
400
 */
401
static herr_t
402
H5EA__cache_hdr_image_len(const void *_thing, size_t *image_len)
403
0
{
404
0
    const H5EA_hdr_t *hdr = (const H5EA_hdr_t *)_thing; /* Pointer to the object */
405
406
0
    FUNC_ENTER_PACKAGE_NOERR
407
408
    /* Check arguments */
409
0
    assert(hdr);
410
0
    assert(image_len);
411
412
    /* Set the image length size */
413
0
    *image_len = hdr->size;
414
415
0
    FUNC_LEAVE_NOAPI(SUCCEED)
416
0
} /* end H5EA__cache_hdr_image_len() */
417
418
/*-------------------------------------------------------------------------
419
 * Function:  H5EA__cache_hdr_serialize
420
 *
421
 * Purpose: Flushes a dirty object to disk.
422
 *
423
 * Return:  Non-negative on success/Negative on failure
424
 *
425
 *-------------------------------------------------------------------------
426
 */
427
static herr_t
428
H5EA__cache_hdr_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing)
429
0
{
430
0
    H5EA_hdr_t *hdr   = (H5EA_hdr_t *)_thing; /* Pointer to the extensible array header */
431
0
    uint8_t    *image = (uint8_t *)_image;    /* Pointer into raw data buffer */
432
0
    uint32_t    metadata_chksum;              /* Computed metadata checksum value */
433
434
0
    FUNC_ENTER_PACKAGE_NOERR
435
436
    /* check arguments */
437
0
    assert(f);
438
0
    assert(image);
439
0
    assert(hdr);
440
441
    /* Magic number */
442
0
    H5MM_memcpy(image, H5EA_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
443
0
    image += H5_SIZEOF_MAGIC;
444
445
    /* Version # */
446
0
    *image++ = H5EA_HDR_VERSION;
447
448
    /* Extensible array type */
449
0
    assert(hdr->cparam.cls->id <= 255);
450
0
    *image++ = (uint8_t)hdr->cparam.cls->id;
451
452
    /* General array creation/configuration information */
453
0
    *image++ = hdr->cparam.raw_elmt_size;      /* Element size in file (in bytes) */
454
0
    *image++ = hdr->cparam.max_nelmts_bits;    /* Log2(Max. # of elements in array) - i.e. # of bits needed to
455
                                                  store    max. # of elements */
456
0
    *image++ = hdr->cparam.idx_blk_elmts;      /* # of elements to store in index block */
457
0
    *image++ = hdr->cparam.data_blk_min_elmts; /* Min. # of elements per data block */
458
0
    *image++ = hdr->cparam.sup_blk_min_data_ptrs; /* Min. # of data block pointers for a super block */
459
0
    *image++ =
460
0
        hdr->cparam.max_dblk_page_nelmts_bits; /* Log2(Max. # of elements in data block page) - i.e. # of bits
461
                                                  needed to store max. # of elements in data block page */
462
463
    /* Array statistics */
464
0
    H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.nsuper_blks);    /* Number of super blocks created */
465
0
    H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.super_blk_size); /* Size of super blocks created */
466
0
    H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.ndata_blks);     /* Number of data blocks created */
467
0
    H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.data_blk_size);  /* Size of data blocks created */
468
0
    H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.max_idx_set);    /* Max. index set (+1) */
469
0
    H5F_ENCODE_LENGTH(f, image, hdr->stats.stored.nelmts);         /* Number of elements 'realized' */
470
471
    /* Internal information */
472
0
    H5F_addr_encode(f, &image, hdr->idx_blk_addr); /* Address of index block */
473
474
    /* Compute metadata checksum */
475
0
    metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
476
477
    /* Metadata checksum */
478
0
    UINT32ENCODE(image, metadata_chksum);
479
480
    /* Sanity check */
481
0
    assert((size_t)(image - (uint8_t *)_image) == len);
482
483
0
    FUNC_LEAVE_NOAPI(SUCCEED)
484
0
} /* end H5EA__cache_hdr_serialize() */
485
486
/*-------------------------------------------------------------------------
487
 * Function:  H5EA__cache_hdr_notify
488
 *
489
 * Purpose: Handle cache action notifications
490
 *
491
 * Return:  Non-negative on success/Negative on failure
492
 *
493
 *-------------------------------------------------------------------------
494
 */
495
static herr_t
496
H5EA__cache_hdr_notify(H5AC_notify_action_t action, void *_thing)
497
0
{
498
0
    H5EA_hdr_t *hdr       = (H5EA_hdr_t *)_thing; /* Pointer to the object */
499
0
    herr_t      ret_value = SUCCEED;
500
501
0
    FUNC_ENTER_PACKAGE
502
503
    /* Sanity check */
504
0
    assert(hdr);
505
506
    /* Check if the file was opened with SWMR-write access */
507
0
    if (hdr->swmr_write) {
508
        /* Determine which action to take */
509
0
        switch (action) {
510
0
            case H5AC_NOTIFY_ACTION_AFTER_INSERT:
511
0
            case H5AC_NOTIFY_ACTION_AFTER_LOAD:
512
0
            case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
513
0
            case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
514
0
            case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
515
0
            case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
516
0
            case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
517
0
            case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
518
0
            case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
519
                /* do nothing */
520
0
                break;
521
522
0
            case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
523
                /* If hdr->parent != NULL, hdr->parent is used to destroy
524
                 * the flush dependency before the header is evicted.
525
                 */
526
0
                if (hdr->parent) {
527
                    /* Sanity check */
528
0
                    assert(hdr->top_proxy);
529
530
                    /* Destroy flush dependency on object header proxy */
531
0
                    if (H5AC_proxy_entry_remove_child((H5AC_proxy_entry_t *)hdr->parent,
532
0
                                                      (void *)hdr->top_proxy) < 0)
533
0
                        HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
534
0
                                    "unable to destroy flush dependency between extensible array and proxy");
535
0
                    hdr->parent = NULL;
536
0
                } /* end if */
537
538
                /* Detach from 'top' proxy for extensible array */
539
0
                if (hdr->top_proxy) {
540
0
                    if (H5AC_proxy_entry_remove_child(hdr->top_proxy, hdr) < 0)
541
0
                        HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
542
0
                                    "unable to destroy flush dependency between header and "
543
0
                                    "extensible array 'top' proxy");
544
                    /* Don't reset hdr->top_proxy here, it's destroyed when the header is freed -QAK */
545
0
                } /* end if */
546
0
                break;
547
548
0
            default:
549
0
#ifdef NDEBUG
550
0
                HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, FAIL, "unknown action from metadata cache");
551
#else     /* NDEBUG */
552
                assert(0 && "Unknown action?!?");
553
#endif    /* NDEBUG */
554
0
        } /* end switch */
555
0
    }     /* end if */
556
0
    else
557
0
        assert(NULL == hdr->parent);
558
559
0
done:
560
0
    FUNC_LEAVE_NOAPI(ret_value)
561
0
} /* end H5EA__cache_hdr_notify() */
562
563
/*-------------------------------------------------------------------------
564
 * Function:  H5EA__cache_hdr_free_icr
565
 *
566
 * Purpose: Destroy/release an "in core representation" of a data
567
 *              structure
568
 *
569
 * Return:  Non-negative on success/Negative on failure
570
 *
571
 *-------------------------------------------------------------------------
572
 */
573
static herr_t
574
H5EA__cache_hdr_free_icr(void *thing)
575
0
{
576
0
    herr_t ret_value = SUCCEED;
577
578
0
    FUNC_ENTER_PACKAGE
579
580
    /* Check arguments */
581
0
    assert(thing);
582
583
    /* Release the extensible array header */
584
0
    if (H5EA__hdr_dest((H5EA_hdr_t *)thing) < 0)
585
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTFREE, FAIL, "can't free extensible array header");
586
587
0
done:
588
0
    FUNC_LEAVE_NOAPI(ret_value)
589
0
} /* end H5EA__cache_hdr_free_icr() */
590
591
/*-------------------------------------------------------------------------
592
 * Function:    H5EA__cache_iblock_get_initial_load_size
593
 *
594
 * Purpose:     Compute the size of the data structure on disk.
595
 *
596
 * Return:      Non-negative on success/Negative on failure
597
 *
598
 *-------------------------------------------------------------------------
599
 */
600
static herr_t
601
H5EA__cache_iblock_get_initial_load_size(void *_udata, size_t *image_len)
602
0
{
603
0
    H5EA_hdr_t   *hdr = (H5EA_hdr_t *)_udata; /* User data for callback */
604
0
    H5EA_iblock_t iblock;                     /* Fake index block for computing size */
605
606
0
    FUNC_ENTER_PACKAGE_NOERR
607
608
    /* Check arguments */
609
0
    assert(hdr);
610
0
    assert(image_len);
611
612
    /* Set up fake index block for computing size on disk */
613
0
    memset(&iblock, 0, sizeof(iblock));
614
0
    iblock.hdr         = (H5EA_hdr_t *)hdr;
615
0
    iblock.nsblks      = H5EA_SBLK_FIRST_IDX(hdr->cparam.sup_blk_min_data_ptrs);
616
0
    iblock.ndblk_addrs = 2 * ((size_t)hdr->cparam.sup_blk_min_data_ptrs - 1);
617
0
    iblock.nsblk_addrs = hdr->nsblks - iblock.nsblks;
618
619
    /* Set the image length size */
620
0
    *image_len = (size_t)H5EA_IBLOCK_SIZE(&iblock);
621
622
0
    FUNC_LEAVE_NOAPI(SUCCEED)
623
0
} /* end H5EA__cache_iblock_get_initial_load_size() */
624
625
/*-------------------------------------------------------------------------
626
 * Function:  H5EA__cache_iblock_verify_chksum
627
 *
628
 * Purpose:     Verify the computed checksum of the data structure is the
629
 *              same as the stored chksum.
630
 *
631
 * Return:      Success:        true/false
632
 *              Failure:        Negative
633
 *
634
 *-------------------------------------------------------------------------
635
 */
636
static htri_t
637
H5EA__cache_iblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
638
0
{
639
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
640
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
641
0
    uint32_t       computed_chksum;                 /* Computed metadata checksum value */
642
0
    htri_t         ret_value = true;
643
644
0
    FUNC_ENTER_PACKAGE
645
646
    /* Check arguments */
647
0
    assert(image);
648
649
    /* Get stored and computed checksums */
650
0
    if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
651
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, FAIL, "can't get checksums");
652
653
0
    if (stored_chksum != computed_chksum)
654
0
        ret_value = false;
655
656
0
done:
657
0
    FUNC_LEAVE_NOAPI(ret_value)
658
0
} /* end H5EA__cache_iblock_verify_chksum() */
659
660
/*-------------------------------------------------------------------------
661
 * Function:  H5EA__cache_iblock_deserialize
662
 *
663
 * Purpose: Loads a data structure from the disk.
664
 *
665
 * Return:  Success:  Pointer to a new B-tree.
666
 *    Failure:  NULL
667
 *
668
 *-------------------------------------------------------------------------
669
 */
670
static void *
671
H5EA__cache_iblock_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty)
672
0
{
673
0
    H5EA_iblock_t *iblock = NULL;                    /* Index block info */
674
0
    H5EA_hdr_t    *hdr    = (H5EA_hdr_t *)_udata;    /* User data for callback */
675
0
    const uint8_t *image  = (const uint8_t *)_image; /* Pointer into raw data buffer */
676
0
    uint32_t       stored_chksum;                    /* Stored metadata checksum value */
677
0
    haddr_t        arr_addr;                         /* Address of array header in the file */
678
0
    size_t         u;                                /* Local index variable */
679
0
    void          *ret_value = NULL;
680
681
0
    FUNC_ENTER_PACKAGE
682
683
    /* Check arguments */
684
0
    assert(image);
685
0
    assert(hdr);
686
687
    /* Allocate the extensible array index block */
688
0
    if (NULL == (iblock = H5EA__iblock_alloc(hdr)))
689
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
690
0
                    "memory allocation failed for extensible array index block");
691
692
    /* Set the extensible array index block's address */
693
0
    iblock->addr = hdr->idx_blk_addr;
694
695
    /* Magic number */
696
0
    if (memcmp(image, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
697
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array index block signature");
698
0
    image += H5_SIZEOF_MAGIC;
699
700
    /* Version */
701
0
    if (*image++ != H5EA_IBLOCK_VERSION)
702
0
        HGOTO_ERROR(H5E_EARRAY, H5E_VERSION, NULL, "wrong extensible array index block version");
703
704
    /* Extensible array type */
705
0
    if (*image++ != (uint8_t)hdr->cparam.cls->id)
706
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADTYPE, NULL, "incorrect extensible array class");
707
708
    /* Address of header for array that owns this block (just for file integrity checks) */
709
0
    H5F_addr_decode(hdr->f, &image, &arr_addr);
710
0
    if (H5_addr_ne(arr_addr, hdr->addr))
711
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array header address");
712
713
    /* Internal information */
714
715
    /* Decode elements in index block */
716
0
    if (hdr->cparam.idx_blk_elmts > 0) {
717
        /* Convert from raw elements on disk into native elements in memory */
718
0
        if ((hdr->cparam.cls->decode)(image, iblock->elmts, (size_t)hdr->cparam.idx_blk_elmts, hdr->cb_ctx) <
719
0
            0)
720
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, NULL, "can't decode extensible array index elements");
721
0
        image += (hdr->cparam.idx_blk_elmts * hdr->cparam.raw_elmt_size);
722
0
    } /* end if */
723
724
    /* Decode data block addresses in index block */
725
0
    if (iblock->ndblk_addrs > 0) {
726
        /* Decode addresses of data blocks in index block */
727
0
        for (u = 0; u < iblock->ndblk_addrs; u++)
728
0
            H5F_addr_decode(hdr->f, &image, &iblock->dblk_addrs[u]);
729
0
    } /* end if */
730
731
    /* Decode super block addresses in index block */
732
0
    if (iblock->nsblk_addrs > 0) {
733
        /* Decode addresses of super blocks in index block */
734
0
        for (u = 0; u < iblock->nsblk_addrs; u++)
735
0
            H5F_addr_decode(hdr->f, &image, &iblock->sblk_addrs[u]);
736
0
    } /* end if */
737
738
    /* Sanity check */
739
    /* (allow for checksum not decoded yet) */
740
0
    assert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
741
742
    /* Save the index block's size */
743
0
    iblock->size = len;
744
745
    /* checksum verification already done in verify_chksum cb */
746
747
    /* Metadata checksum */
748
0
    UINT32DECODE(image, stored_chksum);
749
750
    /* Sanity check */
751
0
    assert((size_t)(image - (const uint8_t *)_image) == iblock->size);
752
753
    /* Set return value */
754
0
    ret_value = iblock;
755
756
0
done:
757
    /* Release resources */
758
0
    if (!ret_value)
759
0
        if (iblock && H5EA__iblock_dest(iblock) < 0)
760
0
            HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, NULL, "unable to destroy extensible array index block");
761
762
0
    FUNC_LEAVE_NOAPI(ret_value)
763
0
} /* end H5EA__cache_iblock_deserialize() */
764
765
/*-------------------------------------------------------------------------
766
 * Function:    H5EA__cache_iblock_image_len
767
 *
768
 * Purpose:     Compute the size of the data structure on disk.
769
 *
770
 * Return:      Non-negative on success/Negative on failure
771
 *
772
 *-------------------------------------------------------------------------
773
 */
774
static herr_t
775
H5EA__cache_iblock_image_len(const void *_thing, size_t *image_len)
776
0
{
777
0
    const H5EA_iblock_t *iblock = (const H5EA_iblock_t *)_thing; /* Pointer to the object */
778
779
0
    FUNC_ENTER_PACKAGE_NOERR
780
781
    /* Check arguments */
782
0
    assert(iblock);
783
0
    assert(image_len);
784
785
    /* Set the image length size */
786
0
    *image_len = iblock->size;
787
788
0
    FUNC_LEAVE_NOAPI(SUCCEED)
789
0
} /* end H5EA__cache_iblock_image_len() */
790
791
/*-------------------------------------------------------------------------
792
 * Function:  H5EA__cache_iblock_serialize
793
 *
794
 * Purpose: Flushes a dirty object to disk.
795
 *
796
 * Return:  Non-negative on success/Negative on failure
797
 *
798
 *-------------------------------------------------------------------------
799
 */
800
static herr_t
801
H5EA__cache_iblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing)
802
0
{
803
0
    H5EA_iblock_t *iblock = (H5EA_iblock_t *)_thing; /* Pointer to the object to serialize */
804
0
    uint8_t       *image  = (uint8_t *)_image;       /* Pointer into raw data buffer */
805
0
    uint32_t       metadata_chksum;                  /* Computed metadata checksum value */
806
0
    herr_t         ret_value = SUCCEED;
807
808
0
    FUNC_ENTER_PACKAGE
809
810
    /* check arguments */
811
0
    assert(f);
812
0
    assert(image);
813
0
    assert(iblock);
814
0
    assert(iblock->hdr);
815
816
    /* Get temporary pointer to serialized info */
817
818
    /* Magic number */
819
0
    H5MM_memcpy(image, H5EA_IBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
820
0
    image += H5_SIZEOF_MAGIC;
821
822
    /* Version # */
823
0
    *image++ = H5EA_IBLOCK_VERSION;
824
825
    /* Extensible array type */
826
0
    assert(iblock->hdr->cparam.cls->id <= 255);
827
0
    *image++ = (uint8_t)iblock->hdr->cparam.cls->id;
828
829
    /* Address of array header for array which owns this block */
830
0
    H5F_addr_encode(f, &image, iblock->hdr->addr);
831
832
    /* Internal information */
833
834
    /* Encode elements in index block */
835
0
    if (iblock->hdr->cparam.idx_blk_elmts > 0) {
836
        /* Convert from native elements in memory into raw elements on disk */
837
0
        if ((iblock->hdr->cparam.cls->encode)(image, iblock->elmts, (size_t)iblock->hdr->cparam.idx_blk_elmts,
838
0
                                              iblock->hdr->cb_ctx) < 0)
839
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTENCODE, FAIL, "can't encode extensible array index elements");
840
0
        image += (iblock->hdr->cparam.idx_blk_elmts * iblock->hdr->cparam.raw_elmt_size);
841
0
    } /* end if */
842
843
    /* Encode data block addresses in index block */
844
0
    if (iblock->ndblk_addrs > 0) {
845
0
        size_t u; /* Local index variable */
846
847
        /* Encode addresses of data blocks in index block */
848
0
        for (u = 0; u < iblock->ndblk_addrs; u++)
849
0
            H5F_addr_encode(f, &image, iblock->dblk_addrs[u]);
850
0
    } /* end if */
851
852
    /* Encode data block addresses in index block */
853
0
    if (iblock->nsblk_addrs > 0) {
854
0
        size_t u; /* Local index variable */
855
856
        /* Encode addresses of super blocks in index block */
857
0
        for (u = 0; u < iblock->nsblk_addrs; u++)
858
0
            H5F_addr_encode(f, &image, iblock->sblk_addrs[u]);
859
0
    } /* end if */
860
861
    /* Compute metadata checksum */
862
0
    metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
863
864
    /* Metadata checksum */
865
0
    UINT32ENCODE(image, metadata_chksum);
866
867
    /* Sanity check */
868
0
    assert((size_t)(image - (uint8_t *)_image) == len);
869
870
0
done:
871
0
    FUNC_LEAVE_NOAPI(ret_value)
872
0
} /* end H5EA__cache_iblock_serialize() */
873
874
/*-------------------------------------------------------------------------
875
 * Function:  H5EA__cache_iblock_notify
876
 *
877
 * Purpose: Handle cache action notifications
878
 *
879
 * Return:  Non-negative on success/Negative on failure
880
 *
881
 *-------------------------------------------------------------------------
882
 */
883
static herr_t
884
H5EA__cache_iblock_notify(H5AC_notify_action_t action, void *_thing)
885
0
{
886
0
    H5EA_iblock_t *iblock    = (H5EA_iblock_t *)_thing; /* Pointer to the object */
887
0
    herr_t         ret_value = SUCCEED;
888
889
0
    FUNC_ENTER_PACKAGE
890
891
    /* Sanity check */
892
0
    assert(iblock);
893
894
    /* Determine which action to take */
895
0
    switch (action) {
896
0
        case H5AC_NOTIFY_ACTION_AFTER_INSERT:
897
0
        case H5AC_NOTIFY_ACTION_AFTER_LOAD:
898
            /* Create flush dependency on extensible array header */
899
0
            if (H5EA__create_flush_depend((H5AC_info_t *)iblock->hdr, (H5AC_info_t *)iblock) < 0)
900
0
                HGOTO_ERROR(
901
0
                    H5E_EARRAY, H5E_CANTDEPEND, FAIL,
902
0
                    "unable to create flush dependency between index block and header, address = %llu",
903
0
                    (unsigned long long)iblock->addr);
904
0
            break;
905
906
0
        case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
907
0
        case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
908
0
        case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
909
0
        case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
910
0
        case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
911
0
        case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
912
0
        case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
913
            /* do nothing */
914
0
            break;
915
916
0
        case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
917
            /* Destroy flush dependency on extensible array header */
918
0
            if (H5EA__destroy_flush_depend((H5AC_info_t *)iblock->hdr, (H5AC_info_t *)iblock) < 0)
919
0
                HGOTO_ERROR(
920
0
                    H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
921
0
                    "unable to destroy flush dependency between index block and header, address = %llu",
922
0
                    (unsigned long long)iblock->addr);
923
924
            /* Detach from 'top' proxy for extensible array */
925
0
            if (iblock->top_proxy) {
926
0
                if (H5AC_proxy_entry_remove_child(iblock->top_proxy, iblock) < 0)
927
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
928
0
                                "unable to destroy flush dependency between index block and "
929
0
                                "extensible array 'top' proxy");
930
0
                iblock->top_proxy = NULL;
931
0
            } /* end if */
932
0
            break;
933
934
0
        default:
935
0
#ifdef NDEBUG
936
0
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, FAIL, "unknown action from metadata cache");
937
#else  /* NDEBUG */
938
            assert(0 && "Unknown action?!?");
939
#endif /* NDEBUG */
940
0
    }  /* end switch */
941
942
0
done:
943
0
    FUNC_LEAVE_NOAPI(ret_value)
944
0
} /* end H5EA__cache_iblock_notify() */
945
946
/*-------------------------------------------------------------------------
947
 * Function:  H5EA__cache_iblock_free_icr
948
 *
949
 * Purpose: Destroy/release an "in core representation" of a data
950
 *              structure
951
 *
952
 * Return:  Non-negative on success/Negative on failure
953
 *
954
 *-------------------------------------------------------------------------
955
 */
956
static herr_t
957
H5EA__cache_iblock_free_icr(void *thing)
958
0
{
959
0
    herr_t ret_value = SUCCEED;
960
961
0
    FUNC_ENTER_PACKAGE
962
963
    /* Check arguments */
964
0
    assert(thing);
965
966
    /* Release the extensible array index block */
967
0
    if (H5EA__iblock_dest((H5EA_iblock_t *)thing) < 0)
968
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTFREE, FAIL, "can't free extensible array index block");
969
970
0
done:
971
0
    FUNC_LEAVE_NOAPI(ret_value)
972
0
} /* end H5EA__cache_iblock_free_icr() */
973
974
/*-------------------------------------------------------------------------
975
 * Function:    H5EA__cache_sblock_get_initial_load_size
976
 *
977
 * Purpose:     Compute the size of the data structure on disk.
978
 *
979
 * Return:      Non-negative on success/Negative on failure
980
 *
981
 *-------------------------------------------------------------------------
982
 */
983
static herr_t
984
H5EA__cache_sblock_get_initial_load_size(void *_udata, size_t *image_len)
985
0
{
986
0
    H5EA_sblock_cache_ud_t *udata = (H5EA_sblock_cache_ud_t *)_udata; /* User data */
987
0
    H5EA_sblock_t           sblock; /* Fake super block for computing size */
988
989
0
    FUNC_ENTER_PACKAGE_NOERR
990
991
    /* Check arguments */
992
0
    assert(udata);
993
0
    assert(udata->hdr);
994
0
    assert(udata->sblk_idx > 0);
995
0
    assert(H5_addr_defined(udata->sblk_addr));
996
0
    assert(image_len);
997
998
    /* Set up fake super block for computing size on disk */
999
    /* (Note: extracted from H5EA__sblock_alloc) */
1000
0
    memset(&sblock, 0, sizeof(sblock));
1001
0
    sblock.hdr         = udata->hdr;
1002
0
    sblock.ndblks      = udata->hdr->sblk_info[udata->sblk_idx].ndblks;
1003
0
    sblock.dblk_nelmts = udata->hdr->sblk_info[udata->sblk_idx].dblk_nelmts;
1004
1005
    /* Check if # of elements in data blocks requires paging */
1006
0
    if (sblock.dblk_nelmts > udata->hdr->dblk_page_nelmts) {
1007
        /* Compute # of pages in each data block from this super block */
1008
0
        sblock.dblk_npages = sblock.dblk_nelmts / udata->hdr->dblk_page_nelmts;
1009
1010
        /* Sanity check that we have at least 2 pages in data block */
1011
0
        assert(sblock.dblk_npages > 1);
1012
1013
        /* Sanity check for integer truncation */
1014
0
        assert((sblock.dblk_npages * udata->hdr->dblk_page_nelmts) == sblock.dblk_nelmts);
1015
1016
        /* Compute size of buffer for each data block's 'page init' bitmask */
1017
0
        sblock.dblk_page_init_size = ((sblock.dblk_npages) + 7) / 8;
1018
0
        assert(sblock.dblk_page_init_size > 0);
1019
0
    } /* end if */
1020
1021
    /* Set the image length size */
1022
0
    *image_len = (size_t)H5EA_SBLOCK_SIZE(&sblock);
1023
1024
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1025
0
} /* end H5EA__cache_sblock_get_initial_load_size() */
1026
1027
/*-------------------------------------------------------------------------
1028
 * Function:  H5EA__cache_sblock_verify_chksum
1029
 *
1030
 * Purpose:     Verify the computed checksum of the data structure is the
1031
 *              same as the stored chksum.
1032
 *
1033
 * Return:      Success:        true/false
1034
 *              Failure:        Negative
1035
 *
1036
 *-------------------------------------------------------------------------
1037
 */
1038
static htri_t
1039
H5EA__cache_sblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
1040
0
{
1041
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
1042
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
1043
0
    uint32_t       computed_chksum;                 /* Computed metadata checksum value */
1044
0
    htri_t         ret_value = true;
1045
1046
0
    FUNC_ENTER_PACKAGE
1047
1048
    /* Check arguments */
1049
0
    assert(image);
1050
1051
    /* Get stored and computed checksums */
1052
0
    if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
1053
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, FAIL, "can't get checksums");
1054
1055
0
    if (stored_chksum != computed_chksum)
1056
0
        ret_value = false;
1057
1058
0
done:
1059
0
    FUNC_LEAVE_NOAPI(ret_value)
1060
0
} /* end H5EA__cache_sblock_verify_chksum() */
1061
1062
/*-------------------------------------------------------------------------
1063
 * Function:  H5EA__cache_sblock_deserialize
1064
 *
1065
 * Purpose: Loads a data structure from the disk.
1066
 *
1067
 * Return:  Success:  Pointer to a new B-tree.
1068
 *    Failure:  NULL
1069
 *
1070
 *-------------------------------------------------------------------------
1071
 */
1072
static void *
1073
H5EA__cache_sblock_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty)
1074
0
{
1075
0
    H5EA_sblock_t          *sblock = NULL;                             /* Super block info */
1076
0
    H5EA_sblock_cache_ud_t *udata  = (H5EA_sblock_cache_ud_t *)_udata; /* User data */
1077
0
    const uint8_t          *image  = (const uint8_t *)_image;          /* Pointer into raw data buffer */
1078
0
    uint32_t                stored_chksum;                             /* Stored metadata checksum value */
1079
0
    haddr_t                 arr_addr; /* Address of array header in the file */
1080
0
    size_t                  u;        /* Local index variable */
1081
0
    void                   *ret_value = NULL;
1082
1083
0
    FUNC_ENTER_PACKAGE
1084
1085
    /* Sanity check */
1086
0
    assert(udata);
1087
0
    assert(udata->hdr);
1088
0
    assert(udata->parent);
1089
0
    assert(udata->sblk_idx > 0);
1090
0
    assert(H5_addr_defined(udata->sblk_addr));
1091
1092
    /* Allocate the extensible array super block */
1093
0
    if (NULL == (sblock = H5EA__sblock_alloc(udata->hdr, udata->parent, udata->sblk_idx)))
1094
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
1095
0
                    "memory allocation failed for extensible array super block");
1096
1097
    /* Set the extensible array super block's address */
1098
0
    sblock->addr = udata->sblk_addr;
1099
1100
    /* Magic number */
1101
0
    if (memcmp(image, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
1102
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array super block signature");
1103
0
    image += H5_SIZEOF_MAGIC;
1104
1105
    /* Version */
1106
0
    if (*image++ != H5EA_SBLOCK_VERSION)
1107
0
        HGOTO_ERROR(H5E_EARRAY, H5E_VERSION, NULL, "wrong extensible array super block version");
1108
1109
    /* Extensible array type */
1110
0
    if (*image++ != (uint8_t)udata->hdr->cparam.cls->id)
1111
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADTYPE, NULL, "incorrect extensible array class");
1112
1113
    /* Address of header for array that owns this block (just for file integrity checks) */
1114
0
    H5F_addr_decode(udata->hdr->f, &image, &arr_addr);
1115
0
    if (H5_addr_ne(arr_addr, udata->hdr->addr))
1116
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array header address");
1117
1118
    /* Offset of block within the array's address space */
1119
0
    UINT64DECODE_VAR(image, sblock->block_off, udata->hdr->arr_off_size);
1120
1121
    /* Internal information */
1122
1123
    /* Check for 'page init' bitmasks for this super block */
1124
0
    if (sblock->dblk_npages > 0) {
1125
0
        size_t tot_page_init_size =
1126
0
            sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
1127
1128
        /* Retrieve the 'page init' bitmasks */
1129
0
        H5MM_memcpy(sblock->page_init, image, tot_page_init_size);
1130
0
        image += tot_page_init_size;
1131
0
    } /* end if */
1132
1133
    /* Decode data block addresses */
1134
0
    for (u = 0; u < sblock->ndblks; u++)
1135
0
        H5F_addr_decode(udata->hdr->f, &image, &sblock->dblk_addrs[u]);
1136
1137
    /* Sanity check */
1138
    /* (allow for checksum not decoded yet) */
1139
0
    assert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
1140
1141
    /* Save the super block's size */
1142
0
    sblock->size = len;
1143
1144
    /* checksum verification already done in verify_chksum cb */
1145
1146
    /* Metadata checksum */
1147
0
    UINT32DECODE(image, stored_chksum);
1148
1149
    /* Sanity check */
1150
0
    assert((size_t)(image - (const uint8_t *)_image) == sblock->size);
1151
1152
    /* Set return value */
1153
0
    ret_value = sblock;
1154
1155
0
done:
1156
    /* Release resources */
1157
0
    if (!ret_value)
1158
0
        if (sblock && H5EA__sblock_dest(sblock) < 0)
1159
0
            HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, NULL, "unable to destroy extensible array super block");
1160
1161
0
    FUNC_LEAVE_NOAPI(ret_value)
1162
0
} /* end H5EA__cache_sblock_deserialize() */
1163
1164
/*-------------------------------------------------------------------------
1165
 * Function:    H5EA__cache_sblock_image_len
1166
 *
1167
 * Purpose:     Compute the size of the data structure on disk.
1168
 *
1169
 * Return:      Non-negative on success/Negative on failure
1170
 *
1171
 *-------------------------------------------------------------------------
1172
 */
1173
static herr_t
1174
H5EA__cache_sblock_image_len(const void *_thing, size_t *image_len)
1175
0
{
1176
0
    const H5EA_sblock_t *sblock = (const H5EA_sblock_t *)_thing; /* Pointer to the object */
1177
1178
0
    FUNC_ENTER_PACKAGE_NOERR
1179
1180
    /* Check arguments */
1181
0
    assert(sblock);
1182
0
    assert(image_len);
1183
1184
    /* Set the image length size */
1185
0
    *image_len = sblock->size;
1186
1187
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1188
0
} /* end H5EA__cache_sblock_image_len() */
1189
1190
/*-------------------------------------------------------------------------
1191
 * Function:  H5EA__cache_sblock_serialize
1192
 *
1193
 * Purpose: Flushes a dirty object to disk.
1194
 *
1195
 * Return:  Non-negative on success/Negative on failure
1196
 *
1197
 *-------------------------------------------------------------------------
1198
 */
1199
static herr_t
1200
H5EA__cache_sblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing)
1201
0
{
1202
0
    H5EA_sblock_t *sblock = (H5EA_sblock_t *)_thing; /* Pointer to the object to serialize */
1203
0
    uint8_t       *image  = (uint8_t *)_image;       /* Pointer into raw data buffer */
1204
0
    uint32_t       metadata_chksum;                  /* Computed metadata checksum value */
1205
0
    size_t         u;                                /* Local index variable */
1206
1207
0
    FUNC_ENTER_PACKAGE_NOERR
1208
1209
    /* check arguments */
1210
0
    assert(f);
1211
0
    assert(image);
1212
0
    assert(sblock);
1213
0
    assert(sblock->hdr);
1214
1215
    /* Magic number */
1216
0
    H5MM_memcpy(image, H5EA_SBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
1217
0
    image += H5_SIZEOF_MAGIC;
1218
1219
    /* Version # */
1220
0
    *image++ = H5EA_SBLOCK_VERSION;
1221
1222
    /* Extensible array type */
1223
0
    assert(sblock->hdr->cparam.cls->id <= 255);
1224
0
    *image++ = (uint8_t)sblock->hdr->cparam.cls->id;
1225
1226
    /* Address of array header for array which owns this block */
1227
0
    H5F_addr_encode(f, &image, sblock->hdr->addr);
1228
1229
    /* Offset of block in array */
1230
0
    UINT64ENCODE_VAR(image, sblock->block_off, sblock->hdr->arr_off_size);
1231
1232
    /* Internal information */
1233
1234
    /* Check for 'page init' bitmasks for this super block */
1235
0
    if (sblock->dblk_npages > 0) {
1236
0
        size_t tot_page_init_size =
1237
0
            sblock->ndblks * sblock->dblk_page_init_size; /* Compute total size of 'page init' buffer */
1238
1239
        /* Store the 'page init' bitmasks */
1240
0
        H5MM_memcpy(image, sblock->page_init, tot_page_init_size);
1241
0
        image += tot_page_init_size;
1242
0
    } /* end if */
1243
1244
    /* Encode addresses of data blocks in super block */
1245
0
    for (u = 0; u < sblock->ndblks; u++)
1246
0
        H5F_addr_encode(f, &image, sblock->dblk_addrs[u]);
1247
1248
    /* Compute metadata checksum */
1249
0
    metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
1250
1251
    /* Metadata checksum */
1252
0
    UINT32ENCODE(image, metadata_chksum);
1253
1254
    /* Sanity check */
1255
0
    assert((size_t)(image - (uint8_t *)_image) == len);
1256
1257
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1258
0
} /* end H5EA__cache_sblock_serialize() */
1259
1260
/*-------------------------------------------------------------------------
1261
 * Function:  H5EA__cache_sblock_notify
1262
 *
1263
 * Purpose: Handle cache action notifications
1264
 *
1265
 * Return:  Non-negative on success/Negative on failure
1266
 *
1267
 *-------------------------------------------------------------------------
1268
 */
1269
static herr_t
1270
H5EA__cache_sblock_notify(H5AC_notify_action_t action, void *_thing)
1271
0
{
1272
0
    H5EA_sblock_t *sblock    = (H5EA_sblock_t *)_thing; /* Pointer to the object */
1273
0
    herr_t         ret_value = SUCCEED;
1274
1275
0
    FUNC_ENTER_PACKAGE
1276
1277
    /* Sanity check */
1278
0
    assert(sblock);
1279
1280
    /* Determine which action to take */
1281
0
    switch (action) {
1282
0
        case H5AC_NOTIFY_ACTION_AFTER_INSERT:
1283
0
        case H5AC_NOTIFY_ACTION_AFTER_LOAD:
1284
            /* Create flush dependency on index block */
1285
0
            if (H5EA__create_flush_depend((H5AC_info_t *)sblock->parent, (H5AC_info_t *)sblock) < 0)
1286
0
                HGOTO_ERROR(
1287
0
                    H5E_EARRAY, H5E_CANTDEPEND, FAIL,
1288
0
                    "unable to create flush dependency between super block and index block, address = %llu",
1289
0
                    (unsigned long long)sblock->addr);
1290
0
            break;
1291
1292
0
        case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
1293
            /* Destroy flush dependency on extensible array header, if set */
1294
0
            if (sblock->has_hdr_depend) {
1295
0
                if (H5EA__destroy_flush_depend((H5AC_info_t *)sblock->hdr, (H5AC_info_t *)sblock) < 0)
1296
0
                    HGOTO_ERROR(
1297
0
                        H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1298
0
                        "unable to destroy flush dependency between super block and header, address = %llu",
1299
0
                        (unsigned long long)sblock->addr);
1300
0
                sblock->has_hdr_depend = false;
1301
0
            } /* end if */
1302
0
            break;
1303
1304
0
        case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
1305
            /* Destroy flush dependency on index block */
1306
0
            if (H5EA__destroy_flush_depend((H5AC_info_t *)sblock->parent, (H5AC_info_t *)sblock) < 0)
1307
0
                HGOTO_ERROR(
1308
0
                    H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1309
0
                    "unable to destroy flush dependency between super block and index block, address = %llu",
1310
0
                    (unsigned long long)sblock->addr);
1311
1312
            /* Destroy flush dependency on extensible array header, if set */
1313
0
            if (sblock->has_hdr_depend) {
1314
0
                if (H5EA__destroy_flush_depend((H5AC_info_t *)sblock->hdr, (H5AC_info_t *)sblock) < 0)
1315
0
                    HGOTO_ERROR(
1316
0
                        H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1317
0
                        "unable to destroy flush dependency between super block and header, address = %llu",
1318
0
                        (unsigned long long)sblock->addr);
1319
0
                sblock->has_hdr_depend = false;
1320
0
            } /* end if */
1321
1322
            /* Detach from 'top' proxy for extensible array */
1323
0
            if (sblock->top_proxy) {
1324
0
                if (H5AC_proxy_entry_remove_child(sblock->top_proxy, sblock) < 0)
1325
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1326
0
                                "unable to destroy flush dependency between super block and "
1327
0
                                "extensible array 'top' proxy");
1328
0
                sblock->top_proxy = NULL;
1329
0
            } /* end if */
1330
0
            break;
1331
1332
0
        case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
1333
0
        case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
1334
0
        case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
1335
0
        case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
1336
0
        case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
1337
0
        case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
1338
            /* do nothing */
1339
0
            break;
1340
1341
0
        default:
1342
0
#ifdef NDEBUG
1343
0
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, FAIL, "unknown action from metadata cache");
1344
#else  /* NDEBUG */
1345
            assert(0 && "Unknown action?!?");
1346
#endif /* NDEBUG */
1347
0
    }  /* end switch */
1348
1349
0
done:
1350
0
    FUNC_LEAVE_NOAPI(ret_value)
1351
0
} /* end H5EA__cache_sblock_notify() */
1352
1353
/*-------------------------------------------------------------------------
1354
 * Function:  H5EA__cache_sblock_free_icr
1355
 *
1356
 * Purpose: Destroy/release an "in core representation" of a data
1357
 *              structure
1358
 *
1359
 * Return:  Non-negative on success/Negative on failure
1360
 *
1361
 *-------------------------------------------------------------------------
1362
 */
1363
static herr_t
1364
H5EA__cache_sblock_free_icr(void *thing)
1365
0
{
1366
0
    herr_t ret_value = SUCCEED;
1367
1368
0
    FUNC_ENTER_PACKAGE
1369
1370
    /* Check arguments */
1371
0
    assert(thing);
1372
1373
    /* Release the extensible array super block */
1374
0
    if (H5EA__sblock_dest((H5EA_sblock_t *)thing) < 0)
1375
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTFREE, FAIL, "can't free extensible array super block");
1376
1377
0
done:
1378
0
    FUNC_LEAVE_NOAPI(ret_value)
1379
0
} /* end H5EA__cache_sblock_free_icr() */
1380
1381
/*-------------------------------------------------------------------------
1382
 * Function:    H5EA__cache_dblock_get_initial_load_size
1383
 *
1384
 * Purpose:     Compute the size of the data structure on disk.
1385
 *
1386
 * Return:      Non-negative on success/Negative on failure
1387
 *
1388
 *-------------------------------------------------------------------------
1389
 */
1390
static herr_t
1391
H5EA__cache_dblock_get_initial_load_size(void *_udata, size_t *image_len)
1392
0
{
1393
0
    H5EA_dblock_cache_ud_t *udata = (H5EA_dblock_cache_ud_t *)_udata; /* User data */
1394
0
    H5EA_dblock_t           dblock;                                   /* Fake data block for computing size */
1395
1396
0
    FUNC_ENTER_PACKAGE_NOERR
1397
1398
    /* Check arguments */
1399
0
    assert(udata);
1400
0
    assert(udata->hdr);
1401
0
    assert(udata->nelmts > 0);
1402
0
    assert(image_len);
1403
1404
    /* Set up fake data block for computing size on disk */
1405
    /* (Note: extracted from H5EA__dblock_alloc) */
1406
0
    memset(&dblock, 0, sizeof(dblock));
1407
1408
    /* need to set:
1409
     *
1410
     *    dblock.hdr
1411
     *    dblock.npages
1412
     *    dblock.nelmts
1413
     *
1414
     * before we invoke either H5EA_DBLOCK_PREFIX_SIZE() or
1415
     * H5EA_DBLOCK_SIZE().
1416
     */
1417
0
    dblock.hdr    = udata->hdr;
1418
0
    dblock.nelmts = udata->nelmts;
1419
1420
0
    if (udata->nelmts > udata->hdr->dblk_page_nelmts) {
1421
        /* Set the # of pages in the direct block */
1422
0
        dblock.npages = udata->nelmts / udata->hdr->dblk_page_nelmts;
1423
0
        assert(udata->nelmts == (dblock.npages * udata->hdr->dblk_page_nelmts));
1424
0
    } /* end if */
1425
1426
    /* Set the image length size */
1427
0
    if (!dblock.npages)
1428
0
        *image_len = H5EA_DBLOCK_SIZE(&dblock);
1429
0
    else
1430
0
        *image_len = H5EA_DBLOCK_PREFIX_SIZE(&dblock);
1431
1432
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1433
0
} /* end H5EA__cache_dblock_get_initial_load_size() */
1434
1435
/*-------------------------------------------------------------------------
1436
 * Function:  H5EA__cache_dblock_verify_chksum
1437
 *
1438
 * Purpose:     Verify the computed checksum of the data structure is the
1439
 *              same as the stored chksum.
1440
 *
1441
 * Return:      Success:        true/false
1442
 *              Failure:        Negative
1443
 *
1444
 *-------------------------------------------------------------------------
1445
 */
1446
static htri_t
1447
H5EA__cache_dblock_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
1448
0
{
1449
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
1450
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
1451
0
    uint32_t       computed_chksum;                 /* Computed metadata checksum value */
1452
0
    htri_t         ret_value = true;
1453
1454
0
    FUNC_ENTER_PACKAGE
1455
1456
    /* Check arguments */
1457
0
    assert(image);
1458
1459
    /* Get stored and computed checksums */
1460
0
    if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
1461
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, FAIL, "can't get checksums");
1462
1463
0
    if (stored_chksum != computed_chksum)
1464
0
        ret_value = false;
1465
1466
0
done:
1467
0
    FUNC_LEAVE_NOAPI(ret_value)
1468
0
} /* end H5EA__cache_sblock_verify_chksum() */
1469
1470
/*-------------------------------------------------------------------------
1471
 * Function:  H5EA__cache_dblock_deserialize
1472
 *
1473
 * Purpose: Loads a data structure from the disk.
1474
 *
1475
 * Return:  Success:  Pointer to a new B-tree.
1476
 *    Failure:  NULL
1477
 *
1478
 *-------------------------------------------------------------------------
1479
 */
1480
static void *
1481
H5EA__cache_dblock_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_udata,
1482
                               bool H5_ATTR_UNUSED *dirty)
1483
0
{
1484
0
    H5EA_dblock_t          *dblock = NULL;                             /* Data block info */
1485
0
    H5EA_dblock_cache_ud_t *udata  = (H5EA_dblock_cache_ud_t *)_udata; /* User data */
1486
0
    const uint8_t          *image  = (const uint8_t *)_image;          /* Pointer into raw data buffer */
1487
0
    uint32_t                stored_chksum;                             /* Stored metadata checksum value */
1488
0
    haddr_t                 arr_addr; /* Address of array header in the file */
1489
0
    void                   *ret_value = NULL;
1490
1491
0
    FUNC_ENTER_PACKAGE
1492
1493
    /* Check arguments */
1494
0
    assert(udata);
1495
0
    assert(udata->hdr);
1496
0
    assert(udata->parent);
1497
0
    assert(udata->nelmts > 0);
1498
0
    assert(H5_addr_defined(udata->dblk_addr));
1499
1500
    /* Allocate the extensible array data block */
1501
0
    if (NULL == (dblock = H5EA__dblock_alloc(udata->hdr, udata->parent, udata->nelmts)))
1502
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
1503
0
                    "memory allocation failed for extensible array data block");
1504
1505
0
    assert(((!dblock->npages) && (len == H5EA_DBLOCK_SIZE(dblock))) ||
1506
0
           (len == H5EA_DBLOCK_PREFIX_SIZE(dblock)));
1507
1508
    /* Set the extensible array data block's information */
1509
0
    dblock->addr = udata->dblk_addr;
1510
1511
    /* Magic number */
1512
0
    if (memcmp(image, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
1513
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array data block signature");
1514
0
    image += H5_SIZEOF_MAGIC;
1515
1516
    /* Version */
1517
0
    if (*image++ != H5EA_DBLOCK_VERSION)
1518
0
        HGOTO_ERROR(H5E_EARRAY, H5E_VERSION, NULL, "wrong extensible array data block version");
1519
1520
    /* Extensible array type */
1521
0
    if (*image++ != (uint8_t)udata->hdr->cparam.cls->id)
1522
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADTYPE, NULL, "incorrect extensible array class");
1523
1524
    /* Address of header for array that owns this block (just for file integrity checks) */
1525
0
    H5F_addr_decode(udata->hdr->f, &image, &arr_addr);
1526
0
    if (H5_addr_ne(arr_addr, udata->hdr->addr))
1527
0
        HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, NULL, "wrong extensible array header address");
1528
1529
    /* Offset of block within the array's address space */
1530
0
    UINT64DECODE_VAR(image, dblock->block_off, udata->hdr->arr_off_size);
1531
1532
    /* Internal information */
1533
1534
    /* Only decode elements if the data block is not paged */
1535
0
    if (!dblock->npages) {
1536
        /* Decode elements in data block */
1537
        /* Convert from raw elements on disk into native elements in memory */
1538
0
        if ((udata->hdr->cparam.cls->decode)(image, dblock->elmts, udata->nelmts, udata->hdr->cb_ctx) < 0)
1539
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, NULL, "can't decode extensible array data elements");
1540
0
        image += (udata->nelmts * udata->hdr->cparam.raw_elmt_size);
1541
0
    } /* end if */
1542
1543
    /* Sanity check */
1544
    /* (allow for checksum not decoded yet) */
1545
0
    assert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
1546
1547
    /* Set the data block's size */
1548
    /* (Note: This is not the same as the image length, for paged data blocks) */
1549
0
    dblock->size = H5EA_DBLOCK_SIZE(dblock);
1550
1551
    /* checksum verification already done in verify_chksum cb */
1552
1553
    /* Metadata checksum */
1554
0
    UINT32DECODE(image, stored_chksum);
1555
1556
    /* Sanity check */
1557
0
    assert((size_t)(image - (const uint8_t *)_image) == len);
1558
1559
    /* Set return value */
1560
0
    ret_value = dblock;
1561
1562
0
done:
1563
1564
    /* Release resources */
1565
0
    if (!ret_value)
1566
0
        if (dblock && H5EA__dblock_dest(dblock) < 0)
1567
0
            HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, NULL, "unable to destroy extensible array data block");
1568
1569
0
    FUNC_LEAVE_NOAPI(ret_value)
1570
0
} /* end H5EA__cache_dblock_deserialize() */
1571
1572
/*-------------------------------------------------------------------------
1573
 * Function:    H5EA__cache_dblock_image_len
1574
 *
1575
 * Purpose:     Compute the size of the data structure on disk.
1576
 *
1577
 * Return:      Non-negative on success/Negative on failure
1578
 *
1579
 *-------------------------------------------------------------------------
1580
 */
1581
static herr_t
1582
H5EA__cache_dblock_image_len(const void *_thing, size_t *image_len)
1583
0
{
1584
0
    const H5EA_dblock_t *dblock = (const H5EA_dblock_t *)_thing; /* Pointer to the object */
1585
1586
0
    FUNC_ENTER_PACKAGE_NOERR
1587
1588
    /* Check arguments */
1589
0
    assert(dblock);
1590
0
    assert(image_len);
1591
1592
    /* Set the image length size */
1593
0
    if (!dblock->npages)
1594
0
        *image_len = dblock->size;
1595
0
    else
1596
0
        *image_len = (size_t)H5EA_DBLOCK_PREFIX_SIZE(dblock);
1597
1598
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1599
0
} /* end H5EA__cache_dblock_image_len() */
1600
1601
/*-------------------------------------------------------------------------
1602
 * Function:  H5EA__cache_dblock_serialize
1603
 *
1604
 * Purpose: Flushes a dirty object to disk.
1605
 *
1606
 * Return:  Non-negative on success/Negative on failure
1607
 *
1608
 *-------------------------------------------------------------------------
1609
 */
1610
static herr_t
1611
H5EA__cache_dblock_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing)
1612
0
{
1613
0
    H5EA_dblock_t *dblock = (H5EA_dblock_t *)_thing; /* Pointer to the object to serialize */
1614
0
    uint8_t       *image  = (uint8_t *)_image;       /* Pointer into raw data buffer */
1615
0
    uint32_t       metadata_chksum;                  /* Computed metadata checksum value */
1616
0
    herr_t         ret_value = SUCCEED;
1617
1618
0
    FUNC_ENTER_PACKAGE
1619
1620
    /* check arguments */
1621
0
    assert(f);
1622
0
    assert(image);
1623
0
    assert(dblock);
1624
0
    assert(dblock->hdr);
1625
1626
    /* Magic number */
1627
0
    H5MM_memcpy(image, H5EA_DBLOCK_MAGIC, (size_t)H5_SIZEOF_MAGIC);
1628
0
    image += H5_SIZEOF_MAGIC;
1629
1630
    /* Version # */
1631
0
    *image++ = H5EA_DBLOCK_VERSION;
1632
1633
    /* Extensible array type */
1634
0
    assert(dblock->hdr->cparam.cls->id <= 255);
1635
0
    *image++ = (uint8_t)dblock->hdr->cparam.cls->id;
1636
1637
    /* Address of array header for array which owns this block */
1638
0
    H5F_addr_encode(f, &image, dblock->hdr->addr);
1639
1640
    /* Offset of block in array */
1641
0
    UINT64ENCODE_VAR(image, dblock->block_off, dblock->hdr->arr_off_size);
1642
1643
    /* Internal information */
1644
1645
    /* Only encode elements if the data block is not paged */
1646
0
    if (!dblock->npages) {
1647
        /* Encode elements in data block */
1648
1649
        /* Convert from native elements in memory into raw elements on disk */
1650
0
        if ((dblock->hdr->cparam.cls->encode)(image, dblock->elmts, dblock->nelmts, dblock->hdr->cb_ctx) < 0)
1651
0
            HGOTO_ERROR(H5E_EARRAY, H5E_CANTENCODE, FAIL, "can't encode extensible array data elements");
1652
0
        image += (dblock->nelmts * dblock->hdr->cparam.raw_elmt_size);
1653
0
    } /* end if */
1654
1655
    /* Compute metadata checksum */
1656
0
    metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
1657
1658
    /* Metadata checksum */
1659
0
    UINT32ENCODE(image, metadata_chksum);
1660
1661
    /* Sanity check */
1662
0
    assert((size_t)(image - (uint8_t *)_image) == len);
1663
1664
0
done:
1665
0
    FUNC_LEAVE_NOAPI(ret_value)
1666
0
} /* end H5EA__cache_dblock_serialize() */
1667
1668
/*-------------------------------------------------------------------------
1669
 * Function:  H5EA__cache_dblock_notify
1670
 *
1671
 * Purpose: Handle cache action notifications
1672
 *
1673
 * Return:  Non-negative on success/Negative on failure
1674
 *
1675
 *-------------------------------------------------------------------------
1676
 */
1677
static herr_t
1678
H5EA__cache_dblock_notify(H5AC_notify_action_t action, void *_thing)
1679
0
{
1680
0
    H5EA_dblock_t *dblock    = (H5EA_dblock_t *)_thing; /* Pointer to the object */
1681
0
    herr_t         ret_value = SUCCEED;
1682
1683
0
    FUNC_ENTER_PACKAGE
1684
1685
    /* Check arguments */
1686
0
    assert(dblock);
1687
1688
    /* Determine which action to take */
1689
0
    switch (action) {
1690
0
        case H5AC_NOTIFY_ACTION_AFTER_INSERT:
1691
0
        case H5AC_NOTIFY_ACTION_AFTER_LOAD:
1692
            /* Create flush dependency on parent */
1693
0
            if (H5EA__create_flush_depend((H5AC_info_t *)dblock->parent, (H5AC_info_t *)dblock) < 0)
1694
0
                HGOTO_ERROR(H5E_EARRAY, H5E_CANTDEPEND, FAIL,
1695
0
                            "unable to create flush dependency between data block and parent, address = %llu",
1696
0
                            (unsigned long long)dblock->addr);
1697
0
            break;
1698
1699
0
        case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
1700
            /* Destroy flush dependency on extensible array header, if set */
1701
0
            if (dblock->has_hdr_depend) {
1702
0
                if (H5EA__destroy_flush_depend((H5AC_info_t *)dblock->hdr, (H5AC_info_t *)dblock) < 0)
1703
0
                    HGOTO_ERROR(
1704
0
                        H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1705
0
                        "unable to destroy flush dependency between direct block and header, address = %llu",
1706
0
                        (unsigned long long)dblock->addr);
1707
0
                dblock->has_hdr_depend = false;
1708
0
            } /* end if */
1709
0
            break;
1710
1711
0
        case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
1712
            /* Destroy flush dependency on parent */
1713
0
            if (H5EA__destroy_flush_depend((H5AC_info_t *)dblock->parent, (H5AC_info_t *)dblock) < 0)
1714
0
                HGOTO_ERROR(
1715
0
                    H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1716
0
                    "unable to destroy flush dependency between data block and parent, address = %llu",
1717
0
                    (unsigned long long)dblock->addr);
1718
1719
            /* Destroy flush dependency on extensible array header, if set */
1720
0
            if (dblock->has_hdr_depend) {
1721
0
                if (H5EA__destroy_flush_depend((H5AC_info_t *)dblock->hdr, (H5AC_info_t *)dblock) < 0)
1722
0
                    HGOTO_ERROR(
1723
0
                        H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1724
0
                        "unable to destroy flush dependency between data block and header, address = %llu",
1725
0
                        (unsigned long long)dblock->addr);
1726
0
                dblock->has_hdr_depend = false;
1727
0
            } /* end if */
1728
1729
            /* Detach from 'top' proxy for extensible array */
1730
0
            if (dblock->top_proxy) {
1731
0
                if (H5AC_proxy_entry_remove_child(dblock->top_proxy, dblock) < 0)
1732
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
1733
0
                                "unable to destroy flush dependency between data block and "
1734
0
                                "extensible array 'top' proxy");
1735
0
                dblock->top_proxy = NULL;
1736
0
            } /* end if */
1737
0
            break;
1738
1739
0
        case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
1740
0
        case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
1741
0
        case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
1742
0
        case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
1743
0
        case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
1744
0
        case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
1745
            /* do nothing */
1746
0
            break;
1747
1748
0
        default:
1749
0
#ifdef NDEBUG
1750
0
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, FAIL, "unknown action from metadata cache");
1751
#else  /* NDEBUG */
1752
            assert(0 && "Unknown action?!?");
1753
#endif /* NDEBUG */
1754
0
    }  /* end switch */
1755
1756
0
done:
1757
0
    FUNC_LEAVE_NOAPI(ret_value)
1758
0
} /* end H5EA__cache_dblock_notify() */
1759
1760
/*-------------------------------------------------------------------------
1761
 * Function:  H5EA__cache_dblock_free_icr
1762
 *
1763
 * Purpose: Destroy/release an "in core representation" of a data
1764
 *              structure
1765
 *
1766
 * Return:  Non-negative on success/Negative on failure
1767
 *
1768
 *-------------------------------------------------------------------------
1769
 */
1770
static herr_t
1771
H5EA__cache_dblock_free_icr(void *thing)
1772
0
{
1773
0
    herr_t ret_value = SUCCEED;
1774
1775
0
    FUNC_ENTER_PACKAGE
1776
1777
    /* Check arguments */
1778
0
    assert(thing);
1779
1780
    /* Release the extensible array data block */
1781
0
    if (H5EA__dblock_dest((H5EA_dblock_t *)thing) < 0)
1782
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTFREE, FAIL, "can't free extensible array data block");
1783
1784
0
done:
1785
0
    FUNC_LEAVE_NOAPI(ret_value)
1786
0
} /* end H5EA__cache_dblock_free_icr() */
1787
1788
/*-------------------------------------------------------------------------
1789
 * Function:    H5EA__cache_dblock_fsf_size
1790
 *
1791
 * Purpose:     Tell the metadata cache the actual amount of file space
1792
 *              to free when a dblock entry is destroyed with the free
1793
 *              file space block set.
1794
 *
1795
 *              This function is needed when the data block is paged, as
1796
 *              the datablock header and all its pages are allocated as a
1797
 *              single contiguous chunk of file space, and must be
1798
 *              deallocated the same way.
1799
 *
1800
 *              The size of the chunk of memory in which the dblock
1801
 *              header and all its pages is stored in the size field,
1802
 *              so we simply pass that value back to the cache.
1803
 *
1804
 *              If the datablock is not paged, then the size field of
1805
 *              the cache_info contains the correct size.  However this
1806
 *              value will be the same as the size field, so we return
1807
 *              the contents of the size field to the cache in this case
1808
 *              as well.
1809
 *
1810
 * Return:      Non-negative on success/Negative on failure
1811
 *
1812
 *-------------------------------------------------------------------------
1813
 */
1814
static herr_t
1815
H5EA__cache_dblock_fsf_size(const void *_thing, hsize_t *fsf_size)
1816
0
{
1817
0
    const H5EA_dblock_t *dblock = (const H5EA_dblock_t *)_thing; /* Pointer to the object */
1818
1819
0
    FUNC_ENTER_PACKAGE_NOERR
1820
1821
    /* Check arguments */
1822
0
    assert(dblock);
1823
0
    assert(dblock->cache_info.type == H5AC_EARRAY_DBLOCK);
1824
0
    assert(fsf_size);
1825
1826
0
    *fsf_size = dblock->size;
1827
1828
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1829
0
} /* end H5EA__cache_dblock_fsf_size() */
1830
1831
/*-------------------------------------------------------------------------
1832
 * Function:    H5EA__cache_dblk_page_get_initial_load_size
1833
 *
1834
 * Purpose:     Compute the size of the data structure on disk.
1835
 *
1836
 * Return:      Non-negative on success/Negative on failure
1837
 *
1838
 *-------------------------------------------------------------------------
1839
 */
1840
static herr_t
1841
H5EA__cache_dblk_page_get_initial_load_size(void *_udata, size_t *image_len)
1842
0
{
1843
0
    H5EA_dblk_page_cache_ud_t *udata = (H5EA_dblk_page_cache_ud_t *)_udata; /* User data */
1844
1845
0
    FUNC_ENTER_PACKAGE_NOERR
1846
1847
    /* Check arguments */
1848
0
    assert(udata);
1849
0
    assert(udata->hdr);
1850
0
    assert(image_len);
1851
1852
    /* Set the image length size */
1853
0
    *image_len = (size_t)H5EA_DBLK_PAGE_SIZE(udata->hdr);
1854
1855
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1856
0
} /* end H5EA__cache_dblk_page_get_initial_load_size() */
1857
1858
/*-------------------------------------------------------------------------
1859
 * Function:  H5EA__cache_dblk_page_verify_chksum
1860
 *
1861
 * Purpose:     Verify the computed checksum of the data structure is the
1862
 *              same as the stored chksum.
1863
 *
1864
 * Return:      Success:        true/false
1865
 *              Failure:        Negative
1866
 *
1867
 *-------------------------------------------------------------------------
1868
 */
1869
static htri_t
1870
H5EA__cache_dblk_page_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
1871
0
{
1872
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
1873
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
1874
0
    uint32_t       computed_chksum;                 /* Computed metadata checksum value */
1875
0
    htri_t         ret_value = true;
1876
1877
0
    FUNC_ENTER_PACKAGE
1878
1879
    /* Check arguments */
1880
0
    assert(image);
1881
1882
    /* Get stored and computed checksums */
1883
0
    if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
1884
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, FAIL, "can't get checksums");
1885
1886
0
    if (stored_chksum != computed_chksum)
1887
0
        ret_value = false;
1888
1889
0
done:
1890
0
    FUNC_LEAVE_NOAPI(ret_value)
1891
0
} /* end H5EA__cache_dblk_page_verify_chksum() */
1892
1893
/*-------------------------------------------------------------------------
1894
 * Function:  H5EA__cache_dblk_page_deserialize
1895
 *
1896
 * Purpose: Loads a data structure from the disk.
1897
 *
1898
 * Return:  Success:  Pointer to a new B-tree.
1899
 *    Failure:  NULL
1900
 *
1901
 *-------------------------------------------------------------------------
1902
 */
1903
static void *
1904
H5EA__cache_dblk_page_deserialize(const void *_image, size_t len, void *_udata, bool H5_ATTR_UNUSED *dirty)
1905
0
{
1906
0
    H5EA_dblk_page_t          *dblk_page = NULL; /* Data block page info */
1907
0
    H5EA_dblk_page_cache_ud_t *udata =
1908
0
        (H5EA_dblk_page_cache_ud_t *)_udata;        /* User data for loading data block page */
1909
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
1910
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
1911
0
    void          *ret_value = NULL;
1912
1913
0
    FUNC_ENTER_PACKAGE
1914
1915
    /* Sanity check */
1916
0
    assert(udata);
1917
0
    assert(udata->hdr);
1918
0
    assert(udata->parent);
1919
0
    assert(H5_addr_defined(udata->dblk_page_addr));
1920
1921
    /* Allocate the extensible array data block page */
1922
0
    if (NULL == (dblk_page = H5EA__dblk_page_alloc(udata->hdr, udata->parent)))
1923
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTALLOC, NULL,
1924
0
                    "memory allocation failed for extensible array data block page");
1925
1926
    /* Set the extensible array data block page's information */
1927
0
    dblk_page->addr = udata->dblk_page_addr;
1928
1929
    /* Internal information */
1930
1931
    /* Decode elements in data block page */
1932
    /* Convert from raw elements on disk into native elements in memory */
1933
0
    if ((udata->hdr->cparam.cls->decode)(image, dblk_page->elmts, udata->hdr->dblk_page_nelmts,
1934
0
                                         udata->hdr->cb_ctx) < 0)
1935
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTDECODE, NULL, "can't decode extensible array data elements");
1936
0
    image += (udata->hdr->dblk_page_nelmts * udata->hdr->cparam.raw_elmt_size);
1937
1938
    /* Sanity check */
1939
    /* (allow for checksum not decoded yet) */
1940
0
    assert((size_t)(image - (const uint8_t *)_image) == (len - H5EA_SIZEOF_CHKSUM));
1941
1942
    /* Set the data block page's size */
1943
0
    dblk_page->size = len;
1944
1945
    /* checksum verification already done in verify_chksum cb */
1946
1947
    /* Metadata checksum */
1948
0
    UINT32DECODE(image, stored_chksum);
1949
1950
    /* Sanity check */
1951
0
    assert((size_t)(image - (const uint8_t *)_image) == dblk_page->size);
1952
1953
    /* Set return value */
1954
0
    ret_value = dblk_page;
1955
1956
0
done:
1957
    /* Release resources */
1958
0
    if (!ret_value)
1959
0
        if (dblk_page && H5EA__dblk_page_dest(dblk_page) < 0)
1960
0
            HDONE_ERROR(H5E_EARRAY, H5E_CANTFREE, NULL, "unable to destroy extensible array data block page");
1961
0
    FUNC_LEAVE_NOAPI(ret_value)
1962
0
} /* end H5EA__cache_dblk_page_deserialize() */
1963
1964
/*-------------------------------------------------------------------------
1965
 * Function:    H5EA__cache_dblk_page_image_len
1966
 *
1967
 * Purpose:     Compute the size of the data structure on disk.
1968
 *
1969
 * Return:      Non-negative on success/Negative on failure
1970
 *
1971
 *-------------------------------------------------------------------------
1972
 */
1973
static herr_t
1974
H5EA__cache_dblk_page_image_len(const void *_thing, size_t *image_len)
1975
0
{
1976
0
    const H5EA_dblk_page_t *dblk_page = (const H5EA_dblk_page_t *)_thing; /* Pointer to the object */
1977
1978
0
    FUNC_ENTER_PACKAGE_NOERR
1979
1980
    /* Check arguments */
1981
0
    assert(dblk_page);
1982
0
    assert(image_len);
1983
1984
    /* Set the image length size */
1985
0
    *image_len = dblk_page->size;
1986
1987
0
    FUNC_LEAVE_NOAPI(SUCCEED)
1988
0
} /* end H5EA__cache_dblk_page_image_len() */
1989
1990
/*-------------------------------------------------------------------------
1991
 * Function:  H5EA__cache_dblk_page_serialize
1992
 *
1993
 * Purpose: Flushes a dirty object to disk.
1994
 *
1995
 * Return:  Non-negative on success/Negative on failure
1996
 *
1997
 *-------------------------------------------------------------------------
1998
 */
1999
static herr_t
2000
H5EA__cache_dblk_page_serialize(const H5F_t H5_ATTR_NDEBUG_UNUSED *f, void *_image, size_t H5_ATTR_UNUSED len,
2001
                                void *_thing)
2002
0
{
2003
0
    H5EA_dblk_page_t *dblk_page = (H5EA_dblk_page_t *)_thing; /* Pointer to the object to serialize */
2004
0
    uint8_t          *image     = (uint8_t *)_image;          /* Pointer into raw data buffer */
2005
0
    uint32_t          metadata_chksum;                        /* Computed metadata checksum value */
2006
0
    herr_t            ret_value = SUCCEED;
2007
2008
0
    FUNC_ENTER_PACKAGE
2009
2010
    /* Check arguments */
2011
0
    assert(f);
2012
0
    assert(image);
2013
0
    assert(dblk_page);
2014
0
    assert(dblk_page->hdr);
2015
2016
    /* Internal information */
2017
2018
    /* Encode elements in data block page */
2019
2020
    /* Convert from native elements in memory into raw elements on disk */
2021
0
    if ((dblk_page->hdr->cparam.cls->encode)(image, dblk_page->elmts, dblk_page->hdr->dblk_page_nelmts,
2022
0
                                             dblk_page->hdr->cb_ctx) < 0)
2023
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTENCODE, FAIL, "can't encode extensible array data elements");
2024
0
    image += (dblk_page->hdr->dblk_page_nelmts * dblk_page->hdr->cparam.raw_elmt_size);
2025
2026
    /* Compute metadata checksum */
2027
0
    metadata_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
2028
2029
    /* Metadata checksum */
2030
0
    UINT32ENCODE(image, metadata_chksum);
2031
2032
    /* Sanity check */
2033
0
    assert((size_t)(image - (uint8_t *)_image) == len);
2034
2035
0
done:
2036
0
    FUNC_LEAVE_NOAPI(ret_value)
2037
0
} /* end H5EA__cache_dblk_page_serialize() */
2038
2039
/*-------------------------------------------------------------------------
2040
 * Function:  H5EA__cache_dblk_page_notify
2041
 *
2042
 * Purpose: Handle cache action notifications
2043
 *
2044
 * Return:  Non-negative on success/Negative on failure
2045
 *
2046
 *-------------------------------------------------------------------------
2047
 */
2048
static herr_t
2049
H5EA__cache_dblk_page_notify(H5AC_notify_action_t action, void *_thing)
2050
0
{
2051
0
    H5EA_dblk_page_t *dblk_page = (H5EA_dblk_page_t *)_thing; /* Pointer to the object */
2052
0
    herr_t            ret_value = SUCCEED;
2053
2054
0
    FUNC_ENTER_PACKAGE
2055
2056
    /* Sanity check */
2057
0
    assert(dblk_page);
2058
2059
    /* Determine which action to take */
2060
0
    switch (action) {
2061
0
        case H5AC_NOTIFY_ACTION_AFTER_INSERT:
2062
0
        case H5AC_NOTIFY_ACTION_AFTER_LOAD:
2063
            /* Create flush dependency on parent */
2064
0
            if (H5EA__create_flush_depend((H5AC_info_t *)dblk_page->parent, (H5AC_info_t *)dblk_page) < 0)
2065
0
                HGOTO_ERROR(
2066
0
                    H5E_EARRAY, H5E_CANTDEPEND, FAIL,
2067
0
                    "unable to create flush dependency between data block page and parent, address = %llu",
2068
0
                    (unsigned long long)dblk_page->addr);
2069
0
            break;
2070
2071
0
        case H5AC_NOTIFY_ACTION_AFTER_FLUSH:
2072
            /* Destroy flush dependency on extensible array header, if set */
2073
0
            if (dblk_page->has_hdr_depend) {
2074
0
                if (H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->hdr, (H5AC_info_t *)dblk_page) < 0)
2075
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
2076
0
                                "unable to destroy flush dependency between data block page and header, "
2077
0
                                "address = %llu",
2078
0
                                (unsigned long long)dblk_page->addr);
2079
0
                dblk_page->has_hdr_depend = false;
2080
0
            } /* end if */
2081
0
            break;
2082
2083
0
        case H5AC_NOTIFY_ACTION_BEFORE_EVICT:
2084
            /* Destroy flush dependency on parent */
2085
0
            if (H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->parent, (H5AC_info_t *)dblk_page) < 0)
2086
0
                HGOTO_ERROR(
2087
0
                    H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
2088
0
                    "unable to destroy flush dependency between data block page and parent, address = %llu",
2089
0
                    (unsigned long long)dblk_page->addr);
2090
2091
            /* Destroy flush dependency on extensible array header, if set */
2092
0
            if (dblk_page->has_hdr_depend) {
2093
0
                if (H5EA__destroy_flush_depend((H5AC_info_t *)dblk_page->hdr, (H5AC_info_t *)dblk_page) < 0)
2094
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
2095
0
                                "unable to destroy flush dependency between data block page and header, "
2096
0
                                "address = %llu",
2097
0
                                (unsigned long long)dblk_page->addr);
2098
0
                dblk_page->has_hdr_depend = false;
2099
0
            } /* end if */
2100
2101
            /* Detach from 'top' proxy for extensible array */
2102
0
            if (dblk_page->top_proxy) {
2103
0
                if (H5AC_proxy_entry_remove_child(dblk_page->top_proxy, dblk_page) < 0)
2104
0
                    HGOTO_ERROR(H5E_EARRAY, H5E_CANTUNDEPEND, FAIL,
2105
0
                                "unable to destroy flush dependency between data block page and "
2106
0
                                "extensible array 'top' proxy");
2107
0
                dblk_page->top_proxy = NULL;
2108
0
            } /* end if */
2109
0
            break;
2110
2111
0
        case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED:
2112
0
        case H5AC_NOTIFY_ACTION_ENTRY_CLEANED:
2113
0
        case H5AC_NOTIFY_ACTION_CHILD_DIRTIED:
2114
0
        case H5AC_NOTIFY_ACTION_CHILD_CLEANED:
2115
0
        case H5AC_NOTIFY_ACTION_CHILD_UNSERIALIZED:
2116
0
        case H5AC_NOTIFY_ACTION_CHILD_SERIALIZED:
2117
            /* do nothing */
2118
0
            break;
2119
2120
0
        default:
2121
0
#ifdef NDEBUG
2122
0
            HGOTO_ERROR(H5E_EARRAY, H5E_BADVALUE, FAIL, "unknown action from metadata cache");
2123
#else  /* NDEBUG */
2124
            assert(0 && "Unknown action?!?");
2125
#endif /* NDEBUG */
2126
0
    }  /* end switch */
2127
2128
0
done:
2129
0
    FUNC_LEAVE_NOAPI(ret_value)
2130
0
} /* end H5EA__cache_dblk_page_notify() */
2131
2132
/*-------------------------------------------------------------------------
2133
 * Function:  H5EA__cache_dblk_page_free_icr
2134
 *
2135
 * Purpose: Destroy/release an "in core representation" of a data
2136
 *              structure
2137
 *
2138
 * Return:  Non-negative on success/Negative on failure
2139
 *
2140
 *-------------------------------------------------------------------------
2141
 */
2142
static herr_t
2143
H5EA__cache_dblk_page_free_icr(void *thing)
2144
0
{
2145
0
    herr_t ret_value = SUCCEED;
2146
2147
0
    FUNC_ENTER_PACKAGE
2148
2149
    /* Check arguments */
2150
0
    assert(thing);
2151
2152
    /* Release the extensible array data block page */
2153
0
    if (H5EA__dblk_page_dest((H5EA_dblk_page_t *)thing) < 0)
2154
0
        HGOTO_ERROR(H5E_EARRAY, H5E_CANTFREE, FAIL, "can't free extensible array data block page");
2155
2156
0
done:
2157
0
    FUNC_LEAVE_NOAPI(ret_value)
2158
0
} /* end H5EA__cache_dblk_page_free_icr() */