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 <songyulu@hdfgroup.org>
16 * 7 September 2010
17 *
18 * Purpose: Make sure dataset, file, and library can close properly when a
19 * mandatory filter fails.
20 */
21
22 #include "h5test.h"
23
24 #define DSET_NAME "dset_fail"
25 #define H5Z_FILTER_FAIL_TEST 312
26 #define DIM 10
27 #define FILTER_CHUNK_DIM 2
28
29 const char *FILENAME[] = {
30 "filter_fail_with_cache",
31 "filter_fail_without_cache",
32 NULL
33 };
34
35 static size_t filter_fail(unsigned int flags, size_t cd_nelmts,
36 const unsigned int *cd_values, size_t nbytes, size_t *buf_size, void **buf);
37
38 /* This message derives from H5Z */
39 const H5Z_class2_t H5Z_FAIL_TEST[1] = {{
40 H5Z_CLASS_T_VERS, /* H5Z_class_t version */
41 H5Z_FILTER_FAIL_TEST, /* Filter id number */
42 1, 1, /* Encoding and decoding enabled */
43 "filter_fail_test", /* Filter name for debugging */
44 NULL, /* The "can apply" callback */
45 NULL, /* The "set local" callback */
46 filter_fail, /* The actual filter function */
47 }};
48
49
50 /*-------------------------------------------------------------------------
51 * Function: filter_fail
52 *
53 * Purpose: For testing library's behavior when a mandatory filter
54 * fails to write a chunk.
55 *
56 * Return: Success: Data chunk size
57 * Failure: 0
58 *
59 * Programmer: Raymond Lu
60 * 7 September 2010
61 *
62 *-------------------------------------------------------------------------
63 */
64 static size_t
filter_fail(unsigned int flags,size_t H5_ATTR_UNUSED cd_nelmts,const unsigned int H5_ATTR_UNUSED * cd_values,size_t nbytes,size_t * buf_size,void ** buf)65 filter_fail(unsigned int flags, size_t H5_ATTR_UNUSED cd_nelmts,
66 const unsigned int H5_ATTR_UNUSED *cd_values, size_t nbytes,
67 size_t *buf_size, void **buf)
68 {
69 int *dst = (int*)(*buf);
70 size_t ret_value = 0;
71
72 if(flags & H5Z_FLAG_REVERSE) { /* do nothing during read */
73 *buf_size = nbytes;
74 ret_value = nbytes;
75 } /* end if */
76 else { /* Write data */
77 /* If it's the last chunk, pretend to fail. Otherwise, do nothing. */
78 if(*dst == 8 || *dst == 9) {
79 ret_value = 0;
80 } else {
81 *buf_size = nbytes;
82 ret_value = *buf_size;
83 }
84 } /* end else */
85
86 return ret_value;
87 } /* end filter_fail() */
88
89
90 /*-------------------------------------------------------------------------
91 * Function: test_filter_write_failure
92 *
93 * Purpose: Tests the library's behavior when a mandate filter returns
94 * failure. There're only 5 chunks with each of them having
95 * 2 integers. The filter will fail in the last chunk. The
96 * dataset should release all resources even though the last
97 * chunk can't be flushed to file. The file should close
98 * successfully.
99 *
100 * Return:
101 * Success: 0
102 * Failure: -1
103 *
104 * Programmer: Raymond Lu
105 * 25 August 2010
106 *
107 * Modifications:
108 * Raymond Lu
109 * 5 Oct 2010
110 * Test when the chunk cache is enable and disabled to make
111 * sure the library behaves properly.
112 *-------------------------------------------------------------------------
113 */
114 static herr_t
test_filter_write(char * file_name,hid_t my_fapl,hbool_t cache_enabled)115 test_filter_write(char *file_name, hid_t my_fapl, hbool_t cache_enabled)
116 {
117 hid_t file = -1;
118 hid_t dataset=-1; /* dataset ID */
119 hid_t sid=-1; /* dataspace ID */
120 hid_t dcpl=-1; /* dataset creation property list ID */
121 hsize_t dims[1]={DIM}; /* dataspace dimension - 10*/
122 hsize_t chunk_dims[1]={FILTER_CHUNK_DIM}; /* chunk dimension - 2*/
123 int points[DIM]; /* Data */
124 herr_t ret; /* generic return value */
125 int i;
126
127 if(cache_enabled) {
128 TESTING("data writing when a mandatory filter fails and chunk cache is enabled");
129 } else {
130 TESTING("data writing when a mandatory filter fails and chunk cache is disabled");
131 }
132
133 /* Create file */
134 if((file = H5Fcreate(file_name, H5F_ACC_TRUNC, H5P_DEFAULT, my_fapl)) < 0) TEST_ERROR
135
136 /* create the data space */
137 if((sid = H5Screate_simple(1, dims, NULL)) < 0) TEST_ERROR
138
139 /* Create dcpl and register the filter */
140 if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR
141
142 if(H5Pset_chunk(dcpl, 1, chunk_dims) < 0) TEST_ERROR
143
144 if(H5Zregister (H5Z_FAIL_TEST) < 0) TEST_ERROR
145
146 /* Check that the filter was registered */
147 if(TRUE != H5Zfilter_avail(H5Z_FILTER_FAIL_TEST)) FAIL_STACK_ERROR
148
149 /* Enable the filter as mandatory */
150 if(H5Pset_filter(dcpl, H5Z_FILTER_FAIL_TEST, 0, (size_t)0, NULL) < 0)
151 TEST_ERROR
152
153 /* create a dataset */
154 if((dataset = H5Dcreate2(file, DSET_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) TEST_ERROR
155
156 /* Initialize the write buffer */
157 for(i = 0; i < DIM; i++)
158 points[i] = i;
159
160 /* Write data. If the chunk cache is enabled, H5Dwrite should succeed. If it is
161 * diabled, H5Dwrite should fail. */
162 if(cache_enabled) {
163 if(H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, sid, H5P_DEFAULT, points) < 0)
164 TEST_ERROR
165 } else {
166 /* Data writing should fail */
167 H5E_BEGIN_TRY {
168 ret = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, sid, H5P_DEFAULT, points);
169 } H5E_END_TRY;
170 if(ret >= 0) {
171 H5_FAILED();
172 puts(" Data writing is supposed to fail because the chunk can't be written to file.");
173 TEST_ERROR
174 }
175 }
176
177 /* clean up objects used for this test */
178 if(H5Pclose (dcpl) < 0) TEST_ERROR
179 if(H5Sclose (sid) < 0) TEST_ERROR
180
181 /* Close dataset. If the chunk cache is enabled, the flushing of chunks should fail
182 * during H5Dclose. If it is diabled, H5Dwrite should fail but H5Dclose should succeed. */
183 if(cache_enabled) {
184 H5E_BEGIN_TRY {
185 ret = H5Dclose (dataset);
186 } H5E_END_TRY;
187 if(ret >= 0) {
188 H5_FAILED();
189 puts(" Dataset is supposed to fail because the chunk can't be flushed to file.");
190 TEST_ERROR
191 }
192 } else {
193 if(H5Dclose (dataset) < 0)
194 TEST_ERROR
195 }
196
197 /* Even though H5Dclose or H5Dwrite fails, it should release all resources.
198 * So the file should close successfully. */
199 if(H5Fclose (file) < 0) TEST_ERROR
200
201 PASSED();
202 return 0;
203
204 error:
205 H5E_BEGIN_TRY {
206 H5Pclose(dcpl);
207 H5Sclose(sid);
208 H5Dclose(dataset);
209 H5Fclose(file);
210 } H5E_END_TRY;
211 return -1;
212 } /* end test_filter_write() */
213
214
215 /*-------------------------------------------------------------------------
216 * Function: test_filter_read
217 *
218 * Purpose: Tests the library's behavior when a mandate filter returns
219 * failure. The first 4 chunks should be in the file. The
220 * last chunk should not.
221 *
222 * Return:
223 * Success: 0
224 * Failure: -1
225 *
226 * Programmer: Raymond Lu
227 * 25 August 2010
228 *
229 * Modifications:
230 *
231 *-------------------------------------------------------------------------
232 */
233 static herr_t
test_filter_read(char * file_name,hid_t my_fapl)234 test_filter_read(char *file_name, hid_t my_fapl)
235 {
236 hid_t file = -1;
237 hid_t dataset=-1; /* dataset ID */
238 hid_t sid = -1;
239 hid_t mspace = -1;
240 hsize_t dims[1]={DIM}; /* dataspace dimension - 10*/
241 int rbuf[DIM]; /* Data */
242 hsize_t dset_size = 0; /* Dataset storage size */
243 hsize_t hs_offset[H5S_MAX_RANK];
244 hsize_t hs_size[H5S_MAX_RANK];
245 hsize_t stride[1] = {2};
246 hsize_t zero[8];
247 hsize_t nelmts = DIM/2;
248 int i;
249
250 TESTING("data reading when a mandatory filter fails");
251
252 /* Open file */
253 if((file = H5Fopen(file_name, H5F_ACC_RDONLY, my_fapl)) < 0) TEST_ERROR
254
255 /* Open dataset */
256 if((dataset = H5Dopen2(file, DSET_NAME, H5P_DEFAULT)) < 0) TEST_ERROR
257
258 /* Verify the storage size is equal to 4 chunks */
259 if((dset_size = H5Dget_storage_size(dataset)) == 0) TEST_ERROR
260
261 if(dset_size != 4 * FILTER_CHUNK_DIM * sizeof(int)) TEST_ERROR
262
263 /* Read the chunks */
264 HDmemset(rbuf, 0, DIM * sizeof(int));
265 if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0)
266 TEST_ERROR
267
268 /* Check that the values read are the same as the values written.
269 * The last chunk should not be in the file. */
270 for(i = 0; i < DIM; i++) {
271 if(i < DIM-2 && rbuf[i] != i) {
272 H5_FAILED();
273 HDprintf(" Read different values than written.\n");
274 HDprintf(" At index %d\n", i);
275 HDprintf(" rbuf[%d]=%d\n", i, rbuf[i]);
276 TEST_ERROR
277 } else if(i >= DIM-2 && rbuf[i] != 0) {
278 H5_FAILED();
279 HDprintf(" No value should be read.\n");
280 HDprintf(" At index %d\n", i);
281 HDprintf(" rbuf[%d]=%d\n", i, rbuf[i]);
282 TEST_ERROR
283 }
284 }
285
286 /* Try to read in hyperslab simulating the h5dump's way of printing data */
287 if((sid = H5Dget_space(dataset)) < 0) TEST_ERROR
288
289 HDmemset(hs_offset, 0, sizeof(hs_offset));
290 HDmemset(hs_size, 0, sizeof(hs_size));
291 hs_size[0] = DIM/2;
292
293 if(H5Sselect_hyperslab(sid, H5S_SELECT_SET, hs_offset, stride, hs_size, NULL) < 0)
294 TEST_ERROR
295
296 /* create the data space */
297 if((mspace = H5Screate_simple(1, dims, NULL)) < 0) TEST_ERROR
298
299 HDmemset(zero, 0, sizeof zero);
300
301 if(H5Sselect_hyperslab(mspace, H5S_SELECT_SET, zero, stride, &nelmts, NULL) < 0)
302 TEST_ERROR
303
304 HDmemset(rbuf, 0, DIM * sizeof(int));
305 if(H5Dread(dataset, H5T_NATIVE_INT, H5S_ALL, sid, H5P_DEFAULT, rbuf) < 0)
306 TEST_ERROR
307
308 /* Check that the values read are the same as the values written.
309 * The last chunk should not be in the file. */
310 for(i = 0; i < DIM; i+=2) {
311 if(i < DIM-2 && rbuf[i] != i) {
312 H5_FAILED();
313 HDprintf(" Read different values than written.\n");
314 HDprintf(" At index %d\n", i);
315 HDprintf(" rbuf[%d]=%d\n", i, rbuf[i]);
316 TEST_ERROR
317 } else if(i >= DIM-2 && rbuf[i] != 0) {
318 H5_FAILED();
319 HDprintf(" No value should be read.\n");
320 HDprintf(" At index %d\n", i);
321 HDprintf(" rbuf[%d]=%d\n", i, rbuf[i]);
322 TEST_ERROR
323 }
324 }
325
326 if(H5Sclose (sid) < 0) TEST_ERROR
327 if(H5Sclose (mspace) < 0) TEST_ERROR
328 if(H5Dclose (dataset) < 0) TEST_ERROR
329 if(H5Fclose (file) < 0) TEST_ERROR
330
331 PASSED();
332 return 0;
333
334 error:
335 H5E_BEGIN_TRY {
336 H5Sclose(sid);
337 H5Sclose(mspace);
338 H5Dclose(dataset);
339 H5Fclose(file);
340 } H5E_END_TRY;
341 return -1;
342 } /* end test_filter_read() */
343
344 /*-------------------------------------------------------------------------
345 * Function: main
346 *
347 * Purpose: Tests the library's behavior when a mandate filter returns
348 * failure.
349 *
350 * Return: EXIT_SUCCESS/EXIT_FAILURE
351 *
352 * Programmer: Raymond Lu
353 * 25 August 2010
354 *
355 *-------------------------------------------------------------------------
356 */
357 int
main(void)358 main(void)
359 {
360 hid_t fapl;
361 int mdc_nelmts = 0;
362 size_t rdcc_nelmts = 0;
363 size_t rdcc_nbytes = 0;
364 double rdcc_w0 = 0;
365 char filename[1024];
366 unsigned nerrors = 0;
367
368 h5_reset();
369 fapl = h5_fileaccess();
370
371 h5_fixname(FILENAME[0], fapl, filename, sizeof filename);
372
373 /* The chunk cache is used so that the flushing of data chunks happens
374 * during H5Dclose. All values are default. */
375 nerrors += (test_filter_write(filename, fapl, TRUE) < 0 ? 1 : 0);
376 nerrors += (test_filter_read(filename, fapl) < 0 ? 1 : 0);
377
378 h5_fixname(FILENAME[1], fapl, filename, sizeof filename);
379
380 /* Disable the chunk cache so that the writing of data chunks happens
381 * during H5Dwrite. */
382 if(H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0) < 0)
383 TEST_ERROR
384
385 /* Run the test again. */
386 nerrors += (test_filter_write(filename, fapl, FALSE) < 0 ? 1 : 0);
387 nerrors += (test_filter_read(filename, fapl) < 0 ? 1 : 0);
388
389 /* Verify symbol table messages are cached */
390 nerrors += (h5_verify_cached_stabs(FILENAME, fapl) < 0 ? 1 : 0);
391
392 h5_cleanup(FILENAME, fapl);
393
394 /* Make sure we can close the library */
395 if(H5close() < 0) TEST_ERROR
396
397 if (nerrors) TEST_ERROR
398
399 HDexit(EXIT_SUCCESS);
400
401 error:
402 if (nerrors) {
403 HDprintf("***** %u FAILURE%s! *****\n",
404 nerrors, 1==nerrors?"":"S");
405 HDexit(EXIT_FAILURE);
406 }
407 } /* end main() */
408