Coverage Report

Created: 2026-07-16 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5SMcache.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:   H5SMcache.c
16
 *
17
 * Purpose:   Implement shared message metadata cache methods.
18
 *
19
 *-------------------------------------------------------------------------
20
 */
21
22
/****************/
23
/* Module Setup */
24
/****************/
25
26
#include "H5SMmodule.h" /* This source code file is part of the H5SM module */
27
28
/***********/
29
/* Headers */
30
/***********/
31
#include "H5private.h"   /* Generic Functions                    */
32
#include "H5Eprivate.h"  /* Error handling         */
33
#include "H5Fprivate.h"  /* File access                          */
34
#include "H5FLprivate.h" /* Free Lists                           */
35
#include "H5MMprivate.h" /* Memory management      */
36
#include "H5SMpkg.h"     /* Shared object header messages        */
37
38
/****************/
39
/* Local Macros */
40
/****************/
41
42
/******************/
43
/* Local Typedefs */
44
/******************/
45
46
/********************/
47
/* Local Prototypes */
48
/********************/
49
50
/* Metadata cache (H5AC) callbacks */
51
static herr_t H5SM__cache_table_get_initial_load_size(void *udata, size_t *image_len);
52
static htri_t H5SM__cache_table_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
53
static void  *H5SM__cache_table_deserialize(const void *image, size_t len, void *udata, bool *dirty);
54
static herr_t H5SM__cache_table_image_len(const void *thing, size_t *image_len);
55
static herr_t H5SM__cache_table_serialize(const H5F_t *f, void *image, size_t len, void *thing);
56
static herr_t H5SM__cache_table_free_icr(void *thing);
57
58
static herr_t H5SM__cache_list_get_initial_load_size(void *udata, size_t *image_len);
59
static htri_t H5SM__cache_list_verify_chksum(const void *image_ptr, size_t len, void *udata_ptr);
60
static void  *H5SM__cache_list_deserialize(const void *image, size_t len, void *udata, bool *dirty);
61
static herr_t H5SM__cache_list_image_len(const void *thing, size_t *image_len);
62
static herr_t H5SM__cache_list_serialize(const H5F_t *f, void *image, size_t len, void *thing);
63
static herr_t H5SM__cache_list_free_icr(void *thing);
64
65
/*********************/
66
/* Package Variables */
67
/*********************/
68
69
/* H5SM inherits cache-like properties from H5AC */
70
const H5AC_class_t H5AC_SOHM_TABLE[1] = {{
71
    H5AC_SOHM_TABLE_ID,                      /* Metadata client ID */
72
    "shared message table",                  /* Metadata client name (for debugging) */
73
    H5FD_MEM_SOHM_TABLE,                     /* File space memory type for client */
74
    H5AC__CLASS_NO_FLAGS_SET,                /* Client class behavior flags */
75
    H5SM__cache_table_get_initial_load_size, /* 'get_initial_load_size' callback */
76
    NULL,                                    /* 'get_final_load_size' callback */
77
    H5SM__cache_table_verify_chksum,         /* 'verify_chksum' callback */
78
    H5SM__cache_table_deserialize,           /* 'deserialize' callback */
79
    H5SM__cache_table_image_len,             /* 'image_len' callback */
80
    NULL,                                    /* 'pre_serialize' callback */
81
    H5SM__cache_table_serialize,             /* 'serialize' callback */
82
    NULL,                                    /* 'notify' callback */
83
    H5SM__cache_table_free_icr,              /* 'free_icr' callback */
84
    NULL,                                    /* 'fsf_size' callback */
85
}};
86
87
const H5AC_class_t H5AC_SOHM_LIST[1] = {{
88
    H5AC_SOHM_LIST_ID,                      /* Metadata client ID */
89
    "shared message list",                  /* Metadata client name (for debugging) */
90
    H5FD_MEM_SOHM_TABLE,                    /* File space memory type for client */
91
    H5AC__CLASS_NO_FLAGS_SET,               /* Client class behavior flags */
92
    H5SM__cache_list_get_initial_load_size, /* 'get_initial_load_size' callback */
93
    NULL,                                   /* 'get_final_load_size' callback */
94
    H5SM__cache_list_verify_chksum,         /* 'verify_chksum' callback */
95
    H5SM__cache_list_deserialize,           /* 'deserialize' callback */
96
    H5SM__cache_list_image_len,             /* 'image_len' callback */
97
    NULL,                                   /* 'pre_serialize' callback */
98
    H5SM__cache_list_serialize,             /* 'serialize' callback */
99
    NULL,                                   /* 'notify' callback */
100
    H5SM__cache_list_free_icr,              /* 'free_icr' callback */
101
    NULL,                                   /* 'fsf_size' callback */
102
}};
103
104
/*****************************/
105
/* Library Private Variables */
106
/*****************************/
107
108
/*******************/
109
/* Local Variables */
110
/*******************/
111
112
/*-------------------------------------------------------------------------
113
 * Function:    H5SM__cache_table_get_initial_load_size()
114
 *
115
 * Purpose: Return the size of the master table of Shared Object Header
116
 *    Message indexes on disk.
117
 *
118
 * Return:      Success:        SUCCEED
119
 *              Failure:        FAIL
120
 *
121
 *-------------------------------------------------------------------------
122
 */
