Coverage Report

Created: 2026-01-17 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Dlayout.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
/* Module Setup */
15
/****************/
16
17
#include "H5Dmodule.h" /* This source code file is part of the H5D module */
18
19
/***********/
20
/* Headers */
21
/***********/
22
#include "H5private.h"   /* Generic Functions                        */
23
#include "H5Dpkg.h"      /* Datasets                                 */
24
#include "H5Eprivate.h"  /* Error handling                           */
25
#include "H5HLprivate.h" /* Local heaps                              */
26
27
/****************/
28
/* Local Macros */
29
/****************/
30
31
/******************/
32
/* Local Typedefs */
33
/******************/
34
35
/********************/
36
/* Local Prototypes */
37
/********************/
38
39
/*********************/
40
/* Package Variables */
41
/*********************/
42
43
/* Format version bounds for layout */
44
const unsigned H5O_layout_ver_bounds[] = {
45
    H5O_LAYOUT_VERSION_1, /* H5F_LIBVER_EARLIEST */
46
    H5O_LAYOUT_VERSION_3,
47
    /* H5F_LIBVER_V18 */      /* H5O_LAYOUT_VERSION_DEFAULT */
48
    H5O_LAYOUT_VERSION_4,     /* H5F_LIBVER_V110 */
49
    H5O_LAYOUT_VERSION_4,     /* H5F_LIBVER_V112 */
50
    H5O_LAYOUT_VERSION_4,     /* H5F_LIBVER_V114 */
51
    H5O_LAYOUT_VERSION_5,     /* H5F_LIBVER_V200 */
52
    H5O_LAYOUT_VERSION_LATEST /* H5F_LIBVER_LATEST */
53
};
54
55
/*****************************/
56
/* Library Private Variables */
57
/*****************************/
58
59
/*******************/
60
/* Local Variables */
61
/*******************/
62
63
/*-------------------------------------------------------------------------
64
 * Function:    H5D__layout_set_io_ops
65
 *
66
 * Purpose:     Set the I/O operation function pointers for a dataset,
67
 *              according to the dataset's layout
68
 *
69
 * Return:      Non-negative on success/Negative on failure
70
 *
71
 *-------------------------------------------------------------------------
72
 */
