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: }