123
static herr_t
124
H5SM__cache_table_get_initial_load_size(void *_udata, size_t *image_len)
125
0
{
126
0
    const H5SM_table_cache_ud_t *udata = (const H5SM_table_cache_ud_t *)_udata; /* User data for callback */
127
128
0
    FUNC_ENTER_PACKAGE_NOERR
129
130
    /* Check arguments */
131
0
    assert(udata);
132
0
    assert(udata->f);
133
0
    assert(image_len);
134
135
    /* Set the image length size */
136
0
    *image_len = H5SM_TABLE_SIZE(udata->f);
137
138
0
    FUNC_LEAVE_NOAPI(SUCCEED)
139
0
} /* end H5SM__cache_table_get_initial_load_size() */
140
141
/*-------------------------------------------------------------------------
142
 * Function:    H5SM__cache_table_verify_chksum
143
 *
144
 * Purpose:     Verify the computed checksum of the data structure is the
145
 *              same as the stored chksum.
146
 *
147
 * Return:      Success:        true/false
148
 *              Failure:        Negative
149
 *
150
 *-------------------------------------------------------------------------
151
 */
152
htri_t
153
H5SM__cache_table_verify_chksum(const void *_image, size_t len, void H5_ATTR_UNUSED *_udata)
154
0
{
155
0
    const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */
156
0
    uint32_t       stored_chksum;                   /* Stored metadata checksum value */
157
0
    uint32_t       computed_chksum;                 /* Computed metadata checksum value */
158
0
    htri_t         ret_value = true;                /* Return value */
159
160
0
    FUNC_ENTER_PACKAGE
161
162
    /* Check arguments */
163
0
    assert(image);
164
165
    /* Get stored and computed checksums */
166
0
    if (H5F_get_checksums(image, len, &stored_chksum, &computed_chksum) < 0)
167
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get checksums");
168
169
0
    if (stored_chksum != computed_chksum)
170
0
        ret_value = false;
171
172
0
done:
173
0
    FUNC_LEAVE_NOAPI(ret_value)
174
0
} /* end H5SM__cache_table_verify_chksum() */
175
176
/*-------------------------------------------------------------------------
177
 * Function:    H5SM__cache_table_deserialize
178
 *
179
 * Purpose: Given a buffer containing the on disk representation of the
180
 *    master table of Shared Object Header Message indexes, deserialize
181
 *    the table, copy the contents into a newly allocated instance of
182
 *    H5SM_master_table_t, and return a pointer to the new instance.
183
 *
184
 * Return:      Success:        Pointer to in core representation
185
 *              Failure:        NULL
186
 *
187
 *-------------------------------------------------------------------------
188
 */