73
herr_t
74
H5D__layout_set_io_ops(const H5D_t *dataset)
75
0
{
76
0
    herr_t ret_value = SUCCEED; /* Return value */
77
78
0
    FUNC_ENTER_PACKAGE
79
80
    /* check args */
81
0
    assert(dataset);
82
83
    /* Set the I/O functions for each layout type */
84
0
    switch (dataset->shared->layout.type) {
85
0
        case H5D_CONTIGUOUS:
86
0
            if (dataset->shared->dcpl_cache.efl.nused > 0)
87
0
                dataset->shared->layout.ops = H5D_LOPS_EFL;
88
0
            else
89
0
                dataset->shared->layout.ops = H5D_LOPS_CONTIG;
90
0
            break;
91
92
0
        case H5D_CHUNKED:
93
0
            dataset->shared->layout.ops = H5D_LOPS_CHUNK;
94
95
            /* Set the chunk operations */
96
0
            switch (dataset->shared->layout.u.chunk.idx_type) {
97
0
                case H5D_CHUNK_IDX_BTREE:
98
0
                    dataset->shared->layout.storage.u.chunk.ops = H5D_COPS_BTREE;
99
0
                    break;
100
101
0
                case H5D_CHUNK_IDX_NONE:
102
0
                    dataset->shared->layout.storage.u.chunk.ops = H5D_COPS_NONE;
103
0
                    break;
104
105
0
                case H5D_CHUNK_IDX_SINGLE:
106
0
                    dataset->shared->layout.storage.u.chunk.ops = H5D_COPS_SINGLE;
107
0
                    break;
108
109
0
                case H5D_CHUNK_IDX_FARRAY:
110
0
                    dataset->shared->layout.storage.u.chunk.ops = H5D_COPS_FARRAY;
111
0
                    break;
112
113
0
                case H5D_CHUNK_IDX_EARRAY:
114
0
                    dataset->shared->layout.storage.u.chunk.ops = H5D_COPS_EARRAY;
115
0
                    break;
116
117
0
                case H5D_CHUNK_IDX_BT2:
118
0
                    dataset->shared->layout.storage.u.chunk.ops = H5D_COPS_BT2;
119
0
                    break;
120
121
0
                case H5D_CHUNK_IDX_NTYPES:
122
0
                default:
123
0
                    assert(0 && "Unknown chunk index method!");
124
0
                    HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unknown chunk index method");
125
0
            } /* end switch */
126
0
            break;
127
128
0
        case H5D_COMPACT:
129
0
            dataset->shared->layout.ops = H5D_LOPS_COMPACT;
130
0
            break;
131
132
0
        case H5D_VIRTUAL:
133
0
            dataset->shared->layout.ops = H5D_LOPS_VIRTUAL;
134
0
            break;
135
136
0
        case H5D_LAYOUT_ERROR:
137
0
        case H5D_NLAYOUTS:
138
0
        default:
139
0
            HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unknown storage method");
140
0
    } /* end switch */
141
142
0
done:
143
0
    FUNC_LEAVE_NOAPI(ret_value)
144
0
} /* end H5D__layout_set_io_ops() */
145
146
/*-------------------------------------------------------------------------
147
 * Function:    H5D__layout_meta_size
148
 *
149
 * Purpose:     Returns the size of the raw message in bytes except raw data
150
 *              part for compact dataset.  This function doesn't take into
151
 *              account message alignment.
152
 *
153
 * Return:      Success:        Message data size in bytes
154
 *              Failure:        0
155
 *
156
 *-------------------------------------------------------------------------
157
 */
