[JGIT PATCH 06/13] Make Repository thread-safe

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

 



The Repository class itself is now thread-safe.  Thread safety is
ensured by copying values onto the caller stack prior to use.

Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx>
---
 .../src/org/spearce/jgit/lib/Repository.java       |   75 ++++++++++++-------
 1 files changed, 47 insertions(+), 28 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 ff36a3d..89ad991 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -46,6 +46,7 @@
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -79,20 +80,22 @@
  * 	</ul>
  * </li>
  * </ul>
- *
+ * <p>
+ * This class is thread-safe.
+ * <p>
  * This implementation only handles a subtly undocumented subset of git features.
  *
  */
 public class Repository {
 	private final File gitDir;
 
-	private final File[] objectsDirs;
-
 	private final RepositoryConfig config;
 
 	private final RefDatabase refs;
 
-	private PackFile[] packs;
+	private File[] objectDirectoryList;
+
+	private PackFile[] packFileList;
 
 	private GitIndex index;
 
@@ -111,18 +114,19 @@
 	public Repository(final File d) throws IOException {
 		gitDir = d.getAbsoluteFile();
 		try {
-			objectsDirs = readObjectsDirs(FS.resolve(gitDir, "objects"),
-					new ArrayList<File>()).toArray(new File[0]);
+			objectDirectoryList = readObjectsDirs(
+					FS.resolve(gitDir, "objects"), new ArrayList<File>())
+					.toArray(new File[0]);
 		} catch (IOException e) {
 			IOException ex = new IOException("Cannot find all object dirs for " + gitDir);
 			ex.initCause(e);
 			throw ex;
 		}
 		refs = new RefDatabase(this);
-		packs = new PackFile[0];
+		packFileList = new PackFile[0];
 		config = new RepositoryConfig(this);
 
-		final boolean isExisting = objectsDirs[0].exists();
+		final boolean isExisting = objectDirectoryList[0].exists();
 		if (isExisting) {
 			getConfig().load();
 			final String repositoryFormatVersion = getConfig().getString(
@@ -138,7 +142,8 @@ public Repository(final File d) throws IOException {
 			scanForPacks();
 	}
 
-	private Collection<File> readObjectsDirs(File objectsDir, Collection<File> ret) throws IOException {
+	private static Collection<File> readObjectsDirs(File objectsDir,
+			Collection<File> ret) throws IOException {
 		ret.add(objectsDir);
 		final File altFile = FS.resolve(objectsDir, "info/alternates");
 		if (altFile.exists()) {
@@ -160,7 +165,7 @@ public Repository(final File d) throws IOException {
 	 *
 	 * @throws IOException
 	 */
-	public void create() throws IOException {
+	public synchronized void create() throws IOException {
 		if (gitDir.exists()) {
 			throw new IllegalStateException("Repository already exists: "
 					+ gitDir);
@@ -169,9 +174,9 @@ public void create() throws IOException {
 		gitDir.mkdirs();
 		refs.create();
 
-		objectsDirs[0].mkdirs();
-		new File(objectsDirs[0], "pack").mkdir();
-		new File(objectsDirs[0], "info").mkdir();
+		objectDirectoryList[0].mkdirs();
+		new File(objectDirectoryList[0], "pack").mkdir();
+		new File(objectDirectoryList[0], "info").mkdir();
 
 		new File(gitDir, "branches").mkdir();
 		new File(gitDir, "remotes").mkdir();
@@ -182,6 +187,14 @@ public void create() throws IOException {
 		getConfig().save();
 	}
 
+	private synchronized File[] objectsDirs(){
+		return objectDirectoryList;
+	}
+
+	private synchronized PackFile[] packs(){
+		return packFileList;
+	}
+
 	/**
 	 * @return GIT_DIR
 	 */
@@ -193,7 +206,7 @@ public File getDirectory() {
 	 * @return the directory containing the objects owned by this repository.
 	 */
 	public File getObjectsDirectory() {
-		return objectsDirs[0];
+		return objectsDirs()[0];
 	}
 
 	/**
@@ -217,6 +230,7 @@ public File toFile(final AnyObjectId objectId) {
 		final String n = objectId.name();
 		String d=n.substring(0, 2);
 		String f=n.substring(2);
+		final File[] objectsDirs = objectsDirs();
 		for (int i=0; i<objectsDirs.length; ++i) {
 			File ret = new File(new File(objectsDirs[i], d), f);
 			if (ret.exists())
@@ -231,6 +245,7 @@ public File toFile(final AnyObjectId objectId) {
 	 *         known shared repositories.
 	 */
 	public boolean hasObject(final AnyObjectId objectId) {
+		final PackFile[] packs = packs();
 		int k = packs.length;
 		if (k > 0) {
 			do {
@@ -271,6 +286,7 @@ public ObjectLoader openObject(final AnyObjectId id)
 	 */
 	public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
 			throws IOException {
+		final PackFile[] packs = packs();
 		int k = packs.length;
 		if (k > 0) {
 			do {
@@ -341,7 +357,7 @@ public ObjectLoader openObject(final WindowCursor curs, final AnyObjectId id)
 	void openObjectInAllPacks(final AnyObjectId objectId,
 			final Collection<PackedObjectLoader> resultLoaders,
 			final WindowCursor curs) throws IOException {
-		for (PackFile pack : packs) {
+		for (PackFile pack : packs()) {
 			final PackedObjectLoader loader = pack.get(curs, objectId);
 			if (loader != null)
 				resultLoaders.add(loader);
@@ -766,11 +782,10 @@ public void close() {
 		closePacks();
 	}
 
-	void closePacks() {
-		for (int k = packs.length - 1; k >= 0; k--) {
-			packs[k].close();
-		}
-		packs = new PackFile[0];
+	synchronized void closePacks() {
+		for (int k = packFileList.length - 1; k >= 0; k--)
+			packFileList[k].close();
+		packFileList = new PackFile[0];
 	}
 
 	/**
@@ -795,11 +810,13 @@ public void openPack(final File pack, final File idx) throws IOException {
 			throw new IllegalArgumentException("Pack " + pack
 					+ "does not match index " + idx);
 
-		final PackFile[] cur = packs;
-		final PackFile[] arr = new PackFile[cur.length + 1];
-		System.arraycopy(cur, 0, arr, 1, cur.length);
-		arr[0] = new PackFile(this, idx, pack);
-		packs = arr;
+		synchronized (this) {
+			final PackFile[] cur = packFileList;
+			final PackFile[] arr = new PackFile[cur.length + 1];
+			System.arraycopy(cur, 0, arr, 1, cur.length);
+			arr[0] = new PackFile(this, idx, pack);
+			packFileList = arr;
+		}
 	}
 
 	/**
@@ -808,11 +825,13 @@ public void openPack(final File pack, final File idx) throws IOException {
 	 */
 	public void scanForPacks() {
 		final ArrayList<PackFile> p = new ArrayList<PackFile>();
-		for (int i=0; i<objectsDirs.length; ++i)
-			scanForPacks(new File(objectsDirs[i], "pack"), p);
+		for (final File d : objectsDirs())
+			scanForPacks(new File(d, "pack"), p);
 		final PackFile[] arr = new PackFile[p.size()];
 		p.toArray(arr);
-		packs = arr;
+		synchronized (this) {
+			packFileList = arr;
+		}
 	}
 
 	private void scanForPacks(final File packDir, Collection<PackFile> packList) {
-- 
1.6.1.rc4.301.g5497a

--
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]

  Powered by Linux