Actual source code: fretrieve.c
1: /*$Id: fretrieve.c,v 1.42 2001/08/10 03:28:49 bsmith Exp $*/
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(PARCH_win32)
21: #include <sys/utsname.h>
22: #endif
23: #if defined(PARCH_win32)
24: #include <windows.h>
25: #include <io.h>
26: #include <direct.h>
27: #endif
28: #if defined (PARCH_win32_gnu)
29: #include <windows.h>
30: #endif
31: #include <fcntl.h>
32: #include <time.h>
33: #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H)
34: #include <sys/systeminfo.h>
35: #endif
36: #include "petscfix.h"
38: EXTERN_C_BEGIN
39: EXTERN int Petsc_DelTag(MPI_Comm,int,void*,void*);
40: EXTERN_C_END
42: #undef __FUNCT__
44: /*@C
45: PetscGetTmp - Gets the name of the tmp directory
47: Collective on MPI_Comm
49: Input Parameters:
50: + comm - MPI_Communicator that may share /tmp
51: - len - length of string to hold name
53: Output Parameters:
54: . dir - directory name
56: Options Database Keys:
57: + -shared_tmp
58: . -not_shared_tmp
59: - -tmp tmpdir
61: Environmental Variables:
62: + PETSC_SHARED_TMP
63: . PETSC_NOT_SHARED_TMP
64: - PETSC_TMP
66: Level: developer
68:
69: If the environmental variable PETSC_TMP is set it will use this directory
70: as the "/tmp" directory.
72: @*/
73: int PetscGetTmp(MPI_Comm comm,char *dir,int len)
74: {
75: int ierr;
76: PetscTruth flg;
79: PetscOptionsGetenv(comm,"PETSC_TMP",dir,len,&flg);
80: if (!flg) {
81: PetscStrncpy(dir,"/tmp",len);
82: }
83: return(0);
84: }
86: #undef __FUNCT__
88: /*@C
89: PetscSharedTmp - Determines if all processors in a communicator share a
90: /tmp or have different ones.
92: Collective on MPI_Comm
94: Input Parameters:
95: . comm - MPI_Communicator that may share /tmp
97: Output Parameters:
98: . shared - PETSC_TRUE or PETSC_FALSE
100: Options Database Keys:
101: + -shared_tmp
102: . -not_shared_tmp
103: - -tmp tmpdir
105: Environmental Variables:
106: + PETSC_SHARED_TMP
107: . PETSC_NOT_SHARED_TMP
108: - PETSC_TMP
110: Level: developer
112: Notes:
113: Stores the status as a MPI attribute so it does not have
114: to be redetermined each time.
116: Assumes that all processors in a communicator either
117: 1) have a common /tmp or
118: 2) each has a seperate /tmp
119: eventually we can write a fancier one that determines which processors
120: share a common /tmp.
122: This will be very slow on runs with a large number of processors since
123: it requires O(p*p) file opens.
125: If the environmental variable PETSC_TMP is set it will use this directory
126: as the "/tmp" directory.
128: @*/
129: int PetscSharedTmp(MPI_Comm comm,PetscTruth *shared)
130: {
131: int ierr,size,rank,*tagvalp,sum,cnt,i;
132: PetscTruth flg,iflg;
133: FILE *fd;
134: static int Petsc_Tmp_keyval = MPI_KEYVAL_INVALID;
137: MPI_Comm_size(comm,&size);
138: if (size == 1) {
139: *shared = PETSC_TRUE;
140: return(0);
141: }
143: PetscOptionsGetenv(comm,"PETSC_SHARED_TMP",PETSC_NULL,0,&flg);
144: if (flg) {
145: *shared = PETSC_TRUE;
146: return(0);
147: }
149: PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_TMP",PETSC_NULL,0,&flg);
150: if (flg) {
151: *shared = PETSC_FALSE;
152: return(0);
153: }
155: if (Petsc_Tmp_keyval == MPI_KEYVAL_INVALID) {
156: MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTag,&Petsc_Tmp_keyval,0);
157: }
159: MPI_Attr_get(comm,Petsc_Tmp_keyval,(void**)&tagvalp,(int*)&iflg);
160: if (!iflg) {
161: char filename[PETSC_MAX_PATH_LEN],tmpname[PETSC_MAX_PATH_LEN];
163: /* This communicator does not yet have a shared tmp attribute */
164: PetscMalloc(sizeof(int),&tagvalp);
165: MPI_Attr_put(comm,Petsc_Tmp_keyval,tagvalp);
167: PetscOptionsGetenv(comm,"PETSC_TMP",tmpname,238,&iflg);
168: if (!iflg) {
169: PetscStrcpy(filename,"/tmp");
170: } else {
171: PetscStrcpy(filename,tmpname);
172: }
174: PetscStrcat(filename,"/petsctestshared");
175: MPI_Comm_rank(comm,&rank);
176:
177: /* each processor creates a /tmp file and all the later ones check */
178: /* this makes sure no subset of processors is shared */
179: *shared = PETSC_FALSE;
180: for (i=0; i<size-1; i++) {
181: if (rank == i) {
182: fd = fopen(filename,"w");
183: if (!fd) {
184: SETERRQ1(1,"Unable to open test file %s",filename);
185: }
186: fclose(fd);
187: }
188: MPI_Barrier(comm);
189: if (rank >= i) {
190: fd = fopen(filename,"r");
191: if (fd) cnt = 1; else cnt = 0;
192: if (fd) {
193: fclose(fd);
194: }
195: } else {
196: cnt = 0;
197: }
198: MPI_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);
199: if (rank == i) {
200: unlink(filename);
201: }
203: if (sum == size) {
204: *shared = PETSC_TRUE;
205: break;
206: } else if (sum != 1) {
207: SETERRQ(1,"Subset of processes share /tmp ");
208: }
209: }
210: *tagvalp = (int)*shared;
211: PetscLogInfo(0,"PetscSharedTmp: processors %s %sn",(*shared == PETSC_TRUE) ? "share":"do NOT share",(iflg ? tmpname:"/tmp"));
212: } else {
213: *shared = (PetscTruth) *tagvalp;
214: }
215: return(0);
216: }
218: #undef __FUNCT__
220: /*@C
221: PetscSharedWorkingDirectory - Determines if all processors in a communicator share a
222: working directory or have different ones.
224: Collective on MPI_Comm
226: Input Parameters:
227: . comm - MPI_Communicator that may share working directory
229: Output Parameters:
230: . shared - PETSC_TRUE or PETSC_FALSE
232: Options Database Keys:
233: + -shared_working_directory
234: . -not_shared_working_directory
236: Environmental Variables:
237: + PETSC_SHARED_WORKING_DIRECTORY
238: . PETSC_NOT_SHARED_WORKING_DIRECTORY
240: Level: developer
242: Notes:
243: Stores the status as a MPI attribute so it does not have
244: to be redetermined each time.
246: Assumes that all processors in a communicator either
247: 1) have a common working directory or
248: 2) each has a seperate working directory
249: eventually we can write a fancier one that determines which processors
250: share a common working directory.
252: This will be very slow on runs with a large number of processors since
253: it requires O(p*p) file opens.
255: @*/
256: int PetscSharedWorkingDirectory(MPI_Comm comm,PetscTruth *shared)
257: {
258: int ierr,size,rank,*tagvalp,sum,cnt,i;
259: PetscTruth flg,iflg;
260: FILE *fd;
261: static int Petsc_WD_keyval = MPI_KEYVAL_INVALID;
264: MPI_Comm_size(comm,&size);
265: if (size == 1) {
266: *shared = PETSC_TRUE;
267: return(0);
268: }
270: PetscOptionsGetenv(comm,"PETSC_SHARED_WORKING_DIRECTORY",PETSC_NULL,0,&flg);
271: if (flg) {
272: *shared = PETSC_TRUE;
273: return(0);
274: }
276: PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_WORKING_DIRECTORY",PETSC_NULL,0,&flg);
277: if (flg) {
278: *shared = PETSC_FALSE;
279: return(0);
280: }
282: if (Petsc_WD_keyval == MPI_KEYVAL_INVALID) {
283: MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTag,&Petsc_WD_keyval,0);
284: }
286: MPI_Attr_get(comm,Petsc_WD_keyval,(void**)&tagvalp,(int*)&iflg);
287: if (!iflg) {
288: char filename[PETSC_MAX_PATH_LEN];
290: /* This communicator does not yet have a shared attribute */
291: PetscMalloc(sizeof(int),&tagvalp);
292: MPI_Attr_put(comm,Petsc_WD_keyval,tagvalp);
294: PetscGetWorkingDirectory(filename,240);
295: PetscStrcat(filename,"/petsctestshared");
296: MPI_Comm_rank(comm,&rank);
297:
298: /* each processor creates a file and all the later ones check */
299: /* this makes sure no subset of processors is shared */
300: *shared = PETSC_FALSE;
301: for (i=0; i<size-1; i++) {
302: if (rank == i) {
303: fd = fopen(filename,"w");
304: if (!fd) {
305: SETERRQ1(1,"Unable to open test file %s",filename);
306: }
307: fclose(fd);
308: }
309: MPI_Barrier(comm);
310: if (rank >= i) {
311: fd = fopen(filename,"r");
312: if (fd) cnt = 1; else cnt = 0;
313: if (fd) {
314: fclose(fd);
315: }
316: } else {
317: cnt = 0;
318: }
319: MPI_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);
320: if (rank == i) {
321: unlink(filename);
322: }
324: if (sum == size) {
325: *shared = PETSC_TRUE;
326: break;
327: } else if (sum != 1) {
328: SETERRQ(1,"Subset of processes share working directory");
329: }
330: }
331: *tagvalp = (int)*shared;
332: } else {
333: *shared = (PetscTruth) *tagvalp;
334: }
335: PetscLogInfo(0,"PetscSharedWorkingDirectory: processors %s working directoryn",(*shared == PETSC_TRUE) ? "shared" : "do NOT share");
336: return(0);
337: }
340: #undef __FUNCT__
342: /*@C
343: PetscFileRetrieve - Obtains a library from a URL or compressed
344: and copies into local disk space as uncompressed.
346: Collective on MPI_Comm
348: Input Parameter:
349: + comm - processors accessing the library
350: . libname - name of library, including entire URL (with or without .gz)
351: - llen - length of llibname
353: Output Parameter:
354: + llibname - name of local copy of library
355: - found - if found and retrieved the file
357: Level: developer
359: @*/
360: int PetscFileRetrieve(MPI_Comm comm,const char *libname,char *llibname,int llen,PetscTruth *found)
361: {
362: char buf[1024],tmpdir[PETSC_MAX_PATH_LEN],urlget[PETSC_MAX_PATH_LEN],*par,*pdir;
363: FILE *fp;
364: int i,rank,ierr,len = 0;
365: PetscTruth flg1,flg2,sharedtmp,exists;
368: *found = PETSC_FALSE;
370: /* if file does not have an ftp:// or http:// or .gz then need not process file */
371: PetscStrstr(libname,".gz",&par);
372: if (par) {PetscStrlen(par,&len);}
374: PetscStrncmp(libname,"ftp://",6,&flg1);
375: PetscStrncmp(libname,"http://",7,&flg2);
376: if (!flg1 && !flg2 && (!par || len != 3)) {
377: PetscStrncpy(llibname,libname,llen);
378: PetscTestFile(libname,'r',found);
379: return(0);
380: }
382: /* Determine if all processors share a common /tmp */
383: PetscSharedTmp(comm,&sharedtmp);
384: PetscOptionsGetenv(comm,"PETSC_TMP",tmpdir,PETSC_MAX_PATH_LEN,&flg1);
386: MPI_Comm_rank(comm,&rank);
387: if (!rank || !sharedtmp) {
388:
389: /* Construct the script to get URL file */
390: PetscGetPetscDir(&pdir);
391: PetscStrcpy(urlget,pdir);
392: PetscStrcat(urlget,"/bin/urlget");
393: PetscTestFile(urlget,'r',&exists);
394: if (!exists) {
395: PetscTestFile("urlget",'r',&exists);
396: if (!exists) {
397: SETERRQ1(1,"Cannot locate PETSc script urlget in %s or current directory",urlget);
398: }
399: PetscStrcpy(urlget,"urlget");
400: }
401: PetscStrcat(urlget," ");
403: /* are we using an alternative /tmp? */
404: if (flg1) {
405: PetscStrcat(urlget,"-tmp ");
406: PetscStrcat(urlget,tmpdir);
407: PetscStrcat(urlget," ");
408: }
410: PetscStrcat(urlget,libname);
411: PetscStrcat(urlget," 2>&1 ");
413: PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,urlget,"r",&fp);
414: if (!fgets(buf,1024,fp)) {
415: SETERRQ1(1,"No output from ${PETSC_DIR}/bin/urlget in getting file %s",libname);
416: }
417: PetscLogInfo(0,"PetscFileRetrieve:Message back from urlget: %sn",buf);
419: PetscStrncmp(buf,"Error",5,&flg1);
420: PetscStrncmp(buf,"Traceback",9,&flg2);
421: PetscPClose(PETSC_COMM_SELF,fp);
422: if (flg1 || flg2) {
423: *found = PETSC_FALSE;
424: } else {
425: *found = PETSC_TRUE;
426:
427: /* Check for n and make it 0 */
428: for (i=0; i<1024; i++) {
429: if (buf[i] == 'n') {
430: buf[i] = 0;
431: break;
432: }
433: }
434: PetscStrncpy(llibname,buf,llen);
435: }
436: }
437: if (sharedtmp) { /* send library name to all processors */
438: MPI_Bcast(found,1,MPI_INT,0,comm);
439: if (*found) {
440: MPI_Bcast(llibname,llen,MPI_CHAR,0,comm);
441: MPI_Bcast(found,1,MPI_INT,0,comm);
442: }
443: }
445: return(0);
446: }