Actual source code: mpiuopen.c
petsc-3.7.7 2017-09-25
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>
11: /*@C
12: PetscFOpen - Has the first process in the communicator open a file;
13: all others do nothing.
15: Logically Collective on MPI_Comm
17: Input Parameters:
18: + comm - the communicator
19: . name - the filename
20: - mode - the mode for fopen(), usually "w"
22: Output Parameter:
23: . fp - the file pointer
25: Level: developer
27: Notes:
28: NULL (0), "stderr" or "stdout" may be passed in as the filename
30: Fortran Note:
31: This routine is not supported in Fortran.
33: Concepts: opening ASCII file
34: Concepts: files^opening ASCII
36: .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
37: PetscFPrintf()
38: @*/
39: PetscErrorCode PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
40: {
42: PetscMPIInt rank;
43: FILE *fd;
44: char fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
47: MPI_Comm_rank(comm,&rank);
48: if (!rank) {
49: PetscBool isstdout,isstderr;
50: PetscStrcmp(name,"stdout",&isstdout);
51: PetscStrcmp(name,"stderr",&isstderr);
52: if (isstdout || !name) fd = PETSC_STDOUT;
53: else if (isstderr) fd = PETSC_STDERR;
54: else {
55: PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
56: PetscFixFilename(tname,fname);
57: PetscInfo1(0,"Opening file %s\n",fname);
58: fd = fopen(fname,mode);
59: if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
60: }
61: } else fd = 0;
62: *fp = fd;
63: return(0);
64: }
68: /*@
69: PetscFClose - Has the first processor in the communicator close a
70: file; all others do nothing.
72: Logically Collective on MPI_Comm
74: Input Parameters:
75: + comm - the communicator
76: - fd - the file, opened with PetscFOpen()
78: Level: developer
80: Fortran Note:
81: This routine is not supported in Fortran.
83: Concepts: files^closing ASCII
84: Concepts: closing file
86: .seealso: PetscFOpen()
87: @*/
88: PetscErrorCode PetscFClose(MPI_Comm comm,FILE *fd)
89: {
91: PetscMPIInt rank;
92: int err;
95: MPI_Comm_rank(comm,&rank);
96: if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
97: err = fclose(fd);
98: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
99: }
100: return(0);
101: }
103: #if defined(PETSC_HAVE_POPEN)
104: static char PetscPOpenMachine[128] = "";
108: /*@C
109: PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
111: Collective on MPI_Comm, but only process 0 runs the command
113: Input Parameters:
114: + comm - MPI communicator, only processor zero runs the program
115: - fp - the file pointer where program input or output may be read or NULL if don't care
117: Output Parameters:
118: . rval - return value from pclose() or NULL to raise an error on failure
120: Level: intermediate
122: Notes:
123: Does not work under Windows
125: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
127: @*/
128: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd,int *rval)
129: {
131: PetscMPIInt rank;
132: int err;
135: MPI_Comm_rank(comm,&rank);
136: if (!rank) {
137: char buf[1024];
138: while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
139: err = pclose(fd);
140: if (rval) *rval = err;
141: else if (err) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"pclose() failed with error code %d, errno %d",err,errno);
142: }
143: return(0);
144: }
149: /*@C
150: PetscPOpen - Runs a program on processor zero and sends either its input or output to
151: a file.
153: Logically Collective on MPI_Comm, but only process 0 runs the command
155: Input Parameters:
156: + comm - MPI communicator, only processor zero runs the program
157: . machine - machine to run command on or NULL, or string with 0 in first location
158: . program - name of program to run
159: - mode - either r or w
161: Output Parameter:
162: . fp - the file pointer where program input or output may be read or NULL if don't care
164: Level: intermediate
166: Notes:
167: Use PetscPClose() to close the file pointer when you are finished with it
168: Does not work under Windows
170: If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
171: will use the machine running node zero of the communicator
173: The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
174: will be replaced with relevent values.
176: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
178: @*/
179: PetscErrorCode PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
180: {
182: PetscMPIInt rank;
183: size_t i,len,cnt;
184: char commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
185: FILE *fd;
188: /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
189: if (PetscPOpenMachine[0] || (machine && machine[0])) {
190: PetscStrcpy(command,"ssh ");
191: if (PetscPOpenMachine[0]) {
192: PetscStrcat(command,PetscPOpenMachine);
193: } else {
194: PetscStrcat(command,machine);
195: }
196: PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
197: /*
198: Copy program into command but protect the " with a \ in front of it
199: */
200: PetscStrlen(command,&cnt);
201: PetscStrlen(program,&len);
202: for (i=0; i<len; i++) {
203: if (program[i] == '\"') command[cnt++] = '\\';
204: command[cnt++] = program[i];
205: }
206: command[cnt] = 0;
208: PetscStrcat(command,"\"");
209: } else {
210: PetscStrcpy(command,program);
211: }
213: PetscStrreplace(comm,command,commandt,1024);
215: MPI_Comm_rank(comm,&rank);
216: if (!rank) {
217: PetscInfo1(0,"Running command :%s\n",commandt);
218: if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
219: if (fp) *fp = fd;
220: }
221: return(0);
222: }
226: /*@C
227: PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
229: Logically Collective on MPI_Comm, but only process 0 runs the command
231: Input Parameter:
232: . machine - machine to run command on or NULL to remove previous entry
234: Options Database:
235: . -popen_machine <machine>
237: Level: intermediate
239: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
241: @*/
242: PetscErrorCode PetscPOpenSetMachine(const char machine[])
243: {
247: if (machine) {
248: PetscStrcpy(PetscPOpenMachine,machine);
249: } else {
250: PetscPOpenMachine[0] = 0;
251: }
252: return(0);
253: }
255: #endif