1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * All rights reserved. *
4 * *
5 * This file is part of HDF5. The full HDF5 copyright notice, including *
6 * terms governing use, modification, and redistribution, is contained in *
7 * the COPYING file, which can be found at the root of the source code *
8 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
9 * If you do not have access to either file, you may request a copy from *
10 * help@hdfgroup.org. *
11 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
14 * Use Case 1.7 Appending a single chunk
15 * Description:
16 * Appending a single chunk of raw data to a dataset along an unlimited
17 * dimension within a pre-created file and reading the new data back.
18 * Goal:
19 * Read data appended by the Writer to a pre-existing dataset in a
20 * file. The dataset has one or more unlimited dimensions. The data is
21 * appended by a hyperslab that is contained in one chunk (for example,
22 * appending 2-dim planes along the slowest changing dimension in the
23 * 3-dim dataset).
24 * Level:
25 * User Level
26 * Guarantees:
27 * o Readers will see the modified dimension sizes after the Writer
28 * finishes HDF5 metadata updates and issues H5Fflush or H5Oflush calls.
29 * o Readers will see newly appended data after the Writer finishes
30 * the flush operation.
31 *
32 * Preconditions:
33 * o Readers are not allowed to modify the file. o All datasets
34 * that are modified by the Writer exist when the Writer opens the file.
35 * o All datasets that are modified by the Writer exist when a Reader
36 * opens the file. o Data is written by a hyperslab contained in
37 * one chunk.
38 *
39 * Main Success Scenario:
40 * 1. An application creates a file with required objects (groups,
41 * datasets, and attributes).
42 * 2. The Writer application opens the file and datasets in the file
43 * and starts adding data along the unlimited dimension using a hyperslab
44 * selection that corresponds to an HDF5 chunk.
45 * 3. A Reader opens the file and a dataset in a file, and queries
46 * the sizes of the dataset; if the extent of the dataset has changed,
47 * reads the appended data back.
48 *
49 * Discussion points:
50 * 1. Since the new data is written to the file, and metadata update
51 * operation of adding pointer to the newly written chunk is atomic and
52 * happens after the chunk is on the disk, only two things may happen
53 * to the Reader:
54 * o The Reader will not see new data.
55 * o The Reader will see all new data written by Writer.
56 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
57
58 /* Created: Albert Cheng, 2013/5/28 */
59
60 #include "h5test.h"
61
62 /* This test uses many POSIX things that are not available on
63 * Windows. We're using a check for fork(2) here as a proxy for
64 * all POSIX/Unix/Linux things until this test can be made
65 * more platform-independent.
66 */
67 #ifdef H5_HAVE_FORK
68
69 #include "use.h"
70
71 /* Global Variable definitions */
72 options_t UC_opts; /* Use Case Options */
73 const char *progname_g="use_append_chunk"; /* program name */
74
75 /* Setup parameters for the use case.
76 * Return: 0 succeed; -1 fail.
77 */
setup_parameters(int argc,char * const argv[])78 int setup_parameters(int argc, char * const argv[])
79 {
80 /* use case defaults */
81 HDmemset(&UC_opts, 0, sizeof(options_t));
82 UC_opts.chunksize = Chunksize_DFT;
83 UC_opts.use_swmr = TRUE; /* use swmr open */
84 UC_opts.iterations = 1;
85 UC_opts.chunkplanes = 1;
86
87 /* parse options */
88 if (parse_option(argc, argv) < 0)
89 return(-1);
90
91 /* set chunk dims */
92 UC_opts.chunkdims[0] = UC_opts.chunkplanes;
93 UC_opts.chunkdims[1] = UC_opts.chunkdims[2] = UC_opts.chunksize;
94
95 /* set dataset initial and max dims */
96 UC_opts.dims[0] = 0;
97 UC_opts.max_dims[0] = H5S_UNLIMITED;
98 UC_opts.dims[1] = UC_opts.dims[2] = UC_opts.max_dims[1] = UC_opts.max_dims[2] = UC_opts.chunksize;
99
100 /* set nplanes */
101 if (UC_opts.nplanes == 0)
102 UC_opts.nplanes = (hsize_t)UC_opts.chunksize;
103
104 /* show parameters and return */
105 show_parameters();
106 return(0);
107 }
108
109
110 /* Overall Algorithm:
111 * Parse options from user;
112 * Generate/pre-created test files needed and close it;
113 * fork: child process becomes the reader process;
114 * while parent process continues as the writer process;
115 * both run till ending conditions are met.
116 */
117 int
main(int argc,char * argv[])118 main(int argc, char *argv[])
119 {
120 pid_t childpid=0;
121 pid_t mypid, tmppid;
122 int child_status;
123 int child_wait_option=0;
124 int ret_value = 0;
125 int child_ret_value;
126 hbool_t send_wait = FALSE;
127 hid_t fapl = -1; /* File access property list */
128 hid_t fid = -1; /* File ID */
129 char *name; /* Test file name */
130
131 /* initialization */
132 if (setup_parameters(argc, argv) < 0){
133 Hgoto_error(1);
134 }
135
136 /* Determine the need to send/wait message file*/
137 if(UC_opts.launch == UC_READWRITE) {
138 HDunlink(WRITER_MESSAGE);
139 send_wait = TRUE;
140 }
141
142 /* ==============================================================*/
143 /* UC_READWRITE: create datafile, launch both reader and writer. */
144 /* UC_WRITER: create datafile, skip reader, launch writer. */
145 /* UC_READER: skip create, launch reader, exit. */
146 /* ==============================================================*/
147 /* ============*/
148 /* Create file */
149 /* ============*/
150 if (UC_opts.launch != UC_READER){
151 HDprintf("Creating skeleton data file for test...\n");
152 if (create_uc_file() < 0){
153 HDfprintf(stderr, "***encounter error\n");
154 Hgoto_error(1);
155 }else
156 HDprintf("File created.\n");
157 }
158
159 if (UC_opts.launch==UC_READWRITE){
160 /* fork process */
161 if((childpid = HDfork()) < 0) {
162 HDperror("fork");
163 Hgoto_error(1);
164 };
165 };
166 mypid = HDgetpid();
167
168 /* ============= */
169 /* launch reader */
170 /* ============= */
171 if (UC_opts.launch != UC_WRITER){
172 /* child process launch the reader */
173 if(0 == childpid) {
174 HDprintf("%d: launch reader process\n", mypid);
175 if (read_uc_file(send_wait) < 0){
176 HDfprintf(stderr, "read_uc_file encountered error\n");
177 HDexit(EXIT_FAILURE);
178 }
179 HDexit(EXIT_SUCCESS);
180 }
181 }
182
183 /* ============= */
184 /* launch writer */
185 /* ============= */
186 /* this process continues to launch the writer */
187 HDprintf("%d: continue as the writer process\n", mypid);
188
189 name = UC_opts.filename;
190
191 /* Set file access proeprty list */
192 if((fapl = h5_fileaccess()) < 0)
193 Hgoto_error(1);
194
195 if(UC_opts.use_swmr)
196 if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
197 Hgoto_error(1);
198
199 /* Open the file */
200 if((fid = H5Fopen(name, H5F_ACC_RDWR | (UC_opts.use_swmr ? H5F_ACC_SWMR_WRITE : 0), fapl)) < 0) {
201 HDfprintf(stderr, "H5Fopen failed\n");
202 Hgoto_error(1);
203 }
204
205 if(write_uc_file(send_wait, fid) < 0) {
206 HDfprintf(stderr, "write_uc_file encountered error\n");
207 Hgoto_error(1);
208 }
209
210 /* ================================================ */
211 /* If readwrite, collect exit code of child process */
212 /* ================================================ */
213 if (UC_opts.launch == UC_READWRITE){
214 if ((tmppid = HDwaitpid(childpid, &child_status, child_wait_option)) < 0){
215 HDperror("waitpid");
216 Hgoto_error(1);
217 }
218
219 /* Close the file */
220 if(H5Fclose(fid) < 0) {
221 HDfprintf(stderr, "Failed to close file id\n");
222 Hgoto_error(1);
223 }
224
225 /* Close the property list */
226 if(H5Pclose(fapl) < 0) {
227 HDfprintf(stderr, "Failed to close the property list\n");
228 Hgoto_error(1);
229 }
230
231 if (WIFEXITED(child_status)){
232 if ((child_ret_value=WEXITSTATUS(child_status)) != 0){
233 HDprintf("%d: child process exited with non-zero code (%d)\n",
234 mypid, child_ret_value);
235 Hgoto_error(2);
236 }
237 } else {
238 HDprintf("%d: child process terminated abnormally\n", mypid);
239 Hgoto_error(2);
240 }
241 }
242
243 done:
244 /* Print result and exit */
245 if (ret_value != 0){
246 HDprintf("Error(s) encountered\n");
247 }else{
248 HDprintf("All passed\n");
249 }
250
251 return(ret_value);
252 }
253
254 #else /* H5_HAVE_FORK */
255
256 int
main(void)257 main(void)
258 {
259 HDfprintf(stderr, "Non-POSIX platform. Skipping.\n");
260 return EXIT_SUCCESS;
261 } /* end main() */
262
263 #endif /* H5_HAVE_FORK */
264
265