Line | Count | Source (jump to first uncovered line) |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /****************/ |
14 | | /* 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, const H5D_t *dset, hid_t dapl_id); |
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 */ |
160 | 0 | dset->shared->cache.contig.sieve_buf_size = H5F_SIEVE_BUF_SIZE(f); |
161 | |
|
162 | 0 | done: |
163 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
164 | 0 | } /* end H5D__efl_construct() */ |
165 | | |
166 | | /*------------------------------------------------------------------------- |
167 | | * Function: H5D__efl_init |
168 | | * |
169 | | * Purpose: Initialize the info for a EFL dataset. This is |
170 | | * called when the dataset is initialized. |
171 | | * |
172 | | * Return: Non-negative on success/Negative on failure |
173 | | * |
174 | | *------------------------------------------------------------------------- |
175 | | */ |
176 | | static herr_t |
177 | | H5D__efl_init(H5F_t H5_ATTR_UNUSED *f, const H5D_t *dset, hid_t H5_ATTR_UNUSED dapl_id) |
178 | 0 | { |
179 | 0 | size_t dt_size; /* Size of datatype */ |
180 | 0 | hssize_t snelmts; /* Temporary holder for number of elements in dataspace */ |
181 | 0 | hsize_t nelmts; /* Number of elements in dataspace */ |
182 | 0 | hsize_t data_size; /* Raw data size */ |
183 | 0 | hsize_t max_storage; /* Maximum storage size */ |
184 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
185 | |
|
186 | 0 | FUNC_ENTER_PACKAGE |
187 | | |
188 | | /* Sanity check */ |
189 | 0 | assert(dset); |
190 | | |
191 | | /* Retrieve the size of the dataset's datatype */ |
192 | 0 | if (0 == (dt_size = H5T_get_size(dset->shared->type))) |
193 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size"); |
194 | | |
195 | | /* Retrieve the number of elements in the dataspace */ |
196 | 0 | if ((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0) |
197 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace"); |
198 | 0 | nelmts = (hsize_t)snelmts; |
199 | | |
200 | | /* Compute the size of the dataset's contiguous storage */ |
201 | 0 | data_size = nelmts * dt_size; |
202 | | |
203 | | /* Check for overflow during multiplication */ |
204 | 0 | if (nelmts != (data_size / dt_size)) |
205 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed"); |
206 | | |
207 | | /* Check for storage overflows */ |
208 | 0 | if (H5O_efl_total_size(&dset->shared->dcpl_cache.efl, &max_storage) < 0) |
209 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of external file"); |
210 | 0 | if (H5O_EFL_UNLIMITED != max_storage && data_size > max_storage) |
211 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "dataspace size exceeds external storage size"); |
212 | | |
213 | 0 | done: |
214 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
215 | 0 | } /* end H5D__efl_init() */ |
216 | | |
217 | | /*------------------------------------------------------------------------- |
218 | | * Function: H5D__efl_is_space_alloc |
219 | | * |
220 | | * Purpose: Query if space is allocated for layout |
221 | | * |
222 | | * Return: Non-negative on success/Negative on failure |
223 | | * |
224 | | *------------------------------------------------------------------------- |
225 | | */ |
226 | | bool |
227 | | H5D__efl_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage) |
228 | 0 | { |
229 | 0 | FUNC_ENTER_PACKAGE_NOERR |
230 | | |
231 | | /* Sanity checks */ |
232 | 0 | assert(storage); |
233 | | |
234 | | /* EFL storage is currently always treated as allocated */ |
235 | 0 | FUNC_LEAVE_NOAPI(true) |
236 | 0 | } /* end H5D__efl_is_space_alloc() */ |
237 | | |
238 | | /*------------------------------------------------------------------------- |
239 | | * Function: H5D__efl_io_init |
240 | | * |
241 | | * Purpose: Performs initialization before any sort of I/O on the raw data |
242 | | * |
243 | | * Return: Non-negative on success/Negative on failure |
244 | | * |
245 | | *------------------------------------------------------------------------- |
246 | | */ |
247 | | static herr_t |
248 | | H5D__efl_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) |
249 | 0 | { |
250 | 0 | FUNC_ENTER_PACKAGE_NOERR |
251 | |
|
252 | 0 | H5MM_memcpy(&dinfo->store->efl, &(dinfo->dset->shared->dcpl_cache.efl), sizeof(H5O_efl_t)); |
253 | | |
254 | | /* No "pieces" selected */ |
255 | 0 | dinfo->layout_io_info.contig_piece_info = NULL; |
256 | | |
257 | | /* Disable selection I/O */ |
258 | 0 | io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; |
259 | 0 | io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; |
260 | |
|
261 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
262 | 0 | } /* end H5D__efl_io_init() */ |
263 | | |
264 | | /*------------------------------------------------------------------------- |
265 | | * Function: H5D__efl_read |
266 | | * |
267 | | * Purpose: Reads data from an external file list. It is an error to |
268 | | * read past the logical end of file, but reading past the end |
269 | | * of any particular member of the external file list results in |
270 | | * zeros. |
271 | | * |
272 | | * Return: SUCCEED/FAIL |
273 | | * |
274 | | *------------------------------------------------------------------------- |
275 | | */ |
276 | | static herr_t |
277 | | H5D__efl_read(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size, uint8_t *buf) |
278 | 0 | { |
279 | 0 | int fd = -1; |
280 | 0 | size_t to_read; |
281 | 0 | size_t left_to_read; |
282 | | #ifndef NDEBUG |
283 | | hsize_t tempto_read; |
284 | | #endif /* NDEBUG */ |
285 | 0 | hsize_t skip = 0; |
286 | 0 | haddr_t cur; |
287 | 0 | size_t u; /* Local index variable */ |
288 | 0 | char *full_name = NULL; /* File name with prefix */ |
289 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
290 | |
|
291 | 0 | FUNC_ENTER_PACKAGE |
292 | | |
293 | | /* Check args */ |
294 | 0 | assert(efl && efl->nused > 0); |
295 | 0 | assert(H5_addr_defined(addr)); |
296 | 0 | assert(size < SIZE_MAX); |
297 | 0 | assert(buf || 0 == size); |
298 | | |
299 | | /* Find the first efl member from which to read */ |
300 | 0 | for (u = 0, cur = 0; u < efl->nused; u++) { |
301 | 0 | if (H5O_EFL_UNLIMITED == efl->slot[u].size || addr < cur + efl->slot[u].size) { |
302 | 0 | skip = addr - cur; |
303 | 0 | break; |
304 | 0 | } /* end if */ |
305 | 0 | cur += efl->slot[u].size; |
306 | 0 | } /* end for */ |
307 | | |
308 | | /* Read the data */ |
309 | 0 | while (size) { |
310 | 0 | assert(buf); |
311 | 0 | if (u >= efl->nused) |
312 | 0 | HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "read past logical end of file"); |
313 | 0 | if (H5F_OVERFLOW_HSIZET2OFFT((hsize_t)efl->slot[u].offset + skip)) |
314 | 0 | HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "external file address overflowed"); |
315 | 0 | if (H5_combine_path(dset->shared->extfile_prefix, efl->slot[u].name, &full_name) < 0) |
316 | 0 | HGOTO_ERROR(H5E_EFL, H5E_NOSPACE, FAIL, "can't build external file name"); |
317 | 0 | if ((fd = HDopen(full_name, O_RDONLY)) < 0) |
318 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "unable to open external raw data file"); |
319 | 0 | if (HDlseek(fd, (HDoff_t)(efl->slot[u].offset + (HDoff_t)skip), SEEK_SET) < 0) |
320 | 0 | HGOTO_ERROR(H5E_EFL, H5E_SEEKERROR, FAIL, "unable to seek in external raw data file"); |
321 | | #ifndef NDEBUG |
322 | | tempto_read = MIN((size_t)(efl->slot[u].size - skip), (hsize_t)size); |
323 | | H5_CHECK_OVERFLOW(tempto_read, hsize_t, size_t); |
324 | | to_read = (size_t)tempto_read; |
325 | | #else /* NDEBUG */ |
326 | 0 | to_read = MIN((size_t)(efl->slot[u].size - skip), (hsize_t)size); |
327 | 0 | #endif /* NDEBUG */ |
328 | | |
329 | | /* Inner loop - read to_read bytes from a single external file */ |
330 | 0 | left_to_read = to_read; |
331 | 0 | while (left_to_read > 0) { |
332 | 0 | h5_posix_io_t bytes_in = 0; /* # of bytes to read */ |
333 | 0 | h5_posix_io_ret_t bytes_read = -1; /* # of bytes actually read */ |
334 | | |
335 | | /* Trying to read more bytes than the return type can handle is |
336 | | * undefined behavior in POSIX. |
337 | | */ |
338 | 0 | if (left_to_read > H5_POSIX_MAX_IO_BYTES) |
339 | 0 | bytes_in = H5_POSIX_MAX_IO_BYTES; |
340 | 0 | else |
341 | 0 | bytes_in = (h5_posix_io_t)left_to_read; |
342 | |
|
343 | 0 | do { |
344 | 0 | bytes_read = HDread(fd, buf, bytes_in); |
345 | 0 | } while (-1 == bytes_read && EINTR == errno); |
346 | |
|
347 | 0 | if (bytes_read < 0) |
348 | 0 | HGOTO_ERROR(H5E_EFL, H5E_READERROR, FAIL, "read error in external raw data file"); |
349 | | |
350 | 0 | if (0 == bytes_read) { |
351 | | /* End of file on disk, fill the remaining sectors to be read from this file with 0 */ |
352 | 0 | memset(buf, 0, left_to_read); |
353 | 0 | bytes_read = (h5_posix_io_ret_t)left_to_read; |
354 | 0 | } /* end if */ |
355 | |
|
356 | 0 | left_to_read -= (size_t)bytes_read; |
357 | 0 | buf += bytes_read; |
358 | 0 | } |
359 | | |
360 | | /* Prepare to advance to next external file */ |
361 | 0 | full_name = (char *)H5MM_xfree(full_name); |
362 | 0 | HDclose(fd); |
363 | 0 | fd = -1; |
364 | 0 | size -= to_read; |
365 | 0 | skip = 0; |
366 | 0 | u++; |
367 | 0 | } /* end while */ |
368 | | |
369 | 0 | done: |
370 | 0 | if (full_name) |
371 | 0 | full_name = (char *)H5MM_xfree(full_name); |
372 | 0 | if (fd >= 0) |
373 | 0 | HDclose(fd); |
374 | |
|
375 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
376 | 0 | } /* end H5D__efl_read() */ |
377 | | |
378 | | /*------------------------------------------------------------------------- |
379 | | * Function: H5D__efl_write |
380 | | * |
381 | | * Purpose: Writes data to an external file list. It is an error to |
382 | | * write past the logical end of file, but writing past the end |
383 | | * of any particular member of the external file list just |
384 | | * extends that file. |
385 | | * |
386 | | * Return: Non-negative on success/Negative on failure |
387 | | * |
388 | | *------------------------------------------------------------------------- |
389 | | */ |
390 | | static herr_t |
391 | | H5D__efl_write(const H5O_efl_t *efl, const H5D_t *dset, haddr_t addr, size_t size, const uint8_t *buf) |
392 | 0 | { |
393 | 0 | int fd = -1; |
394 | 0 | size_t to_write; |
395 | 0 | size_t left_to_write; |
396 | | #ifndef NDEBUG |
397 | | hsize_t tempto_write; |
398 | | #endif /* NDEBUG */ |
399 | 0 | haddr_t cur; |
400 | 0 | hsize_t skip = 0; |
401 | 0 | size_t u; /* Local index variable */ |
402 | 0 | char *full_name = NULL; /* File name with prefix */ |
403 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
404 | |
|
405 | 0 | FUNC_ENTER_PACKAGE |
406 | | |
407 | | /* Check args */ |
408 | 0 | assert(efl && efl->nused > 0); |
409 | 0 | assert(H5_addr_defined(addr)); |
410 | 0 | assert(size < SIZE_MAX); |
411 | 0 | assert(buf || 0 == size); |
412 | | |
413 | | /* Find the first efl member in which to write */ |
414 | 0 | for (u = 0, cur = 0; u < efl->nused; u++) { |
415 | 0 | if (H5O_EFL_UNLIMITED == efl->slot[u].size || addr < cur + efl->slot[u].size) { |
416 | 0 | skip = addr - cur; |
417 | 0 | break; |
418 | 0 | } /* end if */ |
419 | 0 | cur += efl->slot[u].size; |
420 | 0 | } /* end for */ |
421 | | |
422 | | /* Write the data */ |
423 | 0 | while (size) { |
424 | 0 | assert(buf); |
425 | 0 | if (u >= efl->nused) |
426 | 0 | HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "write past logical end of file"); |
427 | 0 | if (H5F_OVERFLOW_HSIZET2OFFT((hsize_t)efl->slot[u].offset + skip)) |
428 | 0 | HGOTO_ERROR(H5E_EFL, H5E_OVERFLOW, FAIL, "external file address overflowed"); |
429 | 0 | if (H5_combine_path(dset->shared->extfile_prefix, efl->slot[u].name, &full_name) < 0) |
430 | 0 | HGOTO_ERROR(H5E_EFL, H5E_NOSPACE, FAIL, "can't build external file name"); |
431 | 0 | if ((fd = HDopen(full_name, O_CREAT | O_RDWR, H5_POSIX_CREATE_MODE_RW)) < 0) { |
432 | 0 | if (HDaccess(full_name, F_OK) < 0) |
433 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "external raw data file does not exist"); |
434 | 0 | else |
435 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTOPENFILE, FAIL, "unable to open external raw data file"); |
436 | 0 | } /* end if */ |
437 | 0 | if (HDlseek(fd, (HDoff_t)(efl->slot[u].offset + (HDoff_t)skip), SEEK_SET) < 0) |
438 | 0 | HGOTO_ERROR(H5E_EFL, H5E_SEEKERROR, FAIL, "unable to seek in external raw data file"); |
439 | | #ifndef NDEBUG |
440 | | tempto_write = MIN(efl->slot[u].size - skip, (hsize_t)size); |
441 | | H5_CHECK_OVERFLOW(tempto_write, hsize_t, size_t); |
442 | | to_write = (size_t)tempto_write; |
443 | | #else /* NDEBUG */ |
444 | 0 | to_write = MIN((size_t)(efl->slot[u].size - skip), size); |
445 | 0 | #endif /* NDEBUG */ |
446 | | |
447 | | /* Inner loop - write to_write bytes to a single external file */ |
448 | 0 | left_to_write = to_write; |
449 | 0 | while (left_to_write > 0) { |
450 | 0 | h5_posix_io_t bytes_in = 0; /* # of bytes to write */ |
451 | 0 | h5_posix_io_ret_t bytes_wrote = -1; /* # of bytes actually written */ |
452 | | |
453 | | /* Trying to write more bytes than the return type can handle is |
454 | | * undefined behavior in POSIX. |
455 | | */ |
456 | 0 | if (left_to_write > H5_POSIX_MAX_IO_BYTES) |
457 | 0 | bytes_in = H5_POSIX_MAX_IO_BYTES; |
458 | 0 | else |
459 | 0 | bytes_in = (h5_posix_io_t)left_to_write; |
460 | |
|
461 | 0 | do { |
462 | 0 | bytes_wrote = HDwrite(fd, buf, bytes_in); |
463 | 0 | } while (-1 == bytes_wrote && EINTR == errno); |
464 | |
|
465 | 0 | if (bytes_wrote < 0) |
466 | 0 | HGOTO_ERROR(H5E_EFL, H5E_WRITEERROR, FAIL, "write error in external raw data file"); |
467 | 0 | if (bytes_wrote == 0) |
468 | 0 | HGOTO_ERROR(H5E_EFL, H5E_WRITEERROR, FAIL, "wrote 0 bytes to external raw data file"); |
469 | | |
470 | 0 | left_to_write -= (size_t)bytes_wrote; |
471 | 0 | buf += bytes_wrote; |
472 | 0 | } |
473 | | |
474 | | /* Prepare to advance to next external file */ |
475 | 0 | full_name = (char *)H5MM_xfree(full_name); |
476 | 0 | HDclose(fd); |
477 | 0 | fd = -1; |
478 | 0 | size -= to_write; |
479 | 0 | skip = 0; |
480 | 0 | u++; |
481 | 0 | } /* end while */ |
482 | | |
483 | 0 | done: |
484 | 0 | if (full_name) |
485 | 0 | full_name = (char *)H5MM_xfree(full_name); |
486 | 0 | if (fd >= 0) |
487 | 0 | HDclose(fd); |
488 | |
|
489 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
490 | 0 | } /* end H5D__efl_write() */ |
491 | | |
492 | | /*------------------------------------------------------------------------- |
493 | | * Function: H5D__efl_readvv_cb |
494 | | * |
495 | | * Purpose: Callback operator for H5D__efl_readvv(). |
496 | | * |
497 | | * Return: Non-negative on success/Negative on failure |
498 | | * |
499 | | *------------------------------------------------------------------------- |
500 | | */ |
501 | | static herr_t |
502 | | H5D__efl_readvv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) |
503 | 0 | { |
504 | 0 | H5D_efl_readvv_ud_t *udata = (H5D_efl_readvv_ud_t *)_udata; /* User data for H5VM_opvv() operator */ |
505 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
506 | |
|
507 | 0 | FUNC_ENTER_PACKAGE |
508 | | |
509 | | /* Read data */ |
510 | 0 | if (H5D__efl_read(udata->efl, udata->dset, dst_off, len, (udata->rbuf + src_off)) < 0) |
511 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "EFL read failed"); |
512 | | |
513 | 0 | done: |
514 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
515 | 0 | } /* end H5D__efl_readvv_cb() */ |
516 | | |
517 | | /*------------------------------------------------------------------------- |
518 | | * Function: H5D__efl_readvv |
519 | | * |
520 | | * Purpose: Reads data from an external file list. It is an error to |
521 | | * read past the logical end of file, but reading past the end |
522 | | * of any particular member of the external file list results in |
523 | | * zeros. |
524 | | * |
525 | | * Return: Non-negative on success/Negative on failure |
526 | | * |
527 | | *------------------------------------------------------------------------- |
528 | | */ |
529 | | static ssize_t |
530 | | H5D__efl_readvv(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_dset_io_info_t *dset_info, |
531 | | size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[], |
532 | | size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[]) |
533 | 0 | { |
534 | 0 | H5D_efl_readvv_ud_t udata; /* User data for H5VM_opvv() operator */ |
535 | 0 | ssize_t ret_value = -1; /* Return value (Total size of sequence in bytes) */ |
536 | |
|
537 | 0 | FUNC_ENTER_PACKAGE |
538 | | |
539 | | /* Check args */ |
540 | 0 | assert(io_info); |
541 | 0 | assert(dset_info); |
542 | 0 | assert(dset_info->store->efl.nused > 0); |
543 | 0 | assert(dset_info->buf.vp); |
544 | 0 | assert(dset_info->dset); |
545 | 0 | assert(dset_info->dset->shared); |
546 | 0 | assert(dset_curr_seq); |
547 | 0 | assert(dset_len_arr); |
548 | 0 | assert(dset_off_arr); |
549 | 0 | assert(mem_curr_seq); |
550 | 0 | assert(mem_len_arr); |
551 | 0 | assert(mem_off_arr); |
552 | | |
553 | | /* Set up user data for H5VM_opvv() */ |
554 | 0 | udata.efl = &(dset_info->store->efl); |
555 | 0 | udata.dset = dset_info->dset; |
556 | 0 | udata.rbuf = (unsigned char *)dset_info->buf.vp; |
557 | | |
558 | | /* Call generic sequence operation routine */ |
559 | 0 | if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq, |
560 | 0 | mem_curr_seq, mem_len_arr, mem_off_arr, H5D__efl_readvv_cb, &udata)) < 0) |
561 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized EFL read"); |
562 | | |
563 | 0 | done: |
564 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
565 | 0 | } /* end H5D__efl_readvv() */ |
566 | | |
567 | | /*------------------------------------------------------------------------- |
568 | | * Function: H5D__efl_writevv_cb |
569 | | * |
570 | | * Purpose: Callback operator for H5D__efl_writevv(). |
571 | | * |
572 | | * Return: Non-negative on success/Negative on failure |
573 | | * |
574 | | *------------------------------------------------------------------------- |
575 | | */ |
576 | | static herr_t |
577 | | H5D__efl_writevv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) |
578 | 0 | { |
579 | 0 | H5D_efl_writevv_ud_t *udata = (H5D_efl_writevv_ud_t *)_udata; /* User data for H5VM_opvv() operator */ |
580 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
581 | |
|
582 | 0 | FUNC_ENTER_PACKAGE |
583 | | |
584 | | /* Write data */ |
585 | 0 | if (H5D__efl_write(udata->efl, udata->dset, dst_off, len, (udata->wbuf + src_off)) < 0) |
586 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "EFL write failed"); |
587 | | |
588 | 0 | done: |
589 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
590 | 0 | } /* end H5D__efl_writevv_cb() */ |
591 | | |
592 | | /*------------------------------------------------------------------------- |
593 | | * Function: H5D__efl_writevv |
594 | | * |
595 | | * Purpose: Writes data to an external file list. It is an error to |
596 | | * write past the logical end of file, but writing past the end |
597 | | * of any particular member of the external file list just |
598 | | * extends that file. |
599 | | * |
600 | | * Return: Non-negative on success/Negative on failure |
601 | | * |
602 | | *------------------------------------------------------------------------- |
603 | | */ |
604 | | static ssize_t |
605 | | H5D__efl_writevv(const H5D_io_info_t H5_ATTR_NDEBUG_UNUSED *io_info, const H5D_dset_io_info_t *dset_info, |
606 | | size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_off_arr[], |
607 | | size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_off_arr[]) |
608 | 0 | { |
609 | 0 | H5D_efl_writevv_ud_t udata; /* User data for H5VM_opvv() operator */ |
610 | 0 | ssize_t ret_value = -1; /* Return value (Total size of sequence in bytes) */ |
611 | |
|
612 | 0 | FUNC_ENTER_PACKAGE |
613 | | |
614 | | /* Check args */ |
615 | 0 | assert(io_info); |
616 | 0 | assert(dset_info); |
617 | 0 | assert(dset_info->store->efl.nused > 0); |
618 | 0 | assert(dset_info->buf.cvp); |
619 | 0 | assert(dset_info->dset); |
620 | 0 | assert(dset_info->dset->shared); |
621 | 0 | assert(dset_curr_seq); |
622 | 0 | assert(dset_len_arr); |
623 | 0 | assert(dset_off_arr); |
624 | 0 | assert(mem_curr_seq); |
625 | 0 | assert(mem_len_arr); |
626 | 0 | assert(mem_off_arr); |
627 | | |
628 | | /* Set up user data for H5VM_opvv() */ |
629 | 0 | udata.efl = &(dset_info->store->efl); |
630 | 0 | udata.dset = dset_info->dset; |
631 | 0 | udata.wbuf = (const unsigned char *)dset_info->buf.cvp; |
632 | | |
633 | | /* Call generic sequence operation routine */ |
634 | 0 | if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq, |
635 | 0 | mem_curr_seq, mem_len_arr, mem_off_arr, H5D__efl_writevv_cb, &udata)) < 0) |
636 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized EFL write"); |
637 | 0 | done: |
638 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
639 | 0 | } /* end H5D__efl_writevv() */ |
640 | | |
641 | | /*------------------------------------------------------------------------- |
642 | | * Function: H5D__efl_bh_info |
643 | | * |
644 | | * Purpose: Retrieve the amount of heap storage used for External File |
645 | | * List message |
646 | | * |
647 | | * Return: Success: Non-negative |
648 | | * Failure: negative |
649 | | * |
650 | | *------------------------------------------------------------------------- |
651 | | */ |
652 | | herr_t |
653 | | H5D__efl_bh_info(H5F_t *f, H5O_efl_t *efl, hsize_t *heap_size) |
654 | 0 | { |
655 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
656 | |
|
657 | 0 | FUNC_ENTER_PACKAGE |
658 | | |
659 | | /* Check args */ |
660 | 0 | assert(f); |
661 | 0 | assert(efl); |
662 | 0 | assert(H5_addr_defined(efl->heap_addr)); |
663 | 0 | assert(heap_size); |
664 | | |
665 | | /* Get the size of the local heap for EFL's file list */ |
666 | 0 | if (H5HL_heapsize(f, efl->heap_addr, heap_size) < 0) |
667 | 0 | HGOTO_ERROR(H5E_EFL, H5E_CANTINIT, FAIL, "unable to retrieve local heap info"); |
668 | | |
669 | 0 | done: |
670 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
671 | 0 | } /* end H5D__efl_bh_info() */ |