Coverage Report

Created: 2026-09-04 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hdf5/src/H5Defl.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 "H5Fprivate.h"  /* Files                                    */
26
#include "H5HLprivate.h" /* Local Heaps                              */
27
#include "H5MMprivate.h" /* Memory management                        */
28
#include "H5VMprivate.h" /* Vector and array functions               */
29
30
/****************/
31
/* Local Macros */
32
/****************/
33
34
/******************/
35
/* Local Typedefs */
36
/******************/
37
38
/* Callback info for readvv operation */
39
typedef struct H5D_efl_readvv_ud_t {
40
    const H5O_efl_t *efl;  /* Pointer to efl info */
41
    const H5D_t     *dset; /* The dataset */
42
    unsigned char   *rbuf; /* Read buffer */
43
} H5D_efl_readvv_ud_t;
44
45
/* Callback info for writevv operation */
46
typedef struct H5D_efl_writevv_ud_t {
47
    const H5O_efl_t     *efl;  /* Pointer to efl info */
48
    const H5D_t         *dset; /* The dataset */
49
    const unsigned char *wbuf; /* Write buffer */
50
} H5D_efl_writevv_ud_t;
51
52
/********************/
53
/* Local Prototypes */
54
/********************/
55
56
/* Layout operation callbacks */
57
static herr_t  H5D__efl_construct(H5F_t *f, H5D_t *dset);
58
static herr_t  H5D__efl_init(H5F_t *f, H5D_t *dset, hid_t dapl_id, bool open_op);
59
static herr_t  H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo);
60
static ssize_t H5D__efl_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
61
                               size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[],
62
                               hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
63
                               size_t mem_len_arr[], hsize_t mem_offset_arr[]);
64
static ssize_t H5D__efl_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info,
65
                                size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[],
66
                                hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
67
                                size_t mem_len_arr[], hsize_t mem_offset_arr[]);
68
69
/* Helper routines */
70
static herr_t H5D__efl_read(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size, uint8_t *buf);
71
static herr_t H5D__efl_write(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size,
72
                             const uint8_t *buf);
73
74
/*********************/
75
/* Package Variables */
76
/*********************/
77
78
/* External File List (EFL) storage layout I/O ops */
79
const H5D_layout_ops_t H5D_LOPS_EFL[1] = {{
80
    H5D__efl_construct,      /* construct */
81
    H5D__efl_init,           /* init */
82
    H5D__efl_is_space_alloc, /* is_space_alloc */
83
    NULL,                    /* is_data_cached */
84
    H5D__efl_io_init,        /* io_init */
85
    NULL,                    /* mdio_init */
86
    H5D__contig_read,        /* ser_read */
87
    H5D__contig_write,       /* ser_write */
88
    H5D__efl_readvv,         /* readvv */
89
    H5D__efl_writevv,        /* writevv */
90
    NULL,                    /* flush */
91
    NULL,                    /* io_term */
92
    NULL                     /* dest */
93
}};
94
95
/*******************/
96
/* Local Variables */
97
/*******************/
98
99
/*-------------------------------------------------------------------------
100
 * Function:  H5D__efl_construct
101
 *
102
 * Purpose: Constructs new EFL layout information for dataset
103
 *
104
 * Return:  Non-negative on success/Negative on failure
105
 *
106
 *-------------------------------------------------------------------------
107
 */
108
static herr_t
109
H5D__efl_construct(H5F_t *f, H5D_t *dset)
110
0
{
111
0
    size_t   dt_size;             /* Size of datatype */
112
0
    hssize_t stmp_size;           /* Temporary holder for raw data size */
113
0
    hsize_t  tmp_size;            /* Temporary holder for raw data size */
114
0
    hsize_t  max_points;          /* Maximum elements */
115
0
    hsize_t  max_storage;         /* Maximum storage size */
116
0
    unsigned u;                   /* Local index variable */
117
0
    herr_t   ret_value = SUCCEED; /* Return value */
118
119
0
    FUNC_ENTER_PACKAGE
120
121
    /* Sanity checks */
122
0
    assert(f);
123
0
    assert(dset);
124
125
    /*
126
     * The maximum size of the dataset cannot exceed the storage size.
127
     * Also, only the slowest varying dimension of a simple dataspace
128
     * can be extendible (currently only for external data storage).
129
     */
130
131
    /* Check for invalid dataset dimensions */
132
0
    for (u = 1; u < dset->shared->ndims; u++)
133
0
        if (dset->shared->max_dims[u] > dset->shared->curr_dims[u])
134
0
            HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "only the first dimension can be extendible");
