/src/hdf5/src/H5Dcompact.c
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 COPYING 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 | | * Purpose: Compact dataset I/O functions. These routines are similar |
15 | | * H5D_contig_* and H5D_chunk_*. |
16 | | */ |
17 | | |
18 | | /****************/ |
19 | | /* Module Setup */ |
20 | | /****************/ |
21 | | |
22 | | #include "H5Dmodule.h" /* This source code file is part of the H5D module */ |
23 | | |
24 | | /***********/ |
25 | | /* Headers */ |
26 | | /***********/ |
27 | | #include "H5private.h" /* Generic Functions */ |
28 | | #include "H5Dpkg.h" /* Dataset functions */ |
29 | | #include "H5Eprivate.h" /* Error handling */ |
30 | | #include "H5Fprivate.h" /* Files */ |
31 | | #include "H5FDprivate.h" /* File drivers */ |
32 | | #include "H5FLprivate.h" /* Free Lists */ |
33 | | #include "H5Iprivate.h" /* IDs */ |
34 | | #include "H5MMprivate.h" /* Memory management */ |
35 | | #include "H5Oprivate.h" /* Object headers */ |
36 | | #include "H5VMprivate.h" /* Vector and array functions */ |
37 | | |
38 | | /****************/ |
39 | | /* Local Macros */ |
40 | | /****************/ |
41 | | |
42 | | /******************/ |
43 | | /* Local Typedefs */ |
44 | | /******************/ |
45 | | |
46 | | /* Callback info for I/O operation when file driver |
47 | | * wishes to do its own memory management |
48 | | */ |
49 | | typedef struct H5D_compact_iovv_memmanage_ud_t { |
50 | | H5F_shared_t *f_sh; /* Shared file for dataset */ |
51 | | void *dstbuf; /* Pointer to buffer to be read into/written into */ |
52 | | const void *srcbuf; /* Pointer to buffer to be read from/written from */ |
53 | | } H5D_compact_iovv_memmanage_ud_t; |
54 | | |
55 | | /********************/ |
56 | | /* Local Prototypes */ |
57 | | /********************/ |
58 | | |
59 | | /* Layout operation callbacks */ |
60 | | static herr_t H5D__compact_construct(H5F_t *f, H5D_t *dset); |
61 | | static herr_t H5D__compact_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id); |
62 | | static bool H5D__compact_is_space_alloc(const H5O_storage_t *storage); |
63 | | static herr_t H5D__compact_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo); |
64 | | static herr_t H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata); |
65 | | static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, |
66 | | size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], |
67 | | hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, |
68 | | size_t mem_size_arr[], hsize_t mem_offset_arr[]); |
69 | | static ssize_t H5D__compact_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, |
70 | | size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], |
71 | | hsize_t dset_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, |
72 | | size_t mem_size_arr[], hsize_t mem_offset_arr[]); |
73 | | static herr_t H5D__compact_flush(H5D_t *dset); |
74 | | static herr_t H5D__compact_dest(H5D_t *dset); |
75 | | |
76 | | /*********************/ |
77 | | /* Package Variables */ |
78 | | /*********************/ |
79 | | |
80 | | /* Compact storage layout I/O ops */ |
81 | | const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{ |
82 | | H5D__compact_construct, /* construct */ |
83 | | H5D__compact_init, /* init */ |
84 | | H5D__compact_is_space_alloc, /* is_space_alloc */ |
85 | | NULL, /* is_data_cached */ |
86 | | H5D__compact_io_init, /* io_init */ |
87 | | NULL, /* mdio_init */ |
88 | | H5D__contig_read, /* ser_read */ |
89 | | H5D__contig_write, /* ser_write */ |
90 | | H5D__compact_readvv, /* readvv */ |
91 | | H5D__compact_writevv, /* writevv */ |
92 | | H5D__compact_flush, /* flush */ |
93 | | NULL, /* io_term */ |
94 | | H5D__compact_dest /* dest */ |
95 | | }}; |
96 | | |
97 | | /*******************/ |
98 | | /* Local Variables */ |
99 | | /*******************/ |
100 | | |
101 | | /* Declare extern the free list to manage blocks of type conversion data */ |
102 | | H5FL_BLK_EXTERN(type_conv); |
103 | | |
104 | | /*------------------------------------------------------------------------- |
105 | | * Function: H5D__compact_fill |
106 | | * |
107 | | * Purpose: Write fill values to a compactly stored dataset. |
108 | | * |
109 | | * Return: Non-negative on success/Negative on failure |
110 | | * |
111 | | *------------------------------------------------------------------------- |
112 | | */ |
113 | | herr_t |
114 | | H5D__compact_fill(const H5D_t *dset) |
115 | 0 | { |
116 | 0 | H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */ |
117 | 0 | bool fb_info_init = false; /* Whether the fill value buffer has been initialized */ |
118 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
119 | |
|
120 | 0 | FUNC_ENTER_PACKAGE |
121 | | |
122 | | /* Check args */ |
123 | 0 | assert(dset && H5D_COMPACT == dset->shared->layout.type); |
124 | 0 | assert(dset->shared->layout.storage.u.compact.buf); |
125 | 0 | assert(dset->shared->type); |
126 | 0 | assert(dset->shared->space); |
127 | | |
128 | | /* Initialize the fill value buffer */ |
129 | | /* (use the compact dataset storage buffer as the fill value buffer) */ |
130 | 0 | if (H5D__fill_init(&fb_info, dset->shared->layout.storage.u.compact.buf, NULL, NULL, NULL, NULL, |
131 | 0 | &dset->shared->dcpl_cache.fill, dset->shared->type, (size_t)0, |
132 | 0 | dset->shared->layout.storage.u.compact.size) < 0) |
133 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info"); |
134 | 0 | fb_info_init = true; |
135 | | |
136 | | /* Check for VL datatype & non-default fill value */ |
137 | 0 | if (fb_info.has_vlen_fill_type) |
138 | | /* Fill the buffer with VL datatype fill values */ |
139 | 0 | if (H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf) < 0) |
140 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer"); |
141 | | |
142 | 0 | done: |
143 | | /* Release the fill buffer info, if it's been initialized */ |
144 | 0 | if (fb_info_init && H5D__fill_term(&fb_info) < 0) |
145 | 0 | HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info"); |
146 | |
|
147 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
148 | 0 | } /* end H5D__compact_fill() */ |
149 | | |
150 | | /*------------------------------------------------------------------------- |
151 | | * Function: H5D__compact_construct |
152 | | * |
153 | | * Purpose: Constructs new compact layout information for dataset |
154 | | * |
155 | | * Return: Non-negative on success/Negative on failure |
156 | | * |
157 | | *------------------------------------------------------------------------- |
158 | | */ |
159 | | static herr_t |
160 | | H5D__compact_construct(H5F_t *f, H5D_t *dset) |
161 | 0 | { |
162 | 0 | hssize_t stmp_size; /* Temporary holder for raw data size */ |
163 | 0 | hsize_t tmp_size; /* Temporary holder for raw data size */ |
164 | 0 | hsize_t max_comp_data_size; /* Max. allowed size of compact data */ |
165 | 0 | unsigned u; /* Local index variable */ |
166 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
167 | |
|
168 | 0 | FUNC_ENTER_PACKAGE |
169 | | |
170 | | /* Sanity checks */ |
171 | 0 | assert(f); |
172 | 0 | assert(dset); |
173 | | |
174 | | /* Check for invalid dataset dimensions */ |
175 | 0 | for (u = 0; u < dset->shared->ndims; u++) |
176 | 0 | if (dset->shared->max_dims[u] > dset->shared->curr_dims[u]) |
177 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible compact dataset not allowed"); |
178 | | |
179 | | /* |
180 | | * Compact dataset is stored in dataset object header message of |
181 | | * layout. |
182 | | */ |
183 | 0 | stmp_size = H5S_GET_EXTENT_NPOINTS(dset->shared->space); |
184 | 0 | assert(stmp_size >= 0); |
185 | 0 | tmp_size = H5T_get_size(dset->shared->type); |
186 | 0 | assert(tmp_size > 0); |
187 | 0 | tmp_size = tmp_size * (hsize_t)stmp_size; |
188 | 0 | H5_CHECKED_ASSIGN(dset->shared->layout.storage.u.compact.size, size_t, tmp_size, hssize_t); |
189 | | |
190 | | /* Verify data size is smaller than maximum header message size |
191 | | * (64KB) minus other layout message fields. |
192 | | */ |
193 | 0 | max_comp_data_size = H5O_MESG_MAX_SIZE - H5D__layout_meta_size(f, &(dset->shared->layout), false); |
194 | 0 | if (dset->shared->layout.storage.u.compact.size > max_comp_data_size) |
195 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, |
196 | 0 | "compact dataset size is bigger than header message maximum size"); |
197 | | |
198 | 0 | done: |
199 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
200 | 0 | } /* end H5D__compact_construct() */ |
201 | | |
202 | | /*------------------------------------------------------------------------- |
203 | | * Function: H5D__compact_init |
204 | | * |
205 | | * Purpose: Initialize the info for a compact dataset. This is |
206 | | * called when the dataset is initialized. |
207 | | * |
208 | | * Return: Non-negative on success/Negative on failure |
209 | | * |
210 | | *------------------------------------------------------------------------- |
211 | | */ |
212 | | static herr_t |
213 | | H5D__compact_init(H5F_t H5_ATTR_UNUSED *f, const H5D_t *dset, hid_t H5_ATTR_UNUSED dapl_id) |
214 | 52 | { |
215 | 52 | hssize_t snelmts; /* Temporary holder for number of elements in dataspace */ |
216 | 52 | hsize_t nelmts; /* Number of elements in dataspace */ |
217 | 52 | size_t dt_size; /* Size of datatype */ |
218 | 52 | hsize_t data_size; /* Dataset size, in bytes */ |
219 | 52 | herr_t ret_value = SUCCEED; /* Return value */ |
220 | | |
221 | 52 | FUNC_ENTER_PACKAGE |
222 | | |
223 | | /* Sanity check */ |
224 | 52 | assert(dset); |
225 | 52 | assert(H5D_COMPACT == dset->shared->layout.storage.type); |
226 | | |
227 | | /* |
228 | | * Now that we've read the dataset's datatype, dataspace and |
229 | | * layout information, perform a quick check for compact datasets |
230 | | * to ensure that the size of the internal buffer that was |
231 | | * allocated for the dataset's raw data matches the size of |
232 | | * the data. A corrupted file can cause a mismatch between the |
233 | | * two, which might result in buffer overflows during future |
234 | | * I/O to the dataset. |
235 | | */ |
236 | 52 | if (0 == (dt_size = H5T_GET_SIZE(dset->shared->type))) |
237 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get datatype size"); |
238 | 52 | if ((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0) |
239 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get number of elements in dataset's dataspace"); |
240 | 52 | nelmts = (hsize_t)snelmts; |
241 | | |
242 | | /* Compute the size of the dataset's contiguous storage */ |
243 | 52 | data_size = nelmts * dt_size; |
244 | | |
245 | | /* Check for overflow during multiplication */ |
246 | 52 | if (nelmts != (data_size / dt_size)) |
247 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed"); |
248 | | |
249 | | /* Check for mismatch */ |
250 | 52 | if (dset->shared->layout.storage.u.compact.size != data_size) |
251 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, |
252 | 52 | "bad value from dataset header - size of compact dataset's data buffer doesn't match " |
253 | 52 | "size of dataset data"); |
254 | | |
255 | 52 | done: |
256 | 52 | FUNC_LEAVE_NOAPI(ret_value) |
257 | 52 | } /* end H5D__compact_init() */ |
258 | | |
259 | | /*------------------------------------------------------------------------- |
260 | | * Function: H5D__compact_is_space_alloc |
261 | | * |
262 | | * Purpose: Query if space is allocated for layout |
263 | | * |
264 | | * Return: Non-negative on success/Negative on failure |
265 | | * |
266 | | *------------------------------------------------------------------------- |
267 | | */ |
268 | | static bool |
269 | | H5D__compact_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage) |
270 | 31 | { |
271 | 31 | FUNC_ENTER_PACKAGE_NOERR |
272 | | |
273 | | /* Sanity checks */ |
274 | 31 | assert(storage); |
275 | | |
276 | | /* Compact storage is currently always allocated */ |
277 | 31 | FUNC_LEAVE_NOAPI(true) |
278 | 31 | } /* end H5D__compact_is_space_alloc() */ |
279 | | |
280 | | /*------------------------------------------------------------------------- |
281 | | * Function: H5D__compact_io_init |
282 | | * |
283 | | * Purpose: Performs initialization before any sort of I/O on the raw data |
284 | | * |
285 | | * Return: Non-negative on success/Negative on failure |
286 | | * |
287 | | *------------------------------------------------------------------------- |
288 | | */ |
289 | | static herr_t |
290 | | H5D__compact_io_init(H5D_io_info_t *io_info, H5D_dset_io_info_t *dinfo) |
291 | 31 | { |
292 | 31 | FUNC_ENTER_PACKAGE_NOERR |
293 | | |
294 | 31 | dinfo->store->compact.buf = dinfo->dset->shared->layout.storage.u.compact.buf; |
295 | 31 | dinfo->store->compact.dirty = &dinfo->dset->shared->layout.storage.u.compact.dirty; |
296 | 31 | dinfo->layout_io_info.contig_piece_info = NULL; |
297 | | |
298 | | /* Disable selection I/O */ |
299 | 31 | io_info->use_select_io = H5D_SELECTION_IO_MODE_OFF; |
300 | 31 | io_info->no_selection_io_cause |= H5D_SEL_IO_NOT_CONTIGUOUS_OR_CHUNKED_DATASET; |
301 | | |
302 | 31 | FUNC_LEAVE_NOAPI(SUCCEED) |
303 | 31 | } /* end H5D__compact_io_init() */ |
304 | | |
305 | | /*------------------------------------------------------------------------- |
306 | | * Function: H5D__compact_iovv_memmanage_cb |
307 | | * |
308 | | * Purpose: Callback operator for H5D__compact_readvv()/_writevv() to |
309 | | * send a memory copy request to the underlying file driver. |
310 | | * |
311 | | * Return: Non-negative on success/Negative on failure |
312 | | * |
313 | | *------------------------------------------------------------------------- |
314 | | */ |
315 | | static herr_t |
316 | | H5D__compact_iovv_memmanage_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata) |
317 | 0 | { |
318 | 0 | H5D_compact_iovv_memmanage_ud_t *udata = (H5D_compact_iovv_memmanage_ud_t *)_udata; |
319 | 0 | H5FD_ctl_memcpy_args_t op_args; |
320 | 0 | uint64_t op_flags; |
321 | 0 | H5FD_t *file_handle = NULL; |
322 | 0 | herr_t ret_value = SUCCEED; |
323 | |
|
324 | 0 | FUNC_ENTER_PACKAGE |
325 | | |
326 | | /* Retrieve pointer to file driver structure for ctl call */ |
327 | 0 | if (H5F_shared_get_file_driver(udata->f_sh, &file_handle) < 0) |
328 | 0 | HGOTO_ERROR(H5E_IO, H5E_CANTGET, FAIL, "can't get file handle"); |
329 | | |
330 | | /* Setup operation flags and arguments */ |
331 | 0 | op_flags = H5FD_CTL_ROUTE_TO_TERMINAL_VFD_FLAG | H5FD_CTL_FAIL_IF_UNKNOWN_FLAG; |
332 | |
|
333 | 0 | op_args.dstbuf = udata->dstbuf; |
334 | 0 | op_args.dst_off = dst_off; |
335 | 0 | op_args.srcbuf = udata->srcbuf; |
336 | 0 | op_args.src_off = src_off; |
337 | 0 | op_args.len = len; |
338 | | |
339 | | /* Make request to file driver */ |
340 | 0 | if (H5FD_ctl(file_handle, H5FD_CTL_MEM_COPY, op_flags, &op_args, NULL) < 0) |
341 | 0 | HGOTO_ERROR(H5E_IO, H5E_FCNTL, FAIL, "VFD memcpy request failed"); |
342 | | |
343 | 0 | done: |
344 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
345 | 0 | } /* end H5D__compact_iovv_memmanage_cb() */ |
346 | | |
347 | | /*------------------------------------------------------------------------- |
348 | | * Function: H5D__compact_readvv |
349 | | * |
350 | | * Purpose: Reads some data vectors from a dataset into a buffer. |
351 | | * The data is in compact dataset. The address is relative |
352 | | * to the beginning address of the dataset. The offsets and |
353 | | * sequence lengths are in bytes. |
354 | | * |
355 | | * Return: Non-negative on success/Negative on failure |
356 | | * |
357 | | * Notes: |
358 | | * Offsets in the sequences must be monotonically increasing |
359 | | * |
360 | | *------------------------------------------------------------------------- |
361 | | */ |
362 | | static ssize_t |
363 | | H5D__compact_readvv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq, |
364 | | size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], |
365 | | size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], |
366 | | hsize_t mem_offset_arr[]) |
367 | 31 | { |
368 | 31 | ssize_t ret_value = -1; /* Return value */ |
369 | | |
370 | 31 | FUNC_ENTER_PACKAGE |
371 | | |
372 | 31 | assert(io_info); |
373 | 31 | assert(dset_info); |
374 | | |
375 | | /* Check if file driver wishes to do its own memory management */ |
376 | 31 | if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) { |
377 | 0 | H5D_compact_iovv_memmanage_ud_t udata; |
378 | | |
379 | | /* Set up udata for memory copy operation */ |
380 | 0 | udata.f_sh = io_info->f_sh; |
381 | 0 | udata.dstbuf = dset_info->buf.vp; |
382 | 0 | udata.srcbuf = dset_info->store->compact.buf; |
383 | | |
384 | | /* Request that file driver does the memory copy */ |
385 | 0 | if ((ret_value = H5VM_opvv(mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, dset_max_nseq, |
386 | 0 | dset_curr_seq, dset_size_arr, dset_offset_arr, |
387 | 0 | H5D__compact_iovv_memmanage_cb, &udata)) < 0) |
388 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed"); |
389 | 0 | } |
390 | 31 | else { |
391 | | /* Use the vectorized memory copy routine to do actual work */ |
392 | 31 | if ((ret_value = H5VM_memcpyvv(dset_info->buf.vp, mem_max_nseq, mem_curr_seq, mem_size_arr, |
393 | 31 | mem_offset_arr, dset_info->store->compact.buf, dset_max_nseq, |
394 | 31 | dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0) |
395 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed"); |
396 | 31 | } |
397 | | |
398 | 31 | done: |
399 | 31 | FUNC_LEAVE_NOAPI(ret_value) |
400 | 31 | } /* end H5D__compact_readvv() */ |
401 | | |
402 | | /*------------------------------------------------------------------------- |
403 | | * Function: H5D__compact_writevv |
404 | | * |
405 | | * Purpose: Writes some data vectors from a dataset into a buffer. |
406 | | * The data is in compact dataset. The address is relative |
407 | | * to the beginning address for the file. The offsets and |
408 | | * sequence lengths are in bytes. This function only copies |
409 | | * data into the buffer in the LAYOUT struct and mark it |
410 | | * as DIRTY. Later in H5D_close, the data is copied into |
411 | | * header message in memory. |
412 | | * |
413 | | * Return: Non-negative on success/Negative on failure |
414 | | * |
415 | | * Notes: |
416 | | * Offsets in the sequences must be monotonically increasing |
417 | | * |
418 | | *------------------------------------------------------------------------- |
419 | | */ |
420 | | static ssize_t |
421 | | H5D__compact_writevv(const H5D_io_info_t *io_info, const H5D_dset_io_info_t *dset_info, size_t dset_max_nseq, |
422 | | size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[], |
423 | | size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], |
424 | | hsize_t mem_offset_arr[]) |
425 | 0 | { |
426 | 0 | ssize_t ret_value = -1; /* Return value */ |
427 | |
|
428 | 0 | FUNC_ENTER_PACKAGE |
429 | |
|
430 | 0 | assert(io_info); |
431 | 0 | assert(dset_info); |
432 | | |
433 | | /* Check if file driver wishes to do its own memory management */ |
434 | 0 | if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_MEMMANAGE)) { |
435 | 0 | H5D_compact_iovv_memmanage_ud_t udata; |
436 | | |
437 | | /* Set up udata for memory copy operation */ |
438 | 0 | udata.f_sh = io_info->f_sh; |
439 | 0 | udata.dstbuf = dset_info->store->compact.buf; |
440 | 0 | udata.srcbuf = dset_info->buf.cvp; |
441 | | |
442 | | /* Request that file driver does the memory copy */ |
443 | 0 | if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, mem_max_nseq, |
444 | 0 | mem_curr_seq, mem_size_arr, mem_offset_arr, H5D__compact_iovv_memmanage_cb, |
445 | 0 | &udata)) < 0) |
446 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed"); |
447 | 0 | } |
448 | 0 | else { |
449 | | /* Use the vectorized memory copy routine to do actual work */ |
450 | 0 | if ((ret_value = H5VM_memcpyvv(dset_info->store->compact.buf, dset_max_nseq, dset_curr_seq, |
451 | 0 | dset_size_arr, dset_offset_arr, dset_info->buf.cvp, mem_max_nseq, |
452 | 0 | mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0) |
453 | 0 | HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed"); |
454 | 0 | } |
455 | | |
456 | | /* Mark the compact dataset's buffer as dirty */ |
457 | 0 | *dset_info->store->compact.dirty = true; |
458 | |
|
459 | 0 | done: |
460 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
461 | 0 | } /* end H5D__compact_writevv() */ |
462 | | |
463 | | /*------------------------------------------------------------------------- |
464 | | * Function: H5D__compact_flush |
465 | | * |
466 | | * Purpose: Writes dirty compact data to object header |
467 | | * |
468 | | * Return: Non-negative on success/Negative on failure |
469 | | * |
470 | | *------------------------------------------------------------------------- |
471 | | */ |
472 | | static herr_t |
473 | | H5D__compact_flush(H5D_t *dset) |
474 | 52 | { |
475 | 52 | herr_t ret_value = SUCCEED; /* Return value */ |
476 | | |
477 | 52 | FUNC_ENTER_PACKAGE |
478 | | |
479 | | /* Sanity check */ |
480 | 52 | assert(dset); |
481 | | |
482 | | /* Check if the buffered compact information is dirty */ |
483 | 52 | if (dset->shared->layout.storage.u.compact.dirty) { |
484 | 0 | dset->shared->layout.storage.u.compact.dirty = false; |
485 | 0 | if (H5O_msg_write(&(dset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dset->shared->layout)) < 0) { |
486 | 0 | dset->shared->layout.storage.u.compact.dirty = true; |
487 | 0 | HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message"); |
488 | 0 | } |
489 | 0 | } /* end if */ |
490 | | |
491 | 52 | done: |
492 | 52 | FUNC_LEAVE_NOAPI(ret_value) |
493 | 52 | } /* end H5D__compact_flush() */ |
494 | | |
495 | | /*------------------------------------------------------------------------- |
496 | | * Function: H5D__compact_dest |
497 | | * |
498 | | * Purpose: Free the compact buffer |
499 | | * |
500 | | * Return: Non-negative on success/Negative on failure |
501 | | * |
502 | | *------------------------------------------------------------------------- |
503 | | */ |
504 | | static herr_t |
505 | | H5D__compact_dest(H5D_t *dset) |
506 | 52 | { |
507 | 52 | FUNC_ENTER_PACKAGE_NOERR |
508 | | |
509 | | /* Sanity check */ |
510 | 52 | assert(dset); |
511 | | |
512 | | /* Free the buffer for the raw data for compact datasets */ |
513 | 52 | dset->shared->layout.storage.u.compact.buf = H5MM_xfree(dset->shared->layout.storage.u.compact.buf); |
514 | | |
515 | 52 | FUNC_LEAVE_NOAPI(SUCCEED) |
516 | 52 | } /* end H5D__compact_dest() */ |
517 | | |
518 | | /*------------------------------------------------------------------------- |
519 | | * Function: H5D__compact_copy |
520 | | * |
521 | | * Purpose: Copy compact storage raw data from SRC file to DST file. |
522 | | * |
523 | | * Return: Non-negative on success, negative on failure. |
524 | | * |
525 | | *------------------------------------------------------------------------- |
526 | | */ |
527 | | herr_t |
528 | | H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_dst, |
529 | | H5O_storage_compact_t *storage_dst, H5T_t *dt_src, H5O_copy_t *cpy_info) |
530 | 0 | { |
531 | 0 | H5T_t *dt_mem = NULL; /* Memory datatype */ |
532 | 0 | H5T_t *dt_dst = NULL; /* Destination datatype */ |
533 | 0 | H5S_t *buf_space = NULL; /* Dataspace describing buffer */ |
534 | 0 | void *buf = NULL; /* Buffer for copying data */ |
535 | 0 | void *bkg = NULL; /* Temporary buffer for copying data */ |
536 | 0 | void *reclaim_buf = NULL; /* Buffer for reclaiming data */ |
537 | 0 | H5D_shared_t *shared_fo = |
538 | 0 | (H5D_shared_t *)cpy_info->shared_fo; /* Pointer to the shared struct for dataset object */ |
539 | 0 | H5O_storage_compact_t *storage_src = _storage_src; /* Pointer to storage_src */ |
540 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
541 | |
|
542 | 0 | FUNC_ENTER_PACKAGE |
543 | | |
544 | | /* Check args */ |
545 | 0 | assert(f_src); |
546 | 0 | assert(storage_src); |
547 | 0 | assert(f_dst); |
548 | 0 | assert(storage_dst); |
549 | 0 | assert(storage_dst->buf); |
550 | 0 | assert(dt_src); |
551 | | |
552 | | /* If the dataset is open in the file, point to "layout" in the shared struct */ |
553 | 0 | if (shared_fo != NULL) |
554 | 0 | storage_src = &(shared_fo->layout.storage.u.compact); |
555 | | |
556 | | /* If there's a VLEN source datatype, do type conversion information */ |
557 | 0 | if (H5T_detect_class(dt_src, H5T_VLEN, false) > 0) { |
558 | 0 | H5T_path_t *tpath_src_mem, *tpath_mem_dst; /* Datatype conversion paths */ |
559 | 0 | size_t buf_size; /* Size of copy buffer */ |
560 | 0 | size_t nelmts; /* Number of elements in buffer */ |
561 | 0 | size_t src_dt_size; /* Source datatype size */ |
562 | 0 | size_t tmp_dt_size; /* Temporary datatype size */ |
563 | 0 | size_t max_dt_size; /* Max atatype size */ |
564 | 0 | hsize_t buf_dim; /* Dimension for buffer */ |
565 | | |
566 | | /* create a memory copy of the variable-length datatype */ |
567 | 0 | if (NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT))) |
568 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy"); |
569 | | |
570 | | /* create variable-length datatype at the destination file */ |
571 | 0 | if (NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT))) |
572 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy"); |
573 | 0 | if (H5T_set_loc(dt_dst, H5F_VOL_OBJ(f_dst), H5T_LOC_DISK) < 0) { |
574 | 0 | (void)H5T_close_real(dt_dst); |
575 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk"); |
576 | 0 | } /* end if */ |
577 | | |
578 | | /* Set up the conversion functions */ |
579 | 0 | if (NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem))) |
580 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes"); |
581 | 0 | if (NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst))) |
582 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes"); |
583 | | |
584 | | /* Determine largest datatype size */ |
585 | 0 | if (0 == (src_dt_size = H5T_get_size(dt_src))) |
586 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size"); |
587 | 0 | if (0 == (tmp_dt_size = H5T_get_size(dt_mem))) |
588 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size"); |
589 | 0 | max_dt_size = MAX(src_dt_size, tmp_dt_size); |
590 | 0 | if (0 == (tmp_dt_size = H5T_get_size(dt_dst))) |
591 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size"); |
592 | 0 | max_dt_size = MAX(max_dt_size, tmp_dt_size); |
593 | | |
594 | | /* Set number of whole elements that fit in buffer */ |
595 | 0 | if (0 == (nelmts = storage_src->size / src_dt_size)) |
596 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "element size too large"); |
597 | | |
598 | | /* Set up number of bytes to copy, and initial buffer size */ |
599 | 0 | buf_size = nelmts * max_dt_size; |
600 | | |
601 | | /* Create dataspace for number of elements in buffer */ |
602 | 0 | buf_dim = nelmts; |
603 | | |
604 | | /* Create the space and set the initial extent */ |
605 | 0 | if (NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL))) |
606 | 0 | HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); |
607 | | |
608 | | /* Allocate memory for recclaim buf */ |
609 | 0 | if (NULL == (reclaim_buf = H5FL_BLK_MALLOC(type_conv, buf_size))) |
610 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); |
611 | | |
612 | | /* Allocate memory for copying the chunk */ |
613 | 0 | if (NULL == (buf = H5FL_BLK_MALLOC(type_conv, buf_size))) |
614 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); |
615 | | |
616 | 0 | H5MM_memcpy(buf, storage_src->buf, storage_src->size); |
617 | | |
618 | | /* allocate temporary bkg buff for data conversion */ |
619 | 0 | if (NULL == (bkg = H5FL_BLK_MALLOC(type_conv, buf_size))) |
620 | 0 | HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); |
621 | | |
622 | | /* Convert from source file to memory */ |
623 | 0 | if (H5T_convert(tpath_src_mem, dt_src, dt_mem, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0) |
624 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); |
625 | | |
626 | | /* Copy into another buffer, to reclaim memory later */ |
627 | 0 | H5MM_memcpy(reclaim_buf, buf, buf_size); |
628 | | |
629 | | /* Set background buffer to all zeros */ |
630 | 0 | memset(bkg, 0, buf_size); |
631 | | |
632 | | /* Convert from memory to destination file */ |
633 | 0 | if (H5T_convert(tpath_mem_dst, dt_mem, dt_dst, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0) |
634 | 0 | HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "datatype conversion failed"); |
635 | | |
636 | 0 | H5MM_memcpy(storage_dst->buf, buf, storage_dst->size); |
637 | |
|
638 | 0 | if (H5T_reclaim(dt_mem, buf_space, reclaim_buf) < 0) |
639 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reclaim variable-length data"); |
640 | 0 | } /* end if */ |
641 | 0 | else if (H5T_get_class(dt_src, false) == H5T_REFERENCE) { |
642 | 0 | if (f_src != f_dst) { |
643 | | /* Check for expanding references */ |
644 | 0 | if (cpy_info->expand_ref) { |
645 | | /* Copy objects referenced in source buffer to destination file and set destination elements |
646 | | */ |
647 | 0 | if (H5O_copy_expand_ref(f_src, dt_src, storage_src->buf, storage_src->size, f_dst, |
648 | 0 | storage_dst->buf, cpy_info) < 0) |
649 | 0 | HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute"); |
650 | 0 | } /* end if */ |
651 | 0 | else |
652 | | /* Reset value to zero */ |
653 | 0 | memset(storage_dst->buf, 0, storage_src->size); |
654 | 0 | } /* end if */ |
655 | 0 | else |
656 | | /* Type conversion not necessary */ |
657 | 0 | H5MM_memcpy(storage_dst->buf, storage_src->buf, storage_src->size); |
658 | 0 | } /* end if */ |
659 | 0 | else |
660 | | /* Type conversion not necessary */ |
661 | 0 | H5MM_memcpy(storage_dst->buf, storage_src->buf, storage_src->size); |
662 | | |
663 | | /* Mark destination buffer as dirty */ |
664 | 0 | storage_dst->dirty = true; |
665 | |
|
666 | 0 | done: |
667 | 0 | if (dt_dst && (H5T_close(dt_dst) < 0)) |
668 | 0 | HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); |
669 | 0 | if (dt_mem && (H5T_close(dt_mem) < 0)) |
670 | 0 | HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary datatype"); |
671 | 0 | if (buf_space && H5S_close(buf_space) < 0) |
672 | 0 | HDONE_ERROR(H5E_DATASET, H5E_CANTCLOSEOBJ, FAIL, "can't close temporary dataspace"); |
673 | 0 | if (buf) |
674 | 0 | buf = H5FL_BLK_FREE(type_conv, buf); |
675 | 0 | if (reclaim_buf) |
676 | 0 | reclaim_buf = H5FL_BLK_FREE(type_conv, reclaim_buf); |
677 | 0 | if (bkg) |
678 | 0 | bkg = H5FL_BLK_FREE(type_conv, bkg); |
679 | |
|
680 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
681 | 0 | } /* end H5D__compact_copy() */ |