added null check in FileChannelCache
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.file.locking;
|
||||
|
||||
import java.io.File;
|
||||
@@ -26,17 +27,18 @@ import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author Iwein Fuld
|
||||
* @since 2.0
|
||||
*/
|
||||
|
||||
final class FileChannelCache {
|
||||
|
||||
private static ConcurrentMap<File, FileChannel> channelCache = new ConcurrentHashMap<File, FileChannel>();
|
||||
|
||||
|
||||
/**
|
||||
* Try to get a lock for this file while guaranteeing that the same channel will be used for all file locks in this
|
||||
* VM. If the lock could not be aquired this method will return <code>null</code>.
|
||||
* VM. If the lock could not be acquired this method will return <code>null</code>.
|
||||
* <p/>
|
||||
* Locks aquired through this method should be passed back to #closeChannelFor to prevent memory leak.
|
||||
* Locks acquired through this method should be passed back to #closeChannelFor to prevent memory leak.
|
||||
* <p/>
|
||||
* Thread safe.
|
||||
*/
|
||||
@@ -45,13 +47,14 @@ final class FileChannelCache {
|
||||
if (channel == null) {
|
||||
FileChannel newChannel = new RandomAccessFile(fileToLock, "rw").getChannel();
|
||||
FileChannel original = channelCache.putIfAbsent(fileToLock, newChannel);
|
||||
channel = original != null ? original : newChannel;
|
||||
channel = (original != null) ? original : newChannel;
|
||||
}
|
||||
FileLock lock = null;
|
||||
if (channel != null) {
|
||||
try {
|
||||
lock = channel.tryLock();
|
||||
} catch (OverlappingFileLockException e) {
|
||||
}
|
||||
catch (OverlappingFileLockException e) {
|
||||
// File is already locked in this thread or virtual machine
|
||||
}
|
||||
}
|
||||
@@ -63,11 +66,20 @@ final class FileChannelCache {
|
||||
* <p/>
|
||||
* Thread safe.
|
||||
*/
|
||||
public static void closeChannelFor(File fileToUnlock) throws IOException {
|
||||
channelCache.remove(fileToUnlock).close();
|
||||
public static void closeChannelFor(File fileToUnlock) {
|
||||
FileChannel fileChannel = channelCache.remove(fileToUnlock);
|
||||
if (fileChannel != null) {
|
||||
try {
|
||||
fileChannel.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLocked(File file) {
|
||||
return channelCache.containsKey(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,17 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.file.locking;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A FileLocker is a strategy that can ensure that files are only processed a single time.
|
||||
*
|
||||
* Implementations are free implement any relation between locking and unlocking (e.g. the Noop
|
||||
* Implementations are free to implement any relation between locking and unlocking.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface FileLocker {
|
||||
|
||||
@@ -36,4 +36,5 @@ public interface FileLocker {
|
||||
* Unlocks the given file.
|
||||
*/
|
||||
void unlock(File fileToUnlock);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.file.locking;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -25,36 +26,39 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
* LockFileFileListFilter keeps track of the files it should pick up by adding lock files in a directory. If this
|
||||
* directory is the same as the directory of the original files addition precautions need to be taken to avoid treating
|
||||
* the lock files as normal input.
|
||||
* directory is the same as the directory of the original files additional precautions need to be taken to avoid
|
||||
* treating the lock files as normal input.
|
||||
*
|
||||
* If different LockFileFileListFilters share their lock directory they are unlikely to pass the same file.
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @since 2.0
|
||||
*/
|
||||
public class LockFileFileListFilter extends AbstractFileListFilter implements FileLocker{
|
||||
|
||||
private static final Log logger = LogFactory.getLog(LockFileFileListFilter.class);
|
||||
|
||||
private static final String LOCK_SUFFIX = ".lock";
|
||||
|
||||
private static final String PRELOCK_SUFFIX = ".prelock";
|
||||
|
||||
private File workdir;
|
||||
|
||||
public LockFileFileListFilter(File workdir) {
|
||||
Assert.notNull(workdir, "Work directy must not be null.");
|
||||
Assert.isTrue(workdir.isDirectory(),"Work directy must be a directory.");
|
||||
Assert.isTrue(workdir.canWrite(), "Work directy must be write accessible.");
|
||||
Assert.notNull(workdir, "Work directory must not be null.");
|
||||
Assert.isTrue(workdir.isDirectory(), "Work directory must be a directory.");
|
||||
Assert.isTrue(workdir.canWrite(), "Work directory must be write accessible.");
|
||||
this.workdir = workdir;
|
||||
}
|
||||
|
||||
protected boolean accept(File file) {
|
||||
File lockFile = new File(workdir, file.getName()+ LOCK_SUFFIX);
|
||||
File preLockFile = new File(workdir, file.getName()+ PRELOCK_SUFFIX);
|
||||
if (lockFile.exists()||preLockFile.exists()){
|
||||
File lockFile = new File(workdir, file.getName() + LOCK_SUFFIX);
|
||||
File preLockFile = new File(workdir, file.getName() + PRELOCK_SUFFIX);
|
||||
if (lockFile.exists() || preLockFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
String name = file.getName();
|
||||
return !name.endsWith(LOCK_SUFFIX)&&!name.endsWith(PRELOCK_SUFFIX);
|
||||
return !name.endsWith(LOCK_SUFFIX) && !name.endsWith(PRELOCK_SUFFIX);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,12 +75,13 @@ public class LockFileFileListFilter extends AbstractFileListFilter implements Fi
|
||||
}
|
||||
try {
|
||||
preLockFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
logger.warn("Failed to lock file", e);
|
||||
return false;
|
||||
}
|
||||
//there is still a small chance that the next line will be done concurrently and the file will be picked up twice
|
||||
if (!lockFile.exists()&&preLockFile.renameTo(lockFile)) {
|
||||
// there is still a small chance that the next line will be done concurrently and the file will be picked up twice
|
||||
if (!lockFile.exists() && preLockFile.renameTo(lockFile)) {
|
||||
lockFile.deleteOnExit();
|
||||
return true;
|
||||
}
|
||||
@@ -91,8 +96,9 @@ public class LockFileFileListFilter extends AbstractFileListFilter implements Fi
|
||||
public void unlock(File fileToUnlock) {
|
||||
File lockFile = new File(workdir, fileToUnlock.getName() + LOCK_SUFFIX);
|
||||
File preLockFile = new File(workdir, fileToUnlock.getName() + PRELOCK_SUFFIX);
|
||||
if (!preLockFile.exists()) {
|
||||
if (!preLockFile.exists()) {
|
||||
lockFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,16 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.file.locking;
|
||||
|
||||
import org.springframework.integration.file.FileListFilter;
|
||||
import org.springframework.integration.file.AbstractFileListFilter;
|
||||
import org.springframework.integration.core.MessagingException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -32,8 +31,10 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NioFileLocker extends AbstractFileListFilter implements FileLocker {
|
||||
|
||||
private final ConcurrentMap<File, FileLock> lockCache = new ConcurrentHashMap<File, FileLock>();
|
||||
|
||||
public boolean lock(File fileToLock) {
|
||||
@@ -42,7 +43,8 @@ public class NioFileLocker extends AbstractFileListFilter implements FileLocker
|
||||
FileLock newLock = null;
|
||||
try {
|
||||
newLock = FileChannelCache.tryLockFor(fileToLock);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to lock file: " + fileToLock, e);
|
||||
}
|
||||
if (newLock != null) {
|
||||
@@ -60,7 +62,8 @@ public class NioFileLocker extends AbstractFileListFilter implements FileLocker
|
||||
fileLock.release();
|
||||
}
|
||||
FileChannelCache.closeChannelFor(fileToUnlock);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to unlock file: " + fileToUnlock, e);
|
||||
}
|
||||
}
|
||||
@@ -68,4 +71,5 @@ public class NioFileLocker extends AbstractFileListFilter implements FileLocker
|
||||
protected boolean accept(File file) {
|
||||
return this.lock(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user