135
136
    /* Retrieve the size of the dataset's datatype */
137
0
    if (0 == (dt_size = H5T_get_size(dset->shared->type)))
138
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size");
139
140
    /* Check for storage overflows */
141
0
    max_points = H5S_get_npoints_max(dset->shared->space);
142
0
    if (H5O_efl_total_size(&dset->shared->dcpl_cache.efl, &max_storage) < 0)
143
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of external file");
144
0
    if (H5S_UNLIMITED == max_points) {
145
0
        if (H5O_EFL_UNLIMITED != max_storage)
146
0
            HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unlimited dataspace but finite storage");
147
0
    } /* end if */
148
0
    else if ((max_points * dt_size) < max_points)
149
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "dataspace * type size overflowed");
150
0
    else if ((max_points * dt_size) > max_storage)
151
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "dataspace size exceeds external storage size");
152
153
    /* Compute the total size of dataset */
154
0
    if ((stmp_size = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0)
155
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace");
156
0
    tmp_size = (hsize_t)stmp_size * dt_size;
157
0
    H5_CHECKED_ASSIGN(dset->shared->layout.storage.u.contig.size, hsize_t, tmp_size, hssize_t);
158
159
    /* Get the sieve buffer size for this dataset - the smaller of the dataset size and
160
     * the sieve buffer size from the FAPL is used
161
     */
162
0
    dset->shared->cache.sieve.sieve_buf_size =
163
0
        MIN(dset->shared->layout.storage.u.contig.size, H5F_SIEVE_BUF_SIZE(f));
164
165
0
done:
166
0
    FUNC_LEAVE_NOAPI(ret_value)
167
0
} /* end H5D__efl_construct() */
168
169
/*-------------------------------------------------------------------------
170
 * Function:  H5D__efl_init
171
 *
172
 * Purpose: Initialize the info for a EFL dataset.  This is
173
 *    called when the dataset is initialized.
174
 *
175
 * Return:  Non-negative on success/Negative on failure
176
 *
177
 *-------------------------------------------------------------------------
178
 */
179
static herr_t
180
H5D__efl_init(H5F_t H5_ATTR_UNUSED *f, H5D_t *dset, hid_t H5_ATTR_UNUSED dapl_id, bool H5_ATTR_UNUSED open_op)
181
0
{
182
0
    size_t   dt_size;             /* Size of datatype */
183
0
    hssize_t snelmts;             /* Temporary holder for number of elements in dataspace */
184
0
    hsize_t  nelmts;              /* Number of elements in dataspace */
185
0
    hsize_t  data_size;           /* Raw data size */
186
0
    hsize_t  max_storage;         /* Maximum storage size */
187
0
    herr_t   ret_value = SUCCEED; /* Return value */
188
189
0
    FUNC_ENTER_PACKAGE
190
191
    /* Sanity check */
192
0
    assert(dset);
193
194
    /* Retrieve the size of the dataset's datatype */
195
0
    if (0 == (dt_size = H5T_get_size(dset->shared->type)))
196
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size");
197
198
    /* Retrieve the number of elements in the dataspace */
199
0
    if ((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0)
200
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace");
201
0
    nelmts = (hsize_t)snelmts;
202
203
    /* Compute the size of the dataset's contiguous storage */
204
0
    data_size = nelmts * dt_size;
205
206
    /* Check for overflow during multiplication */
207
0
    if (nelmts != (data_size / dt_size))
208
0
        HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed");
209
210
    /* Check for storage overflows */
211
0
    if (H5O_efl_total_size(&dset->shared->dcpl_cache.efl, &max_storage) < 0)
212
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of external file");
213
0
    if (H5O_EFL_UNLIMITED != max_storage && data_size > max_storage)
214
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "dataspace size exceeds external storage size");
215
216
0
done:
217
0
    FUNC_LEAVE_NOAPI(ret_value)
218
0
} /* end H5D__efl_init() */
219
220
/*-------------------------------------------------------------------------
221
 * Function:  H5D__efl_is_space_alloc
222
 *
223
 * Purpose: Query if space is allocated for layout
224
 *
225
 * Return:  Non-negative on success/Negative on failure
226
 *
227
 *-------------------------------------------------------------------------
228
 */