189
static void *
190
H5SM__cache_table_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_udata,
191
                              bool H5_ATTR_UNUSED *dirty)
192
0
{
193
0
    H5F_t                 *f;            /* File pointer -- from user data */
194
0
    H5SM_master_table_t   *table = NULL; /* Shared message table that we deserializing */
195
0
    H5SM_table_cache_ud_t *udata = (H5SM_table_cache_ud_t *)_udata; /* Pointer to user data */
196
0
    const uint8_t         *image = (const uint8_t *)_image;         /* Pointer into input buffer */
197
0
    uint32_t               stored_chksum;                           /* Stored metadata checksum value */
198
0
    size_t                 u;                                       /* Counter variable for index headers */
199
0
    void                  *ret_value = NULL;                        /* Return value */
200
201
0
    FUNC_ENTER_PACKAGE
202
203
    /* Check arguments */
204
0
    assert(image);
205
0
    assert(len > 0);
206
0
    assert(udata);
207
0
    assert(udata->f);
208
0
    f = udata->f;
209
0
    assert(dirty);
210
211
    /* Verify that we're reading version 0 of the table; this is the only
212
     * version defined so far.
213
     */
214
0
    assert(H5F_SOHM_VERS(f) == HDF5_SHAREDHEADER_VERSION);
215
216
    /* Allocate space for the master table in memory */
217
0
    if (NULL == (table = H5FL_CALLOC(H5SM_master_table_t)))
218
0
        HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "memory allocation failed");
219
220
    /* Read number of indexes and version from file superblock */
221
0
    table->num_indexes = H5F_SOHM_NINDEXES(f);
222
0
    assert(table->num_indexes > 0);
223
224
    /* Compute the size of the SOHM table header on disk.  This is the "table"
225
     * itself plus each index within the table
226
     */
227
0
    table->table_size = H5SM_TABLE_SIZE(f);
228
0
    assert(table->table_size == len);
229
230
    /* Check magic number */
231
0
    if (memcmp(image, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
232
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM table signature");
233
0
    image += H5_SIZEOF_MAGIC;
234
235
    /* Allocate space for the index headers in memory*/
236
0
    if (NULL == (table->indexes =
237
0
                     (H5SM_index_header_t *)H5FL_ARR_MALLOC(H5SM_index_header_t, (size_t)table->num_indexes)))
238
0
        HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "memory allocation failed for SOHM indexes");
239
240
    /* Read in the index headers */
241
0
    for (u = 0; u < table->num_indexes; ++u) {
242
        /* Verify correct version of index list */
243
0
        if (H5SM_LIST_VERSION != *image++)
244
0
            HGOTO_ERROR(H5E_SOHM, H5E_VERSION, NULL, "bad shared message list version number");
245
246
        /* Type of the index (list or B-tree) */
247
0
        table->indexes[u].index_type = (H5SM_index_type_t)*image++;
248
249
        /* Type of messages in the index */
250
0
        UINT16DECODE(image, table->indexes[u].mesg_types);
251
252
        /* Minimum size of message to share */
253
0
        UINT32DECODE(image, table->indexes[u].min_mesg_size);
254
255
        /* List cutoff; fewer than this number and index becomes a list */
256
0
        UINT16DECODE(image, table->indexes[u].list_max);
257
258
        /* B-tree cutoff; more than this number and index becomes a B-tree */
259
0
        UINT16DECODE(image, table->indexes[u].btree_min);
260
261
        /* Number of messages shared */
262
0
        UINT16DECODE(image, table->indexes[u].num_messages);
263
264
        /* Address of the actual index */
265
0
        H5F_addr_decode(f, &image, &(table->indexes[u].index_addr));
266
267
        /* Address of the index's heap */
268
0
        H5F_addr_decode(f, &image, &(table->indexes[u].heap_addr));
269
270
        /* Compute the size of a list index for this SOHM index */
271
0
        table->indexes[u].list_size = H5SM_LIST_SIZE(f, table->indexes[u].list_max);
272
0
    } /* end for */
273
274
    /* checksum verification already done in verify_chksum cb */
275
276
    /* Read in checksum */
277
0
    UINT32DECODE(image, stored_chksum);
278
279
    /* Sanity check */
280
0
    assert((size_t)(image - (const uint8_t *)_image) == table->table_size);
281
282
    /* Set return value */
283
0
    ret_value = table;
284
285
0
done:
286
0
    if (!ret_value && table)
287
0
        if (H5SM__table_free(table) < 0)
288
0
            HDONE_ERROR(H5E_SOHM, H5E_CANTFREE, NULL, "unable to destroy sohm table");
289
290
0
    FUNC_LEAVE_NOAPI(ret_value)
291
0
} /* end H5SM__cache_table_deserialize() */
292
293
/*-------------------------------------------------------------------------
294
 * Function:    H5SM__cache_table_image_len
295
 *
296
 * Purpose: Compute the size in bytes of the specified instance of
297
 *    H5SM_master_table_t on disk, and return it in *image_len.
298
 *    On failure, the value of *image_len is undefined.
299
 *
300
 * Return:      Success:        SUCCEED
301
 *              Failure:        FAIL
302
 *
303
 *-------------------------------------------------------------------------
304
 */
