testxmdf.c

testxmdf.c provides a Parallel MPI C code example and performance measurements for scalar dataset writes.

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 }

Generated on Mon Oct 16 16:29:13 2006 for XMDF Documentation by  doxygen 1.4.6-NO