[JGIT PATCH 10/11] Use cached Repository instances when resolving alternates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Using a cached Repository instance when opening an alternate object
database ensures that if multiple repositories share the same base
repository (e.g. 4 forks of the Linux kernel all share the same
base "linus-2.6.git" repository) then the base object directory is
only monitored and tracked once in the JVM, instead of 4 times.  In
the case of the WindowCache, this means we will have greater reuse
of the windows from the base, as they won't be loaded 4 different
times under different keys.

Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx>
---
 .../jgit/lib/AlternateRepositoryDatabase.java      |  127 ++++++++++++++++++++
 .../src/org/spearce/jgit/lib/ObjectDatabase.java   |   16 ++-
 .../src/org/spearce/jgit/lib/ObjectDirectory.java  |   18 +++-
 3 files changed, 155 insertions(+), 6 deletions(-)
 create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/AlternateRepositoryDatabase.java

diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/AlternateRepositoryDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/AlternateRepositoryDatabase.java
new file mode 100644
index 0000000..ee4c4cf
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/AlternateRepositoryDatabase.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009, Google Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Git Development Community nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.spearce.jgit.lib;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * An ObjectDatabase of another {@link Repository}.
+ * <p>
+ * This {@code ObjectDatabase} wraps around another {@code Repository}'s object
+ * database, providing its contents to the caller, and closing the Repository
+ * when this database is closed. The primary user of this class is
+ * {@link ObjectDirectory}, when the {@code info/alternates} file points at the
+ * {@code objects/} directory of another repository.
+ */
+public final class AlternateRepositoryDatabase extends ObjectDatabase {
+	private final Repository repository;
+
+	private final ObjectDatabase odb;
+
+	/**
+	 * @param alt
+	 *            the alternate repository to wrap and export.
+	 */
+	public AlternateRepositoryDatabase(final Repository alt) {
+		repository = alt;
+		odb = repository.getObjectDatabase();
+	}
+
+	/** @return the alternate repository objects are borrowed from. */
+	public Repository getRepository() {
+		return repository;
+	}
+
+	public void closeSelf() {
+		repository.close();
+	}
+
+	public void create() throws IOException {
+		repository.create();
+	}
+
+	public boolean exists() {
+		return odb.exists();
+	}
+
+	@Override
+	protected boolean hasObject1(final AnyObjectId objectId) {
+		return odb.hasObject1(objectId);
+	}
+
+	@Override
+	protected boolean tryAgain1() {
+		return odb.tryAgain1();
+	}
+
+	@Override
+	protected boolean hasObject2(final String objectName) {
+		return odb.hasObject2(objectName);
+	}
+
+	@Override
+	protected ObjectLoader openObject1(final WindowCursor curs,
+			final AnyObjectId objectId) throws IOException {
+		return odb.openObject1(curs, objectId);
+	}
+
+	@Override
+	protected ObjectLoader openObject2(final WindowCursor curs,
+			final String objectName, final AnyObjectId objectId)
+			throws IOException {
+		return odb.openObject2(curs, objectName, objectId);
+	}
+
+	@Override
+	void openObjectInAllPacks1(final Collection<PackedObjectLoader> out,
+			final WindowCursor curs, final AnyObjectId objectId)
+			throws IOException {
+		odb.openObjectInAllPacks1(out, curs, objectId);
+	}
+
+	@Override
+	protected ObjectDatabase[] loadAlternates() throws IOException {
+		return odb.getAlternates();
+	}
+
+	@Override
+	protected void closeAlternates(final ObjectDatabase[] alt) {
+		// Do nothing; these belong to odb to close, not us.
+	}
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDatabase.java
index 6a9ba4e..a547052 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDatabase.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDatabase.java
@@ -108,9 +108,7 @@ public final void closeAlternates() {
 		ObjectDatabase[] alt = alternates.get();
 		if (alt != null) {
 			alternates.set(null);
-			for (final ObjectDatabase d : alt) {
-				d.close();
-			}
+			closeAlternates(alt);
 		}
 	}
 
@@ -364,4 +362,16 @@ protected boolean tryAgain1() {
 	protected ObjectDatabase[] loadAlternates() throws IOException {
 		return NO_ALTERNATES;
 	}
+
+	/**
+	 * Close the list of alternates returned by {@link #loadAlternates()}.
+	 *
+	 * @param alt
+	 *            the alternate list, from {@link #loadAlternates()}.
+	 */
+	protected void closeAlternates(ObjectDatabase[] alt) {
+		for (final ObjectDatabase d : alt) {
+			d.close();
+		}
+	}
 }
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDirectory.java b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDirectory.java
index d3c43da..7cc459c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDirectory.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/ObjectDirectory.java
@@ -52,6 +52,7 @@
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.spearce.jgit.errors.PackMismatchException;
+import org.spearce.jgit.lib.RepositoryCache.FileKey;
 import org.spearce.jgit.util.FS;
 
 /**
@@ -415,11 +416,11 @@ public boolean accept(final File baseDir, final String n) {
 	@Override
 	protected ObjectDatabase[] loadAlternates() throws IOException {
 		final BufferedReader br = open(alternatesFile);
-		final List<ObjectDirectory> l = new ArrayList<ObjectDirectory>(4);
+		final List<ObjectDatabase> l = new ArrayList<ObjectDatabase>(4);
 		try {
 			String line;
 			while ((line = br.readLine()) != null) {
-				l.add(new ObjectDirectory(FS.resolve(objects, line)));
+				l.add(openAlternate(line));
 			}
 		} finally {
 			br.close();
@@ -428,11 +429,22 @@ public boolean accept(final File baseDir, final String n) {
 		if (l.isEmpty()) {
 			return NO_ALTERNATES;
 		}
-		return l.toArray(new ObjectDirectory[l.size()]);
+		return l.toArray(new ObjectDatabase[l.size()]);
 	}
 
 	private static BufferedReader open(final File f)
 			throws FileNotFoundException {
 		return new BufferedReader(new FileReader(f));
 	}
+
+	private ObjectDatabase openAlternate(final String location)
+			throws IOException {
+		final File objdir = FS.resolve(objects, location);
+		final File parent = objdir.getParentFile();
+		if (FileKey.isGitRepository(parent)) {
+			final Repository db = RepositoryCache.open(FileKey.exact(parent));
+			return new AlternateRepositoryDatabase(db);
+		}
+		return new ObjectDirectory(objdir);
+	}
 }
-- 
1.6.4.rc0.117.g28cb

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]