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  * MPIO independent overlapping writes.
16  *
17  * First n-1 processes open 1 file.
18  * Each of the n-1 process writes chunks of data to the file in round-robin
19  * fashion, in a interleaved but not overlapped fashion.  Using increasing
20  * chunk sizes for the benefits of testing different write sizes and also
21  * reducing the numbers of writes.
22  *
23  * Last process (n-1) just waits.
24  * First n-1 processes finish writing and cloose the file.
25  * Last process opens the same file and verifies the data.
26  */
27 
28 #include "testpar.h"
29 
30 /* FILENAME and filenames must have the same number of names */
31 const char *FILENAME[2]={
32 	    "MPItest",
33 	    NULL};
34 char	filenames[2][200];
35 int	nerrors = 0;
36 hid_t	fapl;				/* file access property list */
37 
38 /* protocols */
39 static int errors_sum(int nerrs);
40 
41 #define MPIO_TEST_WRITE_SIZE 1024*1024     /* 1 MB */
42 
43 static int
test_mpio_overlap_writes(char * filename)44 test_mpio_overlap_writes(char *filename)
45 {
46     int mpi_size, mpi_rank;
47     MPI_Comm comm;
48     MPI_Info info = MPI_INFO_NULL;
49     int color, mrc;
50     MPI_File	fh;
51     int i;
52     int vrfyerrs, nerrs;
53     unsigned char  buf[4093];		/* use some prime number for size */
54     int bufsize = sizeof(buf);
55     MPI_Offset  stride;
56     MPI_Offset  mpi_off;
57     MPI_Status  mpi_stat;
58 
59 
60     if (VERBOSE_MED)
61 	printf("MPIO independent overlapping writes test on file %s\n",
62 	    filename);
63 
64     nerrs = 0;
65     /* set up MPI parameters */
66     MPI_Comm_size(MPI_COMM_WORLD,&mpi_size);
67     MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank);
68 
69     /* Need at least 2 processes */
70     if (mpi_size < 2) {
71 	if (MAINPROCESS)
72 	    printf("Need at least 2 processes to run MPIO test.\n");
73 	    printf(" -SKIP- \n");
74 	return 0;
75     }
76 
77     /* splits processes 0 to n-2 into one comm. and the last one into another */
78     color = ((mpi_rank < (mpi_size - 1)) ? 0 : 1);
79     mrc = MPI_Comm_split (MPI_COMM_WORLD, color, mpi_rank, &comm);
80     VRFY((mrc==MPI_SUCCESS), "Comm_split succeeded");
81 
82     if (color==0){
83 	/* First n-1 processes (color==0) open a file and write it */
84 	mrc = MPI_File_open(comm, filename, MPI_MODE_CREATE|MPI_MODE_RDWR,
85 		info, &fh);
86 	VRFY((mrc==MPI_SUCCESS), "");
87 
88 	stride = 1;
89 	mpi_off = mpi_rank*stride;
90 	while (mpi_off < MPIO_TEST_WRITE_SIZE){
91 	    /* make sure the write does not exceed the TEST_WRITE_SIZE */
92 	    if (mpi_off+stride > MPIO_TEST_WRITE_SIZE)
93 		stride = MPIO_TEST_WRITE_SIZE - mpi_off;
94 
95 	    /* set data to some trivial pattern for easy verification */
96 	    for (i=0; i<stride; i++)
97 		buf[i] = (unsigned char)(mpi_off+i);
98 	    mrc = MPI_File_write_at(fh, mpi_off, buf, (int)stride, MPI_BYTE,
99 		    &mpi_stat);
100 	    VRFY((mrc==MPI_SUCCESS), "");
101 
102 	    /* move the offset pointer to last byte written by all processes */
103 	    mpi_off += (mpi_size - 1 - mpi_rank) * stride;
104 
105 	    /* Increase chunk size without exceeding buffer size. */
106 	    /* Then move the starting offset for next write. */
107 	    stride *= 2;
108 	    if (stride > bufsize)
109 		stride = bufsize;
110 	    mpi_off += mpi_rank*stride;
111 	}
112 
113 	/* close file and free the communicator */
114 	mrc = MPI_File_close(&fh);
115 	VRFY((mrc==MPI_SUCCESS), "MPI_FILE_CLOSE");
116 	mrc = MPI_Comm_free(&comm);
117 	VRFY((mrc==MPI_SUCCESS), "MPI_Comm_free");
118 
119 	/* sync with the other waiting processes */
120 	mrc = MPI_Barrier(MPI_COMM_WORLD);
121 	VRFY((mrc==MPI_SUCCESS), "Sync after writes");
122     }else{
123 	/* last process waits till writes are done,
124 	 * then opens file to verify data.
125 	 */
126 	mrc = MPI_Barrier(MPI_COMM_WORLD);
127 	VRFY((mrc==MPI_SUCCESS), "Sync after writes");
128 
129 	mrc = MPI_File_open(comm, filename, MPI_MODE_RDONLY,
130 		info, &fh);
131 	VRFY((mrc==MPI_SUCCESS), "");
132 
133 	stride = bufsize;
134 	for (mpi_off=0; mpi_off < MPIO_TEST_WRITE_SIZE; mpi_off += bufsize){
135 	    /* make sure it does not read beyond end of data */
136 	    if (mpi_off+stride > MPIO_TEST_WRITE_SIZE)
137 		stride = MPIO_TEST_WRITE_SIZE - mpi_off;
138 	    mrc = MPI_File_read_at(fh, mpi_off, buf, (int)stride, MPI_BYTE,
139 		    &mpi_stat);
140 	    VRFY((mrc==MPI_SUCCESS), "");
141 	    vrfyerrs=0;
142 	    for (i=0; i<stride; i++){
143 		unsigned char expected;
144 		expected = (unsigned char)(mpi_off+i);
145 		if ((expected != buf[i]) &&
146 		    (vrfyerrs++ < MAX_ERR_REPORT || VERBOSE_MED)) {
147 			printf("proc %d: found data error at [%ld], expect %u, got %u\n",
148 			    mpi_rank, (long)(mpi_off+i), expected, buf[i]);
149 		}
150 	    }
151 	    if (vrfyerrs > MAX_ERR_REPORT && !VERBOSE_MED)
152 		printf("proc %d: [more errors ...]\n", mpi_rank);
153 
154 	    nerrs += vrfyerrs;
155 	}
156 
157 	/* close file and free the communicator */
158 	mrc = MPI_File_close(&fh);
159 	VRFY((mrc==MPI_SUCCESS), "MPI_FILE_CLOSE");
160 	mrc = MPI_Comm_free(&comm);
161 	VRFY((mrc==MPI_SUCCESS), "MPI_Comm_free");
162     }
163 
164     /*
165      * one more sync to ensure all processes have done reading
166      * before ending this test.
167      */
168     mrc = MPI_Barrier(MPI_COMM_WORLD);
169     VRFY((mrc==MPI_SUCCESS), "Sync before leaving test");
170     return (nerrs);
171 }
172 
173 
174 #define MB      1048576        /* 1024*1024 == 2**20 */
175 #define GB      1073741824     /* 1024**3 == 2**30 */
176 #define TWO_GB_LESS1    2147483647     /* 2**31 - 1 */
177 #define FOUR_GB_LESS1   4294967295L     /* 2**32 - 1 */
178 /*
179  * Verify that MPI_Offset exceeding 2**31 can be computed correctly.
180  * Print any failure as information only, not as an error so that this
181  * won't abort the remaining test or other separated tests.
182  *
183  * Test if MPIO can write file from under 2GB to over 2GB and then
184  * from under 4GB to over 4GB.
185  * Each process writes 1MB in round robin fashion.
186  * Then reads the file back in by reverse order, that is process 0
187  * reads the data of process n-1 and vice versa.
188  */
189 static int
test_mpio_gb_file(char * filename)190 test_mpio_gb_file(char *filename)
191 {
192     int mpi_size, mpi_rank;
193     MPI_Info info = MPI_INFO_NULL;
194     int mrc;
195     MPI_File	fh;
196     int i, j, n;
197     int vrfyerrs;
198     int writerrs;		/* write errors */
199     int nerrs;
200     int ntimes;			/* how many times */
201     char  *buf = NULL;
202     char  expected;
203     MPI_Offset  size;
204     MPI_Offset  mpi_off;
205     MPI_Offset  mpi_off_old;
206     MPI_Status  mpi_stat;
207     int is_signed, sizeof_mpi_offset;
208 
209     nerrs = 0;
210     /* set up MPI parameters */
211     MPI_Comm_size(MPI_COMM_WORLD,&mpi_size);
212     MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank);
213 
214     if (VERBOSE_MED)
215         printf("MPI_Offset range test\n");
216 
217     /* figure out the signness and sizeof MPI_Offset */
218     mpi_off = 0;
219     is_signed = ((MPI_Offset)(mpi_off - 1)) < 0;
220     sizeof_mpi_offset = (int)(sizeof(MPI_Offset));
221 
222     /*
223      * Verify the sizeof MPI_Offset and correctness of handling multiple GB
224      * sizes.
225      */
226     if (MAINPROCESS){			/* only process 0 needs to check it*/
227 	printf("MPI_Offset is %s %d bytes integeral type\n",
228 	    is_signed ? "signed" : "unsigned", (int)sizeof(MPI_Offset));
229 	if (sizeof_mpi_offset <= 4 && is_signed){
230 	    printf("Skipped 2GB range test "
231 		    "because MPI_Offset cannot support it\n");
232 	}else {
233 	    /* verify correctness of assigning 2GB sizes */
234 	    mpi_off = 2 * 1024 * (MPI_Offset)MB;
235 	    INFO((mpi_off>0), "2GB OFFSET assignment no overflow");
236 	    INFO((mpi_off-1)==TWO_GB_LESS1, "2GB OFFSET assignment succeed");
237 
238 	    /* verify correctness of increasing from below 2 GB to above 2GB */
239 	    mpi_off = TWO_GB_LESS1;
240 	    for (i=0; i < 3; i++){
241 		mpi_off_old = mpi_off;
242 		mpi_off = mpi_off + 1;
243 		/* no overflow */
244 		INFO((mpi_off>0), "2GB OFFSET increment no overflow");
245 		/* correct inc. */
246 		INFO((mpi_off-1)==mpi_off_old, "2GB OFFSET increment succeed");
247 	    }
248 	}
249 
250 	if (sizeof_mpi_offset <= 4){
251 	    printf("Skipped 4GB range test "
252 		    "because MPI_Offset cannot support it\n");
253 	}else {
254 	    /* verify correctness of assigning 4GB sizes */
255 	    mpi_off = 4 * 1024 * (MPI_Offset)MB;
256 	    INFO((mpi_off>0), "4GB OFFSET assignment no overflow");
257 	    INFO((mpi_off-1)==FOUR_GB_LESS1, "4GB OFFSET assignment succeed");
258 
259 	    /* verify correctness of increasing from below 4 GB to above 4 GB */
260 	    mpi_off = FOUR_GB_LESS1;
261 	    for (i=0; i < 3; i++){
262 		mpi_off_old = mpi_off;
263 		mpi_off = mpi_off + 1;
264 		/* no overflow */
265 		INFO((mpi_off>0), "4GB OFFSET increment no overflow");
266 		/* correct inc. */
267 		INFO((mpi_off-1)==mpi_off_old, "4GB OFFSET increment succeed");
268 	    }
269 	}
270     }
271 
272     /*
273      * Verify if we can write to a file of multiple GB sizes.
274      */
275     if (VERBOSE_MED)
276 	printf("MPIO GB file test %s\n", filename);
277 
278     if (sizeof_mpi_offset <= 4){
279 	printf("Skipped GB file range test "
280 		"because MPI_Offset cannot support it\n");
281     }else{
282 	buf = HDmalloc(MB);
283 	VRFY((buf!=NULL), "malloc succeed");
284 
285 	/* open a new file. Remove it first in case it exists. */
286 	/* Must delete because MPI_File_open does not have a Truncate mode. */
287 	/* Don't care if it has error. */
288 	MPI_File_delete(filename, MPI_INFO_NULL);
289 	MPI_Barrier(MPI_COMM_WORLD);	/* prevent racing condition */
290 
291 	mrc = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE|MPI_MODE_RDWR,
292 		    info, &fh);
293 	VRFY((mrc==MPI_SUCCESS), "MPI_FILE_OPEN");
294 
295 	printf("MPIO GB file write test %s\n", filename);
296 
297 	/* instead of writing every bytes of the file, we will just write
298 	 * some data around the 2 and 4 GB boundaries.  That should cover
299 	 * potential integer overflow and filesystem size limits.
300 	 */
301 	writerrs = 0;
302 	for (n=2; n <= 4; n+=2){
303 	    ntimes = GB/MB*n/mpi_size + 1;
304 	    for (i=ntimes-2; i <= ntimes; i++){
305 		mpi_off = (i*mpi_size + mpi_rank)*(MPI_Offset)MB;
306 		if (VERBOSE_MED)
307 		    HDfprintf(stdout,"proc %d: write to mpi_off=%016llx, %lld\n",
308 			mpi_rank, mpi_off, mpi_off);
309 		/* set data to some trivial pattern for easy verification */
310 		for (j=0; j<MB; j++)
311 		    *(buf+j) = i*mpi_size + mpi_rank;
312 		if (VERBOSE_MED)
313 		    HDfprintf(stdout,"proc %d: writing %d bytes at offset %lld\n",
314 			mpi_rank, MB, mpi_off);
315 		mrc = MPI_File_write_at(fh, mpi_off, buf, MB, MPI_BYTE, &mpi_stat);
316 		INFO((mrc==MPI_SUCCESS), "GB size file write");
317 		if (mrc!=MPI_SUCCESS)
318 		    writerrs++;
319 	    }
320 	}
321 
322 	/* close file and free the communicator */
323 	mrc = MPI_File_close(&fh);
324 	VRFY((mrc==MPI_SUCCESS), "MPI_FILE_CLOSE");
325 
326 	mrc = MPI_Barrier(MPI_COMM_WORLD);
327 	VRFY((mrc==MPI_SUCCESS), "Sync after writes");
328 
329 	/*
330 	 * Verify if we can read the multiple GB file just created.
331 	 */
332 	/* open it again to verify the data written */
333 	/* but only if there was no write errors */
334 	printf("MPIO GB file read test %s\n", filename);
335 	if (errors_sum(writerrs)>0){
336 	    printf("proc %d: Skip read test due to previous write errors\n",
337 		mpi_rank);
338 	    goto finish;
339 	}
340 	mrc = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDONLY, info, &fh);
341 	VRFY((mrc==MPI_SUCCESS), "");
342 
343 	/* Only read back parts of the file that have been written. */
344 	for (n=2; n <= 4; n+=2){
345 	    ntimes = GB/MB*n/mpi_size + 1;
346 	    for (i=ntimes-2; i <= ntimes; i++){
347 		mpi_off = (i*mpi_size + (mpi_size - mpi_rank - 1))*(MPI_Offset)MB;
348 		if (VERBOSE_MED)
349 		    HDfprintf(stdout,"proc %d: read from mpi_off=%016llx, %lld\n",
350 			mpi_rank, mpi_off, mpi_off);
351 		mrc = MPI_File_read_at(fh, mpi_off, buf, MB, MPI_BYTE, &mpi_stat);
352 		INFO((mrc==MPI_SUCCESS), "GB size file read");
353 		expected = i*mpi_size + (mpi_size - mpi_rank - 1);
354 		vrfyerrs=0;
355 		for (j=0; j<MB; j++){
356 		    if ((*(buf+j) != expected) &&
357 			(vrfyerrs++ < MAX_ERR_REPORT || VERBOSE_MED)){
358 			    printf("proc %d: found data error at [%ld+%d], expect %d, got %d\n",
359 				mpi_rank, (long)mpi_off, j, expected, *(buf+j));
360 		    }
361 		}
362 		if (vrfyerrs > MAX_ERR_REPORT && !VERBOSE_MED)
363 		    printf("proc %d: [more errors ...]\n", mpi_rank);
364 
365 		nerrs += vrfyerrs;
366 	    }
367 	}
368 
369 	/* close file and free the communicator */
370 	mrc = MPI_File_close(&fh);
371 	VRFY((mrc==MPI_SUCCESS), "MPI_FILE_CLOSE");
372 
373 	/*
374 	 * one more sync to ensure all processes have done reading
375 	 * before ending this test.
376 	 */
377 	mrc = MPI_Barrier(MPI_COMM_WORLD);
378 	VRFY((mrc==MPI_SUCCESS), "Sync before leaving test");
379 
380         printf("Test if MPI_File_get_size works correctly with %s\n", filename);
381 
382 	mrc = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDONLY, info, &fh);
383         VRFY((mrc==MPI_SUCCESS), "");
384 
385         if (MAINPROCESS){			/* only process 0 needs to check it*/
386             mrc = MPI_File_get_size(fh, &size);
387 	    VRFY((mrc==MPI_SUCCESS), "");
388             VRFY((size == mpi_off+MB), "MPI_File_get_size doesn't return correct file size.");
389         }
390 
391 	/* close file and free the communicator */
392 	mrc = MPI_File_close(&fh);
393 	VRFY((mrc==MPI_SUCCESS), "MPI_FILE_CLOSE");
394 
395 	/*
396 	 * one more sync to ensure all processes have done reading
397 	 * before ending this test.
398 	 */
399 	mrc = MPI_Barrier(MPI_COMM_WORLD);
400 	VRFY((mrc==MPI_SUCCESS), "Sync before leaving test");
401     }
402 
403 finish:
404     if (buf)
405 	HDfree(buf);
406     return (nerrs);
407 }
408 
409 
410 /*
411  * MPI-IO Test: One writes, Many reads.
412  * Verify if only one process writes some data and then all other
413  * processes can read them back correctly. This tests if the
414  * underlaying parallel I/O and file system supports parallel I/O
415  * correctly.
416  *
417  * Algorithm: Only one process (e.g., process 0) writes some data.
418  * Then all processes, including the writing process, read the data
419  * back and verify them against the original values.
420  */
421 
422 /*
423  * Default filename can be specified via first program argument.
424  * Each process writes something, then reads all data back.
425  */
426 
427 #define DIMSIZE	32		/* Dimension size. */
428 #define PRINTID printf("Proc %d: ", mpi_rank)
429 #define USENONE 0
430 #define USEATOM 1		/* request atomic I/O */
431 #define USEFSYNC 2		/* request file_sync */
432 
433 
434 static int
test_mpio_1wMr(char * filename,int special_request)435 test_mpio_1wMr(char *filename, int special_request)
436 {
437     char hostname[128];
438     int  mpi_size, mpi_rank;
439     MPI_File fh;
440     char mpi_err_str[MPI_MAX_ERROR_STRING];
441     int  mpi_err_strlen;
442     int  mpi_err;
443     unsigned char writedata[DIMSIZE], readdata[DIMSIZE];
444     unsigned char expect_val;
445     int  i, irank;
446     int  nerrs = 0;		/* number of errors */
447     int  atomicity;
448     MPI_Offset  mpi_off;
449     MPI_Status  mpi_stat;
450 
451     MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
452     MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
453 
454     if (MAINPROCESS && VERBOSE_MED){
455         printf("Testing one process writes, all processes read.\n");
456 	printf("Using %d processes accessing file %s\n", mpi_size, filename);
457         printf("    (Filename can be specified via program argument)\n");
458     }
459 
460     /* show the hostname so that we can tell where the processes are running */
461     if (VERBOSE_DEF){
462 	if (gethostname(hostname, 128) < 0){
463 	    PRINTID;
464 	    printf("gethostname failed\n");
465 	    return 1;
466 	}
467 	PRINTID;
468 	printf("hostname=%s\n", hostname);
469     }
470 
471     /* Delete any old file in order to start anew. */
472     /* Must delete because MPI_File_open does not have a Truncate mode. */
473     /* Don't care if it has error. */
474     MPI_File_delete(filename, MPI_INFO_NULL);
475     MPI_Barrier(MPI_COMM_WORLD);	/* prevent racing condition */
476 
477     if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename,
478 	    MPI_MODE_RDWR | MPI_MODE_CREATE ,
479 	    MPI_INFO_NULL, &fh))
480 	    != MPI_SUCCESS){
481 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
482 	PRINTID;
483 	printf("MPI_File_open failed (%s)\n", mpi_err_str);
484 	return 1;
485     }
486 
487 if (special_request & USEATOM){
488     /* ==================================================
489      * Set atomcity to true (1).  A POSIX compliant filesystem
490      * should not need this.
491      * ==================================================*/
492     if ((mpi_err = MPI_File_get_atomicity(fh, &atomicity)) != MPI_SUCCESS){
493 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
494 	PRINTID;
495 	printf("MPI_File_get_atomicity failed (%s)\n", mpi_err_str);
496     }
497     if (VERBOSE_HI)
498 	printf("Initial atomicity = %d\n", atomicity);
499     if ((mpi_err = MPI_File_set_atomicity(fh, 1)) != MPI_SUCCESS){
500 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
501 	PRINTID;
502 	printf("MPI_File_set_atomicity failed (%s)\n", mpi_err_str);
503     }
504     if ((mpi_err = MPI_File_get_atomicity(fh, &atomicity)) != MPI_SUCCESS){
505 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
506 	PRINTID;
507 	printf("MPI_File_get_atomicity failed (%s)\n", mpi_err_str);
508     }
509     if (VERBOSE_HI)
510 	printf("After set_atomicity atomicity = %d\n", atomicity);
511 }
512 
513     /* This barrier is not necessary but do it anyway. */
514     MPI_Barrier(MPI_COMM_WORLD);
515     if (VERBOSE_HI){
516 	PRINTID;
517 	printf("between MPI_Barrier and MPI_File_write_at\n");
518     }
519 
520     /* ==================================================
521      * Each process calculates what to write but
522      * only process irank(0) writes.
523      * ==================================================*/
524     irank=0;
525     for (i=0; i < DIMSIZE; i++)
526 	writedata[i] = irank*DIMSIZE + i;
527     mpi_off = irank*DIMSIZE;
528 
529     /* Only one process writes */
530     if (mpi_rank==irank){
531 	if (VERBOSE_HI){
532 	    PRINTID; printf("wrote %d bytes at %ld\n", DIMSIZE, (long)mpi_off);
533 	}
534 	if ((mpi_err = MPI_File_write_at(fh, mpi_off, writedata, DIMSIZE,
535 			MPI_BYTE, &mpi_stat))
536 		!= MPI_SUCCESS){
537 	    MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
538 	    PRINTID;
539 	    printf("MPI_File_write_at offset(%ld), bytes (%d), failed (%s)\n",
540 		    (long) mpi_off, DIMSIZE, mpi_err_str);
541 	    return 1;
542 	};
543     };
544 
545     /* Bcast the return code and */
546     /* make sure all writing are done before reading. */
547     MPI_Bcast(&mpi_err, 1, MPI_INT, irank, MPI_COMM_WORLD);
548     if (VERBOSE_HI){
549 	PRINTID;
550 	printf("MPI_Bcast: mpi_err = %d\n", mpi_err);
551     }
552 
553 if (special_request & USEFSYNC){
554     /* ==================================================
555      * Do a file sync.  A POSIX compliant filesystem
556      * should not need this.
557      * ==================================================*/
558     if (VERBOSE_HI)
559 	printf("Apply MPI_File_sync\n");
560     /* call file_sync to force the write out */
561     if ((mpi_err = MPI_File_sync(fh)) != MPI_SUCCESS){
562 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
563 	PRINTID;
564 	printf("MPI_File_sync failed (%s)\n", mpi_err_str);
565     }
566     MPI_Barrier(MPI_COMM_WORLD);
567     /* call file_sync to force the write out */
568     if ((mpi_err = MPI_File_sync(fh)) != MPI_SUCCESS){
569 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
570 	PRINTID;
571 	printf("MPI_File_sync failed (%s)\n", mpi_err_str);
572     }
573 }
574 
575     /* This barrier is not necessary because the Bcase or File_sync above */
576     /* should take care of it.  Do it anyway. */
577     MPI_Barrier(MPI_COMM_WORLD);
578     if (VERBOSE_HI){
579 	PRINTID;
580 	printf("after MPI_Barrier\n");
581     }
582 
583     /* ==================================================
584      * Each process reads what process 0 wrote and verify.
585      * ==================================================*/
586     irank=0;
587     mpi_off = irank*DIMSIZE;
588     if ((mpi_err = MPI_File_read_at(fh, mpi_off, readdata, DIMSIZE, MPI_BYTE,
589 	    &mpi_stat))
590 	    != MPI_SUCCESS){
591 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
592 	PRINTID;
593 	printf("MPI_File_read_at offset(%ld), bytes (%d), failed (%s)\n",
594 		(long) mpi_off, DIMSIZE, mpi_err_str);
595 	return 1;
596     };
597     for (i=0; i < DIMSIZE; i++){
598 	expect_val = irank*DIMSIZE + i;
599 	if (readdata[i] != expect_val){
600 	    PRINTID;
601 	    printf("read data[%d:%d] got %02x, expect %02x\n", irank, i,
602 		    readdata[i], expect_val);
603 	    nerrs++;
604 	}
605     }
606 
607     MPI_File_close(&fh);
608 
609     if (VERBOSE_HI){
610 	PRINTID;
611 	printf("%d data errors detected\n", nerrs);
612     }
613 
614     mpi_err = MPI_Barrier(MPI_COMM_WORLD);
615     return nerrs;
616 }
617 
618 /*
619 
620 Function: test_mpio_derived_dtype
621 
622 Test Whether the Displacement of MPI derived datatype
623 (+ File_set_view + MPI_write)works or not on this MPI-IO package
624 and this platform.
625 
626 1. Details for the test:
627 1) Create two derived datatypes with MPI_Type_hindexed:
628         datatype1:
629 	count = 1, blocklens = 1, offsets = 0,
630 	base type = MPI_BYTE(essentially a char)
631         datatype2:
632 	count = 1, blocklens = 1, offsets = 1(byte),
633 	base type = MPI_BYTE
634 
635 2) Using these two derived datatypes,
636    Build another derived datatype with MPI_Type_struct:
637         advtype: derived from datatype1 and datatype2
638         advtype:
639 	count = 2, blocklens[0] = 1, blocklens[1]=1,
640 	offsets[0] = 0, offsets[1] = 1(byte),
641         bas_type[0]=datatype1,
642         bas_type[1] = datatype2;
643 
644 3) Setting MPI file view with advtype
645 4) Writing 2 bytes 1 to 2 using MPI_File_write to a file
646 5) File content:
647 Suppose the fill value of the file is 0(most machines indeed do so)
648 and Fill value is embraced with "() in the following output:
649 Expected output should be:
650 1,0,2
651 
652 
653 
654 However, at some platforms, for example, IBM AIX(at March 23rd, 2005):
655 the following values were obtained:
656 1,2,0
657 
658 The problem is that the displacement of the second derived datatype(datatype2) which formed the final derived datatype(advtype)
659  has been put after the basic datatype(MPI_BYTE) of datatype2. This is a bug.
660 
661 
662 2. This test will verify whether the complicated derived datatype is working on
663 the current platform.
664 
665 If this bug has been fixed in the previous not-working package, this test will issue a printf message to tell the developer to change
666 the configuration specific file of HDF5 so that we can change our configurationsetting to support collective IO for irregular selections.
667 
668 If it turns out that the previous working MPI-IO package no longer works, this test will also issue a message to inform the corresponding failure so that
669 we can turn off collective IO support for irregular selections.
670 */
671 
test_mpio_derived_dtype(char * filename)672 static int test_mpio_derived_dtype(char *filename) {
673 
674     MPI_File fh;
675     char mpi_err_str[MPI_MAX_ERROR_STRING];
676     int  mpi_err_strlen;
677     int  mpi_err;
678     int  i;
679     int  nerrors = 0;		/* number of errors */
680     MPI_Datatype  etype,filetype;
681     MPI_Datatype  adv_filetype,bas_filetype[2];
682     MPI_Datatype  etypenew, filetypenew;
683     MPI_Offset    disp;
684     MPI_Status    Status;
685     MPI_Aint      adv_disp[2];
686     MPI_Aint      offsets[1];
687     int           blocklens[1],adv_blocklens[2];
688     int           count,outcount;
689     int           retcode;
690 
691     int mpi_rank,mpi_size;
692 
693     char          buf[3],outbuf[3] = {0};
694 
695     MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
696     MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
697     retcode = 0;
698     for(i=0;i<3;i++)
699       buf[i] = i+1;
700 
701 
702     if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename,
703 				 MPI_MODE_RDWR | MPI_MODE_CREATE,
704 				 MPI_INFO_NULL, &fh))
705 	    != MPI_SUCCESS){
706 	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
707 	printf("MPI_File_open failed (%s)\n", mpi_err_str);
708 	return 1;
709     }
710 
711     disp  = 0;
712     etype = MPI_BYTE;
713 
714     count = 1;
715     blocklens[0] = 1;
716     offsets[0]   = 0;
717 
718     if((mpi_err= MPI_Type_hindexed(count,blocklens,offsets,MPI_BYTE,&filetype))
719        != MPI_SUCCESS){
720       	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
721 	printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
722 	return 1;
723     }
724 
725     if((mpi_err=MPI_Type_commit(&filetype))!=MPI_SUCCESS){
726         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
727 	printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
728 	return 1;
729     }
730 
731     count = 1;
732     blocklens[0]=1;
733     offsets[0] = 1;
734     if((mpi_err= MPI_Type_hindexed(count,blocklens,offsets,MPI_BYTE,&filetypenew))
735        != MPI_SUCCESS){
736       	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
737 	printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
738 	return 1;
739     }
740 
741     if((mpi_err=MPI_Type_commit(&filetypenew))!=MPI_SUCCESS){
742         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
743 	printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
744 	return 1;
745     }
746 
747     outcount         = 2;
748     adv_blocklens[0] = 1;
749     adv_blocklens[1] = 1;
750     adv_disp[0]      = 0;
751     adv_disp[1]      = 1;
752     bas_filetype[0]  = filetype;
753     bas_filetype[1]  = filetypenew;
754 
755     if((mpi_err= MPI_Type_struct(outcount,adv_blocklens,adv_disp,bas_filetype,&adv_filetype))
756        != MPI_SUCCESS){
757       	MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
758 	printf("MPI_Type_struct failed (%s)\n", mpi_err_str);
759 	return 1;
760     }
761     if((mpi_err=MPI_Type_commit(&adv_filetype))!=MPI_SUCCESS){
762         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
763 	printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
764 	return 1;
765     }
766 
767 
768     if((mpi_err = MPI_File_set_view(fh,disp,etype,adv_filetype,"native",MPI_INFO_NULL))!= MPI_SUCCESS){
769       MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
770 	printf("MPI_File_set_view failed (%s)\n", mpi_err_str);
771 	return 1;
772     }
773 
774     if((mpi_err = MPI_File_write(fh,buf,3,MPI_BYTE,&Status))!= MPI_SUCCESS){
775         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
776 	printf("MPI_File_write failed (%s)\n", mpi_err_str);
777 	return 1;
778       ;
779     }
780 
781 
782     if((mpi_err = MPI_File_close(&fh)) != MPI_SUCCESS){
783        MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
784 	printf("MPI_File_close failed (%s)\n", mpi_err_str);
785 	return 1;
786     }
787 
788 
789     if((mpi_err = MPI_File_open(MPI_COMM_WORLD,filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&fh)) != MPI_SUCCESS){
790        MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
791 	printf("MPI_File_open failed (%s)\n", mpi_err_str);
792 	return 1;
793     }
794 
795     if((mpi_err = MPI_File_set_view(fh,0,MPI_BYTE,MPI_BYTE,"native",MPI_INFO_NULL))!= MPI_SUCCESS){
796         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
797 	printf("MPI_File_set_view failed (%s)\n", mpi_err_str);
798 	return 1;
799     }
800     if((mpi_err = MPI_File_read(fh,outbuf,3,MPI_BYTE,&Status))!=MPI_SUCCESS){
801       MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
802       printf("MPI_File_read failed (%s)\n", mpi_err_str);
803       return 1;
804     }
805 
806     if(outbuf[2]==2) {
807        retcode = 0;
808     }
809     else {
810 /*      if(mpi_rank == 0) {
811        printf("complicated derived datatype is NOT working at this platform\n");
812        printf("go back to hdf5/config and find the corresponding\n");
813        printf("configure-specific file and change ?????\n");
814       }
815 */
816        retcode = -1;
817    }
818 
819     if((mpi_err = MPI_File_close(&fh)) != MPI_SUCCESS){
820        MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
821 	printf("MPI_File_close failed (%s)\n", mpi_err_str);
822 	return 1;
823     }
824 
825 
826     mpi_err = MPI_Barrier(MPI_COMM_WORLD);
827     if(retcode == -1) {
828 	if(mpi_rank == 0) {
829 	    printf("Complicated derived datatype is NOT working at this platform\n");
830 	    printf(" Please report to help@hdfgroup.org about this problem.\n");
831 	}
832 	retcode = 1;
833     }
834     return retcode;
835 }
836 /*
837 
838 Function: test_mpio_special_collective
839 
840 Test Whether collective IO is still working when more than one process
841 has no contribution to IO. To properly test this case, at least FOUR
842 processes are needed.
843 
844 1. Details for the test:
845 1) Create one derived datatype with MPI_Type_hindexed:
846 
847 2) Choosing at least two processes to contribute none for IO with
848    the buf size inside MPI_Write_at_all to 0.
849 3) Choosing at least two processes to have real contributions for IO.
850 4) Do collective IO.
851 
852 2. This test will fail with the MPI-IO package that doesn't support this. For example,
853 mpich 1.2.6.
854 
855 If this bug has been fixed in the previous not-working package, this test will issue a printf message to tell the developer to change
856 the configuration specific file of HDF5 so that we can change our configurationsetting to support special collective IO; currently only special collective IO.
857 
858 If it turns out that the previous working MPI-IO package no longer works, this test will also issue a message to inform the corresponding failure so that
859 we can turn off the support for special collective IO; currently only special collective IO.
860 */
861 
862 static int
test_mpio_special_collective(char * filename)863 test_mpio_special_collective(char *filename)
864 {
865     int  mpi_size, mpi_rank;
866     MPI_File fh;
867     MPI_Datatype etype,buftype,filetype;
868     char mpi_err_str[MPI_MAX_ERROR_STRING];
869     int  mpi_err_strlen;
870     int  mpi_err;
871     char writedata[2*DIMSIZE];
872     char filerep[7] = "native";
873     int  i;
874     int  count,bufcount;
875     int blocklens[2];
876     MPI_Aint offsets[2];
877     MPI_Offset  mpi_off = 0;
878     MPI_Status  mpi_stat;
879     int  retcode = 0;
880 
881     MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
882     MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
883 
884     /* create MPI data type */
885     etype = MPI_BYTE;
886     if(mpi_rank == 0 || mpi_rank == 1) {
887         count = DIMSIZE;
888         bufcount = 1;
889     } /* end if */
890     else {
891         count = 0;
892         bufcount = 0;
893     } /* end else */
894 
895     blocklens[0] = count;
896     offsets[0] = mpi_rank*count;
897     blocklens[1] = count;
898     offsets[1] = (mpi_size+mpi_rank)*count;
899 
900     if(count !=0) {
901         if((mpi_err = MPI_Type_hindexed(2,
902                                         blocklens,
903                                         offsets,
904                                         etype,
905                                         &filetype)) != MPI_SUCCESS) {
906             MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
907             printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
908             return 1;
909         } /* end if */
910 
911         if((mpi_err = MPI_Type_commit(&filetype)) != MPI_SUCCESS) {
912             MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
913             printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
914             return 1;
915         } /* end if */
916 
917         if((mpi_err = MPI_Type_hindexed(2,
918                                         blocklens,
919                                         offsets,
920                                         etype,
921                                         &buftype)) != MPI_SUCCESS) {
922             MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
923             printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
924             return 1;
925         } /* end if */
926 
927         if((mpi_err = MPI_Type_commit(&buftype)) != MPI_SUCCESS) {
928             MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
929             printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
930             return 1;
931         } /* end if */
932     } /* end if */
933     else {
934         filetype = MPI_BYTE;
935         buftype  = MPI_BYTE;
936     } /* end else */
937 
938     /* Open a file */
939     if ((mpi_err = MPI_File_open(MPI_COMM_WORLD,
940                                  filename,
941                                  MPI_MODE_RDWR | MPI_MODE_CREATE,
942                                  MPI_INFO_NULL,
943                                  &fh)) != MPI_SUCCESS) {
944         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
945         printf("MPI_File_open failed (%s)\n", mpi_err_str);
946         return 1;
947     } /* end if */
948 
949     /* each process writes some data */
950     for (i=0; i < 2*DIMSIZE; i++)
951         writedata[i] = (char)(mpi_rank*DIMSIZE + i);
952 
953     /* Set the file view */
954     if((mpi_err = MPI_File_set_view(fh,
955                                     mpi_off,
956                                     MPI_BYTE,
957                                     filetype,
958                                     filerep,
959                                     MPI_INFO_NULL)) != MPI_SUCCESS) {
960         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
961         printf("MPI_File_set_view failed (%s)\n", mpi_err_str);
962         return 1;
963     } /* end if */
964 
965     /* Collectively write into the file */
966     if ((mpi_err = MPI_File_write_at_all(fh,
967                                          mpi_off,
968                                          writedata,
969                                          bufcount,
970                                          buftype,
971                                          &mpi_stat)) != MPI_SUCCESS) {
972         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
973         printf("MPI_File_write_at offset(%ld), bytes (%d), failed (%s)\n",
974                (long) mpi_off, bufcount, mpi_err_str);
975         return 1;
976     } /* end if */
977 
978     /* Close the file */
979     if ((mpi_err = MPI_File_close(&fh)) != MPI_SUCCESS) {
980         MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
981         printf("MPI_File_close failed. \n");
982         return 1;
983     } /* end if */
984 
985     /* Perform a barrier */
986     mpi_err = MPI_Barrier(MPI_COMM_WORLD);
987     if(retcode != 0) {
988         if(mpi_rank == 0) {
989             printf("special collective IO is NOT working at this platform\n");
990             printf(" Please report to help@hdfgroup.org about this problem.\n");
991         } /* end if */
992         retcode = 1;
993     } /* end if */
994 
995     return retcode;
996 
997 } /* test_mpio_special_collective */
998 
999 /*
1000  * parse the command line options
1001  */
1002 static int
parse_options(int argc,char ** argv)1003 parse_options(int argc, char **argv)
1004 {
1005     while (--argc){
1006 	if (**(++argv) != '-'){
1007 	    break;
1008 	}else{
1009 	    switch(*(*argv+1)){
1010 		case 'v':   if (*((*argv+1)+1))
1011 				ParseTestVerbosity((*argv+1)+1);
1012 			    else
1013 				SetTestVerbosity(VERBO_MED);
1014 			    break;
1015 		case 'f':   if (--argc < 1) {
1016 				nerrors++;
1017 				return(1);
1018 			    }
1019 			    if (**(++argv) == '-') {
1020 				nerrors++;
1021 				return(1);
1022 			    }
1023 			    paraprefix = *argv;
1024 			    break;
1025 		case 'h':   /* print help message--return with nerrors set */
1026 			    return(1);
1027 		default:    nerrors++;
1028 			    return(1);
1029 	    }
1030 	}
1031     } /*while*/
1032 
1033     /* compose the test filenames */
1034     {
1035 	int i, n;
1036 	hid_t plist;
1037 
1038 	plist = H5Pcreate (H5P_FILE_ACCESS);
1039 	H5Pset_fapl_mpio(plist, MPI_COMM_WORLD, MPI_INFO_NULL);
1040 	n = sizeof(FILENAME)/sizeof(FILENAME[0]) - 1;	/* exclude the NULL */
1041 
1042 	for (i=0; i < n; i++)
1043 	    if (h5_fixname(FILENAME[i],plist,filenames[i],sizeof(filenames[i]))
1044 		== NULL){
1045 		printf("h5_fixname failed\n");
1046 		nerrors++;
1047 		return(1);
1048 	    }
1049 	H5Pclose(plist);
1050 	if (VERBOSE_MED){
1051 	    printf("Test filenames are:\n");
1052 	    for (i=0; i < n; i++)
1053 		printf("    %s\n", filenames[i]);
1054 	}
1055     }
1056 
1057     return(0);
1058 }
1059 
1060 
1061 /*
1062  * Show command usage
1063  */
1064 static void
usage(void)1065 usage(void)
1066 {
1067     printf("Usage: t_mpi [-v<verbosity>] [-f <prefix>]\n");
1068     printf("\t-v<verbosity>\tset verbose level (0-9,l,m,h)\n");
1069     printf("\t-f <prefix>\tfilename prefix\n");
1070     printf("\n");
1071 }
1072 
1073 /*
1074  * return the sum of all errors.
1075  */
1076 static int
errors_sum(int nerrs)1077 errors_sum(int nerrs)
1078 {
1079     int temp;
1080     MPI_Allreduce(&nerrs, &temp, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
1081     return(temp);
1082 }
1083 
1084 
1085 int
main(int argc,char ** argv)1086 main(int argc, char **argv)
1087 {
1088     int mpi_size, mpi_rank;				/* mpi variables */
1089     int ret_code;
1090 
1091     MPI_Init(&argc, &argv);
1092     MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
1093     MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
1094 
1095     /* Attempt to turn off atexit post processing so that in case errors
1096      * happen during the test and the process is aborted, it will not get
1097      * hang in the atexit post processing in which it may try to make MPI
1098      * calls.  By then, MPI calls may not work.
1099      */
1100     if (H5dont_atexit() < 0){
1101 	printf("Failed to turn off atexit processing. Continue.\n", mpi_rank);
1102     };
1103     H5open();
1104     if (parse_options(argc, argv) != 0){
1105 	if (MAINPROCESS)
1106 	    usage();
1107 	goto finish;
1108     }
1109 
1110     if (MAINPROCESS){
1111 	printf("===================================\n");
1112 	printf("MPI functionality tests\n");
1113 	printf("===================================\n");
1114     }
1115 
1116     if (VERBOSE_MED)
1117 	h5_show_hostname();
1118 
1119     fapl = H5Pcreate (H5P_FILE_ACCESS);
1120     H5Pset_fapl_mpio(fapl, MPI_COMM_WORLD, MPI_INFO_NULL);
1121 
1122     /* set alarm. */
1123     ALARM_ON;
1124 
1125 
1126     /*=======================================
1127      * MPIO 1 write Many read test
1128      *=======================================*/
1129     MPI_BANNER("MPIO 1 write Many read test...");
1130     ret_code = test_mpio_1wMr(filenames[0], USENONE);
1131     ret_code = errors_sum(ret_code);
1132     if (mpi_rank==0 && ret_code > 0){
1133 	printf("***FAILED with %d total errors\n", ret_code);
1134 	nerrors += ret_code;
1135     }
1136 
1137     /* test atomicity and file sync in high verbose mode only         */
1138     /* since they often hang when broken and PHDF5 does not use them. */
1139     if (VERBOSE_HI){
1140 	MPI_BANNER("MPIO 1 write Many read test with atomicity...");
1141 	ret_code = test_mpio_1wMr(filenames[0], USEATOM);
1142 	ret_code = errors_sum(ret_code);
1143 	if (mpi_rank==0 && ret_code > 0){
1144 	    printf("***FAILED with %d total errors\n", ret_code);
1145 	    nerrors += ret_code;
1146 	}
1147 
1148 	MPI_BANNER("MPIO 1 write Many read test with file sync...");
1149 	ret_code = test_mpio_1wMr(filenames[0], USEFSYNC);
1150 	ret_code = errors_sum(ret_code);
1151 	if (mpi_rank==0 && ret_code > 0){
1152 	    printf("***FAILED with %d total errors\n", ret_code);
1153 	    nerrors += ret_code;
1154 	}
1155     }
1156 
1157 
1158     /*=======================================
1159      * MPIO MPIO File size range test
1160      *=======================================*/
1161     MPI_BANNER("MPIO File size range test...");
1162 #ifndef H5_HAVE_WIN32_API
1163     ret_code = test_mpio_gb_file(filenames[0]);
1164     ret_code = errors_sum(ret_code);
1165     if (mpi_rank==0 && ret_code > 0){
1166 	printf("***FAILED with %d total errors\n", ret_code);
1167 	nerrors += ret_code;
1168     }
1169 #else
1170     if (mpi_rank==0)
1171         printf(" will be skipped on Windows (JIRA HDDFV-8064)\n");
1172 #endif
1173 
1174     /*=======================================
1175      * MPIO independent overlapping writes
1176      *=======================================*/
1177     MPI_BANNER("MPIO independent overlapping writes...");
1178     ret_code = test_mpio_overlap_writes(filenames[0]);
1179     ret_code = errors_sum(ret_code);
1180     if (mpi_rank==0 && ret_code > 0){
1181 	printf("***FAILED with %d total errors\n", ret_code);
1182 	nerrors += ret_code;
1183     }
1184 
1185     /*=======================================
1186      * MPIO complicated derived datatype test
1187      *=======================================*/
1188     MPI_BANNER("MPIO complicated derived datatype test...");
1189     ret_code = test_mpio_derived_dtype(filenames[0]);
1190     ret_code = errors_sum(ret_code);
1191     if (mpi_rank==0 && ret_code > 0){
1192 	printf("***FAILED with %d total errors\n", ret_code);
1193 	nerrors += ret_code;
1194     }
1195 
1196     /*=======================================
1197      * MPIO special collective IO  test
1198      *=======================================*/
1199     if (mpi_size < 4) {
1200         MPI_BANNER("MPIO special collective io test SKIPPED.");
1201         if (mpi_rank == 0)
1202             printf("This test needs at least four processes to run.\n");
1203         ret_code = 0;
1204         goto sc_finish;
1205     } /* end if */
1206 
1207     MPI_BANNER("MPIO special collective io test...");
1208     ret_code = test_mpio_special_collective(filenames[0]);
1209 
1210 sc_finish:
1211     ret_code = errors_sum(ret_code);
1212     if (mpi_rank==0 && ret_code > 0){
1213 	printf("***FAILED with %d total errors\n", ret_code);
1214 	nerrors += ret_code;
1215     }
1216 
1217 
1218 finish:
1219     /* make sure all processes are finished before final report, cleanup
1220      * and exit.
1221      */
1222     MPI_Barrier(MPI_COMM_WORLD);
1223     if (MAINPROCESS){		/* only process 0 reports */
1224 	printf("===================================\n");
1225 	if (nerrors){
1226 	    printf("***MPI tests detected %d errors***\n", nerrors);
1227 	}
1228 	else{
1229 	    printf("MPI tests finished with no errors\n");
1230 	}
1231 	printf("===================================\n");
1232     }
1233 
1234     /* turn off alarm */
1235     ALARM_OFF;
1236 
1237     h5_clean_files(FILENAME, fapl);
1238     H5close();
1239 
1240     /* MPI_Finalize must be called AFTER H5close which may use MPI calls */
1241     MPI_Finalize();
1242 
1243     /* cannot just return (nerrors) because exit code is limited to 1byte */
1244     return(nerrors!=0);
1245 }
1246 
1247