158
size_t
159
H5D__layout_meta_size(const H5F_t *f, const H5O_layout_t *layout, bool include_compact_data)
160
0
{
161
0
    size_t ret_value = 0; /* Return value */
162
163
0
    FUNC_ENTER_PACKAGE
164
165
    /* check args */
166
0
    assert(f);
167
0
    assert(layout);
168
169
0
    ret_value = 1 + /* Version number                       */
170
0
                1;  /* layout class type                    */
171
172
0
    switch (layout->type) {
173
0
        case H5D_COMPACT:
174
            /* This information only present in older versions of message */
175
            /* Size of raw data */
176
0
            ret_value += 2;
177
0
            if (include_compact_data)
178
0
                ret_value += layout->storage.u.compact.size; /* data for compact dataset             */
179
0
            break;
180
181
0
        case H5D_CONTIGUOUS:
182
            /* This information only present in older versions of message */
183
0
            ret_value += H5F_SIZEOF_ADDR(f); /* Address of data */
184
0
            ret_value += H5F_SIZEOF_SIZE(f); /* Length of data */
185
0
            break;
186
187
0
        case H5D_CHUNKED:
188
0
            if (layout->version < H5O_LAYOUT_VERSION_4) {
189
                /* Number of dimensions (1 byte) */
190
0
                assert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
191
0
                ret_value++;
192
193
                /* B-tree address */
194
0
                ret_value += H5F_SIZEOF_ADDR(f); /* Address of data */
195
196
                /* Dimension sizes */
197
0
                ret_value += layout->u.chunk.ndims * 4;
198
0
            } /* end if */
199
0
            else {
200
                /* Chunked layout feature flags */
201
0
                ret_value++;
202
203
                /* Number of dimensions (1 byte) */
204
0
                assert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS);
205
0
                ret_value++;
206
207
                /* Encoded # of bytes for each chunk dimension */
208
0
                assert(layout->u.chunk.enc_bytes_per_dim > 0 && layout->u.chunk.enc_bytes_per_dim <= 8);
209
0
                ret_value++;
210
211
                /* Dimension sizes */
212
0
                ret_value += layout->u.chunk.ndims * (size_t)layout->u.chunk.enc_bytes_per_dim;
213
214
                /* Type of chunk index */
215
0
                ret_value++;
216
217
0
                switch (layout->u.chunk.idx_type) {
218
0
                    case H5D_CHUNK_IDX_BTREE:
219
0
                        HGOTO_ERROR(H5E_OHDR, H5E_BADVALUE, 0,
220
0
                                    "v1 B-tree index type found for layout message >v3");
221
222
0
                    case H5D_CHUNK_IDX_NONE:
223
                        /* nothing */
224
0
                        break;
225
226
0
                    case H5D_CHUNK_IDX_SINGLE:
227
                        /* Possible filter information */
228
0
                        if (layout->u.chunk.flags & H5O_LAYOUT_CHUNK_SINGLE_INDEX_WITH_FILTER) {
229
0
                            ret_value += H5F_SIZEOF_SIZE(f); /* Size of chunk (in file) */
230
0
                            ret_value += 4;                  /* Filter mask for chunk */
231
0
                        }                                    /* end if */
232
0
                        break;
233
234
0
                    case H5D_CHUNK_IDX_FARRAY:
235
                        /* Fixed array creation parameters */
236
0
                        ret_value += H5D_FARRAY_CREATE_PARAM_SIZE;
237
0
                        break;
238
239
0
                    case H5D_CHUNK_IDX_EARRAY:
240
                        /* Extensible array creation parameters */
241
0
                        ret_value += H5D_EARRAY_CREATE_PARAM_SIZE;
242
0
                        break;
243
244
0
                    case H5D_CHUNK_IDX_BT2:
245
                        /* v2 B-tree creation parameters */
246
0
                        ret_value += H5D_BT2_CREATE_PARAM_SIZE;
247
0
                        break;
248
249
0
                    case H5D_CHUNK_IDX_NTYPES:
250
0
                    default:
251
0
                        HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, 0, "Invalid chunk index type");
252
0
                } /* end switch */
253
254
                /* Chunk index address */
255
0
                ret_value += H5F_SIZEOF_ADDR(f);
256
0
            } /* end else */
257
0
            break;
258
259
0
        case H5D_VIRTUAL:
260
0
            ret_value += H5F_SIZEOF_ADDR(f); /* Address of global heap */
261
0
            ret_value += 4;                  /* Global heap index */
262
0
            break;
263
264
0
        case H5D_LAYOUT_ERROR:
265
0
        case H5D_NLAYOUTS:
266
0
        default:
267
0
            HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, 0, "Invalid layout class");
268
0
    } /* end switch */
269
270
0
done:
271
0
    FUNC_LEAVE_NOAPI(ret_value)
272
0
} /* end H5D__layout_meta_size() */
273
274
/*-------------------------------------------------------------------------
275
 * Function:    H5D__layout_oh_create
276
 *
277
 * Purpose:     Create layout/pline/efl information for dataset
278
 *
279
 * Return:      Success:    SUCCEED
280
 *              Failure:    FAIL
281
 *
282
 *-------------------------------------------------------------------------
283
 */
