From e6e3a0299c6abae113bf5632d1cf12e9e4ea068d Mon Sep 17 00:00:00 2001 From: brinn <brinn> Date: Tue, 9 Oct 2007 08:31:56 +0000 Subject: [PATCH] add: feature to ignore a specifiable number of errors in listing a directory and log only then SVN: 2063 --- .../utilities/DirectoryScanningTimerTask.java | 37 ++++++++-- .../common/logging/LogMonitoringAppender.java | 5 ++ .../DirectoryScanningTimerTaskTest.java | 68 ++++++++++++++++++- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java index ca0cd27531a..da6af97a52f 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java @@ -61,10 +61,13 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ISelf }; private final IPathHandler handler; - + private final File sourceDirectory; - private boolean errorReadingDirectory; + /** The number of consecutive errors of reading a directory that need to occur before the event is logged. */ + private final int ignoredErrorCount; + + private int errorCountReadingDirectory; private final FileFilter filter; @@ -82,11 +85,29 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ISelf * @param handler The handler that is used for treating the matching paths. */ public DirectoryScanningTimerTask(File sourceDirectory, FileFilter filter, IPathHandler handler) + { + this(sourceDirectory, filter, handler, 0); + } + + /** + * Creates a <var>DirectoryScanningTimerTask</var>. + * + * @param sourceDirectory The directory to scan for entries. + * @param filter The file filter that picks the entries to handle. + * @param handler The handler that is used for treating the matching paths. + * @param ignoredErrorCount The number of consecutive errors of reading the directory that need to occur before the + * next error is logged (can be used to suppress error when the directory is on a remote share and the + * server is flaky sometimes) + */ + public DirectoryScanningTimerTask(File sourceDirectory, FileFilter filter, IPathHandler handler, + int ignoredErrorCount) { assert sourceDirectory != null; assert filter != null; assert handler != null; + assert ignoredErrorCount >= 0; + this.ignoredErrorCount = ignoredErrorCount; this.sourceDirectory = sourceDirectory; this.filter = filter; this.handler = handler; @@ -154,18 +175,24 @@ public final class DirectoryScanningTimerTask extends TimerTask implements ISelf private File[] listFiles() { - final boolean logErrors = (errorReadingDirectory == false); + final boolean logErrors = (errorCountReadingDirectory == ignoredErrorCount); // Avoid mailbox flooding. final ISimpleLogger errorLogger = logErrors ? createSimpleErrorLogger() : null; final File[] paths = FileUtilities.tryListFiles(sourceDirectory, filter, errorLogger); - if (errorReadingDirectory && paths != null) + if (errorCountReadingDirectory > ignoredErrorCount && paths != null) { if (notificationLog.isInfoEnabled()) { notificationLog.info(String.format("Directory '%s' is available again.", sourceDirectory)); } } - errorReadingDirectory = (paths == null); // Avoid mailbox flooding. + if (paths == null) + { + ++errorCountReadingDirectory; + } else + { + errorCountReadingDirectory = 0; + } return (paths == null) ? new File[0] : paths; } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/logging/LogMonitoringAppender.java b/common/sourceTest/java/ch/systemsx/cisd/common/logging/LogMonitoringAppender.java index 1b2877e3efd..4f1f3b61936 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/logging/LogMonitoringAppender.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/logging/LogMonitoringAppender.java @@ -109,6 +109,11 @@ public final class LogMonitoringAppender extends AppenderSkeleton return false; } + public void verifyLogHasNotHappened() + { + assert logHappened == false : "Following log snipped was found but shouldn't have: " + messagePart; + } + public void verifyLogHasHappened() { assert logHappened : "Following log snippet has been missed: " + messagePart; diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java index 28bbb47e9fd..802f22a225b 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTaskTest.java @@ -138,9 +138,10 @@ public class DirectoryScanningTimerTaskTest file.delete(); file.deleteOnExit(); file.createNewFile(); - final DirectoryScanningTimerTask task = new DirectoryScanningTimerTask(file, ACCEPT_ALL_FILTER, mockPathHandler); + final DirectoryScanningTimerTask task = + new DirectoryScanningTimerTask(file, ACCEPT_ALL_FILTER, mockPathHandler); task.check(); - } + } @Test(groups = { "requires_unix" }, expectedExceptions = @@ -156,7 +157,8 @@ public class DirectoryScanningTimerTaskTest try { // Here we should get an AssertationError - final DirectoryScanningTimerTask task = new DirectoryScanningTimerTask(readOnlyDirectory, ACCEPT_ALL_FILTER, mockPathHandler); + final DirectoryScanningTimerTask task = + new DirectoryScanningTimerTask(readOnlyDirectory, ACCEPT_ALL_FILTER, mockPathHandler); task.check(); } finally { @@ -359,4 +361,64 @@ public class DirectoryScanningTimerTaskTest LogMonitoringAppender.removeAppender(appender2); } + @Test + public void testSuppressLogging() throws IOException + { + final File dir = new File(workingDirectory, "testSuppressLogging"); + dir.mkdir(); + LogMonitoringAppender appenderError = + LogMonitoringAppender.addAppender(LogCategory.NOTIFY, "Failed to get listing of directory"); + LogMonitoringAppender appenderOK = + LogMonitoringAppender.addAppender(LogCategory.NOTIFY, "' is available again"); + final int numberOfErrorsToIgnore = 2; + // The directory needs to exist when the scanner is created, otherwise the self-test will fail. + final DirectoryScanningTimerTask scanner = + new DirectoryScanningTimerTask(dir, ACCEPT_ALL_FILTER, mockPathHandler, numberOfErrorsToIgnore); + dir.delete(); + assert dir.exists() == false; + // First error -> ignored + scanner.run(); + appenderError.verifyLogHasNotHappened(); + // Second error -> ignored + scanner.run(); + appenderError.verifyLogHasNotHappened(); + // Third error -> recorded + scanner.run(); + appenderError.verifyLogHasHappened(); + dir.mkdir(); + assert dir.exists(); + // Now it is OK again and that should be logged as well + scanner.run(); + appenderOK.verifyLogHasHappened(); + LogMonitoringAppender.removeAppender(appenderError); + LogMonitoringAppender.removeAppender(appenderOK); + } + + @Test + public void testDoNotLogDirectoryAvailableWhenNoErrorWasLogged() throws IOException + { + final File dir = new File(workingDirectory, "testDoNotLogDirectoryAvailableWhenNoErrorWasLogged"); + dir.mkdir(); + LogMonitoringAppender appender = + LogMonitoringAppender.addAppender(LogCategory.NOTIFY, "' is available again."); + final int numberOfErrorsToIgnore = 2; + // The directory needs to exist when the scanner is created, otherwise the self-test will fail. + final DirectoryScanningTimerTask scanner = + new DirectoryScanningTimerTask(dir, ACCEPT_ALL_FILTER, mockPathHandler, numberOfErrorsToIgnore); + dir.delete(); + assert dir.exists() == false; + // First error -> ignored + scanner.run(); + appender.verifyLogHasNotHappened(); + // Second error -> ignored + scanner.run(); + appender.verifyLogHasNotHappened(); + dir.mkdir(); + assert dir.exists(); + // Now it's OK, but nothing should be logged because the error wasn't logged either. + scanner.run(); + appender.verifyLogHasNotHappened(); + LogMonitoringAppender.removeAppender(appender); + } + } -- GitLab