Merge branch 'stable-5.0' into stable-5.1

* stable-5.0:
  Reduce contention on PackFile.idx() function.

Change-Id: Ic50f375faa757076e2dfd6c25e9e0025482aa3d9
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
index ed238a4..7549274 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
@@ -139,7 +139,7 @@
 
 	private byte[] packChecksum;
 
-	private PackIndex loadedIdx;
+	private volatile PackIndex loadedIdx;
 
 	private PackReverseIndex reverseIdx;
 
@@ -174,35 +174,44 @@
 		length = Long.MAX_VALUE;
 	}
 
-	private synchronized PackIndex idx() throws IOException {
-		if (loadedIdx == null) {
-			if (invalid)
-				throw new PackInvalidException(packFile);
+	private PackIndex idx() throws IOException {
+		PackIndex idx = loadedIdx;
+		if (idx == null) {
+			synchronized (this) {
+				idx = loadedIdx;
+				if (idx == null) {
+					if (invalid) {
+						throw new PackInvalidException(packFile);
+					}
+					try {
+						idx = PackIndex.open(extFile(INDEX));
 
-			try {
-				final PackIndex idx = PackIndex.open(extFile(INDEX));
-
-				if (packChecksum == null) {
-					packChecksum = idx.packChecksum;
-				} else if (!Arrays.equals(packChecksum, idx.packChecksum)) {
-					throw new PackMismatchException(MessageFormat.format(
-							JGitText.get().packChecksumMismatch,
-							packFile.getPath(),
-							ObjectId.fromRaw(packChecksum).name(),
-							ObjectId.fromRaw(idx.packChecksum).name()));
+						if (packChecksum == null) {
+							packChecksum = idx.packChecksum;
+						} else if (!Arrays.equals(packChecksum,
+								idx.packChecksum)) {
+							throw new PackMismatchException(MessageFormat
+									.format(JGitText.get().packChecksumMismatch,
+											packFile.getPath(),
+											ObjectId.fromRaw(packChecksum)
+													.name(),
+											ObjectId.fromRaw(idx.packChecksum)
+													.name()));
+						}
+						loadedIdx = idx;
+					} catch (InterruptedIOException e) {
+						// don't invalidate the pack, we are interrupted from
+						// another thread
+						throw e;
+					} catch (IOException e) {
+						invalid = true;
+						throw e;
+					}
 				}
-				loadedIdx = idx;
-			} catch (InterruptedIOException e) {
-				// don't invalidate the pack, we are interrupted from another thread
-				throw e;
-			} catch (IOException e) {
-				invalid = true;
-				throw e;
 			}
 		}
-		return loadedIdx;
+		return idx;
 	}
-
 	/**
 	 * Get the File object which locates this pack on disk.
 	 *