229
bool
230
H5D__efl_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage)
231
0
{
232
0
    FUNC_ENTER_PACKAGE_NOERR
233
234
    /* Sanity checks */
235
0
    assert(storage);
236
237
    /* EFL storage is currently always treated as allocated */
238
0
    FUNC_LEAVE_NOAPI(true)
239
0
} /* end H5D__efl_is_space_alloc() */
240
241
/*-------------------------------------------------------------------------
242
 * Function:  H5D__efl_io_init
243
 *
244
 * Purpose: Performs initialization before any sort of I/O on the raw data
245
 *
246
 * Return:  Non-negative on success/Negative on failure
247
 *
248
 *-------------------------------------------------------------------------
249
 */
250
static herr_t
251
H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo)
252
0
{
253
0
    FUNC_ENTER_PACKAGE_NOERR
254
255
0
    H5MM_memcpy(&dinfo->store->efl, &(dinfo->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t));
256
257
    /* No "pieces" selected */
258
0
    dinfo->layout_io_info.contig_piece_info = NULL;
259
260
    /* Disable selection I/O */
261
0
    io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF;
262
0
    io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET;
263
264
0
    FUNC_LEAVE_NOAPI(SUCCEED)
265
0
} /* end H5D__efl_io_init() */
266
267
/*-------------------------------------------------------------------------
268
 * Function:    H5D__efl_read
269
 *
270
 * Purpose:     Reads data from an external file list.  It is an error to
271
 *              read past the logical end of file, but reading past the end
272
 *              of any particular member of the external file list results in
273
 *              zeros.
274
 *
275
 * Return:      SUCCEED/FAIL
276
 *
277
 *-------------------------------------------------------------------------
278
 */
279
static herr_t
280
H5D__efl_read(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size, uint8_t *buf)
281
0
{
282
0
    int    fd = -1;
283
0
    size_t to_read;
284
0
    size_t left_to_read;
285
#ifndef NDEBUG
286
    hsize_t tempto_read;
287
#endif /* NDEBUG */
288
0
    hsize_t skip = 0;
289
0
    haddr_t cur;
290
0
    size_t  u;                   /* Local index variable */
291
0
    char   *full_name = NULL;    /* File name with prefix */
292
0
    herr_t  ret_value = SUCCEED; /* Return value */
293
294
0
    FUNC_ENTER_PACKAGE
295
296
    /* Check args */
297
0
    assert(efl && efl->nused > 0);
298
0
    assert(H5_addr_defined(addr));
299
0
    assert(size < SIZE_MAX);
300
0
    assert(buf || 0 == size);
301
302
    /* Find the first efl member from which to read */
303
0
    for (u = 0, cur = 0; u < efl->nused; u++) {
304
0
        if (H5O_EFL_UNLIMITED == efl->slot[u].size || addr < cur + efl->slot[u].size) {
305
0
            skip = addr - cur;
306
0
            break;
307
0
        } /* end if */
308
0
        cur += efl->slot[u].size;
309
0
    } /* end for */
310
311
    /* Read the data */
312
0
    while (size) {
313
0
        assert(buf);
314
0
        if (u >= efl->nused)
315
0
            HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "read past logical end of file");
316
0
        if (H5F_OVERFLOW_HSIZET2OFFT((hsize_t)efl->slot[u].offset + skip))
317
0
            HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "external file address overflowed");
