Skip to content
Snippets Groups Projects
Commit 49454af3 authored by ribeaudc's avatar ribeaudc
Browse files

[SE-47]

remove: - 'DirectoryScanningChangeListener', 'PathHandlerInterceptor', 'StoreHandlerInterceptor'.
- 'IStoreHandler.mayHandle' and 'IPathHandler.mayHandle' methods.
add: - 'IDirectoryScanningHandler', 'FaultyPathHandler', 'DirectoryScanningHandlerInterceptor' and 'HighwaterMarkDirectoryScanningHandler'.
change: - DirectoryScanningTimerTask goes into a sleeping mode when high water mark is reached. It does not even write down the faulty path.

SVN: 6272
parent 961492f7
No related merge requests found
Showing
with 480 additions and 239 deletions
......@@ -17,66 +17,78 @@
package ch.systemsx.cisd.common.highwatermark;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import ch.systemsx.cisd.common.highwatermark.HighwaterMarkWatcher.HighwaterMarkEvent;
import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask;
import ch.systemsx.cisd.common.utilities.DirectoryScanningHandlerInterceptor;
import ch.systemsx.cisd.common.utilities.IDirectoryScanningHandler;
import ch.systemsx.cisd.common.utilities.StoreItem;
import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStore;
/**
* A <code>ChangeListener</code> implementation that informs the encapsulated
* {@link DirectoryScanningTimerTask} when the free space is again OK.
* A <code>DirectoryScanningHandlerInterceptor</code> extension which bases its decision on the
* encapsulated {@link HighwaterMarkWatcher} and {@link FileWithHighwaterMark}s.
* <p>
* Subclasses will fill the unhandled paths set.
* Note that the decision has precedence over encapsulated {@link IDirectoryScanningHandler}
* implementation and might short-circuit it.
* </p>
*
* @author Christian Ribeaud
*/
public abstract class DirectoryScanningChangeListener implements ChangeListener
public final class HighwaterMarkDirectoryScanningHandler extends
DirectoryScanningHandlerInterceptor
{
private DirectoryScanningTimerTask directoryScanning;
private final HighwaterMarkWatcher highwaterMarkWatcher;
protected final Set<StoreItem> unhandledItems = new HashSet<StoreItem>();
private final File[] files;
protected DirectoryScanningChangeListener()
public HighwaterMarkDirectoryScanningHandler(
final IDirectoryScanningHandler directoryScanningHandler,
final HighwaterMarkWatcher highwaterMarkWatcher, final File... files)
{
super(directoryScanningHandler);
assert directoryScanningHandler != null : "Unspecified IDirectoryScanningHandler";
assert highwaterMarkWatcher != null : "Unspecified HighwaterMarkWatcher";
assert files != null : "Unspecified files";
this.highwaterMarkWatcher = highwaterMarkWatcher;
this.files = files;
}
private final boolean mayHandle()
{
if (files.length < 1)
{
return isBelow();
}
for (final File file : files)
{
if (isBelow(file))
{
return false;
}
}
return true;
}
/**
* Encapsulates given <var>path</var> in a <code>StoreItem</code> and returns it.
*/
protected final StoreItem asStoreItem(final File path)
private final boolean isBelow()
{
return StoreItem.asItem(path);
// The path has probably been set before.
highwaterMarkWatcher.run();
return highwaterMarkWatcher.isBelow();
}
/**
* Sets the <code>DirectoryScanningTimerTask</code> that should get informed (and remove the
* unhandled paths from the faulty ones) when free space is again OK.
*/
public final void setDirectoryScanning(final DirectoryScanningTimerTask directoryScanning)
private final boolean isBelow(final File path)
{
assert directoryScanning != null : "Unspecified DirectoryScanningTimerTask.";
this.directoryScanning = directoryScanning;
highwaterMarkWatcher.setPathAndRun(path);
return highwaterMarkWatcher.isBelow();
}
//
// ChangeListener
// IDirectoryScanningHandler
//
public final void stateChanged(final ChangeEvent e)
@Override
public final boolean mayHandle(final IScannedStore scannedStore, final StoreItem storeItem)
{
assert directoryScanning != null : "Unspecified DirectoryScanningTimerTask.";
final HighwaterMarkEvent event = (HighwaterMarkEvent) e;
if (event.isBelow() == false)
{
directoryScanning.removeFaultyPaths(unhandledItems.toArray(StoreItem.EMPTY_ARRAY));
unhandledItems.clear();
}
return mayHandle() == false ? false : super.mayHandle(scannedStore, storeItem);
}
}
/*
* 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;
import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStore;
/**
* An <code>IDirectoryScanningHandler</code> implementation which simply delegates the method
* calls to the encapsulated implementation.
*
* @author Christian Ribeaud
*/
public class DirectoryScanningHandlerInterceptor implements IDirectoryScanningHandler
{
private final IDirectoryScanningHandler directoryScanningHandler;
protected DirectoryScanningHandlerInterceptor(
final IDirectoryScanningHandler directoryScanningHandler)
{
assert directoryScanningHandler != null : "Unspecified IDirectoryScanningHandler implementation";
this.directoryScanningHandler = directoryScanningHandler;
}
//
// IDirectoryScanningHandler
//
public void beforeHandle()
{
directoryScanningHandler.beforeHandle();
}
public boolean mayHandle(final IScannedStore scannedStore, final StoreItem storeItem)
{
return directoryScanningHandler.mayHandle(scannedStore, storeItem);
}
public void finishItemHandle(final IScannedStore scannedStore, final StoreItem storeItem)
{
directoryScanningHandler.finishItemHandle(scannedStore, storeItem);
}
}
......@@ -18,14 +18,10 @@ package ch.systemsx.cisd.common.utilities;
import java.io.File;
import java.io.FileFilter;
import java.util.HashSet;
import java.util.Set;
import java.util.TimerTask;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.collections.CollectionIO;
import ch.systemsx.cisd.common.collections.CollectionUtils;
import ch.systemsx.cisd.common.logging.ISimpleLogger;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
......@@ -39,21 +35,20 @@ import ch.systemsx.cisd.common.logging.LogLevel;
* <p>
* The class should be constructed in the start-up phase and as part of the system's self-test in
* order to reveal problems with incorrect paths timely.
* </p>
*
* @author Bernd Rinn
*/
public final class DirectoryScanningTimerTask extends TimerTask
{
static final String FAULTY_PATH_FILENAME = ".faulty_paths";
private static final Logger operationLog =
LogFactory.getLogger(LogCategory.OPERATION, DirectoryScanningTimerTask.class);
private static final Logger notificationLog =
LogFactory.getLogger(LogCategory.NOTIFY, DirectoryScanningTimerTask.class);
private final IStoreHandler handler;
private final IStoreHandler storeHandler;
private final IScannedStore sourceDirectory;
......@@ -65,11 +60,7 @@ public final class DirectoryScanningTimerTask extends TimerTask
private int errorCountReadingDirectory;
private final Set<String> faultyPaths;
private final File faultyPathsFile;
private long faultyPathsLastChanged;
private final IDirectoryScanningHandler directoryScanningHandler;
/**
* Creates a <var>DirectoryScanningTimerTask</var>.
......@@ -77,59 +68,99 @@ public final class DirectoryScanningTimerTask extends TimerTask
* @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 directoryScanningHandler A directory scanning handler.
*/
public DirectoryScanningTimerTask(final File sourceDirectory, final FileFilter filter,
final IPathHandler handler)
final IPathHandler handler, final IDirectoryScanningHandler directoryScanningHandler)
{
this(sourceDirectory, filter, handler, 0);
this(asScannedStore(sourceDirectory, filter), directoryScanningHandler, PathHandlerAdapter
.asScanningHandler(sourceDirectory, handler), 0);
}
/**
* Creates a <var>DirectoryScanningTimerTask</var>.
*
* @param scannedStore The store which is scan for entries.
* @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 storeHandler 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(final File sourceDirectory, final FileFilter filter,
final IPathHandler handler, final int ignoredErrorCount)
public DirectoryScanningTimerTask(final IScannedStore scannedStore, final File sourceDirectory,
final IStoreHandler storeHandler, final int ignoredErrorCount)
{
this(asScannedStore(sourceDirectory, filter), sourceDirectory, PathHandlerAdapter
.asScanningHandler(sourceDirectory, handler), ignoredErrorCount);
this(scannedStore, new FaultyPathHandler(sourceDirectory), storeHandler, ignoredErrorCount);
}
/**
* Creates a <var>DirectoryScanningTimerTask</var>.
*
* @param sourceDirectory The directory to scan for entries.
* @param storeHandler The handler that is used for treating the matching paths.
* @param directoryScanningHandler A directory scanning handler.
*/
public DirectoryScanningTimerTask(final File sourceDirectory, final FileFilter filter,
final IStoreHandler handler)
final IStoreHandler storeHandler,
final IDirectoryScanningHandler directoryScanningHandler)
{
this(asScannedStore(sourceDirectory, filter), directoryScanningHandler, storeHandler, 0);
}
/**
* Creates a <var>DirectoryScanningTimerTask</var>.
*
* @param sourceDirectory The directory to scan for entries.
* @param fileFilter The file filter that picks the entries to handle.
* @param pathHandler 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)
*/
DirectoryScanningTimerTask(final File sourceDirectory, final FileFilter fileFilter,
final IPathHandler pathHandler, final int ignoredErrorCount)
{
this(asScannedStore(sourceDirectory, fileFilter), new FaultyPathHandler(sourceDirectory),
PathHandlerAdapter.asScanningHandler(sourceDirectory, pathHandler),
ignoredErrorCount);
}
/**
* 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 pathHandler The handler that is used for treating the matching paths.
*/
DirectoryScanningTimerTask(final File sourceDirectory, final FileFilter filter,
final IPathHandler pathHandler)
{
this(asScannedStore(sourceDirectory, filter), sourceDirectory, handler, 0);
this(sourceDirectory, filter, pathHandler, 0);
}
/**
* Creates a <var>DirectoryScanningTimerTask</var>.
*
* @param scannedStore The store which is scan for entries.
* @param faultyPathDirectory The directory in which file with faulty paths is should be stored.
* @param handler The handler that is used for treating the matching paths.
* @param directoryScanningHandler A directory scanning handler.
* @param storeHandler 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(final IScannedStore scannedStore,
final File faultyPathDirectory, final IStoreHandler handler, final int ignoredErrorCount)
private DirectoryScanningTimerTask(final IScannedStore scannedStore,
final IDirectoryScanningHandler directoryScanningHandler,
final IStoreHandler storeHandler, final int ignoredErrorCount)
{
assert scannedStore != null;
assert handler != null;
assert storeHandler != null;
assert directoryScanningHandler != null : "Unspecified IDirectoryScanningHandler implementation";
assert ignoredErrorCount >= 0;
this.ignoredErrorCount = ignoredErrorCount;
this.sourceDirectory = scannedStore;
this.handler = handler;
this.faultyPaths = new HashSet<String>();
this.faultyPathsFile = new File(faultyPathDirectory, FAULTY_PATH_FILENAME);
faultyPathsFile.delete();
this.storeHandler = storeHandler;
this.directoryScanningHandler = directoryScanningHandler;
}
private final static IScannedStore asScannedStore(final File directory, final FileFilter filter)
......@@ -137,50 +168,51 @@ public final class DirectoryScanningTimerTask extends TimerTask
return new DirectoryScannedStore(filter, directory);
}
private final static String getLocationDescription(final File file)
{
return file.getPath();
}
/**
* Handles all entries in the source directory that are picked by the filter.
*/
@Override
public final void run()
{
if (operationLog.isTraceEnabled())
{
operationLog.trace("Start scanning directory " + sourceDirectory + ".");
}
try
{
if (operationLog.isTraceEnabled())
final StoreItem[] storeItems = listStoreItems();
directoryScanningHandler.beforeHandle();
for (final StoreItem storeItem : storeItems)
{
operationLog.trace("Start scanning directory " + sourceDirectory + ".");
}
checkForFaultyPathsFileChanged();
final StoreItem[] paths = listFiles();
for (final StoreItem path : paths)
{
if (isFaultyPathsFile(path)) // Never touch the faultyPathsFile.
{
continue;
}
try
{
handle(path);
} catch (final Exception ex) // do not stop when processing of one file has
// failed,
// continue with other files
if (directoryScanningHandler.mayHandle(sourceDirectory, storeItem))
{
printNotification(ex);
try
{
storeHandler.handle(storeItem);
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format(
"Following store item '%s' has been handled.", storeItem));
}
} catch (final Exception ex)
{
// Do not stop when processing of one file has failed,
// continue with other files.
printNotification(ex);
} finally
{
directoryScanningHandler.finishItemHandle(sourceDirectory, storeItem);
}
}
}
if (operationLog.isTraceEnabled())
{
operationLog.trace("Finished scanning directory " + sourceDirectory + ".");
}
} catch (final Exception ex)
{
printNotification(ex);
}
if (operationLog.isTraceEnabled())
{
operationLog.trace("Finished scanning directory " + sourceDirectory + ".");
}
}
private final void printNotification(final Exception ex)
......@@ -188,50 +220,17 @@ public final class DirectoryScanningTimerTask extends TimerTask
notificationLog.error("An exception has occurred. (thread still running)", ex);
}
private boolean isFaultyPathsFile(final StoreItem item)
private final StoreItem[] listStoreItems()
{
final String itemLocation = sourceDirectory.getLocationDescription(item);
final String faultyPathsLocation = getLocationDescription(faultyPathsFile);
return itemLocation.equals(faultyPathsLocation);
}
private final void checkForFaultyPathsFileChanged()
{
if (faultyPathsFile.exists())
{
if (faultyPathsFile.lastModified() > faultyPathsLastChanged) // Handles manual
// manipulation.
{
faultyPaths.clear();
CollectionIO.readCollection(faultyPathsFile, faultyPaths);
faultyPathsLastChanged = faultyPathsFile.lastModified();
if (operationLog.isInfoEnabled())
{
operationLog.info(String.format(
"Reread faulty paths file (%s), new set contains %d entries",
getLocationDescription(faultyPathsFile), faultyPaths.size()));
}
}
} else
// Handles manual removal.
{
faultyPaths.clear();
}
}
private final StoreItem[] listFiles()
{
final boolean logNotifyError = (errorCountReadingDirectory == ignoredErrorCount); // Avoid
// mailbox
// flooding.
// Avoid mailbox flooding.
final boolean logNotifyError = (errorCountReadingDirectory == ignoredErrorCount);
final boolean logOperationError = (errorCountReadingDirectory < ignoredErrorCount);
final ISimpleLogger errorLogger =
logNotifyError ? createSimpleErrorLogger(LogCategory.NOTIFY)
: (logOperationError ? createSimpleErrorLogger(LogCategory.OPERATION)
: null);
final StoreItem[] paths = sourceDirectory.tryListSortedReadyToProcess(errorLogger);
if (errorCountReadingDirectory > ignoredErrorCount && paths != null)
final StoreItem[] storeItems = sourceDirectory.tryListSortedReadyToProcess(errorLogger);
if (errorCountReadingDirectory > ignoredErrorCount && storeItems != null)
{
if (notificationLog.isInfoEnabled())
{
......@@ -239,14 +238,14 @@ public final class DirectoryScanningTimerTask extends TimerTask
sourceDirectory));
}
}
if (paths == null)
if (storeItems == null)
{
++errorCountReadingDirectory;
} else
{
errorCountReadingDirectory = 0;
}
return (paths == null) ? new StoreItem[0] : paths;
return (storeItems == null) ? StoreItem.EMPTY_ARRAY : storeItems;
}
private final ISimpleLogger createSimpleErrorLogger(final LogCategory category)
......@@ -271,79 +270,6 @@ public final class DirectoryScanningTimerTask extends TimerTask
};
}
private final void handle(final StoreItem item)
{
if (isFaultyPath(item))
{ // Guard: skip faulty paths.
return;
}
try
{
final boolean mayHandle = handler.mayHandle(item);
if (mayHandle)
{
handler.handle(item);
}
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format("Following store item '%s' has %sbeen handled.",
item, mayHandle ? "" : "NOT "));
}
} finally
{
// If the item still exists, we assume that it has not been handled. So it should be
// added to the faulty
// paths.
if (sourceDirectory.exists(item))
{
addToFaultyPaths(item);
}
}
}
private final boolean isFaultyPath(final StoreItem item)
{
final String path = sourceDirectory.getLocationDescription(item);
return faultyPaths.contains(path);
}
private final void addToFaultyPaths(final StoreItem item)
{
final String path = sourceDirectory.getLocationDescription(item);
faultyPaths.add(path);
refreshFaultyPathsFile();
}
private final void refreshFaultyPathsFile()
{
CollectionIO.writeIterable(faultyPathsFile, faultyPaths);
faultyPathsLastChanged = faultyPathsFile.lastModified();
}
/** Removes given <var>storeItems</var> from the set of faulty ones. */
public final void removeFaultyPaths(final StoreItem... storeItems)
{
assert storeItems != null : "Unspecified store items.";
final int size = storeItems.length;
if (size == 0)
{
return;
}
final Set<String> paths = new HashSet<String>(size);
for (final StoreItem storeItem : storeItems)
{
paths.add(sourceDirectory.getLocationDescription(storeItem));
}
faultyPaths.removeAll(paths);
if (operationLog.isDebugEnabled())
{
operationLog.debug(String.format(
"Following paths %s have been removed from the the faulty ones.",
CollectionUtils.abbreviate(paths, 10)));
}
refreshFaultyPathsFile();
}
//
// Helper classes
//
......
/*
* 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;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import ch.systemsx.cisd.common.collections.CollectionIO;
import ch.systemsx.cisd.common.logging.LogCategory;
import ch.systemsx.cisd.common.logging.LogFactory;
import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStore;
/**
* An <code>IDirectoryScanningHandler</code> which manages faulty paths.
* <p>
* A faulty path is a {@link StoreItem} which was <i>not handled</i> (still exists in the
* {@link IScannedStore}).
* </p>
*
* @author Christian Ribeaud
*/
public final class FaultyPathHandler implements IDirectoryScanningHandler
{
private static final Logger operationLog =
LogFactory.getLogger(LogCategory.OPERATION, FaultyPathHandler.class);
private final Set<String> faultyPaths;
private final File faultyPathsFile;
private long faultyPathsLastChanged;
static final String FAULTY_PATH_FILENAME = ".faulty_paths";
public FaultyPathHandler(final File faultyPathDirectory)
{
this.faultyPaths = new HashSet<String>();
this.faultyPathsFile = new File(faultyPathDirectory, FAULTY_PATH_FILENAME);
faultyPathsFile.delete();
}
private final void checkForFaultyPathsFileChanged()
{
if (faultyPathsFile.exists())
{
// Handles manual manipulation.
if (faultyPathsFile.lastModified() > faultyPathsLastChanged)
{
faultyPaths.clear();
CollectionIO.readCollection(faultyPathsFile, faultyPaths);
faultyPathsLastChanged = faultyPathsFile.lastModified();
if (operationLog.isInfoEnabled())
{
operationLog.info(String.format(
"Reread faulty paths file (%s), new set contains %d entries",
getLocationDescription(faultyPathsFile), faultyPaths.size()));
}
}
} else
{
// Handles manual removal.
faultyPaths.clear();
}
}
private final static String getLocationDescription(final File file)
{
return file.getPath();
}
private final boolean isFaultyPath(final IScannedStore scannedStore, final StoreItem storeItem)
{
final String path = scannedStore.getLocationDescription(storeItem);
return faultyPaths.contains(path);
}
private final boolean isFaultyPathsFile(final IScannedStore scannedStore,
final StoreItem storeItem)
{
final String itemLocation = scannedStore.getLocationDescription(storeItem);
final String faultyPathsLocation = getLocationDescription(faultyPathsFile);
return itemLocation.equals(faultyPathsLocation);
}
private final void addToFaultyPaths(final IScannedStore scannedStore, final StoreItem item)
{
final String path = scannedStore.getLocationDescription(item);
faultyPaths.add(path);
refreshFaultyPathsFile();
}
private final void refreshFaultyPathsFile()
{
CollectionIO.writeIterable(faultyPathsFile, faultyPaths);
faultyPathsLastChanged = faultyPathsFile.lastModified();
}
//
// IDirectoryScanningHandler
//
public final void beforeHandle()
{
checkForFaultyPathsFileChanged();
}
public final boolean mayHandle(final IScannedStore scannedStore, final StoreItem storeItem)
{
return isFaultyPath(scannedStore, storeItem) == false
&& isFaultyPathsFile(scannedStore, storeItem) == false;
}
public final void 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.exists(storeItem))
{
addToFaultyPaths(scannedStore, storeItem);
}
}
}
......@@ -14,45 +14,33 @@
* limitations under the License.
*/
package ch.systemsx.cisd.common.highwatermark;
package ch.systemsx.cisd.common.utilities;
import ch.systemsx.cisd.common.utilities.IStoreHandler;
import ch.systemsx.cisd.common.utilities.StoreItem;
import ch.systemsx.cisd.common.utilities.DirectoryScanningTimerTask.IScannedStore;
/**
* An <code>IStoreHandler</code> implementation which collects the unhandled store items before
* delegating the calls.
* A helper class for {@link DirectoryScanningTimerTask} which performs operations before and after
* treating the matching paths.
*
* @author Christian Ribeaud
* @see DirectoryScanningTimerTask
*/
public final class StoreHandlerInterceptor extends DirectoryScanningChangeListener implements
IStoreHandler
public interface IDirectoryScanningHandler
{
private final IStoreHandler storeHandler;
public StoreHandlerInterceptor(final IStoreHandler storeHandler)
{
super();
this.storeHandler = storeHandler;
}
//
// IStoreHandler
//
public final void handle(final StoreItem item)
{
storeHandler.handle(item);
}
public final boolean mayHandle(final StoreItem item)
{
final boolean mayHandle = storeHandler.mayHandle(item);
if (mayHandle == false)
{
unhandledItems.add(item);
}
return mayHandle;
}
/**
* Is performed just before handling all the items contained in the store.
*/
public void beforeHandle();
/**
* Whether given <code>storeItem</code> found in given <var>scannedStore</var> should be
* processed or not.
*/
public boolean mayHandle(IScannedStore scannedStore, StoreItem storeItem);
/**
* Finishes and closes the handling of given <var>storeItem</var>.
*/
public void finishItemHandle(IScannedStore scannedStore, StoreItem storeItem);
}
......@@ -32,12 +32,4 @@ public interface IPathHandler
* when the method returns.
*/
public void handle(File path);
/**
* Whether given <var>path</var> may be handled or not.
* <p>
* This method is called just before {@link #handle(File)}.
* </p>
*/
public boolean mayHandle(File path);
}
\ No newline at end of file
......@@ -35,12 +35,4 @@ public interface IStoreHandler
* gone when the method returns.
*/
void handle(StoreItem item);
/**
* Whether given <var>item</var> may be handled or not.
* <p>
* This method is called just before {@link #handle(StoreItem)}.
* </p>
*/
boolean mayHandle(StoreItem item);
}
......@@ -49,11 +49,6 @@ public class PathHandlerAdapter implements IStoreHandler
// IStoreHandler
//
public final boolean mayHandle(final StoreItem item)
{
return pathHandler.mayHandle(asFile(item));
}
public final void handle(final StoreItem item)
{
pathHandler.handle(asFile(item));
......
......@@ -16,42 +16,29 @@
package ch.systemsx.cisd.common.highwatermark;
import java.io.File;
import static org.testng.AssertJUnit.assertFalse;
import ch.systemsx.cisd.common.utilities.IPathHandler;
import org.testng.annotations.Test;
/**
* An <code>IPathHandler</code> implementation which collects the unhandled paths before
* delegating the calls.
* Test cases for the {@link HighwaterMarkDirectoryScanningHandler}.
*
* @author Christian Ribeaud
*/
public final class PathHandlerInterceptor extends DirectoryScanningChangeListener implements
IPathHandler
public final class HighwaterMarkDirectoryScanningHandlerTest
{
private final IPathHandler pathHandler;
public PathHandlerInterceptor(final IPathHandler pathHandler)
@Test
public final void testConstructor()
{
this.pathHandler = pathHandler;
}
//
// IPathHandler
//
public final void handle(final File path)
{
pathHandler.handle(path);
}
public final boolean mayHandle(final File path)
{
final boolean mayHandle = pathHandler.mayHandle(path);
if (mayHandle == false)
boolean fail = true;
try
{
new HighwaterMarkDirectoryScanningHandler(null, null);
} catch (final AssertionError ex)
{
unhandledItems.add(asStoreItem(path));
fail = false;
}
return mayHandle;
assertFalse(fail);
}
}
\ No newline at end of file
......@@ -78,18 +78,11 @@ public class DirectoryScanningTimerTaskTest
private final List<File> handledPaths = new ArrayList<File>();
private boolean mayHandle = true;
public void clear()
{
handledPaths.clear();
}
public final void setMayHandle(final boolean mayHandle)
{
this.mayHandle = mayHandle;
}
//
// IPathHandler
//
......@@ -99,12 +92,6 @@ public class DirectoryScanningTimerTaskTest
handledPaths.add(path);
path.delete();
}
public final boolean mayHandle(final File path)
{
return mayHandle;
}
}
@BeforeClass
......@@ -126,8 +113,7 @@ public class DirectoryScanningTimerTaskTest
private final File getFaultyPathFile()
{
final File faultyPaths =
new File(workingDirectory, DirectoryScanningTimerTask.FAULTY_PATH_FILENAME);
final File faultyPaths = new File(workingDirectory, FaultyPathHandler.FAULTY_PATH_FILENAME);
return faultyPaths;
}
......@@ -422,35 +408,4 @@ public class DirectoryScanningTimerTaskTest
LogMonitoringAppender.removeAppender(appender);
}
}
@Test
public final void testRemoveFaultyPaths() throws IOException
{
final MockPathHandler pathHandler = new MockPathHandler();
pathHandler.setMayHandle(false);
final DirectoryScanningTimerTask directoryScanning =
new DirectoryScanningTimerTask(workingDirectory, ACCEPT_ALL_FILTER, pathHandler);
testPathOrder();
// No faulty file at this point.
assertEquals(1, workingDirectory.listFiles().length);
directoryScanning.run();
// One faulty file found (as mayHandle is set to false).
List<String> faulty = CollectionIO.readList(getFaultyPathFile());
assertEquals(1, faulty.size());
final File file = new File(faulty.get(0));
directoryScanning.removeFaultyPaths(StoreItem.asItem(file));
faulty = CollectionIO.readList(getFaultyPathFile());
// Faulty file is empty.
assertEquals(0, faulty.size());
// Two files found (inclusive the faulty file).
assertEquals(2, workingDirectory.listFiles().length);
pathHandler.setMayHandle(true);
directoryScanning.run();
faulty = CollectionIO.readList(getFaultyPathFile());
assertEquals(0, faulty.size());
// Only the faulty file present now.
final File[] files = workingDirectory.listFiles();
assertEquals(1, files.length);
assertEquals(DirectoryScanningTimerTask.FAULTY_PATH_FILENAME, files[0].getName());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment