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 /* High-level library internal header file */
15 #include "H5HLprivate2.h"
16 
17 /* public LT prototypes			*/
18 #include "H5DOpublic.h"
19 
20 #ifndef H5_NO_DEPRECATED_SYMBOLS
21 
22 /*-------------------------------------------------------------------------
23  * Function:    H5DOwrite_chunk
24  *
25  * Purpose:     Writes an entire chunk to the file directly.
26  *
27  *              The H5DOwrite_chunk() call was moved to H5Dwrite_chunk. This
28  *              simple wrapper remains so that people can still link to the
29  *              high-level library without changing their code.
30  *
31  * Return:      Non-negative on success/Negative on failure
32  *
33  *-------------------------------------------------------------------------
34  */
35 herr_t
H5DOwrite_chunk(hid_t dset_id,hid_t dxpl_id,uint32_t filters,const hsize_t * offset,size_t data_size,const void * buf)36 H5DOwrite_chunk(hid_t dset_id, hid_t dxpl_id, uint32_t filters, const hsize_t *offset,
37          size_t data_size, const void *buf)
38 {
39     /* Call underlying H5D function */
40     if (H5Dwrite_chunk(dset_id, dxpl_id, filters, offset, data_size, buf) < 0)
41         return FAIL;
42     else
43         return SUCCEED;
44 
45 } /* end H5DOwrite_chunk() */
46 
47 
48 /*-------------------------------------------------------------------------
49  * Function:    H5DOread_chunk
50  *
51  * Purpose:     Reads an entire chunk from the file directly.
52  *
53  *              The H5DOread_chunk() call was moved to H5Dread_chunk. This
54  *              simple wrapper remains so that people can still link to the
55  *              high-level library without changing their code.
56  *
57  * Return:      Non-negative on success/Negative on failure
58  *
59  *---------------------------------------------------------------------------
60  */
61 herr_t
H5DOread_chunk(hid_t dset_id,hid_t dxpl_id,const hsize_t * offset,uint32_t * filters,void * buf)62 H5DOread_chunk(hid_t dset_id, hid_t dxpl_id, const hsize_t *offset, uint32_t *filters,
63          void *buf)
64 {
65     /* Call underlying H5D function */
66     if (H5Dread_chunk(dset_id, dxpl_id, offset, filters, buf) < 0)
67         return FAIL;
68     else
69         return SUCCEED;
70  } /* end H5DOread_chunk() */
71 
72 #endif /* H5_NO_DEPRECATED_SYMBOLS */
73 
74 
75 /*-------------------------------------------------------------------------
76  * Function:    H5DOappend()
77  *
78  * Purpose:     To append elements to a dataset.
79  *
80  *      axis:       the dataset dimension (zero-based) for the append
81  *      extension:  the # of elements to append for the axis-th dimension
82  *      memtype:    the datatype
83  *      buf:        buffer with data for the append
84  *
85  * Return:      Non-negative on success/Negative on failure
86  *
87  * Programmer:  Vailin Choi; Jan 2014
88  *
89  * Note:
90  * 	This routine is copied from the fast forward feature branch: features/hdf5_ff
91  *	src/H5FF.c:H5DOappend() with the following modifications:
92  * 	1) Remove and replace macro calls such as
93  *		FUNC_ENTER_API, H5TRACE, HGOTO_ERROR
94  * 	   accordingly because hl does not have these macros
95  *	2) Replace H5I_get_type() by H5Iget_type()
96  *	3) Replace H5P_isa_class() by H5Pisa_class()
97  *	4) Fix a bug in the following: replace extension by size[axis]
98  *		if(extension < old_size) {
99  *		  ret_value = FAIL;
100  *		  goto done;
101  *   		}
102  *
103  *-------------------------------------------------------------------------
104  */
105 herr_t
H5DOappend(hid_t dset_id,hid_t dxpl_id,unsigned axis,size_t extension,hid_t memtype,const void * buf)106 H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension,
107            hid_t memtype, const void *buf)
108 {
109     hbool_t created_dxpl = FALSE;       /* Whether we created a DXPL */
110     hsize_t size[H5S_MAX_RANK];		/* The new size (after extension */
111     hsize_t old_size = 0; 		/* The size of the dimension to be extended */
112     int sndims; 			/* Number of dimensions in dataspace (signed) */
113     unsigned ndims; 			/* Number of dimensions in dataspace */
114     hid_t space_id = FAIL; 		/* Old file space */
115     hid_t new_space_id = FAIL; 		/* New file space (after extension) */
116     hid_t mem_space_id = FAIL; 		/* Memory space for data buffer */
117     hssize_t snelmts; 			/* Number of elements in selection (signed) */
118     hsize_t nelmts; 			/* Number of elements in selection */
119     hid_t dapl = FAIL;			/* Dataset access property list */
120 
121     hsize_t start[H5S_MAX_RANK];	/* H5Sselect_Hyperslab: starting offset */
122     hsize_t count[H5S_MAX_RANK];	/* H5Sselect_hyperslab: # of blocks to select */
123     hsize_t stride[H5S_MAX_RANK];	/* H5Sselect_hyperslab: # of elements to move when selecting */
124     hsize_t block[H5S_MAX_RANK];	/* H5Sselect_hyperslab: # of elements in a block */
125 
126     hsize_t *boundary = NULL;		/* Boundary set in append flush property */
127     H5D_append_cb_t append_cb;		/* Callback function set in append flush property */
128     void *udata;			/* User data set in append flush property */
129     hbool_t hit = FALSE;		/* Boundary is hit or not */
130     hsize_t k;				/* Local index variable */
131     unsigned u; 		        /* Local index variable */
132     herr_t ret_value = FAIL;		/* Return value */
133 
134     /* check arguments */
135     if(H5I_DATASET != H5Iget_type(dset_id))
136         goto done;
137 
138     /* If the user passed in a default DXPL, create one to pass to H5Dwrite() */
139     if(H5P_DEFAULT == dxpl_id) {
140         if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0)
141             goto done;
142         created_dxpl = TRUE;
143     } /* end if */
144     else if(TRUE != H5Pisa_class(dxpl_id, H5P_DATASET_XFER))
145         goto done;
146 
147     /* Get the dataspace of the dataset */
148     if(FAIL == (space_id = H5Dget_space(dset_id)))
149         goto done;
150 
151     /* Get the rank of this dataspace */
152     if((sndims = H5Sget_simple_extent_ndims(space_id)) < 0)
153         goto done;
154     ndims = (unsigned)sndims;
155 
156     /* Verify correct axis */
157     if(axis >= ndims)
158         goto done;
159 
160     /* Get the dimensions sizes of the dataspace */
161     if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0)
162         goto done;
163 
164     /* Adjust the dimension size of the requested dimension,
165      * but first record the old dimension size
166      */
167     old_size = size[axis];
168     size[axis] += extension;
169     if(size[axis] < old_size)
170         goto done;
171 
172     /* Set the extent of the dataset to the new dimension */
173     if(H5Dset_extent(dset_id, size) < 0)
174         goto done;
175 
176     /* Get the new dataspace of the dataset */
177     if(FAIL == (new_space_id = H5Dget_space(dset_id)))
178         goto done;
179 
180     /* Select a hyperslab corresponding to the append operation */
181     for(u = 0 ; u < ndims ; u++) {
182         start[u] = 0;
183         stride[u] = 1;
184         count[u] = size[u];
185         block[u] = 1;
186         if(u == axis) {
187             count[u] = extension;
188             start[u] = old_size;
189         } /* end if */
190     } /* end for */
191     if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block))
192         goto done;
193 
194     /* The # of elemnts in the new extended dataspace */
195     if((snelmts = H5Sget_select_npoints(new_space_id)) < 0)
196         goto done;
197     nelmts = (hsize_t)snelmts;
198 
199     /* create a memory space */
200     if(FAIL == (mem_space_id = H5Screate_simple(1, &nelmts, NULL)))
201         goto done;
202 
203     /* Write the data */
204     if(H5Dwrite(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf) < 0)
205         goto done;
206 
207     /* Obtain the dataset's access property list */
208     if((dapl = H5Dget_access_plist(dset_id)) < 0)
209         goto done;
210 
211     /* Allocate the boundary array */
212     boundary = (hsize_t *)HDmalloc(ndims * sizeof(hsize_t));
213 
214     /* Retrieve the append flush property */
215     if(H5Pget_append_flush(dapl, ndims, boundary, &append_cb, &udata) < 0)
216         goto done;
217 
218     /* No boundary for this axis */
219     if(boundary[axis] != 0) {
220 
221         /* Determine whether a boundary is hit or not */
222         for(k = start[axis]; k < size[axis]; k++)
223             if(!((k + 1) % boundary[axis])) {
224                 hit = TRUE;
225                 break;
226             }
227 
228         if(hit) { /* Hit the boundary */
229             /* Invoke callback if there is one */
230             if(append_cb && append_cb(dset_id, size, udata) < 0)
231                 goto done;
232 
233 	        /* Do a dataset flush */
234             if(H5Dflush(dset_id) < 0)
235                 goto done;
236         } /* end if */
237     } /* end if */
238 
239     /* Indicate success */
240     ret_value = SUCCEED;
241 
242 done:
243     /* Close dxpl if we created it vs. one was passed in */
244     if(created_dxpl) {
245         if(H5Pclose(dxpl_id) < 0)
246             ret_value = FAIL;
247     } /* end if */
248 
249     /* Close old dataspace */
250     if(space_id != FAIL && H5Sclose(space_id) < 0)
251         ret_value = FAIL;
252 
253     /* Close new dataspace */
254     if(new_space_id != FAIL && H5Sclose(new_space_id) < 0)
255         ret_value = FAIL;
256 
257     /* Close memory dataspace */
258     if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0)
259         ret_value = FAIL;
260 
261     /* Close the dataset access property list */
262     if(dapl != FAIL && H5Pclose(dapl) < 0)
263         ret_value = FAIL;
264 
265     if(boundary)
266         HDfree(boundary);
267 
268     return ret_value;
269 } /* H5DOappend() */
270 
271