diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 42a6e8073576..b244b83e9bf6 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -195,6 +195,8 @@ Bug Fixes * GITHUB#15939: Fix thread-safety issues with NFARunAutomaton. (Dimitris Rempapis) +* GITHUB#16278: Refactor NativeFSLockFactory lock acquisition to cleanly separate locking and file system logic. (Bharathi-Kanna) + Changes in Runtime Behavior --------------------- * GITHUB#14187: The query cache is now disabled by default. (Adrien Grand) diff --git a/lucene/core/src/java/org/apache/lucene/store/NativeFSLockFactory.java b/lucene/core/src/java/org/apache/lucene/store/NativeFSLockFactory.java index 909b98e135dc..056bd3cf01a0 100644 --- a/lucene/core/src/java/org/apache/lucene/store/NativeFSLockFactory.java +++ b/lucene/core/src/java/org/apache/lucene/store/NativeFSLockFactory.java @@ -106,20 +106,13 @@ protected Lock obtainFSLock(FSDirectory dir, String lockName) throws IOException Files.readAttributes(realPath, BasicFileAttributes.class).creationTime(); if (LOCK_HELD.add(realPath.toString())) { - FileChannel channel = null; - FileLock lock = null; + NativeFSLock lock = null; try { - channel = FileChannel.open(realPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE); - lock = channel.tryLock(); - if (lock != null) { - return new NativeFSLock(lock, channel, realPath, creationTime); - } else { - throw new LockObtainFailedException("Lock held by another program: " + realPath); - } + lock = tryLock(realPath, creationTime); + return lock; } finally { - if (lock == null) { // not successful - clear up and move out - IOUtils.closeWhileHandlingException(channel); // TODO: addSuppressed - clearLockHeld(realPath); // clear LOCK_HELD last + if (lock == null) { + clearLockHeld(realPath); } } } else { @@ -127,6 +120,30 @@ protected Lock obtainFSLock(FSDirectory dir, String lockName) throws IOException } } + /** + * Attempts to obtain the lock without blocking. + * + * @return a NativeFSLock if successful + * @throws IOException if not successful + */ + private static NativeFSLock tryLock(Path path, FileTime creationTime) throws IOException { + FileChannel channel = null; + FileLock lock = null; + try { + channel = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + lock = channel.tryLock(); + if (lock != null) { + return new NativeFSLock(lock, channel, path, creationTime); + } else { + throw new LockObtainFailedException("Lock held by another program: " + path); + } + } finally { + if (lock == null) { // not successful - clear up and move out + IOUtils.closeWhileHandlingException(channel); // TODO: addSuppressed + } + } + } + private static void clearLockHeld(Path path) throws IOException { boolean remove = LOCK_HELD.remove(path.toString()); if (remove == false) {