Browse Source

Remember the cause for invalidating a packfile

Keep track of the original cause for a packfile invalidation.
It is needed for the sysadmin to understand if there is a real
underlying filesystem problem and repository corruption or if it is
simply a consequence of a concurrency of Git operations (e.g. repack
or GC).

Change-Id: I06ddda9ec847844ec31616ab6d17f153a5a34e33
Signed-off-by: Luca Milanesio <luca.milanesio@gmail.com>
Signed-off-by: David Pursehouse <david.pursehouse@gmail.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
stable-4.5
Luca Milanesio 6 years ago committed by Matthias Sohn
parent
commit
d6e00d2015
  1. 14
      org.eclipse.jgit/.settings/.api_filters
  2. 34
      org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java
  3. 19
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java
  4. 9
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
  5. 23
      org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java

14
org.eclipse.jgit/.settings/.api_filters

@ -8,6 +8,20 @@
</message_arguments> </message_arguments>
</filter> </filter>
</resource> </resource>
<resource path="src/org/eclipse/jgit/errors/PackInvalidException.java" type="org.eclipse.jgit.errors.PackInvalidException">
<filter id="1142947843">
<message_arguments>
<message_argument value="4.5.7"/>
<message_argument value="PackInvalidException(File, Throwable)"/>
</message_arguments>
</filter>
<filter id="1142947843">
<message_arguments>
<message_argument value="4.5.7"/>
<message_argument value="PackInvalidException(String, Throwable)"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants"> <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
<filter id="336658481"> <filter id="336658481">
<message_arguments> <message_arguments>

34
org.eclipse.jgit/src/org/eclipse/jgit/errors/PackInvalidException.java

@ -58,9 +58,24 @@ public class PackInvalidException extends IOException {
* *
* @param path * @param path
* path of the invalid pack file. * path of the invalid pack file.
* @deprecated Use {@link #PackInvalidException(File, Throwable)}.
*/ */
@Deprecated
public PackInvalidException(final File path) { public PackInvalidException(final File path) {
this(path.getAbsolutePath()); this(path, null);
}
/**
* Construct a pack invalid error with cause.
*
* @param path
* path of the invalid pack file.
* @param cause
* cause of the pack file becoming invalid.
* @since 4.5.7
*/
public PackInvalidException(final File path, Throwable cause) {
this(path.getAbsolutePath(), cause);
} }
/** /**
@ -68,8 +83,23 @@ public class PackInvalidException extends IOException {
* *
* @param path * @param path
* path of the invalid pack file. * path of the invalid pack file.
* @deprecated Use {@link #PackInvalidException(String, Throwable)}.
*/ */
@Deprecated
public PackInvalidException(final String path) { public PackInvalidException(final String path) {
super(MessageFormat.format(JGitText.get().packFileInvalid, path)); this(path, null);
}
/**
* Construct a pack invalid error with cause.
*
* @param path
* path of the invalid pack file.
* @param cause
* cause of the pack file becoming invalid.
* @since 4.5.7
*/
public PackInvalidException(final String path, Throwable cause) {
super(MessageFormat.format(JGitText.get().packFileInvalid, path), cause);
} }
} }

19
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFile.java

