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