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