@ -135,6 +135,9 @@ public final class DfsPackFile {
/** True once corruption has been detected that cannot be worked around. */ /** True once corruption has been detected that cannot be worked around. */
private volatile boolean invalid; private volatile boolean invalid;
/** Exception that caused the packfile to be flagged as invalid */
private volatile Exception invalidatingCause;
/** /**
* Lock for initialization of {@link #index} and {@link #corruptObjects}. * Lock for initialization of {@link #index} and {@link #corruptObjects}.
* <p> * <p>
@ -236,8 +239,9 @@ public final class DfsPackFile {
return idx; return idx;
} }
if (invalid) if (invalid) {
throw new PackInvalidException(getPackName()); throw new PackInvalidException(getPackName(), invalidatingCause);
}
Repository.getGlobalListenerList() Repository.getGlobalListenerList()
.dispatch(new BeforeDfsPackIndexLoadedEvent(this)); .dispatch(new BeforeDfsPackIndexLoadedEvent(this));
@ -268,6 +272,7 @@ public final class DfsPackFile {
} }
} catch (EOFException e) { } catch (EOFException e) {
invalid = true; invalid = true;
invalidatingCause = e;
IOException e2 = new IOException(MessageFormat.format( IOException e2 = new IOException(MessageFormat.format(
DfsText.get().shortReadOfIndex, DfsText.get().shortReadOfIndex,
packDesc.getFileName(INDEX))); packDesc.getFileName(INDEX)));
@ -275,6 +280,7 @@ public final class DfsPackFile {
throw e2; throw e2;
} catch (IOException e) { } catch (IOException e) {
invalid = true; invalid = true;
invalidatingCause = e;
IOException e2 = new IOException(MessageFormat.format( IOException e2 = new IOException(MessageFormat.format(
DfsText.get().cannotReadIndex, DfsText.get().cannotReadIndex,
packDesc.getFileName(INDEX))); packDesc.getFileName(INDEX)));
@ -743,8 +749,10 @@ public final class DfsPackFile {
private IOException packfileIsTruncated() { private IOException packfileIsTruncated() {
invalid = true; invalid = true;
return new IOException(MessageFormat.format( IOException exc = new IOException(MessageFormat.format(
JGitText.get().packfileIsTruncated, getPackName())); JGitText.get().packfileIsTruncated, getPackName()));
invalidatingCause = exc;
return exc;
} }
private void readFully(long position, byte[] dstbuf, int dstoff, int cnt, private void readFully(long position, byte[] dstbuf, int dstoff, int cnt,
@ -766,8 +774,9 @@ public final class DfsPackFile {
DfsBlock readOneBlock(long pos, DfsReader ctx) DfsBlock readOneBlock(long pos, DfsReader ctx)
throws IOException { throws IOException {
if (invalid) if (invalid) {
throw new PackInvalidException(getPackName()); throw new PackInvalidException(getPackName(), invalidatingCause);
}
ReadableChannel rc = ctx.db.openFile(packDesc, PACK); ReadableChannel rc = ctx.db.openFile(packDesc, PACK);
try { try {

9
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java

@ -581,13 +581,8 @@ public class ObjectDirectory extends FileObjectDatabase {
transientErrorCount = p.incrementTransientErrorCount(); transientErrorCount = p.incrementTransientErrorCount();
} }
if (warnTmpl != null) { if (warnTmpl != null) {
if (LOG.isDebugEnabled()) { LOG.warn(MessageFormat.format(warnTmpl,
LOG.debug(MessageFormat.format(warnTmpl, p.getPackFile().getAbsolutePath()), e);
p.getPackFile().getAbsolutePath()), e);
} else {
LOG.warn(MessageFormat.format(warnTmpl,
p.getPackFile().getAbsolutePath()));
}
} else { } else {
if (doLogExponentialBackoff(transientErrorCount)) { if (doLogExponentialBackoff(transientErrorCount)) {
// Don't remove the pack from the list, as the error may be // Don't remove the pack from the list, as the error may be

23
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java

@ -133,6 +133,8 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
private volatile boolean invalid; private volatile boolean invalid;
private volatile Exception invalidatingCause;
private boolean invalidBitmap; private boolean invalidBitmap;
private AtomicInteger transientErrorCount = new AtomicInteger(); private AtomicInteger transientErrorCount = new AtomicInteger();
@ -177,8 +179,9 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
private synchronized PackIndex idx() throws IOException { private synchronized PackIndex idx() throws IOException {
if (loadedIdx == null) { if (loadedIdx == null) {
if (invalid) if (invalid) {
throw new PackInvalidException(packFile); throw new PackInvalidException(packFile, invalidatingCause);
}
try { try {
final PackIndex idx = PackIndex.open(extFile(INDEX)); final PackIndex idx = PackIndex.open(extFile(INDEX));
@ -196,6 +199,7 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
throw e; throw e;
} catch (IOException e) { } catch (IOException e) {
invalid = true; invalid = true;
invalidatingCause = e;
throw e; throw e;
} }
} }
@ -644,7 +648,7 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
private void doOpen() throws IOException { private void doOpen() throws IOException {
if (invalid) { if (invalid) {
throw new PackInvalidException(packFile); throw new PackInvalidException(packFile, invalidatingCause);
} }
try { try {
synchronized (readLock) { synchronized (readLock) {
@ -654,13 +658,13 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
} }
} catch (InterruptedIOException e) { } catch (InterruptedIOException e) {
// don't invalidate the pack, we are interrupted from another thread // don't invalidate the pack, we are interrupted from another thread
openFail(false); openFail(false, e);
throw e; throw e;
} catch (FileNotFoundException fn) { } catch (FileNotFoundException fn) {
// don't invalidate the pack if opening an existing file failed // don't invalidate the pack if opening an existing file failed
// since it may be related to a temporary lack of resources (e.g. // since it may be related to a temporary lack of resources (e.g.
// max open files) // max open files)
openFail(!packFile.exists()); openFail(!packFile.exists(), fn);
throw fn; throw fn;
} catch (EOFException | AccessDeniedException | NoSuchFileException } catch (EOFException | AccessDeniedException | NoSuchFileException
| CorruptObjectException | NoPackSignatureException | CorruptObjectException | NoPackSignatureException
@ -668,20 +672,21 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
| UnsupportedPackIndexVersionException | UnsupportedPackIndexVersionException
| UnsupportedPackVersionException pe) { | UnsupportedPackVersionException pe) {
// exceptions signaling permanent problems with a pack // exceptions signaling permanent problems with a pack
openFail(true); openFail(true, pe);
throw pe; throw pe;
} catch (IOException | RuntimeException ge) { } catch (IOException | RuntimeException ge) {
// generic exceptions could be transient so we should not mark the // generic exceptions could be transient so we should not mark the
// pack invalid to avoid false MissingObjectExceptions // pack invalid to avoid false MissingObjectExceptions
openFail(false); openFail(false, ge);
throw ge; throw ge;
} }
} }
private void openFail(boolean invalidate) { private void openFail(boolean invalidate, Exception cause) {
activeWindows = 0; activeWindows = 0;
activeCopyRawData = 0; activeCopyRawData = 0;
invalid = invalidate; invalid = invalidate;
invalidatingCause = cause;
doClose(); doClose();
} }
@ -708,7 +713,7 @@ public class PackFile implements Iterable<PackIndex.MutableEntry> {
// Detect the situation and throw a proper exception so that can be properly // Detect the situation and throw a proper exception so that can be properly
// managed by the main packfile search loop and the Git client won't receive // managed by the main packfile search loop and the Git client won't receive
// any failures. // any failures.
throw new PackInvalidException(packFile); throw new PackInvalidException(packFile, invalidatingCause);
} }
if (length < pos + size) if (length < pos + size)
size = (int) (length - pos); size = (int) (length - pos);

Loading…
Cancel
Save