1 2 /* 3 Code for opening and closing files. 4 */ 5 #include <petscsys.h> 6 #if defined(PETSC_HAVE_PWD_H) 7 #include <pwd.h> 8 #endif 9 #include <ctype.h> 10 #include <sys/stat.h> 11 #if defined(PETSC_HAVE_UNISTD_H) 12 #include <unistd.h> 13 #endif 14 #if defined(PETSC_HAVE_SYS_UTSNAME_H) 15 #include <sys/utsname.h> 16 #endif 17 #include <fcntl.h> 18 #include <time.h> 19 #if defined(PETSC_HAVE_SYS_SYSTEMINFO_H) 20 #include <sys/systeminfo.h> 21 #endif 22 23 /* 24 Private routine to delete tmp/shared storage 25 26 This is called by MPI, not by users. 27 28 Note: this is declared extern "C" because it is passed to MPI_Keyval_create() 29 30 */ 31 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelTmpShared(MPI_Comm comm,PetscMPIInt keyval,void *count_val,void *extra_state) 32 { 33 PetscErrorCode ierr; 34 35 PetscFunctionBegin; 36 ierr = PetscInfo1(0,"Deleting tmp/shared data in an MPI_Comm %ld\n",(long)comm);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr); 37 ierr = PetscFree(count_val);if (ierr) PetscFunctionReturn((PetscMPIInt)ierr); 38 PetscFunctionReturn(MPI_SUCCESS); 39 } 40 41 /*@C 42 PetscGetTmp - Gets the name of the tmp directory 43 44 Collective on MPI_Comm 45 46 Input Parameters: 47 + comm - MPI_Communicator that may share /tmp 48 - len - length of string to hold name 49 50 Output Parameters: 51 . dir - directory name 52 53 Options Database Keys: 54 + -shared_tmp 55 . -not_shared_tmp 56 - -tmp tmpdir 57 58 Environmental Variables: 59 + PETSC_SHARED_TMP 60 . PETSC_NOT_SHARED_TMP 61 - PETSC_TMP 62 63 Level: developer 64 65 66 If the environmental variable PETSC_TMP is set it will use this directory 67 as the "/tmp" directory. 68 69 @*/ 70 PetscErrorCode PetscGetTmp(MPI_Comm comm,char dir[],size_t len) 71 { 72 PetscErrorCode ierr; 73 PetscBool flg; 74 75 PetscFunctionBegin; 76 ierr = PetscOptionsGetenv(comm,"PETSC_TMP",dir,len,&flg);CHKERRQ(ierr); 77 if (!flg) { 78 ierr = PetscStrncpy(dir,"/tmp",len);CHKERRQ(ierr); 79 } 80 PetscFunctionReturn(0); 81 } 82 83 /*@C 84 PetscSharedTmp - Determines if all processors in a communicator share a 85 /tmp or have different ones. 86 87 Collective on MPI_Comm 88 89 Input Parameters: 90 . comm - MPI_Communicator that may share /tmp 91 92 Output Parameters: 93 . shared - PETSC_TRUE or PETSC_FALSE 94 95 Options Database Keys: 96 + -shared_tmp 97 . -not_shared_tmp 98 - -tmp tmpdir 99 100 Environmental Variables: 101 + PETSC_SHARED_TMP 102 . PETSC_NOT_SHARED_TMP 103 - PETSC_TMP 104 105 Level: developer 106 107 Notes: 108 Stores the status as a MPI attribute so it does not have 109 to be redetermined each time. 110 111 Assumes that all processors in a communicator either 112 1) have a common /tmp or 113 2) each has a separate /tmp 114 eventually we can write a fancier one that determines which processors 115 share a common /tmp. 116 117 This will be very slow on runs with a large number of processors since 118 it requires O(p*p) file opens. 119 120 If the environmental variable PETSC_TMP is set it will use this directory 121 as the "/tmp" directory. 122 123 @*/ 124 PetscErrorCode PetscSharedTmp(MPI_Comm comm,PetscBool *shared) 125 { 126 PetscErrorCode ierr; 127 PetscMPIInt size,rank,*tagvalp,sum,cnt,i; 128 PetscBool flg,iflg; 129 FILE *fd; 130 static PetscMPIInt Petsc_Tmp_keyval = MPI_KEYVAL_INVALID; 131 int err; 132 133 PetscFunctionBegin; 134 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 135 if (size == 1) { 136 *shared = PETSC_TRUE; 137 PetscFunctionReturn(0); 138 } 139 140 ierr = PetscOptionsGetenv(comm,"PETSC_SHARED_TMP",NULL,0,&flg);CHKERRQ(ierr); 141 if (flg) { 142 *shared = PETSC_TRUE; 143 PetscFunctionReturn(0); 144 } 145 146 ierr = PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_TMP",NULL,0,&flg);CHKERRQ(ierr); 147 if (flg) { 148 *shared = PETSC_FALSE; 149 PetscFunctionReturn(0); 150 } 151 152 if (Petsc_Tmp_keyval == MPI_KEYVAL_INVALID) { 153 ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTmpShared,&Petsc_Tmp_keyval,0);CHKERRQ(ierr); 154 } 155 156 ierr = MPI_Attr_get(comm,Petsc_Tmp_keyval,(void**)&tagvalp,(int*)&iflg);CHKERRQ(ierr); 157 if (!iflg) { 158 char filename[PETSC_MAX_PATH_LEN],tmpname[PETSC_MAX_PATH_LEN]; 159 160 /* This communicator does not yet have a shared tmp attribute */ 161 ierr = PetscMalloc1(1,&tagvalp);CHKERRQ(ierr); 162 ierr = MPI_Attr_put(comm,Petsc_Tmp_keyval,tagvalp);CHKERRQ(ierr); 163 164 ierr = PetscOptionsGetenv(comm,"PETSC_TMP",tmpname,238,&iflg);CHKERRQ(ierr); 165 if (!iflg) { 166 ierr = PetscStrcpy(filename,"/tmp");CHKERRQ(ierr); 167 } else { 168 ierr = PetscStrcpy(filename,tmpname);CHKERRQ(ierr); 169 } 170 171 ierr = PetscStrcat(filename,"/petsctestshared");CHKERRQ(ierr); 172 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 173 174 /* each processor creates a /tmp file and all the later ones check */ 175 /* this makes sure no subset of processors is shared */ 176 *shared = PETSC_FALSE; 177 for (i=0; i<size-1; i++) { 178 if (rank == i) { 179 fd = fopen(filename,"w"); 180 if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename); 181 err = fclose(fd); 182 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 183 } 184 ierr = MPI_Barrier(comm);CHKERRQ(ierr); 185 if (rank >= i) { 186 fd = fopen(filename,"r"); 187 if (fd) cnt = 1; 188 else cnt = 0; 189 if (fd) { 190 err = fclose(fd); 191 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 192 } 193 } else cnt = 0; 194 195 ierr = MPIU_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr); 196 if (rank == i) unlink(filename); 197 198 if (sum == size) { 199 *shared = PETSC_TRUE; 200 break; 201 } else if (sum != 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Subset of processes share /tmp "); 202 } 203 *tagvalp = (int)*shared; 204 ierr = PetscInfo2(0,"processors %s %s\n",(*shared) ? "share":"do NOT share",(iflg ? tmpname:"/tmp"));CHKERRQ(ierr); 205 } else *shared = (PetscBool) *tagvalp; 206 PetscFunctionReturn(0); 207 } 208 209 /*@C 210 PetscSharedWorkingDirectory - Determines if all processors in a communicator share a 211 working directory or have different ones. 212 213 Collective on MPI_Comm 214 215 Input Parameters: 216 . comm - MPI_Communicator that may share working directory 217 218 Output Parameters: 219 . shared - PETSC_TRUE or PETSC_FALSE 220 221 Options Database Keys: 222 + -shared_working_directory 223 . -not_shared_working_directory 224 225 Environmental Variables: 226 + PETSC_SHARED_WORKING_DIRECTORY 227 . PETSC_NOT_SHARED_WORKING_DIRECTORY 228 229 Level: developer 230 231 Notes: 232 Stores the status as a MPI attribute so it does not have 233 to be redetermined each time. 234 235 Assumes that all processors in a communicator either 236 1) have a common working directory or 237 2) each has a separate working directory 238 eventually we can write a fancier one that determines which processors 239 share a common working directory. 240 241 This will be very slow on runs with a large number of processors since 242 it requires O(p*p) file opens. 243 244 @*/ 245 PetscErrorCode PetscSharedWorkingDirectory(MPI_Comm comm,PetscBool *shared) 246 { 247 PetscErrorCode ierr; 248 PetscMPIInt size,rank,*tagvalp,sum,cnt,i; 249 PetscBool flg,iflg; 250 FILE *fd; 251 static PetscMPIInt Petsc_WD_keyval = MPI_KEYVAL_INVALID; 252 int err; 253 254 PetscFunctionBegin; 255 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 256 if (size == 1) { 257 *shared = PETSC_TRUE; 258 PetscFunctionReturn(0); 259 } 260 261 ierr = PetscOptionsGetenv(comm,"PETSC_SHARED_WORKING_DIRECTORY",NULL,0,&flg);CHKERRQ(ierr); 262 if (flg) { 263 *shared = PETSC_TRUE; 264 PetscFunctionReturn(0); 265 } 266 267 ierr = PetscOptionsGetenv(comm,"PETSC_NOT_SHARED_WORKING_DIRECTORY",NULL,0,&flg);CHKERRQ(ierr); 268 if (flg) { 269 *shared = PETSC_FALSE; 270 PetscFunctionReturn(0); 271 } 272 273 if (Petsc_WD_keyval == MPI_KEYVAL_INVALID) { 274 ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,Petsc_DelTmpShared,&Petsc_WD_keyval,0);CHKERRQ(ierr); 275 } 276 277 ierr = MPI_Attr_get(comm,Petsc_WD_keyval,(void**)&tagvalp,(int*)&iflg);CHKERRQ(ierr); 278 if (!iflg) { 279 char filename[PETSC_MAX_PATH_LEN]; 280 281 /* This communicator does not yet have a shared attribute */ 282 ierr = PetscMalloc1(1,&tagvalp);CHKERRQ(ierr); 283 ierr = MPI_Attr_put(comm,Petsc_WD_keyval,tagvalp);CHKERRQ(ierr); 284 285 ierr = PetscGetWorkingDirectory(filename,240);CHKERRQ(ierr); 286 ierr = PetscStrcat(filename,"/petsctestshared");CHKERRQ(ierr); 287 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 288 289 /* each processor creates a file and all the later ones check */ 290 /* this makes sure no subset of processors is shared */ 291 *shared = PETSC_FALSE; 292 for (i=0; i<size-1; i++) { 293 if (rank == i) { 294 fd = fopen(filename,"w"); 295 if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open test file %s",filename); 296 err = fclose(fd); 297 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 298 } 299 ierr = MPI_Barrier(comm);CHKERRQ(ierr); 300 if (rank >= i) { 301 fd = fopen(filename,"r"); 302 if (fd) cnt = 1; 303 else cnt = 0; 304 if (fd) { 305 err = fclose(fd); 306 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 307 } 308 } else cnt = 0; 309 310 ierr = MPIU_Allreduce(&cnt,&sum,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr); 311 if (rank == i) unlink(filename); 312 313 if (sum == size) { 314 *shared = PETSC_TRUE; 315 break; 316 } else if (sum != 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Subset of processes share working directory"); 317 } 318 *tagvalp = (int)*shared; 319 } else *shared = (PetscBool) *tagvalp; 320 ierr = PetscInfo1(0,"processors %s working directory\n",(*shared) ? "shared" : "do NOT share");CHKERRQ(ierr); 321 PetscFunctionReturn(0); 322 } 323 324 325 /*@C 326 PetscFileRetrieve - Obtains a file from a URL or compressed 327 and copies into local disk space as uncompressed. 328 329 Collective on MPI_Comm 330 331 Input Parameter: 332 + comm - processors accessing the file 333 . url - name of file, including entire URL (with or without .gz) 334 - llen - length of localname 335 336 Output Parameter: 337 + localname - name of local copy of file 338 - found - if found and retrieved the file 339 340 Notes: if the file already exists local this function just returns without downloading it. 341 342 Level: intermediate 343 @*/ 344 PetscErrorCode PetscFileRetrieve(MPI_Comm comm,const char url[],char localname[],size_t llen,PetscBool *found) 345 { 346 char urlget[PETSC_MAX_PATH_LEN],*par,*tlocalname; 347 FILE *fp; 348 PetscErrorCode ierr; 349 PetscMPIInt rank; 350 size_t len = 0; 351 PetscBool flg1,flg2,flg3,flg4; 352 #if defined(PETSC_HAVE_POPEN) 353 int rval; 354 #endif 355 356 PetscFunctionBegin; 357 *found = PETSC_FALSE; 358 359 /* if file does not have an ftp:// or http:// or .gz then need not process file */ 360 ierr = PetscStrstr(url,".gz",&par);CHKERRQ(ierr); 361 if (par) {ierr = PetscStrlen(par,&len);CHKERRQ(ierr);} 362 363 ierr = PetscStrncmp(url,"ftp://",6,&flg1);CHKERRQ(ierr); 364 ierr = PetscStrncmp(url,"http://",7,&flg2);CHKERRQ(ierr); 365 ierr = PetscStrncmp(url,"https://",8,&flg4);CHKERRQ(ierr); 366 ierr = PetscStrncmp(url,"file://",7,&flg3);CHKERRQ(ierr); 367 if (!flg1 && !flg2 && !flg3 && !flg4 && (!par || len != 3)) { 368 ierr = PetscStrncpy(localname,url,llen);CHKERRQ(ierr); 369 ierr = PetscTestFile(url,'r',found);CHKERRQ(ierr); 370 if (*found) { 371 ierr = PetscInfo1(NULL,"Found file %s\n",url);CHKERRQ(ierr); 372 } else { 373 ierr = PetscInfo1(NULL,"Did not find file %s\n",url);CHKERRQ(ierr); 374 } 375 PetscFunctionReturn(0); 376 } 377 378 if (par && len == 3){ 379 size_t llen; 380 ierr = PetscStrlen(url,&llen);CHKERRQ(ierr); 381 ierr = PetscStrncpy(localname,url,llen);CHKERRQ(ierr); 382 localname[llen-len] = 0; 383 ierr = PetscTestFile(localname,'r',found);CHKERRQ(ierr); 384 if (*found) { 385 ierr = PetscInfo1(NULL,"Found uncompressed version of file %s\n",localname);CHKERRQ(ierr); 386 PetscFunctionReturn(0); 387 } else { 388 ierr = PetscInfo1(NULL,"Did not find uncompressed version of file %s\n",url);CHKERRQ(ierr); 389 } 390 } 391 392 ierr = PetscStrrchr(url,'/',&tlocalname);CHKERRQ(ierr); 393 ierr = PetscStrncpy(localname,tlocalname,llen);CHKERRQ(ierr); 394 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 395 if (!rank) { 396 ierr = PetscTestFile(localname,'r',found);CHKERRQ(ierr); 397 if (!*found) { /* local file is not already here so use curl to get it */ 398 ierr = PetscStrcpy(urlget,"curl ");CHKERRQ(ierr); 399 ierr = PetscStrcat(urlget,url);CHKERRQ(ierr); 400 ierr = PetscStrcat(urlget," > ");CHKERRQ(ierr); 401 ierr = PetscStrcat(urlget,localname);CHKERRQ(ierr); 402 403 #if defined(PETSC_HAVE_POPEN) 404 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,urlget,"r",&fp);CHKERRQ(ierr); 405 #else 406 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine"); 407 #endif 408 #if defined(PETSC_HAVE_POPEN) 409 ierr = PetscPClose(PETSC_COMM_SELF,fp,&rval);CHKERRQ(ierr); 410 #endif 411 ierr = PetscTestFile(localname,'r',found);CHKERRQ(ierr); 412 } 413 } 414 ierr = MPI_Bcast(found,1,MPIU_BOOL,0,comm);CHKERRQ(ierr); 415 PetscFunctionReturn(0); 416 } 417