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  MPIAPI 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;
128:   int                err;

131:   MPI_Comm_size(comm,&size);
132:   if (size == 1) {
133:     *shared = PETSC_TRUE;
134:     return(0);
135:   }

137:   PetscOptionsGetenv(comm,"PETSC_SHARED_TMP",PETSC_NULL,0,&flg);
138:   if (flg) {
139:     *shared = PETSC_TRUE;
140:     return(0);
141:   }

143:   PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_TMP",PETSC_NULL,0,&flg);
144:   if (flg) {
145:     *shared = PETSC_FALSE;
146:     return(0);
147:   }

149:   if (Petsc_Tmp_keyval == MPI_KEYVAL_INVALID) {
150:     MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTag,&Petsc_Tmp_keyval,0);
151:   }

153:   MPI_Attr_get(comm,Petsc_Tmp_keyval,(void**)&tagvalp,(int*)&iflg);
154:   if (!iflg) {
155:     char       filename[PETSC_MAX_PATH_LEN],tmpname[PETSC_MAX_PATH_LEN];

157:     /* This communicator does not yet have a shared tmp attribute */
158:     PetscMalloc(sizeof(PetscMPIInt),&tagvalp);
159:     MPI_Attr_put(comm,Petsc_Tmp_keyval,tagvalp);

161:     PetscOptionsGetenv(comm,"PETSC_TMP",tmpname,238,&iflg);
162:     if (!iflg) {
163:       PetscStrcpy(filename,"/tmp");
164:     } else {
165:       PetscStrcpy(filename,tmpname);
166:     }

168:     PetscStrcat(filename,"/petsctestshared");
169:     MPI_Comm_rank(comm,&rank);
170: 
171:     /* each processor creates a /tmp file and all the later ones check */
172:     /* this makes sure no subset of processors is shared */
173:     *shared = PETSC_FALSE;
174:     for (i=0; i<size-1; i++) {
175:       if (rank == i) {
176:         fd = fopen(filename,"w");
177:         if (!fd) {
178:           SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename);
179:         }
180:         err = fclose(fd);
181:         if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
182:       }
183:       MPI_Barrier(comm);
184:       if (rank >= i) {
185:         fd = fopen(filename,"r");
186:         if (fd) cnt = 1; else cnt = 0;
187:         if (fd) {
188:           err = fclose(fd);
189:           if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
190:         }
191:       } else {
192:         cnt = 0;
193:       }
194:       MPI_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);
195:       if (rank == i) {
196:         unlink(filename);
197:       }

199:       if (sum == size) {
200:         *shared = PETSC_TRUE;
201:         break;
202:       } else if (sum != 1) {
203:         SETERRQ(PETSC_ERR_SUP_SYS,"Subset of processes share /tmp ");
204:       }
205:     }
206:     *tagvalp = (int)*shared;
207:     PetscInfo2(0,"processors %s %s\n",(*shared) ? "share":"do NOT share",(iflg ? tmpname:"/tmp"));
208:   } else {
209:     *shared = (PetscTruth) *tagvalp;
210:   }
211:   return(0);
212: }