318
0
        if (H5_combine_path(dset->shared->extfile_prefix, efl->slot[u].name, &full_name) < 0)
319
0
            HGOTO_ERROR(H5E_EFL, H5E_NOSPACE, FAIL, "can't build external file name");
320
0
        if ((fd = HDopen(full_name, O_RDONLY)) < 0)
321
0
            HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "unable to open external raw data file");
322
0
        if (HDlseek(fd, (HDoff_t)(efl->slot[u].offset + (HDoff_t)skip), SEEK_SET) < 0)
323
0
            HGOTO_ERROR(H5E_EFL, H5E_SEEKERROR, FAIL, "unable to seek in external raw data file");
324
#ifndef NDEBUG
325
        tempto_read = MIN((size_t)(efl->slot[u].size - skip), (hsize_t)size);
326
        H5_CHECK_OVERFLOW(tempto_read, hsize_t, size_t);
327
        to_read = (size_t)tempto_read;
328
#else  /* NDEBUG */
329
0
        to_read = MIN((size_t)(efl->slot[u].size - skip), (hsize_t)size);
330
0
#endif /* NDEBUG */
331
332
        /* Inner loop - read to_read bytes from a single external file */
333
0
        left_to_read = to_read;
334
0
        while (left_to_read > 0) {
335
0
            h5_posix_io_t     bytes_in   = 0;  /* # of bytes to read       */
336
0
            h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */
337
338
            /* Trying to read more bytes than the return type can handle is
339
             * undefined behavior in POSIX.
340
             */
341
0
            if (left_to_read > H5_POSIX_MAX_IO_BYTES)
342
0
                bytes_in = H5_POSIX_MAX_IO_BYTES;
343
0
            else
344
0
                bytes_in = (h5_posix_io_t)left_to_read;
345
346
0
            do {
347
0
                bytes_read = HDread(fd, buf, bytes_in);
348
0
            } while (-1 == bytes_read && EINTR == errno);
349
350
0
            if (bytes_read < 0)
351
0
                HGOTO_ERROR(H5E_EFL, H5E_READERROR, FAIL, "read error in external raw data file");
352
353
0
            if (0 == bytes_read) {
354
                /* End of file on disk, fill the remaining sectors to be read from this file with 0 */
355
0
                memset(buf, 0, left_to_read);
356
0
                bytes_read = (h5_posix_io_ret_t)left_to_read;
357
0
            } /* end if */
358
359
0
            left_to_read -= (size_t)bytes_read;
360
0
            buf += bytes_read;
361
0
        }
362
363
        /* Prepare to advance to next external file */
364
0
        full_name = (char *)H5MM_xfree(full_name);
365
0
        HDclose(fd);
366
0
        fd = -1;
367
0
        size -= to_read;
368
0
        skip = 0;
369
0
        u++;
370
0
    } /* end while */
371
372
0
done:
373
0
    if (full_name)
374
0
        full_name = (char *)H5MM_xfree(full_name);
375
0
    if (fd >= 0)
376
0
        HDclose(fd);
377
378
0
    FUNC_LEAVE_NOAPI(ret_value)
379
0
} /* end H5D__efl_read() */
380
381
/*-------------------------------------------------------------------------
382
 * Function:  H5D__efl_write
383
 *
384
 * Purpose: Writes data to an external file list.  It is an error to
385
 *    write past the logical end of file, but writing past the end
386
 *    of any particular member of the external file list just
387
 *    extends that file.
388
 *
389
 * Return:  Non-negative on success/Negative on failure
390
 *
391
 *-------------------------------------------------------------------------
392
 */
