mirror of https://github.com/apache/lucene.git
LUCENE-7959: Improve NativeFSLockFactory's NoSuchFileException
This commit is contained in:
parent
8452edb130
commit
0283d3e28a
|
@ -57,6 +57,10 @@ Bug Fixes
|
||||||
* LUCENE-7891: Lucene's taxonomy facets now uses a non-buggy LRU cache
|
* LUCENE-7891: Lucene's taxonomy facets now uses a non-buggy LRU cache
|
||||||
by default. (Jan-Willem van den Broek via Mike McCandless)
|
by default. (Jan-Willem van den Broek via Mike McCandless)
|
||||||
|
|
||||||
|
* LUCENE-7959: Improve NativeFSLockFactory's exception message if it cannot create
|
||||||
|
write.lock for an empty index due to bad permissions/read-only filesystem/etc.
|
||||||
|
(Erick Erickson, Shawn Heisey, Robert Muir)
|
||||||
|
|
||||||
Build
|
Build
|
||||||
|
|
||||||
* SOLR-11181: Switch order of maven artifact publishing procedure: deploy first
|
* SOLR-11181: Switch order of maven artifact publishing procedure: deploy first
|
||||||
|
|
|
@ -93,15 +93,27 @@ public final class NativeFSLockFactory extends FSLockFactory {
|
||||||
|
|
||||||
Path lockFile = lockDir.resolve(lockName);
|
Path lockFile = lockDir.resolve(lockName);
|
||||||
|
|
||||||
|
IOException creationException = null;
|
||||||
try {
|
try {
|
||||||
Files.createFile(lockFile);
|
Files.createFile(lockFile);
|
||||||
} catch (IOException ignore) {
|
} catch (IOException ignore) {
|
||||||
// we must create the file to have a truly canonical path.
|
// we must create the file to have a truly canonical path.
|
||||||
// if it's already created, we don't care. if it cant be created, it will fail below.
|
// if it's already created, we don't care. if it cant be created, it will fail below.
|
||||||
|
creationException = ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fails if the lock file does not exist
|
// fails if the lock file does not exist
|
||||||
final Path realPath = lockFile.toRealPath();
|
final Path realPath;
|
||||||
|
try {
|
||||||
|
realPath = lockFile.toRealPath();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// if we couldn't resolve the lock file, it might be because we couldn't create it.
|
||||||
|
// so append any exception from createFile as a suppressed exception, in case its useful
|
||||||
|
if (creationException != null) {
|
||||||
|
e.addSuppressed(creationException);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
// used as a best-effort check, to see if the underlying file has changed
|
// used as a best-effort check, to see if the underlying file has changed
|
||||||
final FileTime creationTime = Files.readAttributes(realPath, BasicFileAttributes.class).creationTime();
|
final FileTime creationTime = Files.readAttributes(realPath, BasicFileAttributes.class).creationTime();
|
||||||
|
|
|
@ -18,9 +18,17 @@ package org.apache.lucene.store;
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.channels.SeekableByteChannel;
|
||||||
|
import java.nio.file.AccessDeniedException;
|
||||||
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.OpenOption;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.attribute.FileAttribute;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.lucene.mockfile.FilterFileSystemProvider;
|
||||||
|
import org.apache.lucene.mockfile.FilterPath;
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
import org.apache.lucene.util.TestUtil;
|
import org.apache.lucene.util.TestUtil;
|
||||||
|
|
||||||
|
@ -89,4 +97,38 @@ public class TestNativeFSLockFactory extends BaseLockFactoryTestCase {
|
||||||
IOUtils.closeWhileHandlingException(lock);
|
IOUtils.closeWhileHandlingException(lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** MockFileSystem that throws AccessDeniedException on creating test.lock */
|
||||||
|
static class MockBadPermissionsFileSystem extends FilterFileSystemProvider {
|
||||||
|
public MockBadPermissionsFileSystem(FileSystem delegateInstance) {
|
||||||
|
super("mockbadpermissions://", delegateInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
|
||||||
|
if (path.getFileName().toString().equals("test.lock")) {
|
||||||
|
throw new AccessDeniedException(path.toString(), null, "fake access denied");
|
||||||
|
}
|
||||||
|
return super.newByteChannel(path, options, attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBadPermissions() throws IOException {
|
||||||
|
// create a mock filesystem that will throw exc on creating test.lock
|
||||||
|
Path tmpDir = createTempDir();
|
||||||
|
tmpDir = FilterPath.unwrap(tmpDir).toRealPath();
|
||||||
|
FileSystem mock = new MockBadPermissionsFileSystem(tmpDir.getFileSystem()).getFileSystem(null);
|
||||||
|
Path mockPath = mock.getPath(tmpDir.toString());
|
||||||
|
|
||||||
|
// we should get an IOException (typically NoSuchFileException but no guarantee) with
|
||||||
|
// our fake AccessDenied added as suppressed.
|
||||||
|
Directory dir = getDirectory(mockPath.resolve("indexDir"));
|
||||||
|
IOException expected = expectThrows(IOException.class, () -> {
|
||||||
|
dir.obtainLock("test.lock");
|
||||||
|
});
|
||||||
|
AccessDeniedException suppressed = (AccessDeniedException) expected.getSuppressed()[0];
|
||||||
|
assertTrue(suppressed.getMessage().contains("fake access denied"));
|
||||||
|
|
||||||
|
dir.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue