From 253d461d78c5f3f5983143c4e1e34123f608b07c Mon Sep 17 00:00:00 2001 From: brinn <brinn> Date: Mon, 14 Jul 2008 07:52:55 +0000 Subject: [PATCH] [DMV-31] add support for detection and signaling of errors SVN: 7201 --- ...HighwaterMarkDirectoryScanningHandler.java | 5 +- .../DirectoryScanningHandlerInterceptor.java | 6 +- .../utilities/DirectoryScanningTimerTask.java | 62 +++++++++++++++---- .../FaultyPathDirectoryScanningHandler.java | 20 ++++-- .../utilities/IDirectoryScanningHandler.java | 17 ++++- .../utilities/ITimerTaskStatusProvider.java | 31 ++++++++++ .../TimerTaskWithListenersTest.java | 4 +- ...waterMarkDirectoryScanningHandlerTest.java | 7 ++- 8 files changed, 125 insertions(+), 27 deletions(-) create mode 100644 common/source/java/ch/systemsx/cisd/common/utilities/ITimerTaskStatusProvider.java diff --git a/common/source/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandler.java b/common/source/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandler.java index 9648758b4d2..f252714d3f4 100644 --- a/common/source/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandler.java +++ b/common/source/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandler.java @@ -86,9 +86,10 @@ public final class HighwaterMarkDirectoryScanningHandler extends // @Override - public final boolean mayHandle(final IScannedStore scannedStore, final StoreItem storeItem) + public HandleInstruction mayHandle(final IScannedStore scannedStore, final StoreItem storeItem) { - return mayHandle() == false ? false : super.mayHandle(scannedStore, storeItem); + return mayHandle() == false ? HandleInstruction.ERROR : super.mayHandle( + scannedStore, storeItem); } } diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningHandlerInterceptor.java b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningHandlerInterceptor.java index fbb6ae8cfde..55205035ed2 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningHandlerInterceptor.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningHandlerInterceptor.java @@ -44,13 +44,13 @@ public class DirectoryScanningHandlerInterceptor implements IDirectoryScanningHa directoryScanningHandler.beforeHandle(); } - public boolean mayHandle(final IScannedStore scannedStore, final StoreItem storeItem) + public HandleInstruction mayHandle(final IScannedStore scannedStore, final StoreItem storeItem) { return directoryScanningHandler.mayHandle(scannedStore, storeItem); } - public void finishItemHandle(final IScannedStore scannedStore, final StoreItem storeItem) + public boolean finishItemHandle(final IScannedStore scannedStore, final StoreItem storeItem) { - directoryScanningHandler.finishItemHandle(scannedStore, storeItem); + return directoryScanningHandler.finishItemHandle(scannedStore, storeItem); } } 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 769987aa139..df5e3cf1574 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/DirectoryScanningTimerTask.java @@ -29,6 +29,7 @@ import ch.systemsx.cisd.common.logging.ConditionalNotificationLogger; import ch.systemsx.cisd.common.logging.ISimpleLogger; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.common.utilities.IDirectoryScanningHandler.HandleInstruction; /** * A {@link TimerTask} that scans a source directory for entries that are accepted by some @@ -42,7 +43,7 @@ import ch.systemsx.cisd.common.logging.LogFactory; * * @author Bernd Rinn */ -public final class DirectoryScanningTimerTask extends TimerTask +public final class DirectoryScanningTimerTask extends TimerTask implements ITimerTaskStatusProvider { private static final Logger operationLog = @@ -59,6 +60,10 @@ public final class DirectoryScanningTimerTask extends TimerTask private final ConditionalNotificationLogger notificationLogger; + private int numberOfProcessedItems; + + private int numberOfErrorItems; + /** * Indicates that we should try to exit the {@link #run()} method as soon as possible. * <p> @@ -200,12 +205,14 @@ public final class DirectoryScanningTimerTask extends TimerTask } try { - int numberOfItemsHandled; + numberOfProcessedItems = 0; + numberOfErrorItems = 0; + int numberOfItemsProcessedInLastRound; do { + numberOfItemsProcessedInLastRound = 0; final StoreItem[] storeItems = listStoreItems(); final int numberOfItems = storeItems.length; - numberOfItemsHandled = numberOfItems; directoryScanningHandler.beforeHandle(); for (int i = 0; i < numberOfItems; i++) { @@ -214,14 +221,17 @@ public final class DirectoryScanningTimerTask extends TimerTask { if (operationLog.isDebugEnabled()) { - operationLog.debug(String.format("Scan of store '%s' has been cancelled. " - + "Following items have NOT been handled: %s.", sourceDirectory, - CollectionUtils.abbreviate(ArrayUtils.subarray(storeItems, i + 1, - numberOfItems), 10))); + operationLog.debug(String.format( + "Scan of store '%s' has been cancelled. " + + "Following items have NOT been handled: %s.", + sourceDirectory, CollectionUtils.abbreviate(ArrayUtils + .subarray(storeItems, i + 1, numberOfItems), 10))); } return; } - if (directoryScanningHandler.mayHandle(sourceDirectory, storeItem)) + final HandleInstruction instruction = + directoryScanningHandler.mayHandle(sourceDirectory, storeItem); + if (HandleInstruction.PROCESS.equals(instruction)) { try { @@ -231,26 +241,39 @@ public final class DirectoryScanningTimerTask extends TimerTask operationLog.trace(String.format( "Following store item '%s' has been handled.", storeItem)); } + ++numberOfProcessedItems; + ++numberOfItemsProcessedInLastRound; } catch (final Exception ex) { // Do not stop when processing of one file has failed, // continue with other files. + ++numberOfErrorItems; printNotification(ex); } finally { - directoryScanningHandler.finishItemHandle(sourceDirectory, storeItem); + final boolean ok = + directoryScanningHandler.finishItemHandle(sourceDirectory, + storeItem); + if (ok == false) + { + ++numberOfErrorItems; + } } } else { - --numberOfItemsHandled; + if (HandleInstruction.ERROR.equals(instruction)) + { + ++numberOfErrorItems; + } if (operationLog.isTraceEnabled()) { operationLog.trace(String.format( - "Following store item '%s' has NOT been handled.", storeItem)); + "Following store item '%s' has NOT been handled (%s).", + storeItem, instruction)); } } } - } while (numberOfItemsHandled > 0); + } while (numberOfItemsProcessedInLastRound > 0); } catch (final Exception ex) { printNotification(ex); @@ -261,6 +284,20 @@ public final class DirectoryScanningTimerTask extends TimerTask } } + // + // ITimerTaskStatusProvider + // + + public boolean hasErrors() + { + return (numberOfErrorItems > 0); + } + + public boolean hasPerformedMeaningfulWork() + { + return (numberOfProcessedItems > 0); + } + // // Helper classes // @@ -283,4 +320,5 @@ public final class DirectoryScanningTimerTask extends TimerTask */ String getLocationDescription(StoreItem item); } + } diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/FaultyPathDirectoryScanningHandler.java b/common/source/java/ch/systemsx/cisd/common/utilities/FaultyPathDirectoryScanningHandler.java index f2d036d69b4..d4c62e3586d 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/FaultyPathDirectoryScanningHandler.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/FaultyPathDirectoryScanningHandler.java @@ -129,19 +129,31 @@ public final class FaultyPathDirectoryScanningHandler implements IDirectoryScann checkForFaultyPathsFileChanged(); } - public final boolean mayHandle(final IScannedStore scannedStore, final StoreItem storeItem) + public final HandleInstruction mayHandle(final IScannedStore scannedStore, final StoreItem storeItem) { - return isFaultyPath(scannedStore, storeItem) == false - && isFaultyPathsFile(scannedStore, storeItem) == false; + if (isFaultyPathsFile(scannedStore, storeItem)) + { + return HandleInstruction.IGNORE; + } else if (isFaultyPath(scannedStore, storeItem)) + { + return HandleInstruction.ERROR; + } else + { + return HandleInstruction.PROCESS; + } } - public final void finishItemHandle(final IScannedStore scannedStore, final StoreItem storeItem) + public final boolean finishItemHandle(final IScannedStore scannedStore, final StoreItem storeItem) { // If the item still exists, we assume that it has not been handled. So it // should be added to the faulty paths. if (scannedStore.existsOrError(storeItem)) { addToFaultyPaths(scannedStore, storeItem); + return false; + } else + { + return true; } } diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryScanningHandler.java b/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryScanningHandler.java index db98d072f45..3c794f1a46a 100644 --- a/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryScanningHandler.java +++ b/common/source/java/ch/systemsx/cisd/common/utilities/IDirectoryScanningHandler.java @@ -28,6 +28,14 @@ import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStor public interface IDirectoryScanningHandler { + /** + * The instruction of whether to process an item or not. + */ + public enum HandleInstruction + { + PROCESS, IGNORE, ERROR + } + /** * Is performed just before handling all the items contained in the store. */ @@ -35,12 +43,15 @@ public interface IDirectoryScanningHandler /** * Whether given <code>storeItem</code> found in given <var>scannedStore</var> should be - * processed or not. + * processed or not, and whether not processing it constitues an error or not. */ - public boolean mayHandle(IScannedStore scannedStore, StoreItem storeItem); + public HandleInstruction mayHandle(IScannedStore scannedStore, StoreItem storeItem); /** * Finishes and closes the handling of given <var>storeItem</var>. + * + * @returns <code>true</code>, if the item has been handled correctly and <code>false</code> + * if an error occurred. */ - public void finishItemHandle(IScannedStore scannedStore, StoreItem storeItem); + public boolean finishItemHandle(IScannedStore scannedStore, StoreItem storeItem); } diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ITimerTaskStatusProvider.java b/common/source/java/ch/systemsx/cisd/common/utilities/ITimerTaskStatusProvider.java new file mode 100644 index 00000000000..380baa0a096 --- /dev/null +++ b/common/source/java/ch/systemsx/cisd/common/utilities/ITimerTaskStatusProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.common.utilities; + +/** + * A provider for status information about the last run of a {@link java.util.TimerTask}. + * + * @author Bernd Rinn + */ +public interface ITimerTaskStatusProvider +{ + + public boolean hasPerformedMeaningfulWork(); + + public boolean hasErrors(); + +} diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TimerTaskWithListenersTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TimerTaskWithListenersTest.java index eb26e2c9e51..ff5b01ca487 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TimerTaskWithListenersTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/concurrent/TimerTaskWithListenersTest.java @@ -25,6 +25,8 @@ import java.util.TimerTask; import org.testng.annotations.Test; +import ch.systemsx.cisd.common.utilities.ITimerTaskStatusProvider; + /** * * @@ -77,7 +79,7 @@ public class TimerTaskWithListenersTest recorder.add(name + ".canceling"); } - public void finishRunning() + public void finishRunning(ITimerTaskStatusProvider statusProviderOrNull) { recorder.add(name + ".finishRunning"); } diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandlerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandlerTest.java index ef6a2def7a4..2bcf3fb5952 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandlerTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/highwatermark/HighwaterMarkDirectoryScanningHandlerTest.java @@ -33,6 +33,7 @@ import ch.systemsx.cisd.common.highwatermark.HighwaterMarkWatcher.IFreeSpaceProv import ch.systemsx.cisd.common.utilities.IDirectoryScanningHandler; import ch.systemsx.cisd.common.utilities.StoreItem; import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStore; +import ch.systemsx.cisd.common.utilities.IDirectoryScanningHandler.HandleInstruction; /** * Test cases for the {@link HighwaterMarkDirectoryScanningHandler}. @@ -134,7 +135,8 @@ public final class HighwaterMarkDirectoryScanningHandlerTest } } }); - boolean mayHandle = scanningHandler.mayHandle(scannedStore, storeItem); + boolean mayHandle = + HandleInstruction.PROCESS.equals(scanningHandler.mayHandle(scannedStore, storeItem)); assertEquals(freeSpace > HIGHWATER_MARK, mayHandle); context.assertIsSatisfied(); } @@ -163,7 +165,8 @@ public final class HighwaterMarkDirectoryScanningHandlerTest } } }); - boolean mayHandle = scanningHandler.mayHandle(scannedStore, storeItem); + boolean mayHandle = + HandleInstruction.PROCESS.equals(scanningHandler.mayHandle(scannedStore, storeItem)); assertEquals(freeSpace > HIGHWATER_MARK, mayHandle); context.assertIsSatisfied(); } -- GitLab