summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHongkai Liu <hongkai.liu@ericsson.com>2017-01-24 14:08:25 -0500
committerHongkai Liu <hongkai.liu@ericsson.com>2017-01-30 22:36:59 -0400
commita33663fd4edce3585ff20c842f297e60e0e9af85 (patch)
tree6e7b91ff89d3c887871544336ab51c36ed8b3651
parent62411453f1e821152cad7c8847728cc162a0b561 (diff)
downloadjgit-a33663fd4edce3585ff20c842f297e60e0e9af85.tar.gz
jgit-a33663fd4edce3585ff20c842f297e60e0e9af85.zip
Detect stale-file-handle error in causal chain
Cover the case where the exception is wrapped up as a cause, e.g., PackIndex#open(File). Change-Id: I0df5b1e9c2ff886bdd84dee3658b6a50866699d1 Signed-off-by: Hongkai Liu <hongkai.liu@ericsson.com>
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java40
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java20
4 files changed, 63 insertions, 2 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java
index 73d8038b92..109d0e6ee3 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/FileUtilsTest.java
@@ -50,10 +50,14 @@ import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
+import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
+import java.rmi.RemoteException;
import java.util.regex.Matcher;
+import javax.management.remote.JMXProviderException;
+
import org.eclipse.jgit.junit.JGitTestUtil;
import org.junit.After;
import org.junit.Assume;
@@ -61,6 +65,17 @@ import org.junit.Before;
import org.junit.Test;
public class FileUtilsTest {
+ private static final String MSG = "Stale file handle";
+
+ private static final String SOME_ERROR_MSG = "some error message";
+
+ private static final IOException IO_EXCEPTION = new UnsupportedEncodingException(
+ MSG);
+
+ private static final IOException IO_EXCEPTION_WITH_CAUSE = new RemoteException(
+ SOME_ERROR_MSG,
+ new JMXProviderException(SOME_ERROR_MSG, IO_EXCEPTION));
+
private File trash;
@Before
@@ -541,4 +556,29 @@ public class FileUtilsTest {
return path.replaceAll("/|\\\\",
Matcher.quoteReplacement(File.separator));
}
+
+ @Test
+ public void testIsStaleFileHandleWithDirectCause() throws Exception {
+ assertTrue(FileUtils.isStaleFileHandle(IO_EXCEPTION));
+ }
+
+ @Test
+ public void testIsStaleFileHandleWithIndirectCause() throws Exception {
+ assertFalse(
+ FileUtils.isStaleFileHandle(IO_EXCEPTION_WITH_CAUSE));
+ }
+
+ @Test
+ public void testIsStaleFileHandleInCausalChainWithDirectCause()
+ throws Exception {
+ assertTrue(
+ FileUtils.isStaleFileHandleInCausalChain(IO_EXCEPTION));
+ }
+
+ @Test
+ public void testIsStaleFileHandleInCausalChainWithIndirectCause()
+ throws Exception {
+ assertTrue(FileUtils
+ .isStaleFileHandleInCausalChain(IO_EXCEPTION_WITH_CAUSE));
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
index eec7fb7c3a..b73152222b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
@@ -577,7 +577,7 @@ public class ObjectDirectory extends FileObjectDatabase {
warnTmpl = JGitText.get().packWasDeleted;
}
removePack(p);
- } else if (FileUtils.isStaleFileHandle(e)) {
+ } else if (FileUtils.isStaleFileHandleInCausalChain(e)) {
warnTmpl = JGitText.get().packHandleIsStale;
removePack(p);
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
index e3d0d6162c..023c08c77f 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java
@@ -798,7 +798,8 @@ public class RefDirectory extends RefDatabase {
return new PackedRefList(parsePackedRefs(br), snapshot,
ObjectId.fromRaw(digest.digest()));
} catch (IOException e) {
- if (FileUtils.isStaleFileHandle(e) && retries < maxStaleRetries) {
+ if (FileUtils.isStaleFileHandleInCausalChain(e)
+ && retries < maxStaleRetries) {
if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format(
JGitText.get().packedRefsHandleIsStale,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
index c04dfa9610..1f1d15b324 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -548,6 +548,26 @@ public class FileUtils {
}
/**
+ * Determine if a throwable or a cause in its causal chain is a Stale NFS
+ * File Handle
+ *
+ * @param throwable
+ * @return a boolean true if the throwable or a cause in its causal chain is
+ * a Stale NFS File Handle
+ * @since 4.7
+ */
+ public static boolean isStaleFileHandleInCausalChain(Throwable throwable) {
+ while (throwable != null) {
+ if (throwable instanceof IOException
+ && isStaleFileHandle((IOException) throwable)) {
+ return true;
+ }
+ throwable = throwable.getCause();
+ }
+ return false;
+ }
+
+ /**
* @param file
* @return {@code true} if the passed file is a symbolic link
*/