00001 /****************************************************************************** 00002 * testxmdf.c : Defines the entry point for the parallel XMDF tests. 00003 ******************************************************************************/ 00004 00005 /* 00006 * INCLUDE HEADERS 00007 */ 00008 00009 #include "xmdf_putil.h" 00010 #include <mpi.h> 00011 #include <stdlib.h> 00012 #include <stdio.h> 00013 #include "xmdf_par.h" 00014 00015 #include <sys/types.h> 00016 #include <sys/stat.h> 00017 #include <fcntl.h> 00018 #include <unistd.h> /* ,lseek */ 00019 #include <string.h> 00020 00021 #include "closeh5.h" /* get close library */ 00022 00023 /* 00024 * DEFINITIONS 00025 */ 00026 00027 #define ERRORD(A,B,C) ERROR(A,B,C) 00028 #define PRINTM(A) PRINTS("msg",(A)) 00029 00030 /* FUNCTION fileinit 00031 * PURPOSE initializes xmdf file 00032 * NOTES 00033 */ 00034 xid fileinit( char *a_fname, char *a_gname ) 00035 { 00036 xid fileID, dataSetID; 00037 closeObjPtr closeobj = closeCreate(); 00038 xid ret; 00039 00040 xfiSetComm( MPI_COMM_WORLD ); 00041 00042 ret = xfCreateFilePar( a_fname, &fileID, XTRUE, MPI_INFO_NULL ); 00043 if (0 > closePush( closeobj, xfCloseFile, ret < 0 ? ret : fileID )) 00044 { 00045 PRINTM( "xfCreateFilePar returned error" ); 00046 return ret; 00047 } 00048 00049 /* xfOpenFilePar( a_fname, &fileId, XFALSE, MPI_INFO_NULL ); */ 00050 00051 ret = xfCreateScalarDataset( fileID, a_gname, "", TS_SECONDS, -1, &dataSetID ); 00052 if (0 > closePush( closeobj, xfCloseGroup, ret < 0 ? ret : dataSetID )) 00053 { 00054 PRINTM( "xfCreateScalarDataset returned error" ); 00055 return ret; 00056 } 00057 00058 closePush( closeobj, NULL, -1 ); /* close all */ 00059 return 0; /* return success */ 00060 } 00061 00062 /* FUNCTION setup 00063 * PURPOSE reopens file and returns dataset id and totalcount 00064 * NOTES 00065 */ 00066 xid setup (closeObjPtr a_closeobj, /* stack close calls */ 00067 const char *a_filename, 00068 const char *a_groupname, 00069 const int a_mynum, /* number of values /process/timestep */ 00070 int *a_totalCount) /* number of values /timestep */ 00071 { 00072 xid ret; 00073 xid fileID, dataSetID; 00074 00075 /* open file for write */ 00076 ret = xfOpenFilePar(a_filename, &fileID, XFALSE, MPI_INFO_NULL); 00077 if (0 > closePush( a_closeobj, xfCloseFile, ret < 0 ? ret : fileID )) 00078 { 00079 ERRORD( "setup", "xfOpenFilePar returned error", ret ); 00080 return ret; 00081 } 00082 00083 PRINTS( "filename", a_filename ); 00084 PRINTS( "groupname", a_groupname ); 00085 00086 /* open group */ 00087 ret = xfOpenGroup(fileID, a_groupname, &dataSetID); 00088 if (0 > closePush( a_closeobj, xfCloseGroup, ret < 0 ? ret : dataSetID )) 00089 { 00090 ERRORD( "setup", "xfOpenGroup returned error", ret ); 00091 return ret; 00092 } 00093 00094 /* get totalCount sum of all mynum values */ 00095 { 00096 int num = a_mynum; 00097 MPI_Allreduce( &num, 00098 a_totalCount, 00099 1, 00100 MPI_INT, 00101 MPI_SUM, 00102 MPI_COMM_WORLD ); 00103 } 00104 return dataSetID; 00105 } 00106 00107 /* FUNCTION setup2 00108 * PURPOSE reopens file and returns dataset id and totalcount 00109 * NOTES 00110 */ 00111 xid setup2 (closeObjPtr a_closeobj, /* stack close calls */ 00112 const char *a_filename, 00113 const char *a_groupname, 00114 const int a_mynum, /* number of values /process/timestep */ 00115 int *a_totalCount) /* number of values /timestep */ 00116 { 00117 xid ret; 00118 xid fileID, dataSetID; 00119 00120 /* open file for write */ 00121 ret = xfOpenFilePar(a_filename, &fileID, XFALSE, MPI_INFO_NULL); 00122 if (0 > closePush( a_closeobj, xfCloseFile, ret < 0 ? ret : fileID )) 00123 { 00124 ERRORD( "setup", "xfOpenFilePar returned error", ret ); 00125 return ret; 00126 } 00127 00128 PRINTS( "filename", a_filename ); 00129 PRINTS( "groupname", a_groupname ); 00130 00131 /* open group */ 00132 ret = xfOpenGroup(fileID, a_groupname, &dataSetID); 00133 if (0 > closePush( a_closeobj, xfCloseGroup, ret < 0 ? ret : dataSetID )) 00134 { 00135 ERRORD( "setup", "xfOpenGroup returned error", ret ); 00136 return ret; 00137 } 00138 00139 /* get totalCount sum of all mynum values */ 00140 { 00141 int num = a_mynum; 00142 MPI_Allreduce( &num, 00143 a_totalCount, 00144 1, 00145 MPI_INT, 00146 MPI_SUM, 00147 MPI_COMM_WORLD ); 00148 } 00149 return dataSetID; 00150 } 00151 00152 /* FUNCTION abs 00153 * PURPOSE return absolute value of val 00154 * NOTES 00155 */ 00156 double absd( double a_val ) 00157 { 00158 return a_val < 0 ? -a_val : a_val; 00159 } 00160 00161 /* FUNCTION testminmax 00162 * PURPOSE compares array of values against xfGetDatasetMins/Maxs array 00163 * NOTES returns <0 on miss compare, and prints error 00164 */ 00165 int testminmax( int a_timesteps, /* number of timesteps in file */ 00166 xid a_dataSetID, /* dataset in file */ 00167 int a_minnotmax, /* XTRUE is minimum test, not max */ 00168 double a_tolerance, /* tolerance of compare */ 00169 double *a_expectminmaxs ) /* array of expected mins or maxs */ 00170 { 00171 xid ret; 00172 int ii; 00173 float *minmaxs = malloc(sizeof(float)*a_timesteps); 00174 00175 if (!minmaxs) 00176 { 00177 ERRORD( "testScalar", "malloc", 0 ); 00178 return -1; 00179 } 00180 00181 TIMER("pre"); 00182 ret = a_minnotmax ? 00183 xfGetDatasetMins( a_dataSetID, a_timesteps, minmaxs ) : 00184 xfGetDatasetMaxs( a_dataSetID, a_timesteps, minmaxs ); 00185 TIMER("TIME xfGetDatasetMins/Maxs"); 00186 if (ret < 0) 00187 { 00188 free(minmaxs); 00189 ERRORD( "testminmax", 00190 a_minnotmax ? 00191 "xfGetDatasetMins" : 00192 "xfGetDatasetMaxs", 00193 ret ); 00194 return ret; 00195 } 00196 00197 for (ii=0; ii<a_timesteps; ii++) 00198 { 00199 if (absd(minmaxs[ii]) > absd(a_expectminmaxs[ii]) * (1+a_tolerance) || 00200 absd(minmaxs[ii]) < absd(a_expectminmaxs[ii]) * (1-a_tolerance) ) 00201 { 00202 ERRORD( "testminmax", 00203 a_minnotmax ? 00204 "read min does not match parallel write at timestep" : 00205 "read max does not match parallel write at timestep", 00206 ii ); 00207 PRINTF( "found", minmaxs[ii] ); 00208 PRINTF( "expect", a_expectminmaxs[ii] ); 00209 PRINTF( "difference", a_expectminmaxs[ii]-minmaxs[ii] ); 00210 return -1; 00211 } 00212 } 00213 00214 if (minmaxs) free(minmaxs); 00215 00216 return !0; 00217 } 00218 00219 /* FUNCTION testScalar 00220 * PURPOSE Runs the scalar parallel XMDF test 00221 * NOTES 00222 */ 00223 int testScalar() 00224 { 00225 double *values; /* pointer to data value buffer */ 00226 int *indices; /* index of each data item (parallel issue) */ 00227 int subnum; /* number of values written by each process */ 00228 char *filename = "dbl_test.h5"; 00229 char *groupname = "myData"; 00230 int timesteps = 2; 00231 double average[2]; 00232 int rank; 00233 int offset; 00234 double writemins[2]; 00235 double writemaxs[2]; 00236 00237 /* create file */ 00238 { 00239 xid ret = fileinit(filename, groupname); 00240 if (0 > ret) 00241 return ret; 00242 } 00243 00244 /* init subnum */ 00245 subnum = 1000000; 00246 PRINTD( "subnum", subnum ); 00247 00248 values = malloc( sizeof(double) * subnum); /* allocate data buffer */ 00249 indices = malloc( sizeof(int) * subnum ); 00250 00251 /* init indices and values */ 00252 { 00253 MPI_Comm_rank( MPI_COMM_WORLD, &rank ); /* get process number */ 00254 00255 /* Returns in offset the sum of this process's subnum and 00256 * all subnum's from processes of smaller rank, thus 00257 * rank 0 gets subnum*1, rank 1 gets subnum*2, etc */ 00258 MPI_Scan( &subnum, &offset, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD ); 00259 offset -= subnum; /* start at 0, not at subnum */ 00260 00261 } 00262 00263 /* reopen and write file with scalar */ 00264 { 00265 int ii; 00266 xid ret; 00267 xid dataSetID; 00268 int totalnum; 00269 closeObjPtr closeobj = closeCreate(); 00270 00271 dataSetID = setup( closeobj, filename, groupname, subnum, &totalnum ); 00272 if (dataSetID < 0) return dataSetID; 00273 00274 PRINTF( "totalnum", totalnum ); 00275 00276 /* write timesteps */ 00277 for (ii=0; ii<timesteps; ii++) 00278 { 00279 /* init values and indices */ 00280 { 00281 int jj; 00282 int pick = 777; 00283 00284 average[ii] = 0; 00285 00286 for (jj = 0; jj<subnum; jj++) 00287 { 00288 /* set index and value for each entry */ 00289 indices[jj] = (offset + jj - 3) % totalnum + 1; 00290 values[jj] = indices[jj] + (rank * .01) + (ii * .001); 00291 00292 /* calculate test average, mins, maxs, and test pick */ 00293 average[ii] += values[jj]/subnum; 00294 if (jj==0 || writemins[ii]>values[jj]) writemins[ii] = values[jj]; 00295 if (jj==0 || writemaxs[ii]<values[jj]) writemaxs[ii] = values[jj]; 00296 if( (indices[jj]-1)%subnum == 0 ) pick = jj; 00297 } 00298 00299 PRINTD( "offset", offset ); 00300 PRINTD( "pick", pick ); 00301 PRINTD( "indices[pick]-1", indices[pick]-1 ); 00302 PRINTF( "values[pick]", values[pick] ); 00303 average[ii] *= values[pick]; 00304 } 00305 00306 TIMER("pre"); 00307 xfiPrintDataset( __FILE__, __LINE__, "test", dataSetID); 00308 PRINTD( "totalnum", totalnum ); 00309 PRINTD( "subnum", subnum ); 00310 PRINTF( "values", values[0] ); 00311 PRINTD( "indices", indices[0] ); 00312 ret = xfWriteScalarTimestepPar( dataSetID, 00313 0.0, /* time */ 00314 totalnum, 00315 subnum, 00316 values, 00317 indices, 00318 0 ); /* stride */ 00319 TIMER("TIME xfWriteScalarTimestepPar"); 00320 /* xid a_Id xid of the group containing the dataset 00321 * double a_Time time of the current time step 00322 * int a_NumTotal total number of values in the dataset 00323 * int a_NumValues number of values to be written by this processor 00324 * const double a_Values values to be written to the dataset 00325 * const int a_WhichVals indices corresponding to the location of the 00326 * values in the dataset 00327 * int a_Stride number of values (or bytes) to be skipped in the 00328 * dataset after each value 00329 */ 00330 00331 if (closePush( closeobj, NULL, ret ) < 0) 00332 { 00333 ERRORD( "testScalar", "xfWriteScalarTimestepPar", ret ); 00334 return ret; 00335 } 00336 } 00337 00338 closePush( closeobj, NULL, -1 ); /* close all */ 00339 } 00340 00341 /* reopen and read file */ 00342 { 00343 int ii; 00344 xid ret; 00345 xid dataSetID; 00346 int totalnum; 00347 closeObjPtr closeobj = closeCreate(); 00348 00349 dataSetID = setup( closeobj, filename, groupname, subnum, &totalnum ); 00350 if (dataSetID < 0) return dataSetID; 00351 00352 for (ii=0; ii<timesteps; ii++) 00353 { 00354 TIMER("pre"); 00355 PRINTD("dataSetID",(int)dataSetID); 00356 xfiPrintDataset( __FILE__, __LINE__, "read", dataSetID ); 00357 { 00358 xid DatasetId = H5Dopen(dataSetID, "Values"); 00359 printf( "%s:%d: H5Dopen %d\n", __FILE__, __LINE__, (int)DatasetId ); 00360 H5Dclose(DatasetId); 00361 } 00362 ret = xfReadScalarValuesTimestepPar( dataSetID, 00363 ii+1, /* timestep */ 00364 offset+1, /* start */ 00365 subnum, 00366 values, 00367 0 ); 00368 { 00369 xid DatasetId = H5Dopen(dataSetID, "Values"); 00370 PRINTD( "H5Dopen", DatasetId ); 00371 H5Dclose(DatasetId); 00372 } 00373 TIMER("TIME xfReadScalarValuesTimestepPar"); 00374 /* xid a_Id xid of the group containing the dataset 00375 * int a_Time time index of the current time step (1 based) 00376 * int a_StartIndex indices corresponding to the starting location of the 00377 * values in the dataset to be read 00378 * int a_NumValues number of values to be read 00379 * float a_Values values to be read from the dataset 00380 * int a_Stride number of values (or bytes) to be skipped in the 00381 * dataset after each value 00382 */ 00383 if (closePush( closeobj, NULL, ret ) < 0) 00384 { 00385 printf( "%s:%d: ERROR in %s: %d %d %d %d %d %d %d\n", 00386 __FILE__, __LINE__, 00387 "testScalar", ret, 00388 (int)dataSetID, 00389 ii+1, /* timestep */ 00390 offset+1, /* start */ 00391 subnum, 00392 values==0, 00393 0 ); 00394 return ret; 00395 } 00396 00397 /* compare results */ 00398 { 00399 double avg = 0; 00400 int jj; 00401 00402 for (jj = 0; jj<subnum; jj++) 00403 { 00404 avg += values[jj]/subnum; 00405 } 00406 avg *= values[0]; /* verify ordering (crc would be better) */ 00407 00408 if (avg > average[ii]*(1+.00001) || 00409 avg < average[ii]*(1-.00001) ) 00410 { 00411 ERRORD( "testScalar", "read does not match write for timestep", ii+1 ); 00412 PRINTF( "found", avg ); 00413 PRINTF( "expected", average[ii] ); 00414 PRINTF( "values[0]", values[0] ); 00415 } 00416 else 00417 PRINTD( "PASS: parallel read matches parallel write, step ", ii ); 00418 } 00419 } 00420 00421 closePush( closeobj, NULL, -1 ); /* close all */ 00422 } 00423 00424 /* reopen and read file sequentially via processor 0 */ 00425 MPI_Barrier(MPI_COMM_WORLD); 00426 if (!rank) { 00427 int ii; 00428 xid ret; 00429 xid dataSetID; 00430 xid fileID; 00431 closeObjPtr closeobj = closeCreate(); 00432 00433 /* open file for write */ 00434 ret = xfOpenFile(filename, &fileID, XTRUE); 00435 if (0 > closePush( closeobj, xfCloseFile, ret < 0 ? ret : fileID )) 00436 { 00437 PRINTM( "xfOpenFilePar returned error" ); 00438 return ret; 00439 } 00440 00441 /* open group */ 00442 ret = xfOpenGroup(fileID, groupname, &dataSetID); 00443 if (ret >= 0) ret = dataSetID; 00444 if (0 > closePush( closeobj, xfCloseGroup, ret )) 00445 { 00446 PRINTM( "xfOpenGroup returned error" ); 00447 return ret; 00448 } 00449 00450 ret = testminmax( timesteps, dataSetID, XTRUE, 0.001, writemins ); 00451 if (ret < 0) 00452 { 00453 ERRORD( "testScalar", "testminmax (min)", ret ); 00454 return ret; 00455 } 00456 00457 ret = testminmax( timesteps, dataSetID, XFALSE, 0.001, writemaxs ); 00458 if (ret < 0) 00459 { 00460 ERRORD( "testScalar", "testminmax (max)", ret ); 00461 return ret; 00462 } 00463 00464 for (ii=0; ii<timesteps; ii++) 00465 { 00466 TIMER("pre"); 00467 ret = xfReadScalarValuesTimestepDoublePortion( dataSetID, 00468 ii+1, /* time */ 00469 1, 00470 subnum, 00471 values ); 00472 TIMER("TIME xfReadScalarValuesTimestepDoublePortion"); 00473 /* xid a_Id xid of the group containing the dataset 00474 * int a_Time time index of the current time step (1 based) 00475 * int a_StartIndex indices corresponding to the starting location of the 00476 * values in the dataset to be read 00477 * int a_NumValues number of values to be read 00478 * float a_Values values to be read from the dataset 00479 */ 00480 if (closePush( closeobj, NULL, ret ) < 0) 00481 { 00482 PRINTD( "ERROR in testScalar: xfReadScalarTimestepDoublePortion returned", ret ); 00483 return ret; 00484 } 00485 00486 /* compare results */ 00487 { 00488 double avg = 0; 00489 int jj; 00490 00491 for (jj = 0; jj<subnum; jj++) 00492 { 00493 avg += values[jj]/subnum; 00494 } 00495 avg *= values[0]; /* verify ordering (crc would be better) */ 00496 00497 if (avg > average[ii]*(1+.00001) || 00498 avg < average[ii]*(1-.00001) ) 00499 { 00500 ERRORD( "testScalar", "read does not match write for timestep", ii+1 ); 00501 PRINTF( "found", avg ); 00502 PRINTF( "expected", average[ii] ); 00503 } 00504 else 00505 PRINTM( "PASS: sequential read matches parallel write" ); 00506 } 00507 } 00508 00509 closePush( closeobj, NULL, -1 ); /* close all */ 00510 } 00511 00512 return !0; 00513 } 00514 00515 /* FUNCTION testVector 00516 * PURPOSE Runs the vector parallel XMDF test 00517 * NOTES 00518 */ 00519 int testVector() 00520 { 00521 double *values; /* pointer to data value buffer */ 00522 int valuesRank = 2; /* number of dimensions of the data */ 00523 int *indices; /* index of each data item (parallel issue) */ 00524 int subnum; /* number of values written by each process */ 00525 char *filename = "dbl_test.h5"; /* OS file name */ 00526 char *groupname = "myData"; /* hdf5 group name */ 00527 00528 /* create file */ 00529 { 00530 xid ret = fileinit(filename, groupname); 00531 if (0 > ret) 00532 return ret; 00533 } 00534 00535 /* init subnum */ 00536 subnum = 100; 00537 PRINTD( "subnum", subnum ); 00538 00539 values = malloc( sizeof(*values) * subnum * valuesRank ); /* allocate data buffer */ 00540 indices = malloc( sizeof(*indices) * subnum ); 00541 00542 /* init indices and values */ 00543 { 00544 int rank; 00545 int offset; 00546 00547 MPI_Comm_rank( MPI_COMM_WORLD, &rank ); /* get process number */ 00548 00549 /* Returns in offset the sum of this process's subnum and 00550 * all subnum's from processes of smaller rank, thus 00551 * rank 0 gets subnum*1, rank 1 gets subnum*2, etc */ 00552 MPI_Scan( &subnum, &offset, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD ); 00553 offset -= subnum; /* start at 0, not at subnum */ 00554 00555 { 00556 int ii; 00557 int jj; 00558 00559 for (ii = 0; ii<subnum; ii++) 00560 { 00561 indices[ii] = offset + ii + 1; /* set index of each data value */ 00562 00563 for (jj = 0; jj<valuesRank; jj++) 00564 { 00565 /* init data in buffer */ 00566 values[ii*valuesRank + jj] = (ii*10 + jj)*10 + rank; 00567 } 00568 } 00569 } 00570 } 00571 00572 /* reopen and write file with vector */ 00573 { 00574 xid ret; 00575 xid dataSetID; 00576 int totalnum; 00577 closeObjPtr closeobj = closeCreate(); 00578 00579 dataSetID = setup( closeobj, filename, groupname, subnum, &totalnum ); 00580 if (dataSetID < 0) return dataSetID; 00581 00582 ret = xfWriteVectorTimestepPar( dataSetID, 00583 0.0, 00584 totalnum, 00585 subnum, 00586 valuesRank, 00587 values, 00588 indices, 00589 0 ); 00590 /* xid a_Id xid of the group containing the dataset 00591 * double a_Time time of the current time step 00592 * int a_NumTotal total number of values in the dataset 00593 * int a_NumProc number of values to be written by this processor 00594 * int a_NumComponents number of components in each vector value 00595 * const double*a_Values values to be written to the dataset 00596 * const int *a_WhichVals indices corresponding to the location of the 00597 * values in the dataset 00598 * int a_Stride number of values (or bytes) to be skipped in the 00599 * dataset after each value 00600 */ 00601 00602 /* xfWriteVectorTimestepPar does the following: 00603 * 00604 * return error if number of process values is less than 1 00605 * copy data to a new array if stride is set ??? expand 00606 * flag whether using null value ??? expand 00607 * calculate min and max vector lengths 00608 * open datasets for data, time, min, max 00609 * write time after waiting for other processes, or append 00610 * write data after waiting for other processes, or append ??? expand 00611 * . create dataset 00612 * . select elements 00613 * write min/max after waiting for other processes, or append 00614 */ 00615 00616 if (closePush( closeobj, NULL, ret ) < 0) 00617 { 00618 PRINTD( "ERROR in testVector: xfWriteVectorTimestepPar returned", ret ); 00619 return ret; 00620 } 00621 00622 printf( "%s:%d: wrote values[5][0-1] = %f %f\n", __FILE__, __LINE__, 00623 values[5*valuesRank + 0], 00624 values[5*valuesRank + 1] ); 00625 00626 closePush( closeobj, NULL, -1 ); /* close all */ 00627 } 00628 00629 /* reopen and read file with vector */ 00630 { 00631 xid ret; 00632 xid dataSetID; 00633 int totalnum; 00634 closeObjPtr closeobj = closeCreate(); 00635 00636 dataSetID = setup( closeobj, filename, groupname, subnum, &totalnum ); 00637 if (dataSetID < 0) return dataSetID; 00638 00639 ret = xfReadScalarValuesTimestepPar( dataSetID, 00640 1, 00641 1, 00642 subnum, 00643 values, 00644 0 ); 00645 /* xid a_Id xid of the group containing the dataset 00646 * int a_Time time index of the current time step (1 based) 00647 * int a_StartIndex indices corresponding to the starting location of the 00648 * values in the dataset to be read 00649 * int a_NumValues number of values to be read 00650 * float a_Values values to be read from the dataset 00651 * int a_Stride number of values (or bytes) to be skipped in the 00652 * dataset after each value 00653 */ 00654 if (closePush( closeobj, NULL, ret ) < 0) 00655 { 00656 PRINTD( "ERROR in testVector: xfReadVectorTimestepPar returned", ret ); 00657 return ret; 00658 } 00659 00660 printf( "%s:%d: wrote values[5][0-1] = %f %f\n", __FILE__, __LINE__, 00661 values[5*valuesRank + 0], 00662 values[5*valuesRank + 1] ); 00663 00664 closePush( closeobj, NULL, -1 ); /* close all */ 00665 } 00666 00667 return !0; 00668 } 00669 00670 void timeposix() 00671 { 00672 int fd; 00673 char *fname = "data.posix"; 00674 int numentries = 3000000; 00675 int memsize = sizeof(double) * numentries; 00676 int uniqueloc = numentries/3; 00677 double *ptr = (double*)malloc(memsize); 00678 int ret; 00679 int offset; 00680 double uniquedata; 00681 00682 uniquedata = deltatime(); 00683 00684 /* WRITE */ 00685 00686 fd=open(fname, O_WRONLY|O_CREAT|O_APPEND, 0760); /* open file for writing */ 00687 if (fd < 0 ) 00688 { 00689 printf("%s:%d: ERROR: Failed to open file %s\n", __FILE__,__LINE__, fname); 00690 return; 00691 } 00692 00693 memset(ptr, 0, memsize); /* clear buffer */ 00694 ptr[uniqueloc] = uniquedata; /* set unique value */ 00695 TIMER("PreIsoWrite"); 00696 ret = write(fd, ptr, memsize); /* write buffer */ 00697 offset = lseek(fd, 0, SEEK_CUR); /* get offset into file */ 00698 close(fd); /* close file */ 00699 TIMER("POSTiSOwRITE"); 00700 if (ret != memsize) /* check write failure */ 00701 { 00702 printf("%s:%d: ERROR: Failed to write file %s\n", __FILE__,__LINE__, fname); 00703 return; 00704 } 00705 00706 /* READ */ 00707 00708 memset(ptr, 0, memsize); /* clear buffer */ 00709 if (ptr[uniqueloc] == memsize) /* verify cleared buffer */ 00710 { 00711 printf("%s:%d: ERROR: buffer was not cleared\n", __FILE__,__LINE__); 00712 return; 00713 } 00714 00715 fd=open(fname, O_RDONLY, 0760); /* open file for reading */ 00716 if (fd < 0 ) 00717 { 00718 printf("%s:%d: ERROR: Failed to open readable file %s\n", __FILE__,__LINE__, fname); 00719 return; 00720 } 00721 00722 ret = lseek(fd, offset-memsize, SEEK_CUR); /* offset to where data was written */ 00723 if (ret != offset-memsize) 00724 { 00725 printf("%s:%d: ERROR: lseek return value is off by %d\n", __FILE__,__LINE__, offset - memsize - ret); 00726 close(fd); 00727 return; 00728 } 00729 00730 TIMER("PreIsoRead"); 00731 ret = read(fd, ptr, memsize); 00732 TIMER("POSTiSOrEAD"); 00733 close(fd); 00734 if (ret != memsize) 00735 { 00736 printf("%s:%d: ERROR: Failed to read file %s\n", __FILE__,__LINE__, fname); 00737 return; 00738 } 00739 00740 if (ptr[uniqueloc] != uniquedata) /* verify cleared buffer */ 00741 { 00742 printf("%s:%d: ERROR: data incorrect.\n", __FILE__,__LINE__); 00743 return; 00744 } 00745 00746 printf("%s:%d: PASS PASS PASS.\n", __FILE__,__LINE__); 00747 } 00748 00749 /* FUNCTION main 00750 * PURPOSE runs the test cases for parallel XMDF 00751 * NOTES 00752 */ 00753 int main(int argc, char **argv) 00754 { 00755 int fail = !0; 00756 int ret; 00757 00758 MPI_Init(&argc, &argv); /* init multiprocessor interface */ 00759 TIMER(NULL); /* initialize timer */ 00760 00761 MPI_Barrier(MPI_COMM_WORLD); 00762 timeposix(); 00763 MPI_Barrier(MPI_COMM_WORLD); 00764 00765 ret = testScalar(); if (ret < 0) fail = ret; 00766 TIMER("final time"); /* initialize timer */ 00767 PRINTD( ret < 0 ? "FAIL" : "ALL PASS", fail ); 00768 00769 xfClosePar(); /* must be closed before MPI */ 00770 MPI_Finalize(); 00771 return fail; 00772 }