Clear lock cache in NioFileLocker (#2998)
Fixes https://github.com/spring-projects/spring-integration/issues/2980 # Conflicts: # spring-integration-file/src/test/java/org/springframework/integration/file/locking/NioFileLockerTests.java # Conflicts: # spring-integration-file/src/main/java/org/springframework/integration/file/locking/NioFileLocker.java # spring-integration-file/src/test/java/org/springframework/integration/file/locking/NioFileLockerTests.java
This commit is contained in:
committed by
Artem Bilan
parent
9d4aa8b378
commit
f2bd8c4119
@@ -16,15 +16,15 @@
|
||||
|
||||
package org.springframework.integration.file.locking;
|
||||
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileLock;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
|
||||
/**
|
||||
* File locking strategy that uses java.nio. The locks taken by FileChannel are shared with all the threads in a single
|
||||
* JVM, so this locking strategy <b>does not</b> prevent files being picked up multiple times within the same JVM.
|
||||
@@ -39,45 +39,46 @@ import java.util.concurrent.ConcurrentMap;
|
||||
*/
|
||||
public class NioFileLocker extends AbstractFileLockerFilter {
|
||||
|
||||
private final ConcurrentMap<File, FileLock> lockCache = new ConcurrentHashMap<File, FileLock>();
|
||||
private final ConcurrentMap<File, FileLock> lockCache = new ConcurrentHashMap<File, FileLock>();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean lock(File fileToLock) {
|
||||
FileLock lock = this.lockCache.get(fileToLock);
|
||||
if (lock == null) {
|
||||
FileLock newLock = null;
|
||||
try {
|
||||
newLock = FileChannelCache.tryLockFor(fileToLock);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to lock file: "
|
||||
+ fileToLock, e);
|
||||
}
|
||||
if (newLock != null) {
|
||||
FileLock original = this.lockCache.putIfAbsent(fileToLock, newLock);
|
||||
lock = original != null ? original : newLock;
|
||||
}
|
||||
}
|
||||
return lock != null;
|
||||
}
|
||||
|
||||
public boolean isLockable(File file) {
|
||||
return this.lockCache.containsKey(file) || !FileChannelCache.isLocked(file);
|
||||
}
|
||||
|
||||
public void unlock(File fileToUnlock) {
|
||||
FileLock fileLock = this.lockCache.get(fileToUnlock);
|
||||
try {
|
||||
if (fileLock != null) {
|
||||
fileLock.release();
|
||||
}
|
||||
FileChannelCache.closeChannelFor(fileToUnlock);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to unlock file: "
|
||||
+ fileToUnlock, e);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean lock(File fileToLock) {
|
||||
FileLock lock = this.lockCache.get(fileToLock);
|
||||
if (lock == null) {
|
||||
FileLock newLock;
|
||||
try {
|
||||
newLock = FileChannelCache.tryLockFor(fileToLock);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to lock file: "
|
||||
+ fileToLock, e);
|
||||
}
|
||||
if (newLock != null) {
|
||||
FileLock original = this.lockCache.putIfAbsent(fileToLock, newLock);
|
||||
lock = original != null ? original : newLock;
|
||||
}
|
||||
}
|
||||
return lock != null;
|
||||
}
|
||||
|
||||
public boolean isLockable(File file) {
|
||||
return this.lockCache.containsKey(file) || !FileChannelCache.isLocked(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlock(File fileToUnlock) {
|
||||
FileLock fileLock = this.lockCache.remove(fileToUnlock);
|
||||
try {
|
||||
if (fileLock != null) {
|
||||
fileLock.release();
|
||||
}
|
||||
FileChannelCache.closeChannelFor(fileToUnlock);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to unlock file: " + fileToUnlock, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,20 +18,24 @@ package org.springframework.integration.file.locking;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import org.springframework.integration.file.filters.FileListFilter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
/**
|
||||
* @author Iwein Fuld
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class NioFileLockerTests {
|
||||
|
||||
@@ -46,25 +50,31 @@ public class NioFileLockerTests {
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void fileListedByFirstFilter() throws IOException {
|
||||
NioFileLocker filter = new NioFileLocker();
|
||||
File testFile = new File(workdir, "test0");
|
||||
testFile.createNewFile();
|
||||
assertThat(filter.filterFiles(workdir.listFiles()).get(0), is(testFile));
|
||||
filter.lock(testFile);
|
||||
assertThat(filter.filterFiles(workdir.listFiles()).get(0), is(testFile));
|
||||
}
|
||||
@Test
|
||||
public void fileListedByFirstFilter() throws Exception {
|
||||
NioFileLocker filter = new NioFileLocker();
|
||||
File testFile = new File(workdir, "test0");
|
||||
testFile.createNewFile();
|
||||
assertThat(filter.filterFiles(workdir.listFiles()).get(0), is(testFile));
|
||||
filter.lock(testFile);
|
||||
assertThat(filter.filterFiles(workdir.listFiles()).get(0), is(testFile));
|
||||
filter.unlock(testFile);
|
||||
Field channelCache = FileChannelCache.class.getDeclaredField("channelCache");
|
||||
channelCache.setAccessible(true);
|
||||
assertTrue(((Map<?, ?>) channelCache.get(null)).isEmpty());
|
||||
assertTrue(TestUtils.getPropertyValue(filter, "lockCache", Map.class).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileNotListedWhenLockedByOtherFilter() throws IOException {
|
||||
NioFileLocker filter1 = new NioFileLocker();
|
||||
FileListFilter<File> filter2 = new NioFileLocker();
|
||||
File testFile = new File(workdir, "test1");
|
||||
testFile.createNewFile();
|
||||
assertThat(filter1.filterFiles(workdir.listFiles()).get(0), is(testFile));
|
||||
filter1.lock(testFile);
|
||||
assertThat(filter2.filterFiles(workdir.listFiles()), is((List<File>) new ArrayList<File>()));
|
||||
}
|
||||
@Test
|
||||
public void fileNotListedWhenLockedByOtherFilter() throws IOException {
|
||||
NioFileLocker filter1 = new NioFileLocker();
|
||||
FileListFilter<File> filter2 = new NioFileLocker();
|
||||
File testFile = new File(workdir, "test1");
|
||||
testFile.createNewFile();
|
||||
assertThat(filter1.filterFiles(workdir.listFiles()).get(0), is(testFile));
|
||||
filter1.lock(testFile);
|
||||
assertThat(filter2.filterFiles(workdir.listFiles()), is(new ArrayList<File>()));
|
||||
filter1.unlock(testFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user