47 48 /** 49 * Deletes a file, retrying if necessary. 50 * 51 * @param path the file to delete 52 * 53 * @throws NoSuchFileException 54 * if the file does not exist (optional specific exception) 55 * @throws DirectoryNotEmptyException 56 * if the file is a directory and could not otherwise be deleted 57 * because the directory is not empty (optional specific exception) 58 * @throws IOException 59 * if an I/O error occurs 60 */ 61 public static void deleteFileWithRetry(Path path) 62 throws IOException 63 { 64 try { 65 deleteFileWithRetry0(path); 66 } catch (InterruptedException x) { 67 // Restore the interrupted status 68 Thread.currentThread().interrupt(); 69 } 70 } 71 72 private static void deleteFileWithRetry0(Path path) 73 throws IOException, InterruptedException 74 { 75 int times = 0; 76 IOException ioe = null; 77 while (true) { 78 try { 79 Files.delete(path); 80 break; 81 } catch (NoSuchFileException | DirectoryNotEmptyException x) { 82 throw x; 83 } catch (IOException x) { 84 // Backoff/retry in case another process is accessing the file 85 times++; 86 if (ioe == null) 87 ioe = x; 88 else 89 ioe.addSuppressed(x); 90 if (times > MAX_RETRY_DELETE_TIMES) 91 throw ioe; 92 Thread.sleep(RETRY_DELETE_MILLIS); 93 } 94 } 95 } 96 97 /** 98 * Deletes a directory and its subdirectories, retrying if necessary. 99 * 100 * @param dir the directory to delete 114 if (!excs.isEmpty()) { 115 ioe = excs.remove(0); 116 for (IOException x : excs) 117 ioe.addSuppressed(x); 118 } 119 if (ioe != null) 120 throw ioe; 121 } 122 123 public static List<IOException> deleteFileTreeUnchecked(Path dir) { 124 final List<IOException> excs = new ArrayList<>(); 125 try { 126 java.nio.file.Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { 127 @Override 128 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { 129 try { 130 deleteFileWithRetry0(file); 131 } catch (IOException x) { 132 excs.add(x); 133 } catch (InterruptedException x) { 134 // Restore the interrupted status and terminate 135 Thread.currentThread().interrupt(); 136 return FileVisitResult.TERMINATE; 137 } 138 return FileVisitResult.CONTINUE; 139 } 140 @Override 141 public FileVisitResult postVisitDirectory(Path dir, IOException exc) { 142 try { 143 deleteFileWithRetry0(dir); 144 } catch (IOException x) { 145 excs.add(x); 146 } catch (InterruptedException x) { 147 // Restore the interrupted status and terminate 148 Thread.currentThread().interrupt(); 149 return FileVisitResult.TERMINATE; 150 } 151 return FileVisitResult.CONTINUE; 152 } 153 @Override 154 public FileVisitResult visitFileFailed(Path file, IOException exc) { 155 excs.add(exc); 156 return FileVisitResult.CONTINUE; 157 } 158 }); 159 } catch (IOException x) { 160 excs.add(x); 161 } 162 return excs; 163 } 164 } 165 | 47 48 /** 49 * Deletes a file, retrying if necessary. 50 * 51 * @param path the file to delete 52 * 53 * @throws NoSuchFileException 54 * if the file does not exist (optional specific exception) 55 * @throws DirectoryNotEmptyException 56 * if the file is a directory and could not otherwise be deleted 57 * because the directory is not empty (optional specific exception) 58 * @throws IOException 59 * if an I/O error occurs 60 */ 61 public static void deleteFileWithRetry(Path path) 62 throws IOException 63 { 64 try { 65 deleteFileWithRetry0(path); 66 } catch (InterruptedException x) { 67 throw new IOException("Interrupted while deleting.", x); 68 } 69 } 70 71 private static void deleteFileWithRetry0(Path path) 72 throws IOException, InterruptedException 73 { 74 int times = 0; 75 IOException ioe = null; 76 while (true) { 77 try { 78 Files.delete(path); 79 while (true) { 80 if (Files.notExists(path)) 81 break; 82 times++; 83 if (times > MAX_RETRY_DELETE_TIMES) 84 throw new IOException("File still exists after " + times + " waits."); 85 Thread.sleep(RETRY_DELETE_MILLIS); 86 } 87 break; 88 } catch (NoSuchFileException | DirectoryNotEmptyException x) { 89 throw x; 90 } catch (IOException x) { 91 // Backoff/retry in case another process is accessing the file 92 times++; 93 if (ioe == null) 94 ioe = x; 95 else 96 ioe.addSuppressed(x); 97 if (times > MAX_RETRY_DELETE_TIMES) 98 throw ioe; 99 Thread.sleep(RETRY_DELETE_MILLIS); 100 } 101 } 102 } 103 104 /** 105 * Deletes a directory and its subdirectories, retrying if necessary. 106 * 107 * @param dir the directory to delete 121 if (!excs.isEmpty()) { 122 ioe = excs.remove(0); 123 for (IOException x : excs) 124 ioe.addSuppressed(x); 125 } 126 if (ioe != null) 127 throw ioe; 128 } 129 130 public static List<IOException> deleteFileTreeUnchecked(Path dir) { 131 final List<IOException> excs = new ArrayList<>(); 132 try { 133 java.nio.file.Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { 134 @Override 135 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { 136 try { 137 deleteFileWithRetry0(file); 138 } catch (IOException x) { 139 excs.add(x); 140 } catch (InterruptedException x) { 141 excs.add(new IOException("Interrupted while deleting.", x)); 142 return FileVisitResult.TERMINATE; 143 } 144 return FileVisitResult.CONTINUE; 145 } 146 @Override 147 public FileVisitResult postVisitDirectory(Path dir, IOException exc) { 148 try { 149 deleteFileWithRetry0(dir); 150 } catch (IOException x) { 151 excs.add(x); 152 } catch (InterruptedException x) { 153 excs.add(new IOException("Interrupted while deleting.", x)); 154 return FileVisitResult.TERMINATE; 155 } 156 return FileVisitResult.CONTINUE; 157 } 158 @Override 159 public FileVisitResult visitFileFailed(Path file, IOException exc) { 160 excs.add(exc); 161 return FileVisitResult.CONTINUE; 162 } 163 }); 164 } catch (IOException x) { 165 excs.add(x); 166 } 167 return excs; 168 } 169 } 170 |