305
static herr_t
306
H5SM__cache_table_image_len(const void *_thing, size_t *image_len)
307
0
{
308
0
    const H5SM_master_table_t *table =
309
0
        (const H5SM_master_table_t *)_thing; /* Shared message table to query */
310
311
0
    FUNC_ENTER_PACKAGE_NOERR
312
313
    /* Check arguments */
314
0
    assert(table);
315
0
    assert(table->cache_info.type == H5AC_SOHM_TABLE);
316
0
    assert(image_len);
317
318
0
    *image_len = table->table_size;
319
320
0
    FUNC_LEAVE_NOAPI(SUCCEED)
321
0
} /* end H5SM__cache_table_image_len() */
322
323
/*-------------------------------------------------------------------------
324
 * Function:    H5SM__cache_table_serialize
325
 *
326
 * Purpose: Serialize the contents of the supplied shared message table, and
327
 *    load this data into the supplied buffer.
328
 *
329
 * Return:      Success:        SUCCEED
330
 *              Failure:        FAIL
331
 *
332
 *-------------------------------------------------------------------------
333
 */
334
static herr_t
335
H5SM__cache_table_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_thing)
336
0
{
337
0
    H5SM_master_table_t *table = (H5SM_master_table_t *)_thing; /* Shared message table to encode */
338
0
    uint8_t             *image = (uint8_t *)_image;             /* Pointer into raw data buffer */
339
0
    uint32_t             computed_chksum;                       /* Computed metadata checksum value */
340
0
    size_t               u;                                     /* Counter variable */
341
342
0
    FUNC_ENTER_PACKAGE_NOERR
343
344
    /* Check arguments */
345
0
    assert(f);
346
0
    assert(image);
347
0
    assert(table);
348
0
    assert(table->cache_info.type == H5AC_SOHM_TABLE);
349
0
    assert(table->table_size == len);
350
351
    /* Verify that we're writing version 0 of the table; this is the only
352
     * version defined so far.
353
     */
354
0
    assert(H5F_SOHM_VERS(f) == HDF5_SHAREDHEADER_VERSION);
355
356
    /* Encode magic number */
357
0
    H5MM_memcpy(image, H5SM_TABLE_MAGIC, (size_t)H5_SIZEOF_MAGIC);
358
0
    image += H5_SIZEOF_MAGIC;
359
360
    /* Encode each index header */
361
0
    for (u = 0; u < table->num_indexes; ++u) {
362
        /* Version for this list */
363
0
        *image++ = H5SM_LIST_VERSION;
364
365
        /* Is message index a list or a B-tree? */
366
0
        *image++ = (uint8_t)table->indexes[u].index_type;
367
368
        /* Type of messages in the index */
369
0
        UINT16ENCODE(image, table->indexes[u].mesg_types);
370
371
        /* Minimum size of message to share */
372
0
        UINT32ENCODE(image, table->indexes[u].min_mesg_size);
373
374
        /* List cutoff; fewer than this number and index becomes a list */
375
0
        UINT16ENCODE(image, table->indexes[u].list_max);
376
377
        /* B-tree cutoff; more than this number and index becomes a B-tree */
378
0
        UINT16ENCODE(image, table->indexes[u].btree_min);
379
380
        /* Number of messages shared */
381
0
        UINT16ENCODE(image, table->indexes[u].num_messages);
382
383
        /* Address of the actual index */
384
0
        H5F_addr_encode(f, &image, table->indexes[u].index_addr);
385
386
        /* Address of the index's heap */
387
0
        H5F_addr_encode(f, &image, table->indexes[u].heap_addr);
388
0
    } /* end for */
389
390
    /* Compute checksum on buffer */
391
0
    computed_chksum = H5_checksum_metadata(_image, (table->table_size - H5SM_SIZEOF_CHECKSUM), 0);
392
0
    UINT32ENCODE(image, computed_chksum);
393
394
    /* sanity check */
395
0
    assert((size_t)(image - ((uint8_t *)_image)) == table->table_size);
396
397
0
    FUNC_LEAVE_NOAPI(SUCCEED)
398
0
} /* end H5SM__cache_table_serialize() */
399
400
/*****************************************/
401
/* no H5SM_cache_table_notify() function */
402
/*****************************************/
403
404
/*-------------------------------------------------------------------------
405
 * Function:    H5SM__cache_table_free_icr
406
 *
407
 * Purpose: Free memory used by the SOHM table.
408
 *
409
 * Return:      Success:        SUCCEED
410
 *              Failure:        FAIL
411
 *
412
 *-------------------------------------------------------------------------
413
 */
