mirror of
https://github.com/elastic/logstash.git
synced 2025-04-24 22:57:16 -04:00
support releaseLock
added usage comment
This commit is contained in:
parent
4d28c401f0
commit
6ba6bb4037
2 changed files with 65 additions and 4 deletions
|
@ -27,9 +27,21 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FileLockFactory provides a way to obtain an exclusive file lock for a given dir path and lock name.
|
||||||
|
* The obtainLock() method will return a Filelock object which should be released using the releaseLock()
|
||||||
|
* method. Normally the returned FileLock object should not be manipulated directly. Only the obtainLock()
|
||||||
|
* and releaseLock() methods should be use to gain and release exclusive access.
|
||||||
|
* This is threadsafe and will work across threads on the same JVM and will also work across processes/JVM.
|
||||||
|
*
|
||||||
|
* TODO: because of the releaseLock() method, strictly speaking this class is not only a factory anymore,
|
||||||
|
* maybe we should rename it FileLockManager?
|
||||||
|
*/
|
||||||
public class FileLockFactory {
|
public class FileLockFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,7 +51,8 @@ public class FileLockFactory {
|
||||||
|
|
||||||
private FileLockFactory() {}
|
private FileLockFactory() {}
|
||||||
|
|
||||||
private static final Set<String> LOCK_HELD = Collections.synchronizedSet(new HashSet<String>());
|
private static final Set<String> LOCK_HELD = Collections.synchronizedSet(new HashSet<>());
|
||||||
|
private static final Map<FileLock, String> LOCK_MAP = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
public static final FileLockFactory getDefault() {
|
public static final FileLockFactory getDefault() {
|
||||||
return FileLockFactory.INSTANCE;
|
return FileLockFactory.INSTANCE;
|
||||||
|
@ -71,6 +84,7 @@ public class FileLockFactory {
|
||||||
channel = FileChannel.open(realLockPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
|
channel = FileChannel.open(realLockPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
|
||||||
lock = channel.tryLock();
|
lock = channel.tryLock();
|
||||||
if (lock != null) {
|
if (lock != null) {
|
||||||
|
LOCK_MAP.put(lock, realLockPath.toString());
|
||||||
return lock;
|
return lock;
|
||||||
} else {
|
} else {
|
||||||
throw new LockException("Lock held by another program: " + realLockPath);
|
throw new LockException("Lock held by another program: " + realLockPath);
|
||||||
|
@ -85,8 +99,8 @@ public class FileLockFactory {
|
||||||
// suppress any channel close exceptions
|
// suppress any channel close exceptions
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean remove = LOCK_HELD.remove(realLockPath.toString());
|
boolean removed = LOCK_HELD.remove(realLockPath.toString());
|
||||||
if (remove == false) {
|
if (removed == false) {
|
||||||
throw new LockException("Lock path was cleared but never marked as held: " + realLockPath);
|
throw new LockException("Lock path was cleared but never marked as held: " + realLockPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,4 +109,13 @@ public class FileLockFactory {
|
||||||
throw new LockException("Lock held by this virtual machine: " + realLockPath);
|
throw new LockException("Lock held by this virtual machine: " + realLockPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void releaseLock(FileLock lock) throws IOException {
|
||||||
|
String lockPath = LOCK_MAP.remove(lock);
|
||||||
|
if (lockPath == null) { throw new LockException("Cannot release unobtained lock"); }
|
||||||
|
lock.release();
|
||||||
|
Boolean removed = LOCK_HELD.remove(lockPath);
|
||||||
|
if (removed == false) { throw new LockException("Lock path was not marked as held: " + lockPath); }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ public class FileLockFactoryTest {
|
||||||
private String lockDir;
|
private String lockDir;
|
||||||
private final String LOCK_FILE = ".test";
|
private final String LOCK_FILE = ".test";
|
||||||
|
|
||||||
|
private FileLock lock;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
lockDir = temporaryFolder.newFolder("lock").getPath();
|
lockDir = temporaryFolder.newFolder("lock").getPath();
|
||||||
|
@ -29,7 +31,7 @@ public class FileLockFactoryTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void lockFirst() throws Exception {
|
public void lockFirst() throws Exception {
|
||||||
FileLock lock = FileLockFactory.getDefault().obtainLock(lockDir, LOCK_FILE);
|
lock = FileLockFactory.getDefault().obtainLock(lockDir, LOCK_FILE);
|
||||||
assertThat(lock.isValid(), is(equalTo(true)));
|
assertThat(lock.isValid(), is(equalTo(true)));
|
||||||
assertThat(lock.isShared(), is(equalTo(false)));
|
assertThat(lock.isShared(), is(equalTo(false)));
|
||||||
}
|
}
|
||||||
|
@ -50,4 +52,40 @@ public class FileLockFactoryTest {
|
||||||
assertThat(lock2.isValid(), is(equalTo(true)));
|
assertThat(lock2.isValid(), is(equalTo(true)));
|
||||||
assertThat(lock2.isShared(), is(equalTo(false)));
|
assertThat(lock2.isShared(), is(equalTo(false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void LockReleaseLock() throws IOException {
|
||||||
|
FileLockFactory.getDefault().releaseLock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void LockReleaseLockObtainLock() throws IOException {
|
||||||
|
FileLockFactory.getDefault().releaseLock(lock);
|
||||||
|
|
||||||
|
FileLock lock2 = FileLockFactory.getDefault().obtainLock(lockDir, LOCK_FILE);
|
||||||
|
assertThat(lock2.isValid(), is(equalTo(true)));
|
||||||
|
assertThat(lock2.isShared(), is(equalTo(false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void LockReleaseLockObtainLockRelease() throws IOException {
|
||||||
|
FileLockFactory.getDefault().releaseLock(lock);
|
||||||
|
|
||||||
|
FileLock lock2 = FileLockFactory.getDefault().obtainLock(lockDir, LOCK_FILE);
|
||||||
|
assertThat(lock2.isValid(), is(equalTo(true)));
|
||||||
|
assertThat(lock2.isShared(), is(equalTo(false)));
|
||||||
|
|
||||||
|
FileLockFactory.getDefault().releaseLock(lock2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = LockException.class)
|
||||||
|
public void ReleaseNullLock() throws IOException {
|
||||||
|
FileLockFactory.getDefault().releaseLock(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = LockException.class)
|
||||||
|
public void ReleaseUnobtainedLock() throws IOException {
|
||||||
|
FileLockFactory.getDefault().releaseLock(lock);
|
||||||
|
FileLockFactory.getDefault().releaseLock(lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue