@ -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 ) ;