From f852cff84d7d1890522443b60bbae1444c50c621 Mon Sep 17 00:00:00 2001 From: Dmytro Vyazelenko <696855+vyazelenko@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:56:58 +0200 Subject: [PATCH] [Java] Simplify and harden error handling when dealing with files after the test completion. --- .../java/io/aeron/test/DataCollector.java | 59 ++++++++--------- .../java/io/aeron/test/SystemTestWatcher.java | 64 +++++++++++-------- 2 files changed, 66 insertions(+), 57 deletions(-) diff --git a/aeron-test-support/src/main/java/io/aeron/test/DataCollector.java b/aeron-test-support/src/main/java/io/aeron/test/DataCollector.java index 48c9733483..998633ce9b 100644 --- a/aeron-test-support/src/main/java/io/aeron/test/DataCollector.java +++ b/aeron-test-support/src/main/java/io/aeron/test/DataCollector.java @@ -20,19 +20,16 @@ import org.agrona.SystemUtil; import java.io.File; +import java.io.FileFilter; import java.io.IOException; -import java.io.UncheckedIOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.BiPredicate; import java.util.function.Predicate; -import java.util.stream.Stream; import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static java.util.Collections.singleton; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; import static org.agrona.Strings.isEmpty; @@ -156,7 +153,7 @@ Path dumpData(final String destinationDir, final byte[] threadDump) */ public List cncFiles() { - return findWithRetryOnNoSuchFile(CncFileDescriptor::isCncFile); + return findMatchingFiles(file -> CncFileDescriptor.CNC_FILE.equals(file.getName())); } /** @@ -167,7 +164,7 @@ public List cncFiles() */ public List markFiles(final SystemTestWatcher.MarkFileDissector dissector) { - return findWithRetryOnNoSuchFile(dissector::isRelevantFile); + return findMatchingFiles(dissector::isRelevantFile); } /** @@ -194,39 +191,39 @@ public Collection cleanupLocations() return Collections.unmodifiableList(cleanupLocations); } - private List findWithRetryOnNoSuchFile(final BiPredicate matcher) + private List findMatchingFiles(final FileFilter filter) { - final int retries = 5; - for (int i = 0; i < retries; i++) + final List found = new ArrayList<>(); + for (final Path location : locations) { - try + find(found, location.toFile(), filter); + } + return found; + } + + private static void find(final List found, final File file, final FileFilter filter) + { + if (file.exists()) + { + if (file.isFile()) { - return locations.stream() - .flatMap((path) -> DataCollector.find(path, matcher)) - .collect(toList()); + if (filter.accept(file)) + { + found.add(file.toPath()); + } } - catch (final UncheckedIOException ex) + else if (file.isDirectory()) { - if (!(ex.getCause() instanceof NoSuchFileException)) + final File[] files = file.listFiles(); + if (null != files) { - throw ex; + for (final File f : files) + { + find(found, f, filter); + } } } } - - return Collections.emptyList(); - } - - private static Stream find(final Path p, final BiPredicate matcher) - { - try - { - return Files.find(p, 10, matcher); - } - catch (final IOException ex) - { - throw new UncheckedIOException(ex); - } } public String toString() @@ -324,7 +321,7 @@ private Map> groupByParent(final List locations) final LinkedHashMap> map = new LinkedHashMap<>(); for (final Path p : locations) { - map.put(p, singleton(p)); + map.put(p, Set.of(p)); } removeNestedPaths(locations, map); diff --git a/aeron-test-support/src/main/java/io/aeron/test/SystemTestWatcher.java b/aeron-test-support/src/main/java/io/aeron/test/SystemTestWatcher.java index 1a04ef82f7..fc602479d1 100644 --- a/aeron-test-support/src/main/java/io/aeron/test/SystemTestWatcher.java +++ b/aeron-test-support/src/main/java/io/aeron/test/SystemTestWatcher.java @@ -49,7 +49,6 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; import java.text.SimpleDateFormat; import java.util.*; import java.util.function.Predicate; @@ -469,6 +468,11 @@ private Throwable printCncInfo(final List paths) for (final Path path : paths) { final File cncFile = path.toFile(); + if (!cncFile.exists() || 0 == cncFile.length()) + { + System.out.printf("%n%nCommand `n Control file %s was not created!%n", cncFile); + continue; + } System.out.printf("%n%nCommand `n Control file %s, length=%d%n", cncFile, cncFile.length()); System.out.println("---------------------------------------------------------------------------------"); final MappedByteBuffer mappedByteBuffer = SamplesUtil.mapExistingFileReadOnly(cncFile); @@ -559,7 +563,7 @@ public interface MarkFileDissector Throwable printErrors(List paths, ErrorConsumer errorConsumer); - boolean isRelevantFile(Path path, BasicFileAttributes basicFileAttributes); + boolean isRelevantFile(File file); void filterErrors(List paths, MutableInteger count, StringBuilder errors, Predicate logFilter) throws IOException; @@ -572,9 +576,9 @@ public String filename() return ArchiveMarkFile.FILENAME; } - public boolean isRelevantFile(final Path path, final BasicFileAttributes basicFileAttributes) + public boolean isRelevantFile(final File file) { - return ArchiveMarkFile.isArchiveMarkFile(path, basicFileAttributes); + return ArchiveMarkFile.FILENAME.equals(file.getName()); } public Throwable printErrors(final List paths, final ErrorConsumer errorConsumer) @@ -582,17 +586,20 @@ public Throwable printErrors(final List paths, final ErrorConsumer errorCo Throwable error = null; for (final Path path : paths) { - try (ArchiveMarkFile archiveFile = openArchiveMarkFile(path)) + if (Files.exists(path) && path.toFile().length() > 0) { - final AtomicBuffer buffer = archiveFile.errorBuffer(); + try (ArchiveMarkFile archiveFile = openArchiveMarkFile(path)) + { + final AtomicBuffer buffer = archiveFile.errorBuffer(); - System.out.printf("%n%n%s file %s%n", "Archive Errors", path); - final int distinctErrorCount = ErrorLogReader.read(buffer, errorConsumer); - System.out.format("%d distinct errors observed.%n", distinctErrorCount); - } - catch (final Throwable t) - { - error = Tests.setOrUpdateError(error, t); + System.out.printf("%n%n%s file %s%n", "Archive Errors", path); + final int distinctErrorCount = ErrorLogReader.read(buffer, errorConsumer); + System.out.format("%d distinct errors observed.%n", distinctErrorCount); + } + catch (final Throwable t) + { + error = Tests.setOrUpdateError(error, t); + } } } @@ -626,17 +633,20 @@ public Throwable printErrors(final List paths, final ErrorConsumer errorCo Throwable error = null; for (final Path path : paths) { - try (ClusterMarkFile clusterMarkFile = openClusterMarkFile(path)) + if (Files.exists(path) && path.toFile().length() > 0) { - final AtomicBuffer buffer = clusterMarkFile.errorBuffer(); + try (ClusterMarkFile clusterMarkFile = openClusterMarkFile(path)) + { + final AtomicBuffer buffer = clusterMarkFile.errorBuffer(); - System.out.printf("%n%n%s file %s%n", fileDescription(), path); - final int distinctErrorCount = ErrorLogReader.read(buffer, errorConsumer); - System.out.format("%d distinct errors observed.%n", distinctErrorCount); - } - catch (final Throwable t) - { - error = Tests.setOrUpdateError(error, t); + System.out.printf("%n%n%s file %s%n", fileDescription(), path); + final int distinctErrorCount = ErrorLogReader.read(buffer, errorConsumer); + System.out.format("%d distinct errors observed.%n", distinctErrorCount); + } + catch (final Throwable t) + { + error = Tests.setOrUpdateError(error, t); + } } } return error; @@ -671,9 +681,9 @@ public String filename() return ClusterMarkFile.FILENAME; } - public boolean isRelevantFile(final Path path, final BasicFileAttributes basicFileAttributes) + public boolean isRelevantFile(final File file) { - return ClusterMarkFile.isConsensusModuleMarkFile(path, basicFileAttributes); + return ClusterMarkFile.FILENAME.equals(file.getName()); } protected String fileDescription() @@ -689,9 +699,11 @@ public String filename() return ClusterMarkFile.SERVICE_FILENAME_PREFIX + "X" + ClusterMarkFile.FILE_EXTENSION; } - public boolean isRelevantFile(final Path path, final BasicFileAttributes basicFileAttributes) + public boolean isRelevantFile(final File file) { - return ClusterMarkFile.isServiceMarkFile(path, basicFileAttributes); + final String name = file.getName(); + return name.startsWith(ClusterMarkFile.SERVICE_FILENAME_PREFIX) && + name.endsWith(ClusterMarkFile.FILE_EXTENSION); } protected String fileDescription()