414
static herr_t
415
H5SM__cache_table_free_icr(void *_thing)
416
0
{
417
0
    H5SM_master_table_t *table     = (H5SM_master_table_t *)_thing; /* Shared message table to release */
418
0
    herr_t               ret_value = SUCCEED;                       /* Return value */
419
420
0
    FUNC_ENTER_PACKAGE
421
422
    /* Check arguments */
423
0
    assert(table);
424
0
    assert(table->cache_info.type == H5AC_SOHM_TABLE);
425
426
    /* Destroy Shared Object Header Message table */
427
0
    if (H5SM__table_free(table) < 0)
428
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTRELEASE, FAIL, "unable to free shared message table");
429
430
0
done:
431
0
    FUNC_LEAVE_NOAPI(ret_value)
432
0
} /* end H5SM_cache_table_free_icr() */
433
434
/*-------------------------------------------------------------------------
435
 * Function:    H5SM__cache_list_get_initial_load_size()
436
 *
437
 * Purpose: Return the on disk size of list of SOHM messages.  In this case,
438
 *    we simply look up the size in the user data, and return that value
439
 *    in *image_len.
440
 *
441
 * Return:      Success:        SUCCEED
442
 *              Failure:        FAIL
443
 *
444
 *-------------------------------------------------------------------------
445
 */
446
static herr_t
447
H5SM__cache_list_get_initial_load_size(void *_udata, size_t *image_len)
448
0
{
449
0
    const H5SM_list_cache_ud_t *udata = (const H5SM_list_cache_ud_t *)_udata; /* User data for callback */
450
451
0
    FUNC_ENTER_PACKAGE_NOERR
452
453
    /* Check arguments */
454
0
    assert(udata);
455
0
    assert(udata->header);
456
0
    assert(udata->header->list_size > 0);
457
0
    assert(image_len);
458
459
    /* Set the image length size */
460
0
    *image_len = udata->header->list_size;
461
462
0
    FUNC_LEAVE_NOAPI(SUCCEED)
463
0
} /* end H5SM__cache_list_get_initial_load_size() */
464
465
/*-------------------------------------------------------------------------
466
 * Function:  H5SM__cache_list_verify_chksum
467
 *
468
 * Purpose:     Verify the computed checksum of the data structure is the
469
 *              same as the stored chksum.
470
 *
471
 * Return:      Success:        true/false
472
 *              Failure:        Negative
473
 *
474
 *-------------------------------------------------------------------------
475
 */