393
static herr_t
394
H5D__efl_write(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size, const uint8_t *buf)
395
0
{
396
0
    int    fd = -1;
397
0
    size_t to_write;
398
0
    size_t left_to_write;
399
#ifndef NDEBUG
400
    hsize_t tempto_write;
401
#endif /* NDEBUG */
402
0
    haddr_t cur;
403
0
    hsize_t skip = 0;
404
0
    size_t  u;                   /* Local index variable */
405
0
    char   *full_name = NULL;    /* File name with prefix */
406
0
    herr_t  ret_value = SUCCEED; /* Return value */
407
408
0
    FUNC_ENTER_PACKAGE
409
410
    /* Check args */
411
0
    assert(efl && efl->nused > 0);
412
0
    assert(H5_addr_defined(addr));
413
0
    assert(size < SIZE_MAX);
414
0
    assert(buf || 0 == size);
415
416
    /* Find the first efl member in which to write */
417
0
    for (u = 0, cur = 0; u < efl->nused; u++) {
418
0
        if (H5O_EFL_UNLIMITED == efl->slot[u].size || addr < cur + efl->slot[u].size) {
419
0
            skip = addr - cur;
420
0
            break;
421
0
        } /* end if */
422
0
        cur += efl->slot[u].size;
423
0
    } /* end for */
424
425
    /* Write the data */
426
0
    while (size) {
427
0
        assert(buf);
428
0
        if (u >= efl->nused)
429
0
            HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "write past logical end of file");
430
0
        if (H5F_OVERFLOW_HSIZET2OFFT((hsize_t)efl->slot[u].offset + skip))
431
0
            HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "external file address overflowed");
432
0
        if (H5_combine_path(dset->shared->extfile_prefix, efl->slot[u].name, &full_name) < 0)
433
0
            HGOTO_ERROR(H5E_EFL, H5E_NOSPACE, FAIL, "can't build external file name");
434
0
        if ((fd = HDopen(full_name, O_CREAT | O_RDWR, H5_POSIX_CREATE_MODE_RW)) < 0) {
435
0
            if (HDaccess(full_name, F_OK) < 0)
436
0
                HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "external raw data file does not exist");
437
0
            else
438
0
                HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "unable to open external raw data file");
439
0
        } /* end if */
440
0
        if (HDlseek(fd, (HDoff_t)(efl->slot[u].offset + (HDoff_t)skip), SEEK_SET) < 0)
441
0
            HGOTO_ERROR(H5E_EFL, H5E_SEEKERROR, FAIL, "unable to seek in external raw data file");
442
#ifndef NDEBUG
443
        tempto_write = MIN(efl->slot[u].size - skip, (hsize_t)size);
444
        H5_CHECK_OVERFLOW(tempto_write, hsize_t, size_t);
445
        to_write = (size_t)tempto_write;
446
#else  /* NDEBUG */
447
0
        to_write = MIN((size_t)(efl->slot[u].size - skip), size);
448
0
#endif /* NDEBUG */
449
450
        /* Inner loop - write to_write bytes to a single external file */
451
0
        left_to_write = to_write;
452
0
        while (left_to_write > 0) {
453
0
            h5_posix_io_t     bytes_in    = 0;  /* # of bytes to write         */
454
0
            h5_posix_io_ret_t bytes_wrote = -1; /* # of bytes actually written */
455
456
            /* Trying to write more bytes than the return type can handle is
457
             * undefined behavior in POSIX.
458
             */
459
0
            if (left_to_write > H5_POSIX_MAX_IO_BYTES)
460
0
                bytes_in = H5_POSIX_MAX_IO_BYTES;
461
0
            else
462
0
                bytes_in = (h5_posix_io_t)left_to_write;
463
464
0
            do {
465
0
                bytes_wrote = HDwrite(fd, buf, bytes_in);
466
0
            } while (-1 == bytes_wrote && EINTR == errno);
467
468
0
            if (bytes_wrote < 0)
469
0
                HGOTO_ERROR(H5E_EFL, H5E_WRITEERROR, FAIL, "write error in external raw data file");
470
0
            if (bytes_wrote == 0)
471
0
                HGOTO_ERROR(H5E_EFL, H5E_WRITEERROR, FAIL, "wrote 0 bytes to external raw data file");
472
473
0
            left_to_write -= (size_t)bytes_wrote;
474
0
            buf += bytes_wrote;
475
0
        }
476
477
        /* Prepare to advance to next external file */
478
0
        full_name = (char *)H5MM_xfree(full_name);
479
0
        HDclose(fd);
480
0
        fd = -1;
481
0
        size -= to_write;
482
0
        skip = 0;
483
0
        u++;
484
0
    } /* end while */
485
486
0
done:
487
0
    if (full_name)
488
0
        full_name = (char *)H5MM_xfree(full_name);
489
0
    if (fd >= 0)
490
0
        HDclose(fd);
491
492
0
    FUNC_LEAVE_NOAPI(ret_value)
493
0
} /* end H5D__efl_write() */
494
495
/*-------------------------------------------------------------------------
496
 * Function:  H5D__efl_readvv_cb
497
 *
498
 * Purpose: Callback operator for H5D__efl_readvv().
499
 *
500
 * Return:  Non-negative on success/Negative on failure
501
 *
502
 *-------------------------------------------------------------------------
503
 */
504
static herr_t
505
H5D__efl_readvv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
506
0
{
507
0
    H5D_efl_readvv_ud_t *udata     = (H5D_efl_readvv_ud_t *)_udata; /* User data for H5VM_opvv() operator */
508
0
    herr_t               ret_value = SUCCEED;                       /* Return value */
509
510
0
    FUNC_ENTER_PACKAGE
511
512
    /* Read data */
513
0
    if (H5D__efl_read(udata->efl, udata->dset, dst_off, len, (udata->rbuf + src_off)) < 0)
514
0
        HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "EFL read failed");
515
516
0
done:
517
0
    FUNC_LEAVE_NOAPI(ret_value)
518
0
} /* end H5D__efl_readvv_cb() */
519
520
/*-------------------------------------------------------------------------
521
 * Function:  H5D__efl_readvv
522
 *
523
 * Purpose: Reads data from an external file list.  It is an error to
524
 *    read past the logical end of file, but reading past the end
525
 *    of any particular member of the external file list results in
526
 *    zeros.
527
 *
528
 * Return:  Non-negative on success/Negative on failure
529
 *
530
 *-------------------------------------------------------------------------
531
 */
532
static ssize_t
533
H5D__efl_readvv(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_dset_io_info_t *dset_info,
534
                size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[],
535
                size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
536
0
{
537
0
    H5D_efl_readvv_ud_t udata;          /* User data for H5VM_opvv() operator */
538
0
    ssize_t             ret_value = -1; /* Return value (Total size of sequence in bytes) */
539
540
0
    FUNC_ENTER_PACKAGE
541
542
    /* Check args */
543
0
    assert(io_info);
544
0
    assert(dset_info);
545
0
    assert(dset_info->store->efl.nused > 0);
546
0
    assert(dset_info->buf.vp);
547
0
    assert(dset_info->dset);
548
0
    assert(dset_info->dset->shared);
549
0
    assert(dset_curr_seq);
550
0
    assert(dset_len_arr);
551
0
    assert(dset_off_arr);
552
0
    assert(mem_curr_seq);
553
0
    assert(mem_len_arr);
554
0
    assert(mem_off_arr);
555
556
    /* Set up user data for H5VM_opvv() */
557
0
    udata.efl  = &(dset_info->store->efl);
558
0
    udata.dset = dset_info->dset;
559
0
    udata.rbuf = (unsigned char *)dset_info->buf.vp;
560
561
    /* Call generic sequence operation routine */
562
0
    if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
563
0
                               mem_curr_seq, mem_len_arr, mem_off_arr, H5D__efl_readvv_cb, &udata)) < 0)
564
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized EFL read");
565
566
0
done:
567
0
    FUNC_LEAVE_NOAPI(ret_value)
568
0
} /* end H5D__efl_readvv() */
569
570
/*-------------------------------------------------------------------------
571
 * Function:  H5D__efl_writevv_cb
572
 *
573
 * Purpose: Callback operator for H5D__efl_writevv().
574
 *
575
 * Return:  Non-negative on success/Negative on failure
576
 *
577
 *-------------------------------------------------------------------------
578
 */