284
herr_t
285
H5D__layout_oh_create(H5F_t *file, H5O_t *oh, H5D_t *dset, hid_t dapl_id)
286
0
{
287
0
    H5O_layout_t     *layout;                /* Dataset's layout information */
288
0
    const H5O_fill_t *fill_prop;             /* Pointer to dataset's fill value information */
289
0
    unsigned          layout_mesg_flags;     /* Flags for inserting layout message */
290
0
    bool              layout_init = false;   /* Flag to indicate that chunk information was initialized */
291
0
    herr_t            ret_value   = SUCCEED; /* Return value */
292
293
0
    FUNC_ENTER_PACKAGE_TAG(dset->oloc.addr)
294
295
    /* Sanity checking */
296
0
    assert(file);
297
0
    assert(oh);
298
0
    assert(dset);
299
300
    /* Set some local variables, for convenience */
301
0
    layout    = &dset->shared->layout;
302
0
    fill_prop = &dset->shared->dcpl_cache.fill;
303
304
    /* Update the filters message, if this is a chunked dataset */
305
0
    if (layout->type == H5D_CHUNKED) {
306
0
        H5O_pline_t *pline; /* Dataset's I/O pipeline information */
307
308
0
        pline = &dset->shared->dcpl_cache.pline;
309
0
        if (pline->nused > 0 &&
310
0
            H5O_msg_append_oh(file, oh, H5O_PLINE_ID, H5O_MSG_FLAG_CONSTANT, 0, pline) < 0)
311
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update filter header message");
312
0
    } /* end if */
313
314
    /* Initialize the layout information for the new dataset */
315
0
    if (dset->shared->layout.ops->init && (dset->shared->layout.ops->init)(file, dset, dapl_id, false) < 0)
316
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize layout information");
317
318
    /* Indicate that the layout information was initialized */
319
0
    layout_init = true;
320
321
    /*
322
     * Allocate storage if space allocate time is early; otherwise delay
323
     * allocation until later.
324
     */
325
0
    if (fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY)
326
0
        if (H5D__alloc_storage(dset, H5D_ALLOC_CREATE, false, NULL) < 0)
327
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage");
328
329
    /* Update external storage message, if it's used */
330
0
    if (dset->shared->dcpl_cache.efl.nused > 0) {
331
0
        H5O_efl_t *efl = &dset->shared->dcpl_cache.efl; /* Dataset's external file list */
332
0
        H5HL_t    *heap;                                /* Pointer to local heap for EFL file names */
333
0
        size_t     heap_size = H5HL_ALIGN(1);
334
0
        size_t     u;
335
0
        size_t     name_offset;
336
337
        /* Determine size of heap needed to stored the file names */
338
0
        for (u = 0; u < efl->nused; ++u)
339
0
            heap_size += H5HL_ALIGN(strlen(efl->slot[u].name) + 1);
340
341
        /* Create the heap for the EFL file names */
342
0
        if (H5HL_create(file, heap_size, &efl->heap_addr /*out*/) < 0)
343
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to create EFL file name heap");
344
345
        /* Pin the heap down in memory */
346
0
        if (NULL == (heap = H5HL_protect(file, efl->heap_addr, H5AC__NO_FLAGS_SET)))
347
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTPROTECT, FAIL, "unable to protect EFL file name heap");
348
349
        /* Insert "empty" name first */
350
0
        if (H5HL_insert(file, heap, (size_t)1, "", &name_offset) < 0) {
351
0
            H5HL_unprotect(heap);
352
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert file name into heap");
353
0
        }
354
355
0
        for (u = 0; u < efl->nused; ++u) {
356
            /* Insert file name into heap */
357
0
            if (H5HL_insert(file, heap, strlen(efl->slot[u].name) + 1, efl->slot[u].name, &name_offset) < 0) {
358
0
                H5HL_unprotect(heap);
359
0
                HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert file name into heap");
360
0
            }
361
362
            /* Store EFL file name offset */
363
0
            efl->slot[u].name_offset = name_offset;
364
0
        }
365
366
        /* Release the heap */
367
0
        if (H5HL_unprotect(heap) < 0)
368
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTUNPROTECT, FAIL, "unable to unprotect EFL file name heap");
369
0
        heap = NULL;
370
371
        /* Insert EFL message into dataset object header */
372
0
        if (H5O_msg_append_oh(file, oh, H5O_EFL_ID, H5O_MSG_FLAG_CONSTANT, 0, efl) < 0)
373
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update external file list message");
374
0
    } /* end if */
375
376
    /* Create layout message */
377
    /* (Don't make layout message constant unless allocation time is early and
378
     *  non-filtered and has >0 elements, since space may not be allocated -QAK) */
