1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /*
15  * Programmer: 	Quincey Koziol
16  *	       	Thursday, September 28, 2000
17  *
18  * Purpose:
19  *      Contiguous dataset I/O functions. These routines are similar to
20  *      the H5D_chunk_* routines and really only an abstract way of dealing
21  *      with the data sieve buffer from H5F_seq_read/write.
22  */
23 
24 /****************/
25 /* Module Setup */
26 /****************/
27 
28 #include "H5Dmodule.h" /* This source code file is part of the H5D module */
29 
30 /***********/
31 /* Headers */
32 /***********/
33 #include "H5private.h"   /* Generic Functions            */
34 #include "H5CXprivate.h" /* API Contexts                 */
35 #include "H5Dpkg.h"      /* Dataset functions            */
36 #include "H5Eprivate.h"  /* Error handling               */
37 #include "H5Fprivate.h"  /* Files                        */
38 #include "H5FDprivate.h" /* File drivers                 */
39 #include "H5FLprivate.h" /* Free Lists                   */
40 #include "H5Iprivate.h"  /* IDs                          */
41 #include "H5MFprivate.h" /* File memory management       */
42 #include "H5MMprivate.h" /* Memory management			*/
43 #include "H5FOprivate.h" /* File objects                 */
44 #include "H5Oprivate.h"  /* Object headers               */
45 #include "H5Pprivate.h"  /* Property lists               */
46 #include "H5VMprivate.h" /* Vector and array functions   */
47 
48 /****************/
49 /* Local Macros */
50 /****************/
51 
52 /******************/
53 /* Local Typedefs */
54 /******************/
55 
56 /* Callback info for sieve buffer readvv operation */
57 typedef struct H5D_contig_readvv_sieve_ud_t {
58     H5F_shared_t *              f_sh;         /* Shared file for dataset */
59     H5D_rdcdc_t *               dset_contig;  /* Cached information about contiguous data */
60     const H5D_contig_storage_t *store_contig; /* Contiguous storage info for this I/O operation */
61     unsigned char *             rbuf;         /* Pointer to buffer to fill */
62 } H5D_contig_readvv_sieve_ud_t;
63 
64 /* Callback info for [plain] readvv operation */
65 typedef struct H5D_contig_readvv_ud_t {
66     H5F_shared_t * f_sh;      /* Shared file for dataset */
67     haddr_t        dset_addr; /* Address of dataset */
68     unsigned char *rbuf;      /* Pointer to buffer to fill */
69 } H5D_contig_readvv_ud_t;
70 
71 /* Callback info for sieve buffer writevv operation */
72 typedef struct H5D_contig_writevv_sieve_ud_t {
73     H5F_shared_t *              f_sh;         /* Shared file for dataset */
74     H5D_rdcdc_t *               dset_contig;  /* Cached information about contiguous data */
75     const H5D_contig_storage_t *store_contig; /* Contiguous storage info for this I/O operation */
76     const unsigned char *       wbuf;         /* Pointer to buffer to write */
77 } H5D_contig_writevv_sieve_ud_t;
78 
79 /* Callback info for [plain] writevv operation */
80 typedef struct H5D_contig_writevv_ud_t {
81     H5F_shared_t *       f_sh;      /* Shared file for dataset */
82     haddr_t              dset_addr; /* Address of dataset */
83     const unsigned char *wbuf;      /* Pointer to buffer to write */
84 } H5D_contig_writevv_ud_t;
85 
86 /********************/
87 /* Local Prototypes */
88 /********************/
89 
90 /* Layout operation callbacks */
91 static herr_t  H5D__contig_construct(H5F_t *f, H5D_t *dset);
92 static herr_t  H5D__contig_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id);
93 static herr_t  H5D__contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
94                                    hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
95                                    H5D_chunk_map_t *cm);
96 static ssize_t H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
97                                   size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
98                                   size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
99 static ssize_t H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
100                                    size_t dset_len_arr[], hsize_t dset_offset_arr[], size_t mem_max_nseq,
101                                    size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
102 static herr_t  H5D__contig_flush(H5D_t *dset);
103 
104 /* Helper routines */
105 static herr_t H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size);
106 
107 /*********************/
108 /* Package Variables */
109 /*********************/
110 
111 /* Contiguous storage layout I/O ops */
112 const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {
113     {H5D__contig_construct, H5D__contig_init, H5D__contig_is_space_alloc, H5D__contig_is_data_cached,
114      H5D__contig_io_init, H5D__contig_read, H5D__contig_write,
115 #ifdef H5_HAVE_PARALLEL
116      H5D__contig_collective_read, H5D__contig_collective_write,
117 #endif /* H5_HAVE_PARALLEL */
118      H5D__contig_readvv, H5D__contig_writevv, H5D__contig_flush, NULL, NULL}};
119 
120 /*******************/
121 /* Local Variables */
122 /*******************/
123 
124 /* Declare a PQ free list to manage the sieve buffer information */
125 H5FL_BLK_DEFINE(sieve_buf);
126 
127 /* Declare extern the free list to manage blocks of type conversion data */
128 H5FL_BLK_EXTERN(type_conv);
129 
130 /*-------------------------------------------------------------------------
131  * Function:	H5D__contig_alloc
132  *
133  * Purpose:	Allocate file space for a contiguously stored dataset
134  *
135  * Return:	Non-negative on success/Negative on failure
136  *
137  * Programmer:	Quincey Koziol
138  *		April 19, 2003
139  *
140  *-------------------------------------------------------------------------
141  */
142 herr_t
H5D__contig_alloc(H5F_t * f,H5O_storage_contig_t * storage)143 H5D__contig_alloc(H5F_t *f, H5O_storage_contig_t *storage /*out */)
144 {
145     herr_t ret_value = SUCCEED; /* Return value */
146 
147     FUNC_ENTER_PACKAGE
148 
149     /* check args */
150     HDassert(f);
151     HDassert(storage);
152 
153     /* Allocate space for the contiguous data */
154     if (HADDR_UNDEF == (storage->addr = H5MF_alloc(f, H5FD_MEM_DRAW, storage->size)))
155         HGOTO_ERROR(H5E_IO, H5E_NOSPACE, FAIL, "unable to reserve file space")
156 
157 done:
158     FUNC_LEAVE_NOAPI(ret_value)
159 } /* end H5D__contig_alloc */
160 
161 /*-------------------------------------------------------------------------
162  * Function:	H5D__contig_fill
163  *
164  * Purpose:	Write fill values to a contiguously stored dataset.
165  *
166  * Return:	Non-negative on success/Negative on failure
167  *
168  * Programmer:	Quincey Koziol
169  *		August 22, 2002
170  *
171  *-------------------------------------------------------------------------
172  */
173 herr_t
H5D__contig_fill(const H5D_io_info_t * io_info)174 H5D__contig_fill(const H5D_io_info_t *io_info)
175 {
176     const H5D_t * dset = io_info->dset; /* the dataset pointer */
177     H5D_io_info_t ioinfo;               /* Dataset I/O info */
178     H5D_storage_t store;                /* Union of storage info for dataset */
179     hssize_t      snpoints;             /* Number of points in space (for error checking) */
180     size_t        npoints;              /* Number of points in space */
181     hsize_t       offset;               /* Offset of dataset */
182     size_t        max_temp_buf;         /* Maximum size of temporary buffer */
183 #ifdef H5_HAVE_PARALLEL
184     MPI_Comm mpi_comm = MPI_COMM_NULL; /* MPI communicator for file */
185     int      mpi_rank = (-1);          /* This process's rank  */
186     int      mpi_code;                 /* MPI return code */
187     hbool_t  blocks_written = FALSE;   /* Flag to indicate that chunk was actually written */
188     hbool_t  using_mpi =
189         FALSE; /* Flag to indicate that the file is being accessed with an MPI-capable file driver */
190 #endif         /* H5_HAVE_PARALLEL */
191     H5D_fill_buf_info_t fb_info;                /* Dataset's fill buffer info */
192     hbool_t             fb_info_init = FALSE;   /* Whether the fill value buffer has been initialized */
193     herr_t              ret_value    = SUCCEED; /* Return value */
194 
195     FUNC_ENTER_PACKAGE
196 
197     /* Check args */
198     HDassert(dset && H5D_CONTIGUOUS == dset->shared->layout.type);
199     HDassert(H5F_addr_defined(dset->shared->layout.storage.u.contig.addr));
200     HDassert(dset->shared->layout.storage.u.contig.size > 0);
201     HDassert(dset->shared->space);
202     HDassert(dset->shared->type);
203 
204 #ifdef H5_HAVE_PARALLEL
205     /* Retrieve MPI parameters */
206     if (H5F_HAS_FEATURE(dset->oloc.file, H5FD_FEAT_HAS_MPI)) {
207         /* Get the MPI communicator */
208         if (MPI_COMM_NULL == (mpi_comm = H5F_mpi_get_comm(dset->oloc.file)))
209             HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI communicator")
210 
211         /* Get the MPI rank */
212         if ((mpi_rank = H5F_mpi_get_rank(dset->oloc.file)) < 0)
213             HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, FAIL, "Can't retrieve MPI rank")
214 
215         /* Set the MPI-capable file driver flag */
216         using_mpi = TRUE;
217     }  /* end if */
218 #endif /* H5_HAVE_PARALLEL */
219 
220     /* Initialize storage info for this dataset */
221     store.contig.dset_addr = dset->shared->layout.storage.u.contig.addr;
222     store.contig.dset_size = dset->shared->layout.storage.u.contig.size;
223 
224     /* Get the number of elements in the dataset's dataspace */
225     if ((snpoints = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0)
226         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "dataset has negative number of elements")
227     H5_CHECKED_ASSIGN(npoints, size_t, snpoints, hssize_t);
228 
229     /* Get the maximum size of temporary buffers */
230     if (H5CX_get_max_temp_buf(&max_temp_buf) < 0)
231         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't retrieve max. temp. buf size")
232 
233     /* Initialize the fill value buffer */
234     if (H5D__fill_init(&fb_info, NULL, NULL, NULL, NULL, NULL, &dset->shared->dcpl_cache.fill,
235                        dset->shared->type, dset->shared->type_id, npoints, max_temp_buf) < 0)
236         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
237     fb_info_init = TRUE;
238 
239     /* Start at the beginning of the dataset */
240     offset = 0;
241 
242     /* Simple setup for dataset I/O info struct */
243     H5D_BUILD_IO_INFO_WRT(&ioinfo, dset, &store, fb_info.fill_buf);
244 
245     /*
246      * Fill the entire current extent with the fill value.  We can do
247      * this quite efficiently by making sure we copy the fill value
248      * in relatively large pieces.
249      */
250 
251     /* Loop through writing the fill value to the dataset */
252     while (npoints > 0) {
253         size_t curr_points; /* Number of elements to write on this iteration of the loop */
254         size_t size;        /* Size of buffer to write */
255 
256         /* Compute # of elements and buffer size to write for this iteration */
257         curr_points = MIN(fb_info.elmts_per_buf, npoints);
258         size        = curr_points * fb_info.file_elmt_size;
259 
260         /* Check for VL datatype & non-default fill value */
261         if (fb_info.has_vlen_fill_type)
262             /* Re-fill the buffer to use for this I/O operation */
263             if (H5D__fill_refill_vl(&fb_info, curr_points) < 0)
264                 HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
265 
266 #ifdef H5_HAVE_PARALLEL
267         /* Check if this file is accessed with an MPI-capable file driver */
268         if (using_mpi) {
269             /* Write the chunks out from only one process */
270             /* !! Use the internal "independent" DXPL!! -QAK */
271             if (H5_PAR_META_WRITE == mpi_rank)
272                 if (H5D__contig_write_one(&ioinfo, offset, size) < 0)
273                     HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
274 
275             /* Indicate that blocks are being written */
276             blocks_written = TRUE;
277         } /* end if */
278         else {
279 #endif /* H5_HAVE_PARALLEL */
280             H5_CHECK_OVERFLOW(size, size_t, hsize_t);
281             if (H5D__contig_write_one(&ioinfo, offset, size) < 0)
282                 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset")
283 #ifdef H5_HAVE_PARALLEL
284         } /* end else */
285 #endif    /* H5_HAVE_PARALLEL */
286 
287         npoints -= curr_points;
288         offset += size;
289     } /* end while */
290 
291 #ifdef H5_HAVE_PARALLEL
292     /* Only need to block at the barrier if we actually wrote fill values */
293     /* And if we are using an MPI-capable file driver */
294     if (using_mpi && blocks_written) {
295         /* Wait at barrier to avoid race conditions where some processes are
296          * still writing out fill values and other processes race ahead to data
297          * in, getting bogus data.
298          */
299         if (MPI_SUCCESS != (mpi_code = MPI_Barrier(mpi_comm)))
300             HMPI_GOTO_ERROR(FAIL, "MPI_Barrier failed", mpi_code)
301     }  /* end if */
302 #endif /* H5_HAVE_PARALLEL */
303 
304 done:
305     /* Release the fill buffer info, if it's been initialized */
306     if (fb_info_init && H5D__fill_term(&fb_info) < 0)
307         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
308 
309     FUNC_LEAVE_NOAPI(ret_value)
310 } /* end H5D__contig_fill() */
311 
312 /*-------------------------------------------------------------------------
313  * Function:	H5D__contig_delete
314  *
315  * Purpose:	Delete the file space for a contiguously stored dataset
316  *
317  * Return:	Non-negative on success/Negative on failure
318  *
319  * Programmer:	Quincey Koziol
320  *		March 20, 2003
321  *
322  *-------------------------------------------------------------------------
323  */
324 herr_t
H5D__contig_delete(H5F_t * f,const H5O_storage_t * storage)325 H5D__contig_delete(H5F_t *f, const H5O_storage_t *storage)
326 {
327     herr_t ret_value = SUCCEED; /* Return value */
328 
329     FUNC_ENTER_PACKAGE
330 
331     /* check args */
332     HDassert(f);
333     HDassert(storage);
334 
335     /* Free the file space for the chunk */
336     if (H5MF_xfree(f, H5FD_MEM_DRAW, storage->u.contig.addr, storage->u.contig.size) < 0)
337         HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free contiguous storage space")
338 
339 done:
340     FUNC_LEAVE_NOAPI(ret_value)
341 } /* end H5D__contig_delete */
342 
343 /*-------------------------------------------------------------------------
344  * Function:	H5D__contig_construct
345  *
346  * Purpose:	Constructs new contiguous layout information for dataset
347  *
348  * Return:	Non-negative on success/Negative on failure
349  *
350  * Programmer:	Quincey Koziol
351  *              Thursday, May 22, 2008
352  *
353  *-------------------------------------------------------------------------
354  */
355 static herr_t
H5D__contig_construct(H5F_t * f,H5D_t * dset)356 H5D__contig_construct(H5F_t *f, H5D_t *dset)
357 {
358     hssize_t snelmts;             /* Temporary holder for number of elements in dataspace */
359     hsize_t  nelmts;              /* Number of elements in dataspace */
360     size_t   dt_size;             /* Size of datatype */
361     hsize_t  tmp_size;            /* Temporary holder for raw data size */
362     size_t   tmp_sieve_buf_size;  /* Temporary holder for sieve buffer size */
363     unsigned u;                   /* Local index variable */
364     herr_t   ret_value = SUCCEED; /* Return value */
365 
366     FUNC_ENTER_STATIC
367 
368     /* Sanity checks */
369     HDassert(f);
370     HDassert(dset);
371 
372     /*
373      * The maximum size of the dataset cannot exceed the storage size.
374      * Also, only the slowest varying dimension of a simple dataspace
375      * can be extendible (currently only for external data storage).
376      */
377 
378     /* Check for invalid dataset dimensions */
379     for (u = 0; u < dset->shared->ndims; u++)
380         if (dset->shared->max_dims[u] > dset->shared->curr_dims[u])
381             HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL,
382                         "extendible contiguous non-external dataset not allowed")
383 
384     /* Retrieve the number of elements in the dataspace */
385     if ((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0)
386         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace")
387     nelmts = (hsize_t)snelmts;
388 
389     /* Get the datatype's size */
390     if (0 == (dt_size = H5T_GET_SIZE(dset->shared->type)))
391         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of datatype")
392 
393     /* Compute the size of the dataset's contiguous storage */
394     tmp_size = nelmts * dt_size;
395 
396     /* Check for overflow during multiplication */
397     if (nelmts != (tmp_size / dt_size))
398         HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed")
399 
400     /* Assign the dataset's contiguous storage size */
401     dset->shared->layout.storage.u.contig.size = tmp_size;
402 
403     /* Get the sieve buffer size for the file */
404     tmp_sieve_buf_size = H5F_SIEVE_BUF_SIZE(f);
405 
406     /* Adjust the sieve buffer size to the smaller one between the dataset size and the buffer size
407      * from the file access property. (SLU - 2012/3/30) */
408     if (tmp_size < tmp_sieve_buf_size)
409         dset->shared->cache.contig.sieve_buf_size = tmp_size;
410     else
411         dset->shared->cache.contig.sieve_buf_size = tmp_sieve_buf_size;
412 
413 done:
414     FUNC_LEAVE_NOAPI(ret_value)
415 } /* end H5D__contig_construct() */
416 
417 /*-------------------------------------------------------------------------
418  * Function:	H5D__contig_init
419  *
420  * Purpose:	Initialize the contiguous info for a dataset.  This is
421  *		called when the dataset is initialized.
422  *
423  * Return:	Non-negative on success/Negative on failure
424  *
425  * Programmer:	Quincey Koziol
426  *              Friday, August 28, 2015
427  *
428  *-------------------------------------------------------------------------
429  */
430 static herr_t
H5D__contig_init(H5F_t H5_ATTR_UNUSED * f,const H5D_t * dset,hid_t H5_ATTR_UNUSED dapl_id)431 H5D__contig_init(H5F_t H5_ATTR_UNUSED *f, const H5D_t *dset, hid_t H5_ATTR_UNUSED dapl_id)
432 {
433     hsize_t tmp_size;            /* Temporary holder for raw data size */
434     size_t  tmp_sieve_buf_size;  /* Temporary holder for sieve buffer size */
435     herr_t  ret_value = SUCCEED; /* Return value */
436 
437     FUNC_ENTER_STATIC
438 
439     /* Sanity check */
440     HDassert(f);
441     HDassert(dset);
442 
443     /* Compute the size of the contiguous storage for versions of the
444      * layout message less than version 3 because versions 1 & 2 would
445      * truncate the dimension sizes to 32-bits of information. - QAK 5/26/04
446      */
447     if (dset->shared->layout.version < 3) {
448         hssize_t snelmts; /* Temporary holder for number of elements in dataspace */
449         hsize_t  nelmts;  /* Number of elements in dataspace */
450         size_t   dt_size; /* Size of datatype */
451 
452         /* Retrieve the number of elements in the dataspace */
453         if ((snelmts = H5S_GET_EXTENT_NPOINTS(dset->shared->space)) < 0)
454             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve number of elements in dataspace")
455         nelmts = (hsize_t)snelmts;
456 
457         /* Get the datatype's size */
458         if (0 == (dt_size = H5T_GET_SIZE(dset->shared->type)))
459             HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to retrieve size of datatype")
460 
461         /* Compute the size of the dataset's contiguous storage */
462         tmp_size = nelmts * dt_size;
463 
464         /* Check for overflow during multiplication */
465         if (nelmts != (tmp_size / dt_size))
466             HGOTO_ERROR(H5E_DATASET, H5E_OVERFLOW, FAIL, "size of dataset's storage overflowed")
467 
468         /* Assign the dataset's contiguous storage size */
469         dset->shared->layout.storage.u.contig.size = tmp_size;
470     } /* end if */
471     else
472         tmp_size = dset->shared->layout.storage.u.contig.size;
473 
474     /* Get the sieve buffer size for the file */
475     tmp_sieve_buf_size = H5F_SIEVE_BUF_SIZE(dset->oloc.file);
476 
477     /* Adjust the sieve buffer size to the smaller one between the dataset size and the buffer size
478      * from the file access property.  (SLU - 2012/3/30) */
479     if (tmp_size < tmp_sieve_buf_size)
480         dset->shared->cache.contig.sieve_buf_size = tmp_size;
481     else
482         dset->shared->cache.contig.sieve_buf_size = tmp_sieve_buf_size;
483 
484 done:
485     FUNC_LEAVE_NOAPI(ret_value)
486 } /* end H5D__contig_init() */
487 
488 /*-------------------------------------------------------------------------
489  * Function:	H5D__contig_is_space_alloc
490  *
491  * Purpose:	Query if space is allocated for layout
492  *
493  * Return:	Non-negative on success/Negative on failure
494  *
495  * Programmer:	Quincey Koziol
496  *              Thursday, January 15, 2009
497  *
498  *-------------------------------------------------------------------------
499  */
500 hbool_t
H5D__contig_is_space_alloc(const H5O_storage_t * storage)501 H5D__contig_is_space_alloc(const H5O_storage_t *storage)
502 {
503     hbool_t ret_value = FALSE; /* Return value */
504 
505     FUNC_ENTER_PACKAGE_NOERR
506 
507     /* Sanity checks */
508     HDassert(storage);
509 
510     /* Set return value */
511     ret_value = (hbool_t)H5F_addr_defined(storage->u.contig.addr);
512 
513     FUNC_LEAVE_NOAPI(ret_value)
514 } /* end H5D__contig_is_space_alloc() */
515 
516 /*-------------------------------------------------------------------------
517  * Function:    H5D__contig_is_data_cached
518  *
519  * Purpose:     Query if raw data is cached for dataset
520  *
521  * Return:      Non-negative on success/Negative on failure
522  *
523  * Programmer:  Neil Fortner
524  *              Wednessday, March 6, 2016
525  *
526  *-------------------------------------------------------------------------
527  */
528 hbool_t
H5D__contig_is_data_cached(const H5D_shared_t * shared_dset)529 H5D__contig_is_data_cached(const H5D_shared_t *shared_dset)
530 {
531     FUNC_ENTER_PACKAGE_NOERR
532 
533     /* Sanity checks */
534     HDassert(shared_dset);
535 
536     FUNC_LEAVE_NOAPI(shared_dset->cache.contig.sieve_size > 0)
537 } /* end H5D__contig_is_data_cached() */
538 
539 /*-------------------------------------------------------------------------
540  * Function:	H5D__contig_io_init
541  *
542  * Purpose:	Performs initialization before any sort of I/O on the raw data
543  *
544  * Return:	Non-negative on success/Negative on failure
545  *
546  * Programmer:	Quincey Koziol
547  *              Thursday, March 20, 2008
548  *
549  *-------------------------------------------------------------------------
550  */
551 static herr_t
H5D__contig_io_init(const H5D_io_info_t * io_info,const H5D_type_info_t H5_ATTR_UNUSED * type_info,hsize_t H5_ATTR_UNUSED nelmts,const H5S_t H5_ATTR_UNUSED * file_space,const H5S_t H5_ATTR_UNUSED * mem_space,H5D_chunk_map_t H5_ATTR_UNUSED * cm)552 H5D__contig_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
553                     hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space,
554                     const H5S_t H5_ATTR_UNUSED *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *cm)
555 {
556     FUNC_ENTER_STATIC_NOERR
557 
558     io_info->store->contig.dset_addr = io_info->dset->shared->layout.storage.u.contig.addr;
559     io_info->store->contig.dset_size = io_info->dset->shared->layout.storage.u.contig.size;
560 
561     FUNC_LEAVE_NOAPI(SUCCEED)
562 } /* end H5D__contig_io_init() */
563 
564 /*-------------------------------------------------------------------------
565  * Function:	H5D__contig_read
566  *
567  * Purpose:	Read from a contiguous dataset.
568  *
569  * Return:	Non-negative on success/Negative on failure
570  *
571  * Programmer:	Raymond Lu
572  *		Thursday, April 10, 2003
573  *
574  *-------------------------------------------------------------------------
575  */
576 herr_t
H5D__contig_read(H5D_io_info_t * io_info,const H5D_type_info_t * type_info,hsize_t nelmts,const H5S_t * file_space,const H5S_t * mem_space,H5D_chunk_map_t H5_ATTR_UNUSED * fm)577 H5D__contig_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
578                  const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm)
579 {
580     herr_t ret_value = SUCCEED; /*return value		*/
581 
582     FUNC_ENTER_PACKAGE
583 
584     /* Sanity check */
585     HDassert(io_info);
586     HDassert(io_info->u.rbuf);
587     HDassert(type_info);
588     HDassert(mem_space);
589     HDassert(file_space);
590 
591     /* Read data */
592     if ((io_info->io_ops.single_read)(io_info, type_info, nelmts, file_space, mem_space) < 0)
593         HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "contiguous read failed")
594 
595 done:
596     FUNC_LEAVE_NOAPI(ret_value)
597 } /* end H5D__contig_read() */
598 
599 /*-------------------------------------------------------------------------
600  * Function:	H5D__contig_write
601  *
602  * Purpose:	Write to a contiguous dataset.
603  *
604  * Return:	Non-negative on success/Negative on failure
605  *
606  * Programmer:	Raymond Lu
607  *		Thursday, April 10, 2003
608  *
609  *-------------------------------------------------------------------------
610  */
611 herr_t
H5D__contig_write(H5D_io_info_t * io_info,const H5D_type_info_t * type_info,hsize_t nelmts,const H5S_t * file_space,const H5S_t * mem_space,H5D_chunk_map_t H5_ATTR_UNUSED * fm)612 H5D__contig_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info, hsize_t nelmts,
613                   const H5S_t *file_space, const H5S_t *mem_space, H5D_chunk_map_t H5_ATTR_UNUSED *fm)
614 {
615     herr_t ret_value = SUCCEED; /*return value		*/
616 
617     FUNC_ENTER_PACKAGE
618 
619     /* Sanity check */
620     HDassert(io_info);
621     HDassert(io_info->u.wbuf);
622     HDassert(type_info);
623     HDassert(mem_space);
624     HDassert(file_space);
625 
626     /* Write data */
627     if ((io_info->io_ops.single_write)(io_info, type_info, nelmts, file_space, mem_space) < 0)
628         HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "contiguous write failed")
629 
630 done:
631     FUNC_LEAVE_NOAPI(ret_value)
632 } /* end H5D__contig_write() */
633 
634 /*-------------------------------------------------------------------------
635  * Function:	H5D__contig_write_one
636  *
637  * Purpose:	Writes some data from a dataset into a buffer.
638  *		The data is contiguous.	 The address is relative to the base
639  *		address for the file.
640  *
641  * Return:	Non-negative on success/Negative on failure
642  *
643  * Programmer:	Quincey Koziol
644  *              Thursday, September 28, 2000
645  *
646  *-------------------------------------------------------------------------
647  */
648 static herr_t
H5D__contig_write_one(H5D_io_info_t * io_info,hsize_t offset,size_t size)649 H5D__contig_write_one(H5D_io_info_t *io_info, hsize_t offset, size_t size)
650 {
651     hsize_t dset_off      = offset;  /* Offset in dataset */
652     size_t  dset_len      = size;    /* Length in dataset */
653     size_t  dset_curr_seq = 0;       /* "Current sequence" in dataset */
654     hsize_t mem_off       = 0;       /* Offset in memory */
655     size_t  mem_len       = size;    /* Length in memory */
656     size_t  mem_curr_seq  = 0;       /* "Current sequence" in memory */
657     herr_t  ret_value     = SUCCEED; /* Return value */
658 
659     FUNC_ENTER_STATIC
660 
661     HDassert(io_info);
662 
663     if (H5D__contig_writevv(io_info, (size_t)1, &dset_curr_seq, &dset_len, &dset_off, (size_t)1,
664                             &mem_curr_seq, &mem_len, &mem_off) < 0)
665         HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed")
666 
667 done:
668     FUNC_LEAVE_NOAPI(ret_value)
669 } /* end H5D__contig_write_one() */
670 
671 /*-------------------------------------------------------------------------
672  * Function:	H5D__contig_readvv_sieve_cb
673  *
674  * Purpose:	Callback operator for H5D__contig_readvv() with sieve buffer.
675  *
676  * Return:	Non-negative on success/Negative on failure
677  *
678  * Programmer:	Quincey Koziol
679  *              Thursday, Sept 30, 2010
680  *
681  *-------------------------------------------------------------------------
682  */
683 static herr_t
H5D__contig_readvv_sieve_cb(hsize_t dst_off,hsize_t src_off,size_t len,void * _udata)684 H5D__contig_readvv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
685 {
686     H5D_contig_readvv_sieve_ud_t *udata =
687         (H5D_contig_readvv_sieve_ud_t *)_udata;     /* User data for H5VM_opvv() operator */
688     H5F_shared_t *f_sh        = udata->f_sh;        /* Shared file for dataset */
689     H5D_rdcdc_t * dset_contig = udata->dset_contig; /* Cached information about contiguous data */
690     const H5D_contig_storage_t *store_contig =
691         udata->store_contig; /* Contiguous storage info for this I/O operation */
692     unsigned char *buf;      /* Pointer to buffer to fill */
693     haddr_t        addr;     /* Actual address to read */
694     haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
695     haddr_t contig_end;                                         /* End locations of block to write */
696     size_t  sieve_size = (size_t)-1;                            /* Size of sieve buffer */
697     haddr_t rel_eoa;                                            /* Relative end of file address	*/
698     hsize_t max_data;                                           /* Actual maximum size of data to cache */
699     hsize_t min;                 /* temporary minimum value (avoids some ugly macro nesting) */
700     herr_t  ret_value = SUCCEED; /* Return value */
701 
702     FUNC_ENTER_STATIC
703 
704     /* Stash local copies of these value */
705     if (dset_contig->sieve_buf != NULL) {
706         sieve_start = dset_contig->sieve_loc;
707         sieve_size  = dset_contig->sieve_size;
708         sieve_end   = sieve_start + sieve_size;
709     } /* end if */
710 
711     /* Compute offset on disk */
712     addr = store_contig->dset_addr + dst_off;
713 
714     /* Compute offset in memory */
715     buf = udata->rbuf + src_off;
716 
717     /* Check if the sieve buffer is allocated yet */
718     if (NULL == dset_contig->sieve_buf) {
719         /* Check if we can actually hold the I/O request in the sieve buffer */
720         if (len > dset_contig->sieve_buf_size) {
721             if (H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
722                 HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
723         } /* end if */
724         else {
725             /* Allocate room for the data sieve buffer */
726             if (NULL == (dset_contig->sieve_buf = H5FL_BLK_CALLOC(sieve_buf, dset_contig->sieve_buf_size)))
727                 HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed")
728 
729             /* Determine the new sieve buffer size & location */
730             dset_contig->sieve_loc = addr;
731 
732             /* Make certain we don't read off the end of the file */
733             if (HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
734                 HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
735 
736             /* Set up the buffer parameters */
737             max_data = store_contig->dset_size - dst_off;
738 
739             /* Compute the size of the sieve buffer */
740             min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
741             H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
742 
743             /* Read the new sieve buffer */
744             if (H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc, dset_contig->sieve_size,
745                                       dset_contig->sieve_buf) < 0)
746                 HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
747 
748             /* Grab the data out of the buffer (must be first piece of data in buffer ) */
749             H5MM_memcpy(buf, dset_contig->sieve_buf, len);
750 
751             /* Reset sieve buffer dirty flag */
752             dset_contig->sieve_dirty = FALSE;
753         } /* end else */
754     }     /* end if */
755     else {
756         /* Compute end of sequence to retrieve */
757         contig_end = addr + len - 1;
758 
759         /* If entire read is within the sieve buffer, read it from the buffer */
760         if (addr >= sieve_start && contig_end < sieve_end) {
761             unsigned char *base_sieve_buf = dset_contig->sieve_buf + (addr - sieve_start);
762 
763             /* Grab the data out of the buffer */
764             H5MM_memcpy(buf, base_sieve_buf, len);
765         } /* end if */
766         /* Entire request is not within this data sieve buffer */
767         else {
768             /* Check if we can actually hold the I/O request in the sieve buffer */
769             if (len > dset_contig->sieve_buf_size) {
770                 /* Check for any overlap with the current sieve buffer */
771                 if ((sieve_start >= addr && sieve_start < (contig_end + 1)) ||
772                     ((sieve_end - 1) >= addr && (sieve_end - 1) < (contig_end + 1))) {
773                     /* Flush the sieve buffer, if it's dirty */
774                     if (dset_contig->sieve_dirty) {
775                         /* Write to file */
776                         if (H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size,
777                                                    dset_contig->sieve_buf) < 0)
778                             HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
779 
780                         /* Reset sieve buffer dirty flag */
781                         dset_contig->sieve_dirty = FALSE;
782                     } /* end if */
783                 }     /* end if */
784 
785                 /* Read directly into the user's buffer */
786                 if (H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
787                     HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
788             } /* end if */
789             /* Element size fits within the buffer size */
790             else {
791                 /* Flush the sieve buffer if it's dirty */
792                 if (dset_contig->sieve_dirty) {
793                     /* Write to file */
794                     if (H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size,
795                                                dset_contig->sieve_buf) < 0)
796                         HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
797 
798                     /* Reset sieve buffer dirty flag */
799                     dset_contig->sieve_dirty = FALSE;
800                 } /* end if */
801 
802                 /* Determine the new sieve buffer size & location */
803                 dset_contig->sieve_loc = addr;
804 
805                 /* Make certain we don't read off the end of the file */
806                 if (HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
807                     HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
808 
809                 /* Only need this when resizing sieve buffer */
810                 max_data = store_contig->dset_size - dst_off;
811 
812                 /* Compute the size of the sieve buffer.
813                  * Don't read off the end of the file, don't read past
814                  * the end of the data element, and don't read more than
815                  * the buffer size.
816                  */
817                 min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
818                 H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
819 
820                 /* Read the new sieve buffer */
821                 if (H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc,
822                                           dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
823                     HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
824 
825                 /* Grab the data out of the buffer (must be first piece of data in buffer ) */
826                 H5MM_memcpy(buf, dset_contig->sieve_buf, len);
827 
828                 /* Reset sieve buffer dirty flag */
829                 dset_contig->sieve_dirty = FALSE;
830             } /* end else */
831         }     /* end else */
832     }         /* end else */
833 
834 done:
835     FUNC_LEAVE_NOAPI(ret_value)
836 } /* end H5D__contig_readvv_sieve_cb() */
837 
838 /*-------------------------------------------------------------------------
839  * Function:	H5D__contig_readvv_cb
840  *
841  * Purpose:	Callback operator for H5D__contig_readvv() without sieve buffer.
842  *
843  * Return:	Non-negative on success/Negative on failure
844  *
845  * Programmer:	Quincey Koziol
846  *              Thursday, Sept 30, 2010
847  *
848  *-------------------------------------------------------------------------
849  */
850 static herr_t
H5D__contig_readvv_cb(hsize_t dst_off,hsize_t src_off,size_t len,void * _udata)851 H5D__contig_readvv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
852 {
853     H5D_contig_readvv_ud_t *udata = (H5D_contig_readvv_ud_t *)_udata; /* User data for H5VM_opvv() operator */
854     herr_t                  ret_value = SUCCEED;                      /* Return value */
855 
856     FUNC_ENTER_STATIC
857 
858     /* Write data */
859     if (H5F_shared_block_read(udata->f_sh, H5FD_MEM_DRAW, (udata->dset_addr + dst_off), len,
860                               (udata->rbuf + src_off)) < 0)
861         HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
862 
863 done:
864     FUNC_LEAVE_NOAPI(ret_value)
865 } /* end H5D__contig_readvv_cb() */
866 
867 /*-------------------------------------------------------------------------
868  * Function:	H5D__contig_readvv
869  *
870  * Purpose:	Reads some data vectors from a dataset into a buffer.
871  *		The data is contiguous.	 The address is the start of the dataset,
872  *              relative to the base address for the file and the offsets and
873  *              sequence lengths are in bytes.
874  *
875  * Return:	Non-negative on success/Negative on failure
876  *
877  * Programmer:	Quincey Koziol
878  *              Friday, May 3, 2001
879  *
880  * Notes:
881  *      Offsets in the sequences must be monotonically increasing
882  *
883  *-------------------------------------------------------------------------
884  */
885 static ssize_t
H5D__contig_readvv(const H5D_io_info_t * io_info,size_t dset_max_nseq,size_t * dset_curr_seq,size_t dset_len_arr[],hsize_t dset_off_arr[],size_t mem_max_nseq,size_t * mem_curr_seq,size_t mem_len_arr[],hsize_t mem_off_arr[])886 H5D__contig_readvv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
887                    size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
888                    size_t mem_len_arr[], hsize_t mem_off_arr[])
889 {
890     ssize_t ret_value = -1; /* Return value */
891 
892     FUNC_ENTER_STATIC
893 
894     /* Check args */
895     HDassert(io_info);
896     HDassert(dset_curr_seq);
897     HDassert(dset_len_arr);
898     HDassert(dset_off_arr);
899     HDassert(mem_curr_seq);
900     HDassert(mem_len_arr);
901     HDassert(mem_off_arr);
902 
903     /* Check if data sieving is enabled */
904     if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_DATA_SIEVE)) {
905         H5D_contig_readvv_sieve_ud_t udata; /* User data for H5VM_opvv() operator */
906 
907         /* Set up user data for H5VM_opvv() */
908         udata.f_sh         = io_info->f_sh;
909         udata.dset_contig  = &(io_info->dset->shared->cache.contig);
910         udata.store_contig = &(io_info->store->contig);
911         udata.rbuf         = (unsigned char *)io_info->u.rbuf;
912 
913         /* Call generic sequence operation routine */
914         if ((ret_value =
915                  H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
916                            mem_curr_seq, mem_len_arr, mem_off_arr, H5D__contig_readvv_sieve_cb, &udata)) < 0)
917             HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized sieve buffer read")
918     } /* end if */
919     else {
920         H5D_contig_readvv_ud_t udata; /* User data for H5VM_opvv() operator */
921 
922         /* Set up user data for H5VM_opvv() */
923         udata.f_sh      = io_info->f_sh;
924         udata.dset_addr = io_info->store->contig.dset_addr;
925         udata.rbuf      = (unsigned char *)io_info->u.rbuf;
926 
927         /* Call generic sequence operation routine */
928         if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
929                                    mem_curr_seq, mem_len_arr, mem_off_arr, H5D__contig_readvv_cb, &udata)) <
930             0)
931             HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized read")
932     } /* end else */
933 
934 done:
935     FUNC_LEAVE_NOAPI(ret_value)
936 } /* end H5D__contig_readvv() */
937 
938 /*-------------------------------------------------------------------------
939  * Function:	H5D__contig_writevv_sieve_cb
940  *
941  * Purpose:	Callback operator for H5D__contig_writevv() with sieve buffer.
942  *
943  * Return:	Non-negative on success/Negative on failure
944  *
945  * Programmer:	Quincey Koziol
946  *              Thursday, Sept 30, 2010
947  *
948  *-------------------------------------------------------------------------
949  */
950 static herr_t
H5D__contig_writevv_sieve_cb(hsize_t dst_off,hsize_t src_off,size_t len,void * _udata)951 H5D__contig_writevv_sieve_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
952 {
953     H5D_contig_writevv_sieve_ud_t *udata =
954         (H5D_contig_writevv_sieve_ud_t *)_udata;    /* User data for H5VM_opvv() operator */
955     H5F_shared_t *f_sh        = udata->f_sh;        /* Shared file for dataset */
956     H5D_rdcdc_t * dset_contig = udata->dset_contig; /* Cached information about contiguous data */
957     const H5D_contig_storage_t *store_contig =
958         udata->store_contig;   /* Contiguous storage info for this I/O operation */
959     const unsigned char *buf;  /* Pointer to buffer to fill */
960     haddr_t              addr; /* Actual address to read */
961     haddr_t sieve_start = HADDR_UNDEF, sieve_end = HADDR_UNDEF; /* Start & end locations of sieve buffer */
962     haddr_t contig_end;                                         /* End locations of block to write */
963     size_t  sieve_size = (size_t)-1;                            /* size of sieve buffer */
964     haddr_t rel_eoa;                                            /* Relative end of file address	*/
965     hsize_t max_data;                                           /* Actual maximum size of data to cache */
966     hsize_t min;                 /* temporary minimum value (avoids some ugly macro nesting) */
967     herr_t  ret_value = SUCCEED; /* Return value */
968 
969     FUNC_ENTER_STATIC
970 
971     /* Stash local copies of these values */
972     if (dset_contig->sieve_buf != NULL) {
973         sieve_start = dset_contig->sieve_loc;
974         sieve_size  = dset_contig->sieve_size;
975         sieve_end   = sieve_start + sieve_size;
976     } /* end if */
977 
978     /* Compute offset on disk */
979     addr = store_contig->dset_addr + dst_off;
980 
981     /* Compute offset in memory */
982     buf = udata->wbuf + src_off;
983 
984     /* No data sieve buffer yet, go allocate one */
985     if (NULL == dset_contig->sieve_buf) {
986         /* Check if we can actually hold the I/O request in the sieve buffer */
987         if (len > dset_contig->sieve_buf_size) {
988             if (H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
989                 HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
990         } /* end if */
991         else {
992             /* Allocate room for the data sieve buffer */
993             if (NULL == (dset_contig->sieve_buf = H5FL_BLK_CALLOC(sieve_buf, dset_contig->sieve_buf_size)))
994                 HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed")
995 
996             /* Clear memory */
997             if (dset_contig->sieve_size > len)
998                 HDmemset(dset_contig->sieve_buf + len, 0, (dset_contig->sieve_size - len));
999 
1000             /* Determine the new sieve buffer size & location */
1001             dset_contig->sieve_loc = addr;
1002 
1003             /* Make certain we don't read off the end of the file */
1004             if (HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
1005                 HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
1006 
1007             /* Set up the buffer parameters */
1008             max_data = store_contig->dset_size - dst_off;
1009 
1010             /* Compute the size of the sieve buffer */
1011             min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
1012             H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
1013 
1014             /* Check if there is any point in reading the data from the file */
1015             if (dset_contig->sieve_size > len) {
1016                 /* Read the new sieve buffer */
1017                 if (H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc,
1018                                           dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
1019                     HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
1020             } /* end if */
1021 
1022             /* Grab the data out of the buffer (must be first piece of data in buffer ) */
1023             H5MM_memcpy(dset_contig->sieve_buf, buf, len);
1024 
1025             /* Set sieve buffer dirty flag */
1026             dset_contig->sieve_dirty = TRUE;
1027 
1028             /* Stash local copies of these values */
1029             sieve_start = dset_contig->sieve_loc;
1030             sieve_size  = dset_contig->sieve_size;
1031             sieve_end   = sieve_start + sieve_size;
1032         } /* end else */
1033     }     /* end if */
1034     else {
1035         /* Compute end of sequence to retrieve */
1036         contig_end = addr + len - 1;
1037 
1038         /* If entire write is within the sieve buffer, write it to the buffer */
1039         if (addr >= sieve_start && contig_end < sieve_end) {
1040             unsigned char *base_sieve_buf = dset_contig->sieve_buf + (addr - sieve_start);
1041 
1042             /* Put the data into the sieve buffer */
1043             H5MM_memcpy(base_sieve_buf, buf, len);
1044 
1045             /* Set sieve buffer dirty flag */
1046             dset_contig->sieve_dirty = TRUE;
1047         } /* end if */
1048         /* Entire request is not within this data sieve buffer */
1049         else {
1050             /* Check if we can actually hold the I/O request in the sieve buffer */
1051             if (len > dset_contig->sieve_buf_size) {
1052                 /* Check for any overlap with the current sieve buffer */
1053                 if ((sieve_start >= addr && sieve_start < (contig_end + 1)) ||
1054                     ((sieve_end - 1) >= addr && (sieve_end - 1) < (contig_end + 1))) {
1055                     /* Flush the sieve buffer, if it's dirty */
1056                     if (dset_contig->sieve_dirty) {
1057                         /* Write to file */
1058                         if (H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size,
1059                                                    dset_contig->sieve_buf) < 0)
1060                             HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
1061 
1062                         /* Reset sieve buffer dirty flag */
1063                         dset_contig->sieve_dirty = FALSE;
1064                     } /* end if */
1065 
1066                     /* Force the sieve buffer to be re-read the next time */
1067                     dset_contig->sieve_loc  = HADDR_UNDEF;
1068                     dset_contig->sieve_size = 0;
1069                 } /* end if */
1070 
1071                 /* Write directly from the user's buffer */
1072                 if (H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, addr, len, buf) < 0)
1073                     HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
1074             } /* end if */
1075             /* Element size fits within the buffer size */
1076             else {
1077                 /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */
1078                 if (((addr + len) == sieve_start || addr == sieve_end) &&
1079                     (len + sieve_size) <= dset_contig->sieve_buf_size && dset_contig->sieve_dirty) {
1080                     /* Prepend to existing sieve buffer */
1081                     if ((addr + len) == sieve_start) {
1082                         /* Move existing sieve information to correct location */
1083                         HDmemmove(dset_contig->sieve_buf + len, dset_contig->sieve_buf,
1084                                   dset_contig->sieve_size);
1085 
1086                         /* Copy in new information (must be first in sieve buffer) */
1087                         H5MM_memcpy(dset_contig->sieve_buf, buf, len);
1088 
1089                         /* Adjust sieve location */
1090                         dset_contig->sieve_loc = addr;
1091 
1092                     } /* end if */
1093                     /* Append to existing sieve buffer */
1094                     else {
1095                         /* Copy in new information */
1096                         H5MM_memcpy(dset_contig->sieve_buf + sieve_size, buf, len);
1097                     } /* end else */
1098 
1099                     /* Adjust sieve size */
1100                     dset_contig->sieve_size += len;
1101                 } /* end if */
1102                 /* Can't add the new data onto the existing sieve buffer */
1103                 else {
1104                     /* Flush the sieve buffer if it's dirty */
1105                     if (dset_contig->sieve_dirty) {
1106                         /* Write to file */
1107                         if (H5F_shared_block_write(f_sh, H5FD_MEM_DRAW, sieve_start, sieve_size,
1108                                                    dset_contig->sieve_buf) < 0)
1109                             HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
1110 
1111                         /* Reset sieve buffer dirty flag */
1112                         dset_contig->sieve_dirty = FALSE;
1113                     } /* end if */
1114 
1115                     /* Determine the new sieve buffer size & location */
1116                     dset_contig->sieve_loc = addr;
1117 
1118                     /* Make certain we don't read off the end of the file */
1119                     if (HADDR_UNDEF == (rel_eoa = H5F_shared_get_eoa(f_sh, H5FD_MEM_DRAW)))
1120                         HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to determine file size")
1121 
1122                     /* Only need this when resizing sieve buffer */
1123                     max_data = store_contig->dset_size - dst_off;
1124 
1125                     /* Compute the size of the sieve buffer.
1126                      * Don't read off the end of the file, don't read past
1127                      * the end of the data element, and don't read more than
1128                      * the buffer size.
1129                      */
1130                     min = MIN3(rel_eoa - dset_contig->sieve_loc, max_data, dset_contig->sieve_buf_size);
1131                     H5_CHECKED_ASSIGN(dset_contig->sieve_size, size_t, min, hsize_t);
1132 
1133                     /* Check if there is any point in reading the data from the file */
1134                     if (dset_contig->sieve_size > len) {
1135                         /* Read the new sieve buffer */
1136                         if (H5F_shared_block_read(f_sh, H5FD_MEM_DRAW, dset_contig->sieve_loc,
1137                                                   dset_contig->sieve_size, dset_contig->sieve_buf) < 0)
1138                             HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
1139                     } /* end if */
1140 
1141                     /* Grab the data out of the buffer (must be first piece of data in buffer ) */
1142                     H5MM_memcpy(dset_contig->sieve_buf, buf, len);
1143 
1144                     /* Set sieve buffer dirty flag */
1145                     dset_contig->sieve_dirty = TRUE;
1146                 } /* end else */
1147             }     /* end else */
1148         }         /* end else */
1149     }             /* end else */
1150 
1151 done:
1152     FUNC_LEAVE_NOAPI(ret_value)
1153 } /* end H5D__contig_writevv_sieve_cb() */
1154 
1155 /*-------------------------------------------------------------------------
1156  * Function:	H5D__contig_writevv_cb
1157  *
1158  * Purpose:	Callback operator for H5D__contig_writevv().
1159  *
1160  * Return:	Non-negative on success/Negative on failure
1161  *
1162  * Programmer:	Quincey Koziol
1163  *              Thursday, Sept 30, 2010
1164  *
1165  *-------------------------------------------------------------------------
1166  */
1167 static herr_t
H5D__contig_writevv_cb(hsize_t dst_off,hsize_t src_off,size_t len,void * _udata)1168 H5D__contig_writevv_cb(hsize_t dst_off, hsize_t src_off, size_t len, void *_udata)
1169 {
1170     H5D_contig_writevv_ud_t *udata =
1171         (H5D_contig_writevv_ud_t *)_udata; /* User data for H5VM_opvv() operator */
1172     herr_t ret_value = SUCCEED;            /* Return value */
1173 
1174     FUNC_ENTER_STATIC
1175 
1176     /* Write data */
1177     if (H5F_shared_block_write(udata->f_sh, H5FD_MEM_DRAW, (udata->dset_addr + dst_off), len,
1178                                (udata->wbuf + src_off)) < 0)
1179         HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "block write failed")
1180 
1181 done:
1182     FUNC_LEAVE_NOAPI(ret_value)
1183 } /* end H5D__contig_writevv_cb() */
1184 
1185 /*-------------------------------------------------------------------------
1186  * Function:	H5D__contig_writevv
1187  *
1188  * Purpose:	Writes some data vectors into a dataset from vectors into a
1189  *              buffer.  The address is the start of the dataset,
1190  *              relative to the base address for the file and the offsets and
1191  *              sequence lengths are in bytes.
1192  *
1193  * Return:	Non-negative on success/Negative on failure
1194  *
1195  * Programmer:	Quincey Koziol
1196  *              Friday, May 2, 2003
1197  *
1198  * Notes:
1199  *      Offsets in the sequences must be monotonically increasing
1200  *
1201  *-------------------------------------------------------------------------
1202  */
1203 static ssize_t
H5D__contig_writevv(const H5D_io_info_t * io_info,size_t dset_max_nseq,size_t * dset_curr_seq,size_t dset_len_arr[],hsize_t dset_off_arr[],size_t mem_max_nseq,size_t * mem_curr_seq,size_t mem_len_arr[],hsize_t mem_off_arr[])1204 H5D__contig_writevv(const H5D_io_info_t *io_info, size_t dset_max_nseq, size_t *dset_curr_seq,
1205                     size_t dset_len_arr[], hsize_t dset_off_arr[], size_t mem_max_nseq, size_t *mem_curr_seq,
1206                     size_t mem_len_arr[], hsize_t mem_off_arr[])
1207 {
1208     ssize_t ret_value = -1; /* Return value (Size of sequence in bytes) */
1209 
1210     FUNC_ENTER_STATIC
1211 
1212     /* Check args */
1213     HDassert(io_info);
1214     HDassert(dset_curr_seq);
1215     HDassert(dset_len_arr);
1216     HDassert(dset_off_arr);
1217     HDassert(mem_curr_seq);
1218     HDassert(mem_len_arr);
1219     HDassert(mem_off_arr);
1220 
1221     /* Check if data sieving is enabled */
1222     if (H5F_SHARED_HAS_FEATURE(io_info->f_sh, H5FD_FEAT_DATA_SIEVE)) {
1223         H5D_contig_writevv_sieve_ud_t udata; /* User data for H5VM_opvv() operator */
1224 
1225         /* Set up user data for H5VM_opvv() */
1226         udata.f_sh         = io_info->f_sh;
1227         udata.dset_contig  = &(io_info->dset->shared->cache.contig);
1228         udata.store_contig = &(io_info->store->contig);
1229         udata.wbuf         = (const unsigned char *)io_info->u.wbuf;
1230 
1231         /* Call generic sequence operation routine */
1232         if ((ret_value =
1233                  H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
1234                            mem_curr_seq, mem_len_arr, mem_off_arr, H5D__contig_writevv_sieve_cb, &udata)) < 0)
1235             HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized sieve buffer write")
1236     } /* end if */
1237     else {
1238         H5D_contig_writevv_ud_t udata; /* User data for H5VM_opvv() operator */
1239 
1240         /* Set up user data for H5VM_opvv() */
1241         udata.f_sh      = io_info->f_sh;
1242         udata.dset_addr = io_info->store->contig.dset_addr;
1243         udata.wbuf      = (const unsigned char *)io_info->u.wbuf;
1244 
1245         /* Call generic sequence operation routine */
1246         if ((ret_value = H5VM_opvv(dset_max_nseq, dset_curr_seq, dset_len_arr, dset_off_arr, mem_max_nseq,
1247                                    mem_curr_seq, mem_len_arr, mem_off_arr, H5D__contig_writevv_cb, &udata)) <
1248             0)
1249             HGOTO_ERROR(H5E_DATASET, H5E_CANTOPERATE, FAIL, "can't perform vectorized read")
1250     } /* end else */
1251 
1252 done:
1253     FUNC_LEAVE_NOAPI(ret_value)
1254 } /* end H5D__contig_writevv() */
1255 
1256 /*-------------------------------------------------------------------------
1257  * Function:	H5D__contig_flush
1258  *
1259  * Purpose:	Writes all dirty data to disk.
1260  *
1261  * Return:	Non-negative on success/Negative on failure
1262  *
1263  * Programmer:	Quincey Koziol
1264  *              Monday, July 27, 2009
1265  *
1266  *-------------------------------------------------------------------------
1267  */
1268 static herr_t
H5D__contig_flush(H5D_t * dset)1269 H5D__contig_flush(H5D_t *dset)
1270 {
1271     herr_t ret_value = SUCCEED; /* Return value */
1272 
1273     FUNC_ENTER_STATIC
1274 
1275     /* Sanity check */
1276     HDassert(dset);
1277 
1278     /* Flush any data in sieve buffer */
1279     if (H5D__flush_sieve_buf(dset) < 0)
1280         HGOTO_ERROR(H5E_DATASET, H5E_CANTFLUSH, FAIL, "unable to flush sieve buffer")
1281 
1282 done:
1283     FUNC_LEAVE_NOAPI(ret_value)
1284 } /* end H5D__contig_flush() */
1285 
1286 /*-------------------------------------------------------------------------
1287  * Function:	H5D__contig_copy
1288  *
1289  * Purpose:	Copy contiguous storage raw data from SRC file to DST file.
1290  *
1291  * Return:	Non-negative on success, negative on failure.
1292  *
1293  * Programmer:  Quincey Koziol
1294  *	        Monday, November 21, 2005
1295  *
1296  *-------------------------------------------------------------------------
1297  */
1298 herr_t
H5D__contig_copy(H5F_t * f_src,const H5O_storage_contig_t * storage_src,H5F_t * f_dst,H5O_storage_contig_t * storage_dst,H5T_t * dt_src,H5O_copy_t * cpy_info)1299 H5D__contig_copy(H5F_t *f_src, const H5O_storage_contig_t *storage_src, H5F_t *f_dst,
1300                  H5O_storage_contig_t *storage_dst, H5T_t *dt_src, H5O_copy_t *cpy_info)
1301 {
1302     haddr_t       addr_src;                                    /* File offset in source dataset */
1303     haddr_t       addr_dst;                                    /* File offset in destination dataset */
1304     H5T_path_t *  tpath_src_mem = NULL, *tpath_mem_dst = NULL; /* Datatype conversion paths */
1305     H5T_t *       dt_dst      = NULL;                          /* Destination datatype */
1306     H5T_t *       dt_mem      = NULL;                          /* Memory datatype */
1307     hid_t         tid_src     = -1;                            /* Datatype ID for source datatype */
1308     hid_t         tid_dst     = -1;                            /* Datatype ID for destination datatype */
1309     hid_t         tid_mem     = -1;                            /* Datatype ID for memory datatype */
1310     size_t        src_dt_size = 0;                             /* Source datatype size */
1311     size_t        mem_dt_size = 0;                             /* Memory datatype size */
1312     size_t        dst_dt_size = 0;                             /* Destination datatype size */
1313     size_t        max_dt_size;                                 /* Max. datatype size */
1314     size_t        nelmts = 0;                                  /* Number of elements in buffer */
1315     size_t        src_nbytes;                                  /* Number of bytes to read from source */
1316     size_t        mem_nbytes;                                  /* Number of bytes to convert in memory */
1317     size_t        dst_nbytes;                                  /* Number of bytes to write to destination */
1318     hsize_t       total_src_nbytes;                            /* Total number of bytes to copy */
1319     size_t        buf_size;                                    /* Size of copy buffer */
1320     void *        buf         = NULL;                          /* Buffer for copying data */
1321     void *        bkg         = NULL;                          /* Temporary buffer for copying data */
1322     void *        reclaim_buf = NULL;                          /* Buffer for reclaiming data */
1323     H5S_t *       buf_space   = NULL;                          /* Dataspace describing buffer */
1324     hid_t         buf_sid     = -1;                            /* ID for buffer dataspace */
1325     hsize_t       buf_dim[1]  = {0};                           /* Dimension for buffer */
1326     hbool_t       is_vlen     = FALSE; /* Flag to indicate that VL type conversion should occur */
1327     hbool_t       fix_ref     = FALSE; /* Flag to indicate that ref values should be fixed */
1328     H5D_shared_t *shared_fo =
1329         (H5D_shared_t *)cpy_info->shared_fo; /* Pointer to the shared struct for dataset object */
1330     hbool_t try_sieve   = FALSE;             /* Try to get data from the sieve buffer */
1331     haddr_t sieve_start = HADDR_UNDEF;       /* Start location of sieve buffer */
1332     haddr_t sieve_end   = HADDR_UNDEF;       /* End locations of sieve buffer */
1333     herr_t  ret_value   = SUCCEED;           /* Return value */
1334 
1335     FUNC_ENTER_PACKAGE
1336 
1337     /* Check args */
1338     HDassert(f_src);
1339     HDassert(storage_src);
1340     HDassert(f_dst);
1341     HDassert(storage_dst);
1342     HDassert(dt_src);
1343 
1344     /* Allocate space for destination raw data */
1345     if (H5D__contig_alloc(f_dst, storage_dst) < 0)
1346         HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to allocate contiguous storage")
1347 
1348     /* Set up number of bytes to copy, and initial buffer size */
1349     /* (actually use the destination size, which has been fixed up, if necessary) */
1350     total_src_nbytes = storage_dst->size;
1351     H5_CHECK_OVERFLOW(total_src_nbytes, hsize_t, size_t);
1352     buf_size = MIN(H5D_TEMP_BUF_SIZE, (size_t)total_src_nbytes);
1353 
1354     /* Create datatype ID for src datatype.  We may or may not use this ID,
1355      * but this ensures that the src datatype will be freed.
1356      */
1357     if ((tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
1358         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
1359 
1360     /* If there's a VLEN source datatype, set up type conversion information */
1361     if (H5T_detect_class(dt_src, H5T_VLEN, FALSE) > 0) {
1362         /* create a memory copy of the variable-length datatype */
1363         if (NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
1364             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
1365         if ((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0) {
1366             (void)H5T_close_real(dt_mem);
1367             HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
1368         } /* end if */
1369 
1370         /* create variable-length datatype at the destinaton file */
1371         if (NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
1372             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to copy")
1373         if (H5T_set_loc(dt_dst, H5F_VOL_OBJ(f_dst), H5T_LOC_DISK) < 0) {
1374             (void)H5T_close_real(dt_dst);
1375             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
1376         } /* end if */
1377         if ((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0) {
1378             (void)H5T_close_real(dt_dst);
1379             HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
1380         } /* end if */
1381 
1382         /* Set up the conversion functions */
1383         if (NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem)))
1384             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
1385         if (NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst)))
1386             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
1387 
1388         /* Determine largest datatype size */
1389         if (0 == (src_dt_size = H5T_get_size(dt_src)))
1390             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
1391         if (0 == (mem_dt_size = H5T_get_size(dt_mem)))
1392             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
1393         max_dt_size = MAX(src_dt_size, mem_dt_size);
1394         if (0 == (dst_dt_size = H5T_get_size(dt_dst)))
1395             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to determine datatype size")
1396         max_dt_size = MAX(max_dt_size, dst_dt_size);
1397 
1398         /* Set maximum number of whole elements that fit in buffer */
1399         if (0 == (nelmts = buf_size / max_dt_size))
1400             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "element size too large")
1401 
1402         /* Set the number of bytes to transfer */
1403         src_nbytes = nelmts * src_dt_size;
1404         dst_nbytes = nelmts * dst_dt_size;
1405         mem_nbytes = nelmts * mem_dt_size;
1406 
1407         /* Adjust buffer size to be multiple of elements */
1408         buf_size = nelmts * max_dt_size;
1409 
1410         /* Create dataspace for number of elements in buffer */
1411         buf_dim[0] = nelmts;
1412 
1413         /* Create the space and set the initial extent */
1414         if (NULL == (buf_space = H5S_create_simple((unsigned)1, buf_dim, NULL)))
1415             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
1416 
1417         /* Atomize */
1418         if ((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
1419             H5S_close(buf_space);
1420             HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
1421         } /* end if */
1422 
1423         /* Set flag to do type conversion */
1424         is_vlen = TRUE;
1425     } /* end if */
1426     else {
1427         /* Check for reference datatype */
1428         if (H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
1429             /* Need to fix values of references when copying across files */
1430             if (f_src != f_dst)
1431                 fix_ref = TRUE;
1432         } /* end if */
1433 
1434         /* Set the number of bytes to read & write to the buffer size */
1435         src_nbytes = dst_nbytes = mem_nbytes = buf_size;
1436     } /* end else */
1437 
1438     /* Allocate space for copy buffer */
1439     HDassert(buf_size);
1440     if (NULL == (buf = H5FL_BLK_MALLOC(type_conv, buf_size)))
1441         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer")
1442 
1443     /* Need extra buffer for datatype conversions, to prevent stranding/leaking memory */
1444     if (is_vlen || fix_ref) {
1445         if (NULL == (reclaim_buf = H5FL_BLK_MALLOC(type_conv, buf_size)))
1446             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer")
1447 
1448         /* allocate temporary bkg buff for data conversion */
1449         if (NULL == (bkg = H5FL_BLK_MALLOC(type_conv, buf_size)))
1450             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for copy buffer")
1451     } /* end if */
1452 
1453     /* Loop over copying data */
1454     addr_src = storage_src->addr;
1455     addr_dst = storage_dst->addr;
1456 
1457     /* If data sieving is enabled and the dataset is open in the file,
1458        set up to copy data out of the sieve buffer if deemed possible later */
1459     if (H5F_HAS_FEATURE(f_src, H5FD_FEAT_DATA_SIEVE) && shared_fo && shared_fo->cache.contig.sieve_buf) {
1460         try_sieve   = TRUE;
1461         sieve_start = shared_fo->cache.contig.sieve_loc;
1462         sieve_end   = sieve_start + shared_fo->cache.contig.sieve_size;
1463     }
1464 
1465     while (total_src_nbytes > 0) {
1466         /* Check if we should reduce the number of bytes to transfer */
1467         if (total_src_nbytes < src_nbytes) {
1468             /* Adjust bytes to transfer */
1469             src_nbytes = (size_t)total_src_nbytes;
1470 
1471             /* Adjust dataspace describing buffer */
1472             if (is_vlen) {
1473                 /* Adjust destination & memory bytes to transfer */
1474                 nelmts     = src_nbytes / src_dt_size;
1475                 dst_nbytes = nelmts * dst_dt_size;
1476                 mem_nbytes = nelmts * mem_dt_size;
1477 
1478                 /* Adjust size of buffer's dataspace dimension */
1479                 buf_dim[0] = nelmts;
1480 
1481                 /* Adjust size of buffer's dataspace */
1482                 if (H5S_set_extent_real(buf_space, buf_dim) < 0)
1483                     HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "unable to change buffer dataspace size")
1484             } /* end if */
1485             else
1486                 /* Adjust destination & memory bytes to transfer */
1487                 dst_nbytes = mem_nbytes = src_nbytes;
1488         } /* end if */
1489 
1490         /* If the entire copy is within the sieve buffer, copy data from the sieve buffer */
1491         if (try_sieve && (addr_src >= sieve_start) && ((addr_src + src_nbytes - 1) < sieve_end)) {
1492             unsigned char *base_sieve_buf = shared_fo->cache.contig.sieve_buf + (addr_src - sieve_start);
1493 
1494             H5MM_memcpy(buf, base_sieve_buf, src_nbytes);
1495         }
1496         else
1497             /* Read raw data from source file */
1498             if (H5F_block_read(f_src, H5FD_MEM_DRAW, addr_src, src_nbytes, buf) < 0)
1499             HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "unable to read raw data")
1500 
1501         /* Perform datatype conversion, if necessary */
1502         if (is_vlen) {
1503             /* Convert from source file to memory */
1504             if (H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
1505                 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
1506 
1507             /* Copy into another buffer, to reclaim memory later */
1508             H5MM_memcpy(reclaim_buf, buf, mem_nbytes);
1509 
1510             /* Set background buffer to all zeros */
1511             HDmemset(bkg, 0, buf_size);
1512 
1513             /* Convert from memory to destination file */
1514             if (H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
1515                 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
1516 
1517             /* Reclaim space from variable length data */
1518             if (H5T_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
1519                 HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to reclaim variable-length data")
1520         } /* end if */
1521         else if (fix_ref) {
1522             /* Check for expanding references */
1523             if (cpy_info->expand_ref) {
1524                 /* Copy the reference elements */
1525                 if (H5O_copy_expand_ref(f_src, tid_src, dt_src, buf, buf_size, f_dst, bkg, cpy_info) < 0)
1526                     HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
1527 
1528                 /* After fix ref, copy the new reference elements to the buffer to write out */
1529                 H5MM_memcpy(buf, bkg, buf_size);
1530             } /* end if */
1531             else
1532                 /* Reset value to zero */
1533                 HDmemset(buf, 0, src_nbytes);
1534         } /* end if */
1535 
1536         /* Write raw data to destination file */
1537         if (H5F_block_write(f_dst, H5FD_MEM_DRAW, addr_dst, dst_nbytes, buf) < 0)
1538             HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data")
1539 
1540         /* Adjust loop variables */
1541         addr_src += src_nbytes;
1542         addr_dst += dst_nbytes;
1543         total_src_nbytes -= src_nbytes;
1544     } /* end while */
1545 
1546 done:
1547     if (buf_sid > 0 && H5I_dec_ref(buf_sid) < 0)
1548         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't decrement temporary dataspace ID")
1549     if (tid_src > 0 && H5I_dec_ref(tid_src) < 0)
1550         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
1551     if (tid_dst > 0 && H5I_dec_ref(tid_dst) < 0)
1552         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
1553     if (tid_mem > 0 && H5I_dec_ref(tid_mem) < 0)
1554         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
1555     if (buf)
1556         buf = H5FL_BLK_FREE(type_conv, buf);
1557     if (reclaim_buf)
1558         reclaim_buf = H5FL_BLK_FREE(type_conv, reclaim_buf);
1559     if (bkg)
1560         bkg = H5FL_BLK_FREE(type_conv, bkg);
1561 
1562     FUNC_LEAVE_NOAPI(ret_value)
1563 } /* end H5D__contig_copy() */
1564