Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lucene/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ Bug Fixes

* GITHUB#16278: Refactor NativeFSLockFactory lock acquisition to cleanly separate locking and file system logic. (Bharathi-Kanna)

* GITHUB#16303: Add suppressed exception details when lock acquisition fails in NativeFSLockFactory. (Bharathi-Kanna)

Changes in Runtime Behavior
---------------------
* GITHUB#14187: The query cache is now disabled by default. (Adrien Grand)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,9 @@ private static NativeFSLock tryLock(Path path, FileTime creationTime) throws IOE
} 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
}
} catch (Throwable t) {
IOUtils.closeWhileSuppressingExceptions(t, channel);
throw t;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package org.apache.lucene.store;

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessDeniedException;
import java.nio.file.FileSystem;
Expand All @@ -25,6 +27,7 @@
import java.nio.file.Path;
import java.nio.file.attribute.FileAttribute;
import java.util.Set;
import org.apache.lucene.tests.mockfile.FilterFileChannel;
import org.apache.lucene.tests.mockfile.FilterFileSystemProvider;
import org.apache.lucene.tests.mockfile.FilterPath;
import org.apache.lucene.tests.store.BaseLockFactoryTestCase;
Expand Down Expand Up @@ -143,4 +146,54 @@ public void testBadPermissions() throws IOException {

dir.close();
}

/** MockFileSystem that throws exception on lock and close */
static class MockFailingCloseFileSystem extends FilterFileSystemProvider {
public MockFailingCloseFileSystem(FileSystem delegateInstance) {
super("mockfailingclose://", delegateInstance);
}

@Override
public FileChannel newFileChannel(
Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs)
throws IOException {
if (path.getFileName().toString().equals("test.lock")) {
return new FilterFileChannel(super.newFileChannel(path, options, attrs)) {
@Override
public FileLock tryLock(long position, long size, boolean shared) throws IOException {
throw new IOException("fake lock failure");
}

@Override
protected void implCloseChannel() throws IOException {
super.implCloseChannel();
throw new IOException("fake close failure");
}
};
}
return super.newFileChannel(path, options, attrs);
}
}

public void testSuppressedExceptionOnLockFailure() throws IOException {
Path tmpDir = createTempDir();
tmpDir = FilterPath.unwrap(tmpDir).toRealPath();
FileSystem mock = new MockFailingCloseFileSystem(tmpDir.getFileSystem()).getFileSystem(null);
Path mockPath = mock.getPath(tmpDir.toString());

Directory dir = getDirectory(mockPath.resolve("indexDir"));
IOException expected =
expectThrows(
IOException.class,
() -> {
dir.obtainLock("test.lock");
});

assertEquals("fake lock failure", expected.getMessage());
Throwable[] suppressed = expected.getSuppressed();
assertEquals(1, suppressed.length);
assertEquals("fake close failure", suppressed[0].getMessage());

dir.close();
}
}
Loading