379
    /* (Note: this is relying on H5D__alloc_storage not calling H5O_msg_write during dataset creation) */
380
0
    if (fill_prop->alloc_time == H5D_ALLOC_TIME_EARLY && H5D_COMPACT != layout->type &&
381
0
        !dset->shared->dcpl_cache.pline.nused && (0 != H5S_GET_EXTENT_NPOINTS(dset->shared->space)))
382
0
        layout_mesg_flags = H5O_MSG_FLAG_CONSTANT;
383
0
    else
384
0
        layout_mesg_flags = 0;
385
386
    /* Store VDS info in global heap */
387
0
    if (H5D_VIRTUAL == layout->type)
388
0
        if (H5D__virtual_store_layout(file, layout) < 0)
389
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to store VDS info");
390
391
    /* Create layout message */
392
0
    if (H5O_msg_append_oh(file, oh, H5O_LAYOUT_ID, layout_mesg_flags, 0, layout) < 0)
393
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update layout");
394
395
0
done:
396
    /* Error cleanup */
397
0
    if (ret_value < 0)
398
0
        if (layout_init)
399
            /* Destroy any cached layout information for the dataset */
400
0
            if (dset->shared->layout.ops->dest && (dset->shared->layout.ops->dest)(dset) < 0)
401
0
                HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to destroy layout info");
402
403
0
    FUNC_LEAVE_NOAPI_TAG(ret_value)
404
0
} /* end H5D__layout_oh_create() */
405
406
/*-------------------------------------------------------------------------
407
 * Function:    H5D__layout_oh_read
408
 *
409
 * Purpose:     Read layout/pline/efl information for dataset
410
 *
411
 * Return:      Success:    SUCCEED
412
 *              Failure:    FAIL
413
 *
414
 *-------------------------------------------------------------------------
415
 */
416
herr_t
417
H5D__layout_oh_read(H5D_t *dataset, hid_t dapl_id, H5P_genplist_t *plist)
418
0
{
419
0
    htri_t msg_exists;                      /* Whether a particular type of message exists */
420
0
    bool   pline_copied          = false;   /* Flag to indicate that dcpl_cache.pline's message was copied */
421
0
    bool   layout_copied_to_dset = false;   /* Flag to indicate that layout message was copied */
422
0
    bool   efl_copied            = false;   /* Flag to indicate that the EFL message was copied */
423
0
    herr_t ret_value             = SUCCEED; /* Return value */
424
425
0
    FUNC_ENTER_PACKAGE
426
427
    /* Sanity checking */
428
0
    assert(dataset);
429
0
    assert(plist);
430
431
    /* Get the optional filters message */
432
0
    if ((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_PLINE_ID)) < 0)
433
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists");
434
0
    if (msg_exists) {
435
        /* Retrieve the I/O pipeline message */
436
0
        if (NULL == H5O_msg_read(&(dataset->oloc), H5O_PLINE_ID, &dataset->shared->dcpl_cache.pline))
437
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message");
438
0
        pline_copied = true;
439
        /* Set the I/O pipeline info in the property list */
440
0
        if (H5P_set(plist, H5O_CRT_PIPELINE_NAME, &dataset->shared->dcpl_cache.pline) < 0)
441
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set pipeline");
442
0
    } /* end if */
443
444
    /*
445
     * Get the raw data layout info.  It's actually stored in two locations:
446
     * the storage message of the dataset (dataset->storage) and certain
447
     * values are copied to the dataset create plist so the user can query
448
     * them.
449
     */
450
0
    if (NULL == H5O_msg_read(&(dataset->oloc), H5O_LAYOUT_ID, &(dataset->shared->layout)))
451
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read data layout message");
452
0
    layout_copied_to_dset = true;
453
454
    /* Check for external file list message (which might not exist) */
455
0
    if ((msg_exists = H5O_msg_exists(&(dataset->oloc), H5O_EFL_ID)) < 0)