216: /*@C
217:    PetscSharedWorkingDirectory - Determines if all processors in a communicator share a
218:          working directory or have different ones.

220:    Collective on MPI_Comm

222:    Input Parameters:
223: .  comm - MPI_Communicator that may share working directory

225:    Output Parameters:
226: .  shared - PETSC_TRUE or PETSC_FALSE

228:    Options Database Keys:
229: +    -shared_working_directory 
230: .    -not_shared_working_directory

232:    Environmental Variables:
233: +     PETSC_SHARED_WORKING_DIRECTORY
234: .     PETSC_NOT_SHARED_WORKING_DIRECTORY

236:    Level: developer

238:    Notes:
239:    Stores the status as a MPI attribute so it does not have
240:     to be redetermined each time.

242:       Assumes that all processors in a communicator either
243:        1) have a common working directory or
244:        2) each has a separate working directory
245:       eventually we can write a fancier one that determines which processors
246:       share a common working directory.

248:    This will be very slow on runs with a large number of processors since
249:    it requires O(p*p) file opens.

251: @*/
252: PetscErrorCode  PetscSharedWorkingDirectory(MPI_Comm comm,PetscTruth *shared)
253: {
254:   PetscErrorCode     ierr;
255:   PetscMPIInt        size,rank,*tagvalp,sum,cnt,i;
256:   PetscTruth         flg,iflg;
257:   FILE               *fd;
258:   static PetscMPIInt Petsc_WD_keyval = MPI_KEYVAL_INVALID;
259:   int                err;

262:   MPI_Comm_size(comm,&size);
263:   if (size == 1) {
264:     *shared = PETSC_TRUE;
265:     return(0);
266:   }

268:   PetscOptionsGetenv(comm,"PETSC_SHARED_WORKING_DIRECTORY",PETSC_NULL,0,&flg);
269:   if (flg) {
270:     *shared = PETSC_TRUE;
271:     return(0);
272:   }

274:   PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_WORKING_DIRECTORY",PETSC_NULL,0,&flg);
275:   if (flg) {
276:     *shared = PETSC_FALSE;
277:     return(0);
278:   }

280:   if (Petsc_WD_keyval == MPI_KEYVAL_INVALID) {
281:     MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTag,&Petsc_WD_keyval,0);
282:   }

284:   MPI_Attr_get(comm,Petsc_WD_keyval,(void**)&tagvalp,(int*)&iflg);
285:   if (!iflg) {
286:     char       filename[PETSC_MAX_PATH_LEN];

288:     /* This communicator does not yet have a shared  attribute */
289:     PetscMalloc(sizeof(PetscMPIInt),&tagvalp);
290:     MPI_Attr_put(comm,Petsc_WD_keyval,tagvalp);

292:     PetscGetWorkingDirectory(filename,240);
293:     PetscStrcat(filename,"/petsctestshared");
294:     MPI_Comm_rank(comm,&rank);
295: 
296:     /* each processor creates a  file and all the later ones check */
297:     /* this makes sure no subset of processors is shared */
298:     *shared = PETSC_FALSE;
299:     for (i=0; i<size-1; i++) {
300:       if (rank == i) {
301:         fd = fopen(filename,"w");
302:         if (!fd) SETERRQ1(PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename);
303:         err = fclose(fd);
304:         if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
305:       }
306:       MPI_Barrier(comm);
307:       if (rank >= i) {
308:         fd = fopen(filename,"r");
309:         if (fd) cnt = 1; else cnt = 0;
310:         if (fd) {
311:           err = fclose(fd);
312:           if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
313:         }
314:       } else {
315:         cnt = 0;
316:       }
317:       MPI_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);
318:       if (rank == i) {
319:         unlink(filename);
320:       }

322:       if (sum == size) {
323:         *shared = PETSC_TRUE;
324:         break;
325:       } else if (sum != 1) {
326:         SETERRQ(PETSC_ERR_SUP_SYS,"Subset of processes share working directory");
327:       }
328:     }
329:     *tagvalp = (int)*shared;
330:   } else {
331:     *shared = (PetscTruth) *tagvalp;
332:   }
333:   PetscInfo1(0,"processors %s working directory\n",(*shared) ? "shared" : "do NOT share");
334:   return(0);
335: }


