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://support.hdfgroup.org/ftp/HDF5/releases.  *
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:  Raymond Lu <slu@ncsa.uiuc.edu>
16  *              August 5, 2002
17  *
18  * Purpose:     Compact dataset I/O functions.  These routines are similar
19  *              H5D_contig_* and H5D_chunk_*.
20  */
21 
22 /****************/
23 /* Module Setup */
24 /****************/
25 
26 #include "H5Dmodule.h"          /* This source code file is part of the H5D module */
27 
28 
29 /***********/
30 /* Headers */
31 /***********/
32 #include "H5private.h"		/* Generic Functions			*/
33 #include "H5Dpkg.h"		/* Dataset functions			*/
34 #include "H5Eprivate.h"		/* Error handling		  	*/
35 #include "H5Fprivate.h"		/* Files				*/
36 #include "H5FDprivate.h"	/* File drivers				*/
37 #include "H5FLprivate.h"	/* Free Lists                           */
38 #include "H5Iprivate.h"		/* IDs			  		*/
39 #include "H5MMprivate.h"	/* Memory management			*/
40 #include "H5Oprivate.h"		/* Object headers		  	*/
41 #include "H5VMprivate.h"		/* Vector and array functions		*/
42 
43 
44 /****************/
45 /* Local Macros */
46 /****************/
47 
48 
49 /******************/
50 /* Local Typedefs */
51 /******************/
52 
53 
54 /********************/
55 /* Local Prototypes */
56 /********************/
57 
58 /* Layout operation callbacks */
59 static herr_t H5D__compact_construct(H5F_t *f, H5D_t *dset);
60 static hbool_t H5D__compact_is_space_alloc(const H5O_storage_t *storage);
61 static herr_t H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
62     hsize_t nelmts, const H5S_t *file_space, const H5S_t *mem_space,
63     H5D_chunk_map_t *cm);
64 static ssize_t H5D__compact_readvv(const H5D_io_info_t *io_info,
65     size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
66     size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
67 static ssize_t H5D__compact_writevv(const H5D_io_info_t *io_info,
68     size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
69     size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
70 static herr_t H5D__compact_flush(H5D_t *dset);
71 static herr_t H5D__compact_dest(H5D_t *dset);
72 
73 
74 /*********************/
75 /* Package Variables */
76 /*********************/
77 
78 /* Compact storage layout I/O ops */
79 const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{
80     H5D__compact_construct,
81     NULL,
82     H5D__compact_is_space_alloc,
83     NULL,
84     H5D__compact_io_init,
85     H5D__contig_read,
86     H5D__contig_write,
87 #ifdef H5_HAVE_PARALLEL
88     NULL,
89     NULL,
90 #endif /* H5_HAVE_PARALLEL */
91     H5D__compact_readvv,
92     H5D__compact_writevv,
93     H5D__compact_flush,
94     NULL,
95     H5D__compact_dest
96 }};
97 
98 
99 /*******************/
100 /* Local Variables */
101 /*******************/
102 
103 /* Declare extern the free list to manage blocks of type conversion data */
104 H5FL_BLK_EXTERN(type_conv);
105 
106 
107 
108 /*-------------------------------------------------------------------------
109  * Function:	H5D__compact_fill
110  *
111  * Purpose:	Write fill values to a compactly stored dataset.
112  *
113  * Return:	Non-negative on success/Negative on failure
114  *
115  * Programmer:	Quincey Koziol
116  *		May 6, 2007
117  *
118  *-------------------------------------------------------------------------
119  */
120 herr_t
H5D__compact_fill(const H5D_t * dset)121 H5D__compact_fill(const H5D_t *dset)
122 {
123     H5D_fill_buf_info_t fb_info;        /* Dataset's fill buffer info */
124     hbool_t     fb_info_init = FALSE;   /* Whether the fill value buffer has been initialized */
125     herr_t	ret_value = SUCCEED;	/* Return value */
126 
127     FUNC_ENTER_PACKAGE
128 
129     /* Check args */
130     HDassert(dset && H5D_COMPACT == dset->shared->layout.type);
131     HDassert(dset->shared->layout.storage.u.compact.buf);
132     HDassert(dset->shared->type);
133     HDassert(dset->shared->space);
134 
135     /* Initialize the fill value buffer */
136     /* (use the compact dataset storage buffer as the fill value buffer) */
137     if(H5D__fill_init(&fb_info, dset->shared->layout.storage.u.compact.buf,
138             NULL, NULL, NULL, NULL,
139             &dset->shared->dcpl_cache.fill, dset->shared->type,
140             dset->shared->type_id, (size_t)0, dset->shared->layout.storage.u.compact.size) < 0)
141         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
142     fb_info_init = TRUE;
143 
144     /* Check for VL datatype & non-default fill value */
145     if(fb_info.has_vlen_fill_type)
146         /* Fill the buffer with VL datatype fill values */
147         if(H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf) < 0)
148             HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "can't refill fill value buffer")
149 
150 done:
151     /* Release the fill buffer info, if it's been initialized */
152     if(fb_info_init && H5D__fill_term(&fb_info) < 0)
153         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
154 
155     FUNC_LEAVE_NOAPI(ret_value)
156 } /* end H5D__compact_fill() */
157 
158 
159 /*-------------------------------------------------------------------------
160  * Function:	H5D__compact_construct
161  *
162  * Purpose:	Constructs new compact layout information for dataset
163  *
164  * Return:	Non-negative on success/Negative on failure
165  *
166  * Programmer:	Quincey Koziol
167  *              Thursday, May 22, 2008
168  *
169  *-------------------------------------------------------------------------
170  */
171 static herr_t
H5D__compact_construct(H5F_t * f,H5D_t * dset)172 H5D__compact_construct(H5F_t *f, H5D_t *dset)
173 {
174     hssize_t stmp_size;         /* Temporary holder for raw data size */
175     hsize_t tmp_size;           /* Temporary holder for raw data size */
176     hsize_t max_comp_data_size; /* Max. allowed size of compact data */
177     unsigned u;                 /* Local index variable */
178     herr_t ret_value = SUCCEED; /* Return value */
179 
180     FUNC_ENTER_STATIC
181 
182     /* Sanity checks */
183     HDassert(f);
184     HDassert(dset);
185 
186     /* Check for invalid dataset dimensions */
187     for(u = 0; u < dset->shared->ndims; u++)
188         if(dset->shared->max_dims[u] > dset->shared->curr_dims[u])
189             HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "extendible compact dataset not allowed")
190 
191     /*
192      * Compact dataset is stored in dataset object header message of
193      * layout.
194      */
195     stmp_size = H5S_GET_EXTENT_NPOINTS(dset->shared->space);
196     HDassert(stmp_size >= 0);
197     tmp_size = H5T_get_size(dset->shared->type);
198     HDassert(tmp_size > 0);
199     tmp_size = tmp_size * (hsize_t)stmp_size;
200     H5_CHECKED_ASSIGN(dset->shared->layout.storage.u.compact.size, size_t, tmp_size, hssize_t);
201 
202     /* Verify data size is smaller than maximum header message size
203      * (64KB) minus other layout message fields.
204      */
205     max_comp_data_size = H5O_MESG_MAX_SIZE - H5D__layout_meta_size(f, &(dset->shared->layout), FALSE);
206     if(dset->shared->layout.storage.u.compact.size > max_comp_data_size)
207         HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "compact dataset size is bigger than header message maximum size")
208 
209 done:
210     FUNC_LEAVE_NOAPI(ret_value)
211 } /* end H5D__compact_construct() */
212 
213 
214 /*-------------------------------------------------------------------------
215  * Function:	H5D__compact_is_space_alloc
216  *
217  * Purpose:	Query if space is allocated for layout
218  *
219  * Return:	Non-negative on success/Negative on failure
220  *
221  * Programmer:	Quincey Koziol
222  *              Thursday, January 15, 2009
223  *
224  *-------------------------------------------------------------------------
225  */
226 static hbool_t
H5D__compact_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED * storage)227 H5D__compact_is_space_alloc(const H5O_storage_t H5_ATTR_UNUSED *storage)
228 {
229     FUNC_ENTER_STATIC_NOERR
230 
231     /* Sanity checks */
232     HDassert(storage);
233 
234     /* Compact storage is currently always allocated */
235     FUNC_LEAVE_NOAPI(TRUE)
236 } /* end H5D__compact_is_space_alloc() */
237 
238 
239 /*-------------------------------------------------------------------------
240  * Function:	H5D__compact_io_init
241  *
242  * Purpose:	Performs initialization before any sort of I/O on the raw data
243  *
244  * Return:	Non-negative on success/Negative on failure
245  *
246  * Programmer:	Quincey Koziol
247  *              Thursday, March 20, 2008
248  *
249  *-------------------------------------------------------------------------
250  */
251 static herr_t
H5D__compact_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)252 H5D__compact_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t H5_ATTR_UNUSED *type_info,
253     hsize_t H5_ATTR_UNUSED nelmts, const H5S_t H5_ATTR_UNUSED *file_space, const H5S_t H5_ATTR_UNUSED *mem_space,
254     H5D_chunk_map_t H5_ATTR_UNUSED *cm)
255 {
256     FUNC_ENTER_STATIC_NOERR
257 
258     io_info->store->compact.buf = io_info->dset->shared->layout.storage.u.compact.buf;
259     io_info->store->compact.dirty = &io_info->dset->shared->layout.storage.u.compact.dirty;
260 
261     FUNC_LEAVE_NOAPI(SUCCEED)
262 } /* end H5D__compact_io_init() */
263 
264 
265 /*-------------------------------------------------------------------------
266  * Function:    H5D__compact_readvv
267  *
268  * Purpose:     Reads some data vectors from a dataset into a buffer.
269  *              The data is in compact dataset.  The address is relative
270  *              to the beginning address of the dataset.  The offsets and
271  *              sequence lengths are in bytes.
272  *
273  * Return:      Non-negative on success/Negative on failure
274  *
275  * Programmer:  Quincey Koziol
276  *              May 7, 2003
277  *
278  * Notes:
279  *              Offsets in the sequences must be monotonically increasing
280  *
281  *-------------------------------------------------------------------------
282  */
283 static ssize_t
H5D__compact_readvv(const H5D_io_info_t * io_info,size_t dset_max_nseq,size_t * dset_curr_seq,size_t dset_size_arr[],hsize_t dset_offset_arr[],size_t mem_max_nseq,size_t * mem_curr_seq,size_t mem_size_arr[],hsize_t mem_offset_arr[])284 H5D__compact_readvv(const H5D_io_info_t *io_info,
285     size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
286     size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
287 {
288     ssize_t ret_value = -1;     /* Return value */
289 
290     FUNC_ENTER_STATIC
291 
292     HDassert(io_info);
293 
294     /* Use the vectorized memory copy routine to do actual work */
295     if((ret_value = H5VM_memcpyvv(io_info->u.rbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr, io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr)) < 0)
296         HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
297 
298 done:
299     FUNC_LEAVE_NOAPI(ret_value)
300 }   /* end H5D__compact_readvv() */
301 
302 
303 /*-------------------------------------------------------------------------
304  * Function:    H5D__compact_writevv
305  *
306  * Purpose:     Writes some data vectors from a dataset into a buffer.
307  *              The data is in compact dataset.  The address is relative
308  *              to the beginning address for the file.  The offsets and
309  *              sequence lengths are in bytes.  This function only copies
310  *              data into the buffer in the LAYOUT struct and mark it
311  *              as DIRTY.  Later in H5D_close, the data is copied into
312  *              header message in memory.
313  *
314  * Return:      Non-negative on success/Negative on failure
315  *
316  * Programmer:  Quincey Koziol
317  *              May 2, 2003
318  *
319  * Notes:
320  *              Offsets in the sequences must be monotonically increasing
321  *
322  *-------------------------------------------------------------------------
323  */
324 static ssize_t
H5D__compact_writevv(const H5D_io_info_t * io_info,size_t dset_max_nseq,size_t * dset_curr_seq,size_t dset_size_arr[],hsize_t dset_offset_arr[],size_t mem_max_nseq,size_t * mem_curr_seq,size_t mem_size_arr[],hsize_t mem_offset_arr[])325 H5D__compact_writevv(const H5D_io_info_t *io_info,
326     size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
327     size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[])
328 {
329     ssize_t ret_value = -1;             /* Return value */
330 
331     FUNC_ENTER_STATIC
332 
333     HDassert(io_info);
334 
335     /* Use the vectorized memory copy routine to do actual work */
336     if((ret_value = H5VM_memcpyvv(io_info->store->compact.buf, dset_max_nseq, dset_curr_seq, dset_size_arr, dset_offset_arr, io_info->u.wbuf, mem_max_nseq, mem_curr_seq, mem_size_arr, mem_offset_arr)) < 0)
337         HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed")
338 
339     /* Mark the compact dataset's buffer as dirty */
340     *io_info->store->compact.dirty = TRUE;
341 
342 done:
343     FUNC_LEAVE_NOAPI(ret_value)
344 }   /* end H5D__compact_writevv() */
345 
346 
347 /*-------------------------------------------------------------------------
348  * Function:	H5D__compact_flush
349  *
350  * Purpose:	Writes dirty compact data to object header
351  *
352  * Return:	Non-negative on success/Negative on failure
353  *
354  * Programmer:	Quincey Koziol
355  *              Monday, July 27, 2009
356  *
357  *-------------------------------------------------------------------------
358  */
359 static herr_t
H5D__compact_flush(H5D_t * dset)360 H5D__compact_flush(H5D_t *dset)
361 {
362     herr_t ret_value = SUCCEED;       /* Return value */
363 
364     FUNC_ENTER_STATIC
365 
366     /* Sanity check */
367     HDassert(dset);
368 
369     /* Check if the buffered compact information is dirty */
370     if(dset->shared->layout.storage.u.compact.dirty) {
371         dset->shared->layout.storage.u.compact.dirty = FALSE;
372         if(H5O_msg_write(&(dset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dset->shared->layout)) < 0) {
373             dset->shared->layout.storage.u.compact.dirty = TRUE;
374             HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message")
375         }
376     } /* end if */
377 
378 done:
379     FUNC_LEAVE_NOAPI(ret_value)
380 } /* end H5D__compact_flush() */
381 
382 
383 /*-------------------------------------------------------------------------
384  * Function:	H5D__compact_dest
385  *
386  * Purpose:	Free the compact buffer
387  *
388  * Return:	Non-negative on success/Negative on failure
389  *
390  * Programmer:	Quincey Koziol
391  *              Thursday, Sept 3, 2015
392  *
393  *-------------------------------------------------------------------------
394  */
395 static herr_t
H5D__compact_dest(H5D_t * dset)396 H5D__compact_dest(H5D_t *dset)
397 {
398     FUNC_ENTER_STATIC_NOERR
399 
400     /* Sanity check */
401     HDassert(dset);
402 
403     /* Free the buffer for the raw data for compact datasets */
404     dset->shared->layout.storage.u.compact.buf = H5MM_xfree(dset->shared->layout.storage.u.compact.buf);
405 
406     FUNC_LEAVE_NOAPI(SUCCEED)
407 } /* end H5D__compact_dest() */
408 
409 
410 /*-------------------------------------------------------------------------
411  * Function:    H5D__compact_copy
412  *
413  * Purpose:     Copy compact storage raw data from SRC file to DST file.
414  *
415  * Return:      Non-negative on success, negative on failure.
416  *
417  * Programmer:  Peter Cao
418  *              December 11, 2005
419  *
420  *-------------------------------------------------------------------------
421  */
422 herr_t
H5D__compact_copy(H5F_t * f_src,H5O_storage_compact_t * _storage_src,H5F_t * f_dst,H5O_storage_compact_t * storage_dst,H5T_t * dt_src,H5O_copy_t * cpy_info)423 H5D__compact_copy(H5F_t *f_src, H5O_storage_compact_t *_storage_src, H5F_t *f_dst,
424     H5O_storage_compact_t *storage_dst, H5T_t *dt_src, H5O_copy_t *cpy_info)
425 {
426     hid_t       tid_src = -1;           /* Datatype ID for source datatype */
427     hid_t       tid_dst = -1;           /* Datatype ID for destination datatype */
428     hid_t       tid_mem = -1;           /* Datatype ID for memory datatype */
429     void       *buf = NULL;             /* Buffer for copying data */
430     void       *bkg = NULL;             /* Temporary buffer for copying data */
431     void       *reclaim_buf = NULL;     /* Buffer for reclaiming data */
432     hid_t       buf_sid = -1;           /* ID for buffer dataspace */
433     H5D_shared_t    *shared_fo = (H5D_shared_t *)cpy_info->shared_fo;   /* Pointer to the shared struct for dataset object */
434     H5O_storage_compact_t *storage_src = _storage_src;  /* Pointer to storage_src */
435     herr_t      ret_value = SUCCEED;    /* Return value */
436 
437     FUNC_ENTER_PACKAGE
438 
439     /* Check args */
440     HDassert(f_src);
441     HDassert(storage_src);
442     HDassert(f_dst);
443     HDassert(storage_dst);
444     HDassert(storage_dst->buf);
445     HDassert(dt_src);
446 
447     /* If the dataset is open in the file, point to "layout" in the shared struct */
448     if(shared_fo != NULL)
449         storage_src = &(shared_fo->layout.storage.u.compact);
450 
451     /* Create datatype ID for src datatype, so it gets freed */
452     if((tid_src = H5I_register(H5I_DATATYPE, dt_src, FALSE)) < 0)
453         HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register source file datatype")
454 
455     /* If there's a VLEN source datatype, do type conversion information */
456     if(H5T_detect_class(dt_src, H5T_VLEN, FALSE) > 0) {
457         H5T_path_t  *tpath_src_mem, *tpath_mem_dst;   /* Datatype conversion paths */
458         H5T_t *dt_dst;              /* Destination datatype */
459         H5T_t *dt_mem;              /* Memory datatype */
460         H5S_t *buf_space;           /* Dataspace describing buffer */
461         size_t buf_size;            /* Size of copy buffer */
462         size_t nelmts;              /* Number of elements in buffer */
463         size_t src_dt_size;         /* Source datatype size */
464         size_t tmp_dt_size;         /* Temporary datatype size */
465         size_t max_dt_size;         /* Max atatype size */
466         hsize_t buf_dim;            /* Dimension for buffer */
467 
468         /* create a memory copy of the variable-length datatype */
469         if(NULL == (dt_mem = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
470             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
471         if((tid_mem = H5I_register(H5I_DATATYPE, dt_mem, FALSE)) < 0) {
472             (void)H5T_close_real(dt_mem);
473             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register memory datatype")
474         } /* end if */
475 
476         /* create variable-length datatype at the destinaton file */
477         if(NULL == (dt_dst = H5T_copy(dt_src, H5T_COPY_TRANSIENT)))
478             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy")
479         if(H5T_set_loc(dt_dst, f_dst, H5T_LOC_DISK) < 0) {
480             (void)H5T_close_real(dt_dst);
481             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
482         } /* end if */
483         if((tid_dst = H5I_register(H5I_DATATYPE, dt_dst, FALSE)) < 0) {
484             (void)H5T_close_real(dt_dst);
485             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register destination file datatype")
486         } /* end if */
487 
488         /* Set up the conversion functions */
489         if(NULL == (tpath_src_mem = H5T_path_find(dt_src, dt_mem)))
490             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between src and mem datatypes")
491         if(NULL == (tpath_mem_dst = H5T_path_find(dt_mem, dt_dst)))
492             HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to convert between mem and dst datatypes")
493 
494         /* Determine largest datatype size */
495         if(0 == (src_dt_size = H5T_get_size(dt_src)))
496             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
497         if(0 == (tmp_dt_size = H5T_get_size(dt_mem)))
498             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
499         max_dt_size = MAX(src_dt_size, tmp_dt_size);
500         if(0 == (tmp_dt_size = H5T_get_size(dt_dst)))
501             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to determine datatype size")
502         max_dt_size = MAX(max_dt_size, tmp_dt_size);
503 
504         /* Set number of whole elements that fit in buffer */
505         if(0 == (nelmts = storage_src->size / src_dt_size))
506             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "element size too large")
507 
508         /* Set up number of bytes to copy, and initial buffer size */
509         buf_size = nelmts * max_dt_size;
510 
511         /* Create dataspace for number of elements in buffer */
512         buf_dim = nelmts;
513 
514         /* Create the space and set the initial extent */
515         if(NULL == (buf_space = H5S_create_simple((unsigned)1, &buf_dim, NULL)))
516             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
517 
518         /* Atomize */
519         if((buf_sid = H5I_register(H5I_DATASPACE, buf_space, FALSE)) < 0) {
520             H5S_close(buf_space);
521             HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID")
522         } /* end if */
523 
524         /* Allocate memory for recclaim buf */
525         if(NULL == (reclaim_buf = H5FL_BLK_MALLOC(type_conv, buf_size)))
526             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
527 
528         /* Allocate memory for copying the chunk */
529         if(NULL == (buf = H5FL_BLK_MALLOC(type_conv, buf_size)))
530             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
531 
532         HDmemcpy(buf, storage_src->buf, storage_src->size);
533 
534         /* allocate temporary bkg buff for data conversion */
535         if(NULL == (bkg = H5FL_BLK_MALLOC(type_conv, buf_size)))
536             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
537 
538         /* Convert from source file to memory */
539         if(H5T_convert(tpath_src_mem, tid_src, tid_mem, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
540             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
541 
542         /* Copy into another buffer, to reclaim memory later */
543         HDmemcpy(reclaim_buf, buf, buf_size);
544 
545         /* Set background buffer to all zeros */
546         HDmemset(bkg, 0, buf_size);
547 
548         /* Convert from memory to destination file */
549         if(H5T_convert(tpath_mem_dst, tid_mem, tid_dst, nelmts, (size_t)0, (size_t)0, buf, bkg) < 0)
550             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "datatype conversion failed")
551 
552         HDmemcpy(storage_dst->buf, buf, storage_dst->size);
553 
554         if(H5D_vlen_reclaim(tid_mem, buf_space, reclaim_buf) < 0)
555             HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to reclaim variable-length data")
556     } /* end if */
557     else if(H5T_get_class(dt_src, FALSE) == H5T_REFERENCE) {
558         if(f_src != f_dst) {
559             /* Check for expanding references */
560             if(cpy_info->expand_ref) {
561                 size_t ref_count;
562 
563                 /* Determine # of reference elements to copy */
564                 ref_count = storage_src->size / H5T_get_size(dt_src);
565 
566                 /* Copy objects referenced in source buffer to destination file and set destination elements */
567                 if(H5O_copy_expand_ref(f_src, storage_src->buf, f_dst,
568                         storage_dst->buf, ref_count, H5T_get_ref_type(dt_src), cpy_info) < 0)
569                     HGOTO_ERROR(H5E_DATASET, H5E_CANTCOPY, FAIL, "unable to copy reference attribute")
570             } /* end if */
571             else
572                 /* Reset value to zero */
573                 HDmemset(storage_dst->buf, 0, storage_src->size);
574         } /* end if */
575         else
576             /* Type conversion not necessary */
577             HDmemcpy(storage_dst->buf, storage_src->buf, storage_src->size);
578     } /* end if */
579     else
580         /* Type conversion not necessary */
581         HDmemcpy(storage_dst->buf, storage_src->buf, storage_src->size);
582 
583     /* Mark destination buffer as dirty */
584     storage_dst->dirty = TRUE;
585 
586 done:
587     if(buf_sid > 0 && H5I_dec_ref(buf_sid) < 0)
588         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't decrement temporary dataspace ID")
589     if(tid_src > 0 && H5I_dec_ref(tid_src) < 0)
590         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
591     if(tid_dst > 0 && H5I_dec_ref(tid_dst) < 0)
592         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
593     if(tid_mem > 0 && H5I_dec_ref(tid_mem) < 0)
594         HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't decrement temporary datatype ID")
595     if(buf)
596         buf = H5FL_BLK_FREE(type_conv, buf);
597     if(reclaim_buf)
598         reclaim_buf = H5FL_BLK_FREE(type_conv, reclaim_buf);
599     if(bkg)
600         bkg = H5FL_BLK_FREE(type_conv, bkg);
601 
602     FUNC_LEAVE_NOAPI(ret_value)
603 } /* end H5D__compact_copy() */
604 
605