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