476
htri_t
477
H5SM__cache_list_verify_chksum(const void *_image, size_t H5_ATTR_UNUSED len, void *_udata)
478
0
{
479
0
    const uint8_t        *image = (const uint8_t *)_image;        /* Pointer into raw data buffer */
480
0
    H5SM_list_cache_ud_t *udata = (H5SM_list_cache_ud_t *)_udata; /* User data for callback */
481
0
    size_t                chk_size;         /* Exact size of the node with checksum at the end */
482
0
    uint32_t              stored_chksum;    /* Stored metadata checksum value */
483
0
    uint32_t              computed_chksum;  /* Computed metadata checksum value */
484
0
    htri_t                ret_value = true; /* Return value */
485
486
0
    FUNC_ENTER_PACKAGE
487
488
    /* Check arguments */
489
0
    assert(image);
490
0
    assert(udata);
491
492
    /* The buffer only holds list_max messages; a corrupted header whose message
493
     * count exceeds that would size the checksum region past the end of it.
494
     */
495
0
    if (udata->header->num_messages > udata->header->list_max)
496
0
        HGOTO_ERROR(H5E_SOHM, H5E_BADVALUE, FAIL, "number of SOHM messages exceeds list size");
497
498
    /* Exact size with checksum at the end */
499
0
    chk_size = H5SM_LIST_SIZE(udata->f, udata->header->num_messages);
500
501
    /* Get stored and computed checksums */
502
0
    if (H5F_get_checksums(image, chk_size, &stored_chksum, &computed_chksum) < 0)
503
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTGET, FAIL, "can't get checksums");
504
505
0
    if (stored_chksum != computed_chksum)
506
0
        ret_value = false;
507
508
0
done:
509
0
    FUNC_LEAVE_NOAPI(ret_value)
510
0
} /* end H5SM__cache_list_verify_chksum() */
511
512
/*-------------------------------------------------------------------------
513
 * Function:    H5SM__cache_list_deserialize
514
 *
515
 * Purpose: Given a buffer containing the on disk image of a list of
516
 *    SOHM message, deserialize the list, load it into a newly allocated
517
 *    instance of H5SM_list_t, and return a pointer to same.
518
 *
519
 * Return:      Success:        Pointer to in core representation
520
 *              Failure:        NULL
521
 *
522
 *-------------------------------------------------------------------------
523
 */
524
static void *
525
H5SM__cache_list_deserialize(const void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_udata,
526
                             bool H5_ATTR_UNUSED *dirty)
527
0
{
528
0
    H5SM_list_t          *list  = NULL;                           /* The SOHM list being read in */
529
0
    H5SM_list_cache_ud_t *udata = (H5SM_list_cache_ud_t *)_udata; /* User data for callback */
530
0
    H5SM_bt2_ctx_t        ctx;                                    /* Message encoding context */
531
0
    const uint8_t        *image = (const uint8_t *)_image;        /* Pointer into input buffer */
532
0
    uint32_t              stored_chksum;                          /* Stored metadata checksum value */
533
0
    size_t                u;                                      /* Counter variable for messages in list */
534
0
    void                 *ret_value = NULL;                       /* Return value */
535
536
0
    FUNC_ENTER_PACKAGE
537
538
    /* Check arguments */
539
0
    assert(image);
540
0
    assert(len > 0);
541
0
    assert(udata);
542
0
    assert(udata->header);
543
0
    assert(udata->header->list_size == len);
544
0
    assert(dirty);
545
546
    /* Allocate space for the SOHM list data structure */
547
0
    if (NULL == (list = H5FL_MALLOC(H5SM_list_t)))
548
0
        HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "memory allocation failed");
549
0
    memset(&list->cache_info, 0, sizeof(H5AC_info_t));
550
551
    /* Allocate list in memory as an array*/
