From: Robin Rosenberg <robin.rosenberg@dewire.com>
To: spearce@spearce.org
Cc: git@vger.kernel.org, Robin Rosenberg <robin.rosenberg@dewire.com>
Subject: [JGIT PATCH 3/3] Rescan for packs and retry once if object lookup scan fails
Date: Sun, 19 Apr 2009 20:30:09 +0200 [thread overview]
Message-ID: <1240165809-16703-4-git-send-email-robin.rosenberg@dewire.com> (raw)
In-Reply-To: <1240165809-16703-3-git-send-email-robin.rosenberg@dewire.com>
We do this by catching the FileNotFoundException thrown by the lower
layers an rescan for packs.
A lookup failure may happen if no pack contains the requested object, so
the loose object lookup fails. The other case is that one of the packs
we use has been deleted by a repack. In either case there is a good chance
that there is a new pack or loose object that contains the object.
Therefore we scan for new packs, invalidating an old ones that may have
been deleted and retry the lookup.
At the same time we stop scanning for new packs regularly since we now
have another mechanism for finding them.
---
.../src/org/spearce/jgit/lib/Repository.java | 76 ++++++++++++++++----
1 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index cfd92b8..ec4226c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -100,6 +100,8 @@
private GitIndex index;
private List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
+
+ private int packFileListGeneration;
static private List<RepositoryListener> allListeners = new Vector<RepositoryListener>(); // thread safe
/**
@@ -291,6 +293,40 @@ public ObjectLoader openObject(final AnyObjectId id)
*/
public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
throws IOException {
+ boolean scanned = false;
+ try {
+ ObjectLoader loader = openObjectInPacks(curs, id);
+ if (loader != null)
+ return loader;
+ } catch (FileNotFoundException fnfe) {
+ System.out.println(new java.util.Date().toString() + ": failed to load " + id + ", rescanning for new packs");
+ scanned = true;
+ if (scanForPacks()) {
+ ObjectLoader loader = openObjectInPacks(curs, id);
+ if (loader != null)
+ return loader;
+ }
+ }
+ try {
+ return new UnpackedObjectLoader(this, id);
+ } catch (FileNotFoundException fnfe) {
+ System.out.println(new java.util.Date().toString() + ": failed to load " + id + ", rescanning for new packs");
+ if (!scanned && scanForPacks()) {
+ ObjectLoader loader = openObjectInPacks(curs, id);
+ if (loader != null)
+ return loader;
+ try {
+ return new UnpackedObjectLoader(this, id);
+ } catch (FileNotFoundException fnfe2) {
+ return null;
+ }
+ }
+ return null;
+ }
+ }
+
+ private ObjectLoader openObjectInPacks(final WindowCursor curs, final AnyObjectId id)
+ throws IOException {
final PackFile[] packs = packs();
int k = packs.length;
while (k > 0) {
@@ -298,11 +334,7 @@ public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
if (ol != null)
return ol;
}
- try {
- return new UnpackedObjectLoader(this, id);
- } catch (FileNotFoundException fnfe) {
- return null;
- }
+ return null;
}
/**
@@ -813,23 +845,39 @@ synchronized (this) {
}
/**
- * Scan the object dirs, including alternates for packs
- * to use.
+ * Scan the object dirs, including alternates for packs to use.
+ *
+ * @return true if new packs were found
*/
- public void scanForPacks() {
+ public boolean scanForPacks() {
+ int oldPackFileListGeneration = packFileListGeneration;
final ArrayList<PackFile> p = new ArrayList<PackFile>();
- p.addAll(Arrays.asList(packs()));
for (final File d : objectsDirs())
- scanForPacks(new File(d, "pack"), p);
+ scanForPacks(new File(d, "pack"), p, packFileList);
final PackFile[] arr = new PackFile[p.size()];
p.toArray(arr);
Arrays.sort(arr, PackFile.SORT);
synchronized (this) {
+ if (!samePackfileArray(packFileList, arr))
+ packFileListGeneration++;
packFileList = arr;
}
+ return oldPackFileListGeneration != packFileListGeneration;
}
- private void scanForPacks(final File packDir, Collection<PackFile> packList) {
+ private static<T> boolean samePackfileArray(PackFile[] oldList, PackFile[] newList) {
+ if (oldList == null)
+ return false;
+ if (oldList.length != newList.length)
+ return false;
+ for (int i = 0; i < oldList.length; ++i) {
+ if (!oldList[i].getPackFile().equals(newList[i].getPackFile()))
+ return false;
+ }
+ return true;
+ }
+
+ private void scanForPacks(final File packDir, Collection<PackFile> packList, PackFile[] oldPackFileList) {
final String[] idxList = packDir.list(new FilenameFilter() {
public boolean accept(final File baseDir, final String n) {
// Must match "pack-[0-9a-f]{40}.idx" to be an index.
@@ -851,9 +899,11 @@ public boolean accept(final File baseDir, final String n) {
continue;
}
- for (final PackFile p : packList) {
- if (packFile.equals(p.getPackFile()))
+ for (final PackFile p : oldPackFileList) {
+ if (packFile.equals(p.getPackFile())) {
+ packList.add(p);
continue SCAN;
+ }
}
packList.add(new PackFile(idxFile, packFile));
--
1.6.2.2.446.gfbdc0
next prev parent reply other threads:[~2009-04-19 18:32 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-18 17:05 JGit cache bug Robin Rosenberg
2009-04-19 18:30 ` [JGIT PATCH 0/3 RFC] http://code.google.com/p/egit/issues/detail?id=79 Robin Rosenberg
2009-04-19 18:30 ` [JGIT PATCH 1/3] Add test cases dedicated to the WindowCache Robin Rosenberg
2009-04-19 18:30 ` [JGIT PATCH 2/3] Simulate breakpoints Robin Rosenberg
2009-04-19 18:30 ` Robin Rosenberg [this message]
2009-04-20 14:32 ` [JGIT PATCH 3/3] Rescan for packs and retry once if object lookup scan fails Shawn O. Pearce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1240165809-16703-4-git-send-email-robin.rosenberg@dewire.com \
--to=robin.rosenberg@dewire.com \
--cc=git@vger.kernel.org \
--cc=spearce@spearce.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).