Allow to discover bitmap on disk created after the packfile When the bitmap file was created *after* a packfile had been loaded into the memory, JGit was unable to discover them. That happed because of two problems: 1. The PackDirectory.getPacks() does not implement the usual while loop that is scanning through the packs directory as in the other parts of JGit. 2. The scan packs does not look for newly created bitmap files if the packfile is already loaded in memory. Implement the normal packfiles scanning whenever the PackDirectory needs to return a list of packs, and make sure that any reused Pack object would have its associated bitmap properly refreshed from disk. Adapt the assertions in GcConcurrentTest with the rescanned list of Pack from the objects/packs directory. Bug: jgit-15 Change-Id: I2ed576cefd78a0e128b175228a59c9af51523d7b
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java index 1519873..96a0649 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java
@@ -186,13 +186,12 @@ public void repackAndCheckBitmapUsage() throws Exception { // make sure gc() has caused creation of a new packfile assertNotEquals(oldPackName, newPackName); - // Even when asking again for the set of packfiles outdated data - // will be returned. As long as the repository can work on cached data - // it will do so and not detect that a new packfile exists. - assertNotEquals(getSinglePack(repository).getPackName(), newPackName); + // When asking again for the set of packfiles the new updated data + // will be returned because of the rescan of the pack directory. + assertEquals(getSinglePack(repository).getPackName(), newPackName); - // Only when accessing object content it is required to rescan the pack - // directory and the new packfile will be detected. + // When accessing object content the new packfile refreshed from + // the rescan triggered from the list of packs. repository.getObjectDatabase().open(b).getSize(); assertEquals(getSinglePack(repository).getPackName(), newPackName); assertNotNull(getSinglePack(repository).getBitmapIndex());
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index 45a6794..eabb0c6 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -64,6 +64,8 @@ binaryHunkInvalidLength=Binary hunk, line {0}: input corrupt; expected length byte, got 0x{1} binaryHunkLineTooShort=Binary hunk, line {0}: input ended prematurely binaryHunkMissingNewline=Binary hunk, line {0}: input line not terminated by newline +bitmapAccessErrorForPackfile=Error whilst trying to access bitmap file for {} +bitmapFailedToGet=Failed to get bitmap index file {} bitmapMissingObject=Bitmap at {0} is missing {1}. bitmapsMustBePrepared=Bitmaps must be prepared before they may be written. blameNotCommittedYet=Not Committed Yet
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index c7cad43..1d5a2e1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -93,6 +93,8 @@ public static JGitText get() { /***/ public String binaryHunkInvalidLength; /***/ public String binaryHunkLineTooShort; /***/ public String binaryHunkMissingNewline; + /***/ public String bitmapAccessErrorForPackfile; + /***/ public String bitmapFailedToGet; /***/ public String bitmapMissingObject; /***/ public String bitmapsMustBePrepared; /***/ public String blameNotCommittedYet;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java index d6c25b2..7d39b1f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/Pack.java
@@ -1160,6 +1160,19 @@ synchronized PackBitmapIndex getBitmapIndex() throws IOException { return bitmapIdx; } + synchronized void refreshBitmapIndex(PackFile bitmapIndexFile) { + this.bitmapIdx = null; + this.invalid = false; + this.bitmapIdxFile = bitmapIndexFile; + try { + getBitmapIndex(); + } catch (IOException e) { + LOG.warn(JGitText.get().bitmapFailedToGet, bitmapIdxFile, e); + this.bitmapIdx = null; + this.bitmapIdxFile = null; + } + } + private synchronized PackReverseIndex getReverseIdx() throws IOException { if (reverseIdx == null) reverseIdx = new PackReverseIndex(idx());
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java index 6a99cb3..1676d8b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackDirectory.java
@@ -115,10 +115,13 @@ void close() { } Collection<Pack> getPacks() { - PackList list = packList.get(); - if (list == NO_PACKS) { - list = scanPacks(list); - } + PackList list; + do { + list = packList.get(); + if (list == NO_PACKS) { + list = scanPacks(list); + } + } while (searchPacksAgain(list)); Pack[] packs = list.packs; return Collections.unmodifiableCollection(Arrays.asList(packs)); } @@ -455,6 +458,13 @@ private PackList scanPacksImpl(PackList old) { && !oldPack.getFileSnapshot().isModified(packFile)) { forReuse.remove(packFile.getName()); list.add(oldPack); + try { + if(oldPack.getBitmapIndex() == null) { + oldPack.refreshBitmapIndex(packFilesByExt.get(BITMAP_INDEX)); + } + } catch (IOException e) { + LOG.warn(JGitText.get().bitmapAccessErrorForPackfile, oldPack.getPackName(), e); + } continue; }