340: /*@C
341:     PetscFileRetrieve - Obtains a library from a URL or compressed 
342:         and copies into local disk space as uncompressed.

344:     Collective on MPI_Comm

346:     Input Parameter:
347: +   comm     - processors accessing the library
348: .   libname  - name of library, including entire URL (with or without .gz)
349: -   llen     - length of llibname

351:     Output Parameter:
352: +   llibname - name of local copy of library
353: -   found - if found and retrieved the file

355:     Level: developer

357: @*/
358: PetscErrorCode  PetscFileRetrieve(MPI_Comm comm,const char libname[],char llibname[],size_t llen,PetscTruth *found)
359: {
360:   char              buf[1024],tmpdir[PETSC_MAX_PATH_LEN],urlget[PETSC_MAX_PATH_LEN],*par;
361:   const char        *pdir;
362:   FILE              *fp;
363:   PetscErrorCode    ierr;
364:   int               i;
365:   PetscMPIInt       rank;
366:   size_t            len = 0;
367:   PetscTruth        flg1,flg2,flg3,sharedtmp,exists;

370:   *found = PETSC_FALSE;

372:   /* if file does not have an ftp:// or http:// or .gz then need not process file */
373:   PetscStrstr(libname,".gz",&par);
374:   if (par) {PetscStrlen(par,&len);}

376:   PetscStrncmp(libname,"ftp://",6,&flg1);
377:   PetscStrncmp(libname,"http://",7,&flg2);
378:   PetscStrncmp(libname,"file://",7,&flg3);
379:   if (!flg1 && !flg2 && !flg3 && (!par || len != 3)) {
380:     PetscStrncpy(llibname,libname,llen);
381:     PetscTestFile(libname,'r',found);
382:     if (*found) {
383:       PetscInfo1(PETSC_NULL,"Found file %s\n",libname);
384:     } else {
385:       PetscInfo1(PETSC_NULL,"Did not find file %s\n",libname);
386:     }
387:     return(0);
388:   }

390:   /* Determine if all processors share a common /tmp */
391:   PetscSharedTmp(comm,&sharedtmp);
392:   PetscOptionsGetenv(comm,"PETSC_TMP",tmpdir,PETSC_MAX_PATH_LEN,&flg1);

394:   MPI_Comm_rank(comm,&rank);
395:   if (!rank || !sharedtmp) {
396: 
397:     /* Construct the script to get URL file */
398:     PetscGetPetscDir(&pdir);
399:     PetscStrcpy(urlget,pdir);
400:     PetscStrcat(urlget,"/bin/urlget");
401:     PetscTestFile(urlget,'r',&exists);
402:     if (!exists) {
403:       PetscTestFile("urlget",'r',&exists);
404:       if (!exists) {
405:         SETERRQ1(PETSC_ERR_PLIB,"Cannot locate PETSc script urlget in %s or current directory",urlget);
406:       }
407:       PetscStrcpy(urlget,"urlget");
408:     }
409:     PetscStrcat(urlget," ");

411:     /* are we using an alternative /tmp? */
412:     if (flg1) {
413:       PetscStrcat(urlget,"-tmp ");
414:       PetscStrcat(urlget,tmpdir);
415:       PetscStrcat(urlget," ");
416:     }

418:     PetscStrcat(urlget,libname);
419:     PetscStrcat(urlget," 2>&1 ");

421: #if defined(PETSC_HAVE_POPEN)
422:     PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,urlget,"r",&fp);
423: #else
424:     SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
425: #endif
426:     if (!fgets(buf,1024,fp)) {
427:       SETERRQ1(PETSC_ERR_PLIB,"No output from ${PETSC_DIR}/bin/urlget in getting file %s",libname);
428:     }
429:     PetscInfo1(0,"Message back from urlget: %s\n",buf);

431:     PetscStrncmp(buf,"Error",5,&flg1);
432:     PetscStrncmp(buf,"Traceback",9,&flg2);
433: #if defined(PETSC_HAVE_POPEN)
434:     PetscPClose(PETSC_COMM_SELF,fp);
435: #endif
436:     if (flg1 || flg2) {
437:       *found = PETSC_FALSE;
438:     } else {
439:       *found = PETSC_TRUE;
440: 
441:       /* Check for \n and make it 0 */
442:       for (i=0; i<1024; i++) {
443:         if (buf[i] == '\n') {
444:           buf[i] = 0;
445:           break;
446:         }
447:       }
448:       PetscStrncpy(llibname,buf,llen);
449:     }
450:   }
451:   if (sharedtmp) { /* send library name to all processors */
452:     MPI_Bcast(found,1,MPI_INT,0,comm);
453:     if (*found) {
454:       MPI_Bcast(llibname,llen,MPI_CHAR,0,comm);
455:       MPI_Bcast(found,1,MPI_INT,0,comm);
456:     }
457:   }

459:   return(0);
460: }