1 /*
2 * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
30 import java.io.IOException;
31 import java.io.PrintStream;
32 import java.io.UncheckedIOException;
33 import java.lang.ProcessBuilder.Redirect;
34 import java.nio.file.DirectoryNotEmptyException;
35 import java.nio.file.FileVisitResult;
36 import java.nio.file.Files;
37 import java.nio.file.NoSuchFileException;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.nio.file.SimpleFileVisitor;
41 import java.nio.file.attribute.BasicFileAttributes;
42 import java.time.Instant;
43 import java.time.Duration;
44 import java.util.Arrays;
45 import java.util.ArrayList;
46 import java.util.ArrayDeque;
47 import java.util.HashSet;
48 import java.util.List;
49 import java.util.Optional;
50 import java.util.concurrent.atomic.AtomicBoolean;
51 import java.util.concurrent.atomic.AtomicReference;
52 import java.util.concurrent.TimeUnit;
53
54 /**
55 * Common library for various test file utility functions.
56 */
57 public final class FileUtils {
58 private static final boolean IS_WINDOWS = Platform.isWindows();
59 private static final int RETRY_DELETE_MILLIS = IS_WINDOWS ? 500 : 0;
60 private static final int MAX_RETRY_DELETE_TIMES = IS_WINDOWS ? 15 : 0;
61
62 /**
63 * Deletes a file, retrying if necessary.
64 *
65 * @param path the file to delete
66 *
67 * @throws NoSuchFileException
68 * if the file does not exist (optional specific exception)
69 * @throws DirectoryNotEmptyException
225 try {
226 proc.waitFor(90, TimeUnit.SECONDS);
227 } catch (InterruptedException ignored) {
228 }
229 try {
230 int exitValue = proc.exitValue();
231 if (exitValue != 0) {
232 System.err.printf("df process exited with %d != 0%n",
233 exitValue);
234 areFileSystemsAccessible = false;
235 }
236 } catch (IllegalThreadStateException ignored) {
237 System.err.println("df command apparently hung");
238 areFileSystemsAccessible = false;
239 }
240 }
241 return areFileSystemsAccessible;
242 }
243
244 /**
245 * Checks whether all file systems are accessible. This is performed
246 * by checking free disk space on all mounted file systems via a
247 * separate, spawned process. File systems are considered to be
248 * accessible if this process completes successfully before a given
249 * fixed duration has elapsed.
250 *
251 * @implNote On Unix this executes the {@code df} command in a separate
252 * process and on Windows always returns {@code true}.
253 *
254 * @return whether file systems appear to be accessible
255 *
256 * @throws RuntimeException if there are duplicate mount points or some
257 * other execution problem occurs
258 */
259 public static boolean areAllMountPointsAccessible() {
260 final AtomicBoolean areMountPointsOK = new AtomicBoolean(true);
261 if (!IS_WINDOWS) {
262 Thread thr = new Thread(() -> {
263 try {
264 Process proc = new ProcessBuilder("df").start();
265 BufferedReader reader = new BufferedReader
266 (new InputStreamReader(proc.getInputStream()));
267 // Skip the first line as it is the "df" output header.
268 if (reader.readLine() != null ) {
269 String prevMountPoint = null, mountPoint = null;
270 while ((mountPoint = reader.readLine()) != null) {
271 if (prevMountPoint != null &&
272 mountPoint.equals(prevMountPoint)) {
273 throw new RuntimeException
274 ("System configuration error: " +
275 "duplicate mount point " + mountPoint +
276 " detected");
277 }
278 prevMountPoint = mountPoint;
279 }
280 }
281
282 try {
283 proc.waitFor(90, TimeUnit.SECONDS);
284 } catch (InterruptedException ignored) {
285 }
286 try {
287 int exitValue = proc.exitValue();
288 if (exitValue != 0) {
289 System.err.printf("df process exited with %d != 0%n",
290 exitValue);
291 areMountPointsOK.set(false);
292 }
293 } catch (IllegalThreadStateException ignored) {
294 System.err.println("df command apparently hung");
295 areMountPointsOK.set(false);
296 }
297 } catch (IOException ioe) {
298 throw new RuntimeException(ioe);
306 public void uncaughtException(Thread t, Throwable e) {
307 throwableReference.set(e);
308 }
309 });
310
311 thr.start();
312 try {
313 thr.join(120*1000L);
314 } catch (InterruptedException ie) {
315 throw new RuntimeException(ie);
316 }
317
318 Throwable uncaughtException = (Throwable)throwableReference.get();
319 if (uncaughtException != null) {
320 throw new RuntimeException(uncaughtException);
321 }
322
323 if (thr.isAlive()) {
324 throw new RuntimeException("df thread did not join in time");
325 }
326 }
327
328 return areMountPointsOK.get();
329 }
330
331 /**
332 * List the open file descriptors (if supported by the 'lsof' command).
333 * @param ps a printStream to send the output to
334 * @throws UncheckedIOException if an error occurs
335 */
336 public static void listFileDescriptors(PrintStream ps) {
337
338 Optional<String[]> lsof = Arrays.stream(lsCommands)
339 .filter(args -> Files.isExecutable(Path.of(args[0])))
340 .findFirst();
341 lsof.ifPresent(args -> {
342 try {
343 ps.printf("Open File Descriptors:%n");
344 long pid = ProcessHandle.current().pid();
345 ProcessBuilder pb = new ProcessBuilder(args[0], args[1], Integer.toString((int) pid));
346 pb.redirectErrorStream(true); // combine stderr and stdout
|
1 /*
2 * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
30 import java.io.IOException;
31 import java.io.PrintStream;
32 import java.io.UncheckedIOException;
33 import java.lang.ProcessBuilder.Redirect;
34 import java.nio.file.DirectoryNotEmptyException;
35 import java.nio.file.FileVisitResult;
36 import java.nio.file.Files;
37 import java.nio.file.NoSuchFileException;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.nio.file.SimpleFileVisitor;
41 import java.nio.file.attribute.BasicFileAttributes;
42 import java.time.Instant;
43 import java.time.Duration;
44 import java.util.Arrays;
45 import java.util.ArrayList;
46 import java.util.ArrayDeque;
47 import java.util.HashSet;
48 import java.util.List;
49 import java.util.Optional;
50 import java.util.Set;
51 import java.util.concurrent.atomic.AtomicBoolean;
52 import java.util.concurrent.atomic.AtomicReference;
53 import java.util.concurrent.TimeUnit;
54
55 /**
56 * Common library for various test file utility functions.
57 */
58 public final class FileUtils {
59 private static final boolean IS_WINDOWS = Platform.isWindows();
60 private static final int RETRY_DELETE_MILLIS = IS_WINDOWS ? 500 : 0;
61 private static final int MAX_RETRY_DELETE_TIMES = IS_WINDOWS ? 15 : 0;
62
63 /**
64 * Deletes a file, retrying if necessary.
65 *
66 * @param path the file to delete
67 *
68 * @throws NoSuchFileException
69 * if the file does not exist (optional specific exception)
70 * @throws DirectoryNotEmptyException
226 try {
227 proc.waitFor(90, TimeUnit.SECONDS);
228 } catch (InterruptedException ignored) {
229 }
230 try {
231 int exitValue = proc.exitValue();
232 if (exitValue != 0) {
233 System.err.printf("df process exited with %d != 0%n",
234 exitValue);
235 areFileSystemsAccessible = false;
236 }
237 } catch (IllegalThreadStateException ignored) {
238 System.err.println("df command apparently hung");
239 areFileSystemsAccessible = false;
240 }
241 }
242 return areFileSystemsAccessible;
243 }
244
245 /**
246 * Checks whether all file systems are accessible and there are no
247 * duplicate mount points. This is performed by checking free disk
248 * space on all mounted file systems via a separate, spawned process.
249 * File systems are considered to be accessible if this process completes
250 * successfully before a given fixed duration has elapsed.
251 *
252 * @implNote On Unix this executes the {@code df} command in a separate
253 * process and on Windows always returns {@code true}.
254 *
255 * @return whether file systems appear to be accessible and duplicate-free
256 */
257 public static boolean areMountPointsAccessibleAndUnique() {
258 if (IS_WINDOWS) return true;
259
260 final AtomicBoolean areMountPointsOK = new AtomicBoolean(true);
261 Thread thr = new Thread(() -> {
262 try {
263 Process proc = new ProcessBuilder("df").start();
264 BufferedReader reader = new BufferedReader
265 (new InputStreamReader(proc.getInputStream()));
266 // Skip the first line as it is the "df" output header.
267 if (reader.readLine() != null ) {
268 Set mountPoints = new HashSet();
269 String mountPoint = null;
270 while ((mountPoint = reader.readLine()) != null) {
271 if (!mountPoints.add(mountPoint)) {
272 System.err.printf
273 ("Config error: duplicate mount point %s%n",
274 mountPoint);
275 areMountPointsOK.set(false);
276 break;
277 }
278 }
279 }
280
281 try {
282 proc.waitFor(90, TimeUnit.SECONDS);
283 } catch (InterruptedException ignored) {
284 }
285 try {
286 int exitValue = proc.exitValue();
287 if (exitValue != 0) {
288 System.err.printf("df process exited with %d != 0%n",
289 exitValue);
290 areMountPointsOK.set(false);
291 }
292 } catch (IllegalThreadStateException ignored) {
293 System.err.println("df command apparently hung");
294 areMountPointsOK.set(false);
295 }
296 } catch (IOException ioe) {
297 throw new RuntimeException(ioe);
305 public void uncaughtException(Thread t, Throwable e) {
306 throwableReference.set(e);
307 }
308 });
309
310 thr.start();
311 try {
312 thr.join(120*1000L);
313 } catch (InterruptedException ie) {
314 throw new RuntimeException(ie);
315 }
316
317 Throwable uncaughtException = (Throwable)throwableReference.get();
318 if (uncaughtException != null) {
319 throw new RuntimeException(uncaughtException);
320 }
321
322 if (thr.isAlive()) {
323 throw new RuntimeException("df thread did not join in time");
324 }
325
326 return areMountPointsOK.get();
327 }
328
329 /**
330 * List the open file descriptors (if supported by the 'lsof' command).
331 * @param ps a printStream to send the output to
332 * @throws UncheckedIOException if an error occurs
333 */
334 public static void listFileDescriptors(PrintStream ps) {
335
336 Optional<String[]> lsof = Arrays.stream(lsCommands)
337 .filter(args -> Files.isExecutable(Path.of(args[0])))
338 .findFirst();
339 lsof.ifPresent(args -> {
340 try {
341 ps.printf("Open File Descriptors:%n");
342 long pid = ProcessHandle.current().pid();
343 ProcessBuilder pb = new ProcessBuilder(args[0], args[1], Integer.toString((int) pid));
344 pb.redirectErrorStream(true); // combine stderr and stdout
|