git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Shawn O. Pearce" <spearce@spearce.org>
To: Robin Rosenberg <robin.rosenberg@dewire.com>
Cc: git@vger.kernel.org
Subject: [JGIT PATCH 06/13] Make Repository thread-safe
Date: Mon, 22 Dec 2008 16:27:16 -0800	[thread overview]
Message-ID: <1229992043-1053-7-git-send-email-spearce@spearce.org> (raw)
In-Reply-To: <1229992043-1053-6-git-send-email-spearce@spearce.org>

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@spearce.org>
---
 .../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

  reply	other threads:[~2008-12-23  0:30 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-23  0:27 [JGIT PATCH 00/13] Add receive-pack server side support Shawn O. Pearce
2008-12-23  0:27 ` [JGIT PATCH 01/13] Fix invalid "double checked locking" in InflaterCache Shawn O. Pearce
2008-12-23  0:27   ` [JGIT PATCH 02/13] Cleanup stupid release of the cached Inflater in IndexPack Shawn O. Pearce
2008-12-23  0:27     ` [JGIT PATCH 03/13] Cache an Inflater inside a WindowCursor and reuse it as much as possible Shawn O. Pearce
2008-12-23  0:27       ` [JGIT PATCH 04/13] Make RefDatabase thread-safe Shawn O. Pearce
2008-12-23  0:27         ` [JGIT PATCH 05/13] Make PackFile thread-safe Shawn O. Pearce
2008-12-23  0:27           ` Shawn O. Pearce [this message]
2008-12-23  0:27             ` [JGIT PATCH 07/13] Don't open a PackFile multiple times on scanForPacks Shawn O. Pearce
2008-12-23  0:27               ` [JGIT PATCH 08/13] Expose RepositoryConfig.getBoolean so applications can use it Shawn O. Pearce
2008-12-23  0:27                 ` [JGIT PATCH 09/13] Add AnyObjectId.copyTo(StringBuilder) Shawn O. Pearce
2008-12-23  0:27                   ` [JGIT PATCH 10/13] Add compare-and-swap semantics to RefUpdate Shawn O. Pearce
2008-12-23  0:27                     ` [JGIT PATCH 11/13] Allow null new ObjectId during RefUpdate.delete Shawn O. Pearce
2008-12-23  0:27                       ` [JGIT PATCH 12/13] Implement the git-receive-pack process in Java Shawn O. Pearce
2008-12-23  0:27                         ` [JGIT PATCH 13/13] Add basic git daemon support to publish receive-pack Shawn O. Pearce
2009-01-03 23:48                           ` Robin Rosenberg
2009-01-05  2:46                             ` [PATCH] Permit a wider range of repository names in jgit daemon requests Shawn O. Pearce
2009-01-05 23:07                               ` Robin Rosenberg

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=1229992043-1053-7-git-send-email-spearce@spearce.org \
    --to=spearce@spearce.org \
    --cc=git@vger.kernel.org \
    --cc=robin.rosenberg@dewire.com \
    /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).