456
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't check if message exists");
457
0
    if (msg_exists) {
458
        /* Retrieve the EFL  message */
459
0
        if (NULL == H5O_msg_read(&(dataset->oloc), H5O_EFL_ID, &dataset->shared->dcpl_cache.efl))
460
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve message");
461
0
        efl_copied = true;
462
463
        /* Set the EFL info in the property list */
464
0
        if (H5P_set(plist, H5D_CRT_EXT_FILE_LIST_NAME, &dataset->shared->dcpl_cache.efl) < 0)
465
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set external file list");
466
467
        /* Set the dataset's I/O operations */
468
0
        dataset->shared->layout.ops = H5D_LOPS_EFL;
469
0
    } /* end if */
470
471
    /* Sanity check that the layout operations are set up */
472
0
    assert(dataset->shared->layout.ops);
473
474
    /* Initialize the layout information for the dataset */
475
0
    if (dataset->shared->layout.ops->init &&
476
0
        (dataset->shared->layout.ops->init)(dataset->oloc.file, dataset, dapl_id, true) < 0)
477
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize layout information");
478
479
#ifndef NDEBUG
480
    /* Set invalid layout to detect erroneous usage */
481
    H5O_layout_t error_layout;
482
    error_layout.type         = H5D_LAYOUT_ERROR;
483
    error_layout.version      = 0;
484
    error_layout.ops          = NULL;
485
    error_layout.storage.type = H5D_LAYOUT_ERROR;
486
487
    if (H5P_poke(plist, H5D_CRT_LAYOUT_NAME, &error_layout) < 0)
488
        HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "unable to setup placeholder layout");
489
#endif
490
491
0
done:
492
0
    if (ret_value < 0) {
493
0
        if (pline_copied)
494
0
            if (H5O_msg_reset(H5O_PLINE_ID, &dataset->shared->dcpl_cache.pline) < 0)
495
0
                HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset pipeline info");
496
0
        if (layout_copied_to_dset)
497
0
            if (H5O_msg_reset(H5O_LAYOUT_ID, &dataset->shared->layout) < 0)
498
0
                HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset layout info");
499
0
        if (efl_copied)
500
0
            if (H5O_msg_reset(H5O_EFL_ID, &dataset->shared->dcpl_cache.efl) < 0)
501
0
                HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset efl message");
502
0
    }
503
0
    FUNC_LEAVE_NOAPI(ret_value)
504
0
} /* end H5D__layout_oh_read() */
505
506
/*-------------------------------------------------------------------------
507
 * Function:    H5D__layout_oh_write
508
 *
509
 * Purpose:     Write layout information for dataset
510
 *
511
 * Return:      Success:    SUCCEED
512
 *              Failure:    FAIL
513
 *
514
 *-------------------------------------------------------------------------
515
 */
516
herr_t
517
H5D__layout_oh_write(const H5D_t *dataset, H5O_t *oh, unsigned update_flags)
518
0
{
519
0
    htri_t msg_exists;          /* Whether the layout message exists */
520
0
    herr_t ret_value = SUCCEED; /* Return value */
521
522
0
    FUNC_ENTER_PACKAGE
523
524
    /* Sanity checking */
525
0
    assert(dataset);
526
0
    assert(oh);
527
528
    /* Check if the layout message has been added to the dataset's header */
529
0
    if ((msg_exists = H5O_msg_exists_oh(oh, H5O_LAYOUT_ID)) < 0)
530
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to check if layout message exists");
531
0
    if (msg_exists) {
532
        /* Write the layout message to the dataset's header */
533
0
        if (H5O_msg_write_oh(dataset->oloc.file, oh, H5O_LAYOUT_ID, 0, update_flags,
534
0
                             &dataset->shared->layout) < 0)
535
0
            HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to update layout message");
536
0
    } /* end if */
537
538
0
done:
539
0
    FUNC_LEAVE_NOAPI(ret_value)
540
0
} /* end H5D__layout_oh_write() */