579
static herr_t
580
H5D__efl_writevv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
581
0
{
582
0
    H5D_efl_writevv_ud_t *udata     = (H5D_efl_writevv_ud_t *)_udata; /* User data for H5VM_opvv() operator */
583
0
    herr_t                ret_value = SUCCEED;                        /* Return value */
584
585
0
    FUNC_ENTER_PACKAGE
586
587
    /* Write data */
588
0
    if (H5D__efl_write(udata->efl, udata->dset, dst_off, len, (udata->wbuf + src_off)) < 0)
589
0
        HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "EFL write failed");
590
591
0
done:
592
0
    FUNC_LEAVE_NOAPI(ret_value)
593
0
} /* end H5D__efl_writevv_cb() */
594
595
/*-------------------------------------------------------------------------
596
 * Function:  H5D__efl_writevv
597
 *
598
 * Purpose: Writes data to an external file list.  It is an error to
599
 *    write past the logical end of file, but writing past the end
600
 *    of any particular member of the external file list just
601
 *    extends that file.
602
 *
603
 * Return:  Non-negative on success/Negative on failure
604
 *
605
 *-------------------------------------------------------------------------
606
 */
607
static ssize_t
608
H5D__efl_writevv(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_dset_io_info_t *dset_info,
609
                 size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[],
610
                 size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[])
611
0
{
612
0
    H5D_efl_writevv_ud_t udata;          /* User data for H5VM_opvv() operator */
613
0
    ssize_t              ret_value = -1; /* Return value (Total size of sequence in bytes) */
614
615
0
    FUNC_ENTER_PACKAGE
616
617
    /* Check args */
618
0
    assert(io_info);
619
0
    assert(dset_info);
620
0
    assert(dset_info->store->efl.nused > 0);
621
0
    assert(dset_info->buf.cvp);
622
0
    assert(dset_info->dset);
623
0
    assert(dset_info->dset->shared);
624
0
    assert(dset_curr_seq);
625
0
    assert(dset_len_arr);
626
0
    assert(dset_off_arr);
627
0
    assert(mem_curr_seq);
628
0
    assert(mem_len_arr);
629
0
    assert(mem_off_arr);
630
631
    /* Set up user data for H5VM_opvv() */
632
0
    udata.efl  = &(dset_info->store->efl);
633
0
    udata.dset = dset_info->dset;
634
0
    udata.wbuf = (const unsigned char *)dset_info->buf.cvp;
635
636
    /* Call generic sequence operation routine */
637
0
    if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
638
0
                               mem_curr_seq, mem_len_arr, mem_off_arr, H5D__efl_writevv_cb, &udata)) < 0)
639
0
        HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized EFL write");
640
0
done:
641
0
    FUNC_LEAVE_NOAPI(ret_value)
642
0
} /* end H5D__efl_writevv() */
643
644
/*-------------------------------------------------------------------------
645
 * Function:    H5D__efl_bh_info
646
 *
647
 * Purpose:     Retrieve the amount of heap storage used for External File
648
 *    List message
649
 *
650
 * Return:      Success:        Non-negative
651
 *              Failure:        negative
652
 *
653
 *-------------------------------------------------------------------------
654
 */
655
herr_t
656
H5D__efl_bh_info(H5F_t *f, H5O_efl_t *efl, hsize_t *heap_size)
657
0
{
658
0
    herr_t ret_value = SUCCEED; /* Return value */
659
660
0
    FUNC_ENTER_PACKAGE
661
662
    /* Check args */
663
0
    assert(f);
664
0
    assert(efl);
665
0
    assert(H5_addr_defined(efl->heap_addr));
666
0
    assert(heap_size);
667
668
    /* Get the size of the local heap for EFL's file list */
669
0
    if (H5HL_heapsize(f, efl->heap_addr, heap_size) < 0)
670
0
        HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, FAIL, "unable to retrieve local heap info");
671
672
0
done:
673
0
    FUNC_LEAVE_NOAPI(ret_value)
674
0
} /* end H5D__efl_bh_info() */