Actual source code: mpiuopen.c

petsc-3.11.4 2019-09-28
Report Typos and Errors
  1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
  2: /*
  3:       Some PETSc utilites routines to add simple parallel IO capability
  4: */
  5:  #include <petscsys.h>

  7: #include <errno.h>

  9: /*@C
 10:     PetscFOpen - Has the first process in the communicator open a file;
 11:     all others do nothing.

 13:     Logically Collective on MPI_Comm

 15:     Input Parameters:
 16: +   comm - the communicator
 17: .   name - the filename
 18: -   mode - the mode for fopen(), usually "w"

 20:     Output Parameter:
 21: .   fp - the file pointer

 23:     Level: developer

 25:     Notes:
 26:        NULL (0), "stderr" or "stdout" may be passed in as the filename

 28:     Fortran Note:
 29:     This routine is not supported in Fortran.

 31:     Concepts: opening ASCII file
 32:     Concepts: files^opening ASCII

 34: .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
 35:           PetscFPrintf()
 36: @*/
 37: PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
 38: {
 40:   PetscMPIInt    rank;
 41:   FILE           *fd;
 42:   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];

 45:   MPI_Comm_rank(comm,&rank);
 46:   if (!rank) {
 47:     PetscBool isstdout,isstderr;
 48:     PetscStrcmp(name,"stdout",&isstdout);
 49:     PetscStrcmp(name,"stderr",&isstderr);
 50:     if (isstdout || !name) fd = PETSC_STDOUT;
 51:     else if (isstderr) fd = PETSC_STDERR;
 52:     else {
 53:       PetscBool devnull;
 54:       PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
 55:       PetscFixFilename(tname,fname);
 56:       PetscStrbeginswith(fname,"/dev/null",&devnull);
 57:       if (devnull) {
 58:         PetscStrcpy(fname,"/dev/null");
 59:       }
 60:       PetscInfo1(0,"Opening file %s\n",fname);
 61:       fd   = fopen(fname,mode);
 62:       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
 63:     }
 64:   } else fd = 0;
 65:   *fp = fd;
 66:   return(0);
 67: }

 69: /*@C
 70:     PetscFClose - Has the first processor in the communicator close a
 71:     file; all others do nothing.

 73:     Logically Collective on MPI_Comm

 75:     Input Parameters:
 76: +   comm - the communicator
 77: -   fd - the file, opened with PetscFOpen()

 79:    Level: developer

 81:     Fortran Note:
 82:     This routine is not supported in Fortran.

 84:     Concepts: files^closing ASCII
 85:     Concepts: closing file

 87: .seealso: PetscFOpen()
 88: @*/
 89: PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
 90: {
 92:   PetscMPIInt    rank;
 93:   int            err;

 96:   MPI_Comm_rank(comm,&rank);
 97:   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
 98:     err = fclose(fd);
 99:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
100:   }
101:   return(0);
102: }

104: #if defined(PETSC_HAVE_POPEN)
105: static char PetscPOpenMachine[128] = "";

107: /*@C
108:       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()

110:      Collective on MPI_Comm, but only process 0 runs the command

112:    Input Parameters:
113: +   comm - MPI communicator, only processor zero runs the program
114: -   fp - the file pointer where program input or output may be read or NULL if don't care

116:    Level: intermediate

118:    Notes:
119:        Does not work under Windows

121: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()

123: @*/
124: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
125: {
127:   PetscMPIInt    rank;

130:   MPI_Comm_rank(comm,&rank);
131:   if (!rank) {
132:     char buf[1024];
133:     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
134:     (void) pclose(fd);
135:   }
136:   return(0);
137: }


140: /*@C
141:       PetscPOpen - Runs a program on processor zero and sends either its input or output to
142:           a file.

144:      Logically Collective on MPI_Comm, but only process 0 runs the command

146:    Input Parameters:
147: +   comm - MPI communicator, only processor zero runs the program
148: .   machine - machine to run command on or NULL, or string with 0 in first location
149: .   program - name of program to run
150: -   mode - either r or w

152:    Output Parameter:
153: .   fp - the file pointer where program input or output may be read or NULL if don't care

155:    Level: intermediate

157:    Notes:
158:        Use PetscPClose() to close the file pointer when you are finished with it
159:        Does not work under Windows

161:        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
162:        will use the machine running node zero of the communicator

164:        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
165:     will be replaced with relevent values.

167: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()

169: @*/
170: PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
171: {
173:   PetscMPIInt    rank;
174:   size_t         i,len,cnt;
175:   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
176:   FILE           *fd;

179:   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
180:   if (PetscPOpenMachine[0] || (machine && machine[0])) {
181:     PetscStrcpy(command,"ssh ");
182:     if (PetscPOpenMachine[0]) {
183:       PetscStrcat(command,PetscPOpenMachine);
184:     } else {
185:       PetscStrcat(command,machine);
186:     }
187:     PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
188:     /*
189:         Copy program into command but protect the " with a \ in front of it
190:     */
191:     PetscStrlen(command,&cnt);
192:     PetscStrlen(program,&len);
193:     for (i=0; i<len; i++) {
194:       if (program[i] == '\"') command[cnt++] = '\\';
195:       command[cnt++] = program[i];
196:     }
197:     command[cnt] = 0;

199:     PetscStrcat(command,"\"");
200:   } else {
201:     PetscStrcpy(command,program);
202:   }

204:   PetscStrreplace(comm,command,commandt,1024);

206:   MPI_Comm_rank(comm,&rank);
207:   if (!rank) {
208:     PetscInfo1(0,"Running command :%s\n",commandt);
209:     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
210:     if (fp) *fp = fd;
211:   }
212:   return(0);
213: }

215: /*@C
216:       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on

218:      Logically Collective on MPI_Comm, but only process 0 runs the command

220:    Input Parameter:
221: .   machine - machine to run command on or NULL to remove previous entry

223:    Options Database:
224: .   -popen_machine <machine>

226:    Level: intermediate

228: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()

230: @*/
231: PetscErrorCode  PetscPOpenSetMachine(const char machine[])
232: {

236:   if (machine) {
237:     PetscStrcpy(PetscPOpenMachine,machine);
238:   } else {
239:     PetscPOpenMachine[0] = 0;
240:   }
241:   return(0);
242: }

244: #endif