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