Actual source code: mpiuopen.c
petsc-3.8.4 2018-03-24
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: Output Parameters:
117: . rval - return value from pclose() or NULL to raise an error on failure
119: Level: intermediate
121: Notes:
122: Does not work under Windows
124: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
126: @*/
127: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd,int *rval)
128: {
130: PetscMPIInt rank;
131: int err;
134: MPI_Comm_rank(comm,&rank);
135: if (!rank) {
136: char buf[1024];
137: while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
138: err = pclose(fd);
139: if (rval) *rval = err;
140: else if (err) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"pclose() failed with error code %d, errno %d",err,errno);
141: }
142: return(0);
143: }
146: /*@C
147: PetscPOpen - Runs a program on processor zero and sends either its input or output to
148: a file.
150: Logically Collective on MPI_Comm, but only process 0 runs the command
152: Input Parameters:
153: + comm - MPI communicator, only processor zero runs the program
154: . machine - machine to run command on or NULL, or string with 0 in first location
155: . program - name of program to run
156: - mode - either r or w
158: Output Parameter:
159: . fp - the file pointer where program input or output may be read or NULL if don't care
161: Level: intermediate
163: Notes:
164: Use PetscPClose() to close the file pointer when you are finished with it
165: Does not work under Windows
167: If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
168: will use the machine running node zero of the communicator
170: The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
171: will be replaced with relevent values.
173: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
175: @*/
176: PetscErrorCode PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
177: {
179: PetscMPIInt rank;
180: size_t i,len,cnt;
181: char commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
182: FILE *fd;
185: /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
186: if (PetscPOpenMachine[0] || (machine && machine[0])) {
187: PetscStrcpy(command,"ssh ");
188: if (PetscPOpenMachine[0]) {
189: PetscStrcat(command,PetscPOpenMachine);
190: } else {
191: PetscStrcat(command,machine);
192: }
193: PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
194: /*
195: Copy program into command but protect the " with a \ in front of it
196: */
197: PetscStrlen(command,&cnt);
198: PetscStrlen(program,&len);
199: for (i=0; i<len; i++) {
200: if (program[i] == '\"') command[cnt++] = '\\';
201: command[cnt++] = program[i];
202: }
203: command[cnt] = 0;
205: PetscStrcat(command,"\"");
206: } else {
207: PetscStrcpy(command,program);
208: }
210: PetscStrreplace(comm,command,commandt,1024);
212: MPI_Comm_rank(comm,&rank);
213: if (!rank) {
214: PetscInfo1(0,"Running command :%s\n",commandt);
215: if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
216: if (fp) *fp = fd;
217: }
218: return(0);
219: }
221: /*@C
222: PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
224: Logically Collective on MPI_Comm, but only process 0 runs the command
226: Input Parameter:
227: . machine - machine to run command on or NULL to remove previous entry
229: Options Database:
230: . -popen_machine <machine>
232: Level: intermediate
234: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
236: @*/
237: PetscErrorCode PetscPOpenSetMachine(const char machine[])
238: {
242: if (machine) {
243: PetscStrcpy(PetscPOpenMachine,machine);
244: } else {
245: PetscPOpenMachine[0] = 0;
246: }
247: return(0);
248: }
250: #endif