Actual source code: fretrieve.c
1: #define PETSC_DLL
2: /*
3: Code for opening and closing files.
4: */
5: #include petsc.h
6: #include petscsys.h
7: #include "petscfix.h"
8: #if defined(PETSC_HAVE_PWD_H)
9: #include <pwd.h>
10: #endif
11: #include <ctype.h>
12: #include <sys/types.h>
13: #include <sys/stat.h>
14: #if defined(PETSC_HAVE_UNISTD_H)
15: #include <unistd.h>
16: #endif
17: #if defined(PETSC_HAVE_STDLIB_H)
18: #include <stdlib.h>
19: #endif
20: #if defined(PETSC_HAVE_SYS_UTSNAME_H)
21: #include <sys/utsname.h>
22: #endif
23: #include <fcntl.h>
24: #include <time.h>
25: #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
26: #include <sys/systeminfo.h>
27: #endif
28: #include "petscfix.h"
31: EXTERN PetscMPIInt Petsc_DelTag(MPI_Comm,PetscMPIInt,void*,void*);
36: /*@C
37: PetscGetTmp - Gets the name of the tmp directory
39: Collective on MPI_Comm
41: Input Parameters:
42: + comm - MPI_Communicator that may share /tmp
43: - len - length of string to hold name
45: Output Parameters:
46: . dir - directory name
48: Options Database Keys:
49: + -shared_tmp
50: . -not_shared_tmp
51: - -tmp tmpdir
53: Environmental Variables:
54: + PETSC_SHARED_TMP
55: . PETSC_NOT_SHARED_TMP
56: - PETSC_TMP
58: Level: developer
60:
61: If the environmental variable PETSC_TMP is set it will use this directory
62: as the "/tmp" directory.
64: @*/
65: PetscErrorCode PetscGetTmp(MPI_Comm comm,char *dir,size_t len)
66: {
68: PetscTruth flg;
71: PetscOptionsGetenv(comm,"PETSC_TMP",dir,len,&flg);
72: if (!flg) {
73: PetscStrncpy(dir,"/tmp",len);
74: }
75: return(0);
76: }
80: /*@C
81: PetscSharedTmp - Determines if all processors in a communicator share a
82: /tmp or have different ones.
84: Collective on MPI_Comm
86: Input Parameters:
87: . comm - MPI_Communicator that may share /tmp
89: Output Parameters:
90: . shared - PETSC_TRUE or PETSC_FALSE
92: Options Database Keys:
93: + -shared_tmp
94: . -not_shared_tmp
95: - -tmp tmpdir
97: Environmental Variables:
98: + PETSC_SHARED_TMP
99: . PETSC_NOT_SHARED_TMP
100: - PETSC_TMP
102: Level: developer
104: Notes:
105: Stores the status as a MPI attribute so it does not have
106: to be redetermined each time.
108: Assumes that all processors in a communicator either
109: 1) have a common /tmp or
110: 2) each has a separate /tmp
111: eventually we can write a fancier one that determines which processors
112: share a common /tmp.
114: This will be very slow on runs with a large number of processors since
115: it requires O(p*p) file opens.
117: If the environmental variable PETSC_TMP is set it will use this directory
118: as the "/tmp" directory.
120: @*/
121: PetscErrorCode PetscSharedTmp(MPI_Comm comm,PetscTruth *shared)
122: {
123: PetscErrorCode ierr;
124: PetscMPIInt size,rank,*tagvalp,sum,cnt,i;
125: PetscTruth flg,iflg;
126: FILE *fd;
127: static PetscMPIInt Petsc_Tmp_keyval = MPI_KEYVAL_INVALID;
130: MPI_Comm_size(comm,&size);
131: if (size == 1) {
132: *shared = PETSC_TRUE;
133: return(0);
134: }
136: PetscOptionsGetenv(comm,"PETSC_SHARED_TMP",PETSC_NULL,0,&flg);
137: if (flg) {
138: *shared = PETSC_TRUE;
139: return(0);
140: }
142: PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_TMP",PETSC_NULL,0,&flg);
143: if (flg) {
144: *shared = PETSC_FALSE;
145: return(0);
146: }
148: if (Petsc_Tmp_keyval == MPI_KEYVAL_INVALID) {
149: MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTag,&Petsc_Tmp_keyval,0);
150: }
152: MPI_Attr_get(comm,Petsc_Tmp_keyval,(void**)&tagvalp,(int*)&iflg);
153: if (!iflg) {
154: char filename[PETSC_MAX_PATH_LEN],tmpname[PETSC_MAX_PATH_LEN];
156: /* This communicator does not yet have a shared tmp attribute */
157: PetscMalloc(sizeof(PetscMPIInt),&tagvalp);
158: MPI_Attr_put(comm,Petsc_Tmp_keyval,tagvalp);
160: PetscOptionsGetenv(comm,"PETSC_TMP",tmpname,238,&iflg);
161: if (!iflg) {
162: PetscStrcpy(filename,"/tmp");
163: } else {
164: PetscStrcpy(filename,tmpname);
165: }
167: PetscStrcat(filename,"/petsctestshared");
168: MPI_Comm_rank(comm,&rank);
169:
170: /* each processor creates a /tmp file and all the later ones check */
171: /* this makes sure no subset of processors is shared */
172: *shared = PETSC_FALSE;
173: for (i=0; i<size-1; i++) {
174: if (rank == i) {
175: fd = fopen(filename,"w");
176: if (!fd) {
177: SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename);
178: }
179: fclose(fd);
180: }
181: MPI_Barrier(comm);
182: if (rank >= i) {
183: fd = fopen(filename,"r");
184: if (fd) cnt = 1; else cnt = 0;
185: if (fd) {
186: fclose(fd);
187: }
188: } else {
189: cnt = 0;
190: }
191: MPI_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);
192: if (rank == i) {
193: unlink(filename);
194: }
196: if (sum == size) {
197: *shared = PETSC_TRUE;
198: break;
199: } else if (sum != 1) {
200: SETERRQ(PETSC_ERR_SUP_SYS,"Subset of processes share /tmp ");
201: }
202: }
203: *tagvalp = (int)*shared;
204: PetscInfo2(0,"processors %s %s\n",(*shared) ? "share":"do NOT share",(iflg ? tmpname:"/tmp"));
205: } else {
206: *shared = (PetscTruth) *tagvalp;
207: }
208: return(0);
209: }
213: /*@C
214: PetscSharedWorkingDirectory - Determines if all processors in a communicator share a
215: working directory or have different ones.
217: Collective on MPI_Comm
219: Input Parameters:
220: . comm - MPI_Communicator that may share working directory
222: Output Parameters:
223: . shared - PETSC_TRUE or PETSC_FALSE
225: Options Database Keys:
226: + -shared_working_directory
227: . -not_shared_working_directory
229: Environmental Variables:
230: + PETSC_SHARED_WORKING_DIRECTORY
231: . PETSC_NOT_SHARED_WORKING_DIRECTORY
233: Level: developer
235: Notes:
236: Stores the status as a MPI attribute so it does not have
237: to be redetermined each time.
239: Assumes that all processors in a communicator either
240: 1) have a common working directory or
241: 2) each has a separate working directory
242: eventually we can write a fancier one that determines which processors
243: share a common working directory.
245: This will be very slow on runs with a large number of processors since
246: it requires O(p*p) file opens.
248: @*/
249: PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm,PetscTruth *shared)
250: {
251: PetscErrorCode ierr;
252: PetscMPIInt size,rank,*tagvalp,sum,cnt,i;
253: PetscTruth flg,iflg;
254: FILE *fd;
255: static PetscMPIInt Petsc_WD_keyval = MPI_KEYVAL_INVALID;
258: MPI_Comm_size(comm,&size);
259: if (size == 1) {
260: *shared = PETSC_TRUE;
261: return(0);
262: }
264: PetscOptionsGetenv(comm,"PETSC_SHARED_WORKING_DIRECTORY",PETSC_NULL,0,&flg);
265: if (flg) {
266: *shared = PETSC_TRUE;
267: return(0);
268: }
270: PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_WORKING_DIRECTORY",PETSC_NULL,0,&flg);
271: if (flg) {
272: *shared = PETSC_FALSE;
273: return(0);
274: }
276: if (Petsc_WD_keyval == MPI_KEYVAL_INVALID) {
277: MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTag,&Petsc_WD_keyval,0);
278: }
280: MPI_Attr_get(comm,Petsc_WD_keyval,(void**)&tagvalp,(int*)&iflg);
281: if (!iflg) {
282: char filename[PETSC_MAX_PATH_LEN];
284: /* This communicator does not yet have a shared attribute */
285: PetscMalloc(sizeof(PetscMPIInt),&tagvalp);
286: MPI_Attr_put(comm,Petsc_WD_keyval,tagvalp);
288: PetscGetWorkingDirectory(filename,240);
289: PetscStrcat(filename,"/petsctestshared");
290: MPI_Comm_rank(comm,&rank);
291:
292: /* each processor creates a file and all the later ones check */
293: /* this makes sure no subset of processors is shared */
294: *shared = PETSC_FALSE;
295: for (i=0; i<size-1; i++) {
296: if (rank == i) {
297: fd = fopen(filename,"w");
298: if (!fd) {
299: SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename);
300: }
301: fclose(fd);
302: }
303: MPI_Barrier(comm);
304: if (rank >= i) {
305: fd = fopen(filename,"r");
306: if (fd) cnt = 1; else cnt = 0;
307: if (fd) {
308: fclose(fd);
309: }
310: } else {
311: cnt = 0;
312: }
313: MPI_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);
314: if (rank == i) {
315: unlink(filename);
316: }
318: if (sum == size) {
319: *shared = PETSC_TRUE;
320: break;
321: } else if (sum != 1) {
322: SETERRQ(PETSC_ERR_SUP_SYS,"Subset of processes share working directory");
323: }
324: }
325: *tagvalp = (int)*shared;
326: } else {
327: *shared = (PetscTruth) *tagvalp;
328: }
329: PetscInfo1(0,"processors %s working directory\n",(*shared) ? "shared" : "do NOT share");
330: return(0);
331: }
336: /*@C
337: PetscFileRetrieve - Obtains a library from a URL or compressed
338: and copies into local disk space as uncompressed.
340: Collective on MPI_Comm
342: Input Parameter:
343: + comm - processors accessing the library
344: . libname - name of library, including entire URL (with or without .gz)
345: - llen - length of llibname
347: Output Parameter:
348: + llibname - name of local copy of library
349: - found - if found and retrieved the file
351: Level: developer
353: @*/
354: PetscErrorCode PetscFileRetrieve(MPI_Comm comm,const char *libname,char *llibname,size_t llen,PetscTruth *found)
355: {
356: char buf[1024],tmpdir[PETSC_MAX_PATH_LEN],urlget[PETSC_MAX_PATH_LEN],*par;
357: const char *pdir;
358: FILE *fp;
359: PetscErrorCode ierr;
360: int i;
361: PetscMPIInt rank;
362: size_t len = 0;
363: PetscTruth flg1,flg2,sharedtmp,exists;
366: *found = PETSC_FALSE;
368: /* if file does not have an ftp:// or http:// or .gz then need not process file */
369: PetscStrstr(libname,".gz",&par);
370: if (par) {PetscStrlen(par,&len);}
372: PetscStrncmp(libname,"ftp://",6,&flg1);
373: PetscStrncmp(libname,"http://",7,&flg2);
374: if (!flg1 && !flg2 && (!par || len != 3)) {
375: PetscStrncpy(llibname,libname,llen);
376: PetscTestFile(libname,'r',found);
377: return(0);
378: }
380: /* Determine if all processors share a common /tmp */
381: PetscSharedTmp(comm,&sharedtmp);
382: PetscOptionsGetenv(comm,"PETSC_TMP",tmpdir,PETSC_MAX_PATH_LEN,&flg1);
384: MPI_Comm_rank(comm,&rank);
385: if (!rank || !sharedtmp) {
386:
387: /* Construct the script to get URL file */
388: PetscGetPetscDir(&pdir);
389: PetscStrcpy(urlget,pdir);
390: PetscStrcat(urlget,"/bin/urlget");
391: PetscTestFile(urlget,'r',&exists);
392: if (!exists) {
393: PetscTestFile("urlget",'r',&exists);
394: if (!exists) {
395: SETERRQ1(PETSC_ERR_PLIB,"Cannot locate PETSc script urlget in %s or current directory",urlget);
396: }
397: PetscStrcpy(urlget,"urlget");
398: }
399: PetscStrcat(urlget," ");
401: /* are we using an alternative /tmp? */
402: if (flg1) {
403: PetscStrcat(urlget,"-tmp ");
404: PetscStrcat(urlget,tmpdir);
405: PetscStrcat(urlget," ");
406: }
408: PetscStrcat(urlget,libname);
409: PetscStrcat(urlget," 2>&1 ");
411: #if defined(PETSC_HAVE_POPEN)
412: PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,urlget,"r",&fp);
413: #else
414: SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
415: #endif
416: if (!fgets(buf,1024,fp)) {
417: SETERRQ1(PETSC_ERR_PLIB,"No output from ${PETSC_DIR}/bin/urlget in getting file %s",libname);
418: }
419: PetscInfo1(0,"Message back from urlget: %s\n",buf);
421: PetscStrncmp(buf,"Error",5,&flg1);
422: PetscStrncmp(buf,"Traceback",9,&flg2);
423: #if defined(PETSC_HAVE_POPEN)
424: PetscPClose(PETSC_COMM_SELF,fp);
425: #endif
426: if (flg1 || flg2) {
427: *found = PETSC_FALSE;
428: } else {
429: *found = PETSC_TRUE;
430:
431: /* Check for \n and make it 0 */
432: for (i=0; i<1024; i++) {
433: if (buf[i] == '\n') {
434: buf[i] = 0;
435: break;
436: }
437: }
438: PetscStrncpy(llibname,buf,llen);
439: }
440: }
441: if (sharedtmp) { /* send library name to all processors */
442: MPI_Bcast(found,1,MPI_INT,0,comm);
443: if (*found) {
444: MPI_Bcast(llibname,llen,MPI_CHAR,0,comm);
445: MPI_Bcast(found,1,MPI_INT,0,comm);
446: }
447: }
449: return(0);
450: }