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() */ |