552
0
    if (NULL == (list->messages = (H5SM_sohm_t *)H5FL_ARR_MALLOC(H5SM_sohm_t, udata->header->list_max)))
553
0
        HGOTO_ERROR(H5E_SOHM, H5E_NOSPACE, NULL, "file allocation failed for SOHM list");
554
0
    list->header = udata->header;
555
556
    /* Check magic number */
557
0
    if (memcmp(image, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0)
558
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "bad SOHM list signature");
559
0
    image += H5_SIZEOF_MAGIC;
560
561
    /* The message array is sized for list_max entries; a list index always
562
     * holds at most that many before it is promoted to a B-tree. Reject a
563
     * corrupted header whose message count would drive the decode loop past
564
     * the allocation and the input buffer.
565
     */
566
0
    if (udata->header->num_messages > udata->header->list_max)
567
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "number of SOHM messages exceeds list size");
568
569
    /* Read messages into the list array */
570
0
    ctx.sizeof_addr = H5F_SIZEOF_ADDR(udata->f);
571
0
    for (u = 0; u < udata->header->num_messages; u++) {
572
0
        if (H5SM__message_decode(image, &(list->messages[u]), &ctx) < 0)
573
0
            HGOTO_ERROR(H5E_SOHM, H5E_CANTLOAD, NULL, "can't decode shared message");
574
575
0
        image += H5SM_SOHM_ENTRY_SIZE(udata->f);
576
0
    } /* end for */
577
578
    /* checksum verification already done in verify_chksum cb */
579
580
    /* Read in checksum */
581
0
    UINT32DECODE(image, stored_chksum);
582
583
    /* Sanity check */
584
0
    assert((size_t)(image - (const uint8_t *)_image) <= udata->header->list_size);
585
586
    /* Initialize the rest of the array */
587
0
    for (u = udata->header->num_messages; u < udata->header->list_max; u++)
588
0
        list->messages[u].location = H5SM_NO_LOC;
589
590
    /* Set return value */
591
0
    ret_value = list;
592
593
0
done:
594
0
    if (!ret_value && list) {
595
0
        if (list->messages)
596
0
            list->messages = H5FL_ARR_FREE(H5SM_sohm_t, list->messages);
597
0
        list = H5FL_FREE(H5SM_list_t, list);
598
0
    } /* end if */
599
600
0
    FUNC_LEAVE_NOAPI(ret_value)
601
0
} /* end H5SM__cache_list_deserialize() */
602
603
/*-------------------------------------------------------------------------
604
 * Function:    H5SM__cache_list_image_len
605
 *
606
 * Purpose: Get the size of the shared message list on disk.
607
 *
608
 * Return:      Success:        SUCCEED
609
 *              Failure:        FAIL
610
 *
611
 *-------------------------------------------------------------------------
612
 */
613
static herr_t
614
H5SM__cache_list_image_len(const void *_thing, size_t *image_len)
615
0
{
616
0
    const H5SM_list_t *list = (const H5SM_list_t *)_thing; /* Shared message list to query */
617
618
0
    FUNC_ENTER_PACKAGE_NOERR
619
620
    /* Check arguments */
621
0
    assert(list);
622
0
    assert(list->cache_info.type == H5AC_SOHM_LIST);
623
0
    assert(list->header);
624
0
    assert(image_len);
625
626
0
    *image_len = list->header->list_size;
627
628
0
    FUNC_LEAVE_NOAPI(SUCCEED)
629
0
} /* end H5SM__cache_list_image_len() */
630
631
/*-------------------------------------------------------------------------
632
 * Function:    H5SM__cache_list_serialize
633
 *
634
 * Purpose: Serialize the contents of the supplied shared message list, and
635
 *    load this data into the supplied buffer.
636
 *
637
 * Return:      Success:        SUCCEED
638
 *              Failure:        FAIL
639
 *
640
 *-------------------------------------------------------------------------
641
 */
642
static herr_t
643
H5SM__cache_list_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_NDEBUG_UNUSED len, void *_thing)
644
0
{
645
0
    H5SM_list_t   *list = (H5SM_list_t *)_thing; /* Instance being serialized */
646
0
    H5SM_bt2_ctx_t ctx;                          /* Message encoding context */
647
0
    uint8_t       *image = (uint8_t *)_image;    /* Pointer into raw data buffer */
648
0
    uint32_t       computed_chksum;              /* Computed metadata checksum value */
649
0
    size_t         mesgs_serialized;             /* Number of messages serialized */
650
0
    size_t         u;                            /* Local index variable */
651
0
    herr_t         ret_value = SUCCEED;          /* Return value */
652
653
0
    FUNC_ENTER_PACKAGE
654
655
    /* Check arguments */
656
0
    assert(f);
657
0
    assert(image);
658
0
    assert(list);
659
0
    assert(list->cache_info.type == H5AC_SOHM_LIST);
660
0
    assert(list->header);
661
0
    assert(list->header->list_size == len);
662
663
    /* Encode magic number */
664
0
    H5MM_memcpy(image, H5SM_LIST_MAGIC, (size_t)H5_SIZEOF_MAGIC);
665
0
    image += H5_SIZEOF_MAGIC;
666
667
    /* serialize messages from the messages array */
668
0
    mesgs_serialized = 0;
669
0
    ctx.sizeof_addr  = H5F_SIZEOF_ADDR(f);
670
0
    for (u = 0; ((u < list->header->list_max) && (mesgs_serialized < list->header->num_messages)); u++) {
671
0
        if (list->messages[u].location != H5SM_NO_LOC) {
672
0
            if (H5SM__message_encode(image, &(list->messages[u]), &ctx) < 0)
673
0
                HGOTO_ERROR(H5E_SOHM, H5E_CANTFLUSH, FAIL, "unable to serialize shared message");
674
675
0
            image += H5SM_SOHM_ENTRY_SIZE(f);
676
0
            ++mesgs_serialized;
677
0
        } /* end if */
678
0
    }     /* end for */
679
680
0
    assert(mesgs_serialized == list->header->num_messages);
681
682
    /* Compute checksum on buffer */
683
0
    computed_chksum = H5_checksum_metadata(_image, (size_t)(image - (uint8_t *)_image), 0);
684
0
    UINT32ENCODE(image, computed_chksum);
685
686
    /* sanity check */
687
0
    assert((size_t)(image - (uint8_t *)_image) <= list->header->list_size);
688
689
    /* Clear memory */
690
0
    memset(image, 0, (list->header->list_size - (size_t)(image - (uint8_t *)_image)));
691
692
0
done:
693
0
    FUNC_LEAVE_NOAPI(ret_value)
694
0
} /* end H5SM__cache_list_serialize() */
695
696
/****************************************/
697
/* no H5SM_cache_list_notify() function */
698
/****************************************/
699
700
/*-------------------------------------------------------------------------
701
 * Function:    H5SM__cache_list_free_icr
702
 *
703
 * Purpose: Free all memory used by the list.
704
 *
705
 * Return:      Success:        SUCCEED
706
 *              Failure:        FAIL
707
 *
708
 *-------------------------------------------------------------------------
709
 */
710
static herr_t
711
H5SM__cache_list_free_icr(void *_thing)
712
0
{
713
0
    H5SM_list_t *list      = (H5SM_list_t *)_thing; /* Shared message list to release */
714
0
    herr_t       ret_value = SUCCEED;               /* Return value */
715
716
0
    FUNC_ENTER_PACKAGE
717
718
    /* Check arguments */
719
0
    assert(list);
720
0
    assert(list->cache_info.type == H5AC_SOHM_LIST);
721
722
    /* Destroy Shared Object Header Message list */
723
0
    if (H5SM__list_free(list) < 0)
724
0
        HGOTO_ERROR(H5E_SOHM, H5E_CANTRELEASE, FAIL, "unable to free shared message list");
725
726
0
done:
727
0
    FUNC_LEAVE_NOAPI(ret_value)
728
0
} /* end H5O_cache_list_free_icr() */