diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java index 6c6292558..a1cec2d91 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java @@ -173,4 +173,39 @@ public class RepositoryCacheTest extends RepositoryTestCase { assertEquals(0, RepositoryCache.getRegisteredKeys().size()); } + @Test + public void testRepositoryUsageCount() throws Exception { + FileKey loc = FileKey.exact(db.getDirectory(), db.getFS()); + Repository d2 = RepositoryCache.open(loc); + assertEquals(1, d2.useCnt.get()); + RepositoryCache.open(FileKey.exact(loc.getFile(), db.getFS())); + assertEquals(2, d2.useCnt.get()); + d2.close(); + assertEquals(1, d2.useCnt.get()); + d2.close(); + assertEquals(0, d2.useCnt.get()); + } + + @Test + public void testRepositoryUsageCountWithRegisteredRepository() { + assertEquals(1, ((Repository) db).useCnt.get()); + RepositoryCache.register(db); + assertEquals(1, ((Repository) db).useCnt.get()); + db.close(); + assertEquals(0, ((Repository) db).useCnt.get()); + } + + public void testRepositoryUnregisteringWhenClosing() throws Exception { + FileKey loc = FileKey.exact(db.getDirectory(), db.getFS()); + Repository d2 = RepositoryCache.open(loc); + assertEquals(1, d2.useCnt.get()); + assertThat(RepositoryCache.getRegisteredKeys(), + hasItem(FileKey.exact(db.getDirectory(), db.getFS()))); + assertEquals(1, RepositoryCache.getRegisteredKeys().size()); + + d2.close(); + + assertEquals(0, d2.useCnt.get()); + assertEquals(0, RepositoryCache.getRegisteredKeys().size()); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java index b8c2fb4a5..6f3166a68 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java @@ -203,10 +203,10 @@ public class RefDirectory extends RefDatabase { @Override public void close() { - // We have no resources to close. + clearReferences(); } - void rescan() { + private void clearReferences() { looseRefs.set(RefList. emptyList()); packedRefs.set(PackedRefList.NO_PACKED_REFS); } @@ -214,7 +214,7 @@ public class RefDirectory extends RefDatabase { @Override public void refresh() { super.refresh(); - rescan(); + clearReferences(); } @Override diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index f8266133a..ba0dea39f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -110,7 +110,8 @@ public abstract class Repository implements AutoCloseable { return globalListeners; } - private final AtomicInteger useCnt = new AtomicInteger(1); + /** Use counter */ + final AtomicInteger useCnt = new AtomicInteger(1); /** Metadata directory holding the repository's critical files. */ private final File gitDir; @@ -864,6 +865,7 @@ public abstract class Repository implements AutoCloseable { public void close() { if (useCnt.decrementAndGet() == 0) { doClose(); + RepositoryCache.unregister(this); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java index 23cc264c1..22b5fcd11 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java @@ -130,10 +130,10 @@ public class RepositoryCache { } /** - * Remove a repository from the cache. + * Close and remove a repository from the cache. *

- * Removes a repository from the cache, if it is still registered here, - * permitting it to close. + * Removes a repository from the cache, if it is still registered here, and + * close it. * * @param db * repository to unregister. @@ -141,15 +141,35 @@ public class RepositoryCache { public static void close(final Repository db) { if (db.getDirectory() != null) { FileKey key = FileKey.exact(db.getDirectory(), db.getFS()); - cache.unregisterRepository(key); + cache.unregisterAndCloseRepository(key); } } /** * Remove a repository from the cache. *

- * Removes a repository from the cache, if it is still registered here, - * permitting it to close. + * Removes a repository from the cache, if it is still registered here. This + * method will not close the repository, only remove it from the cache. See + * {@link RepositoryCache#close(Repository)} to remove and close the + * repository. + * + * @param db + * repository to unregister. + * @since 4.3 + */ + public static void unregister(final Repository db) { + if (db.getDirectory() != null) { + unregister(FileKey.exact(db.getDirectory(), db.getFS())); + } + } + + /** + * Remove a repository from the cache. + *

+ * Removes a repository from the cache, if it is still registered here. This + * method will not close the repository, only remove it from the cache. See + * {@link RepositoryCache#close(Repository)} to remove and close the + * repository. * * @param location * location of the repository to remove. @@ -196,15 +216,17 @@ public class RepositoryCache { db = location.open(mustExist); ref = new SoftReference(db); cacheMap.put(location, ref); + } else { + db.incrementOpen(); } } + } else { + db.incrementOpen(); } - db.incrementOpen(); return db; } private void registerRepository(final Key location, final Repository db) { - db.incrementOpen(); SoftReference newRef = new SoftReference(db); Reference oldRef = cacheMap.put(location, newRef); Repository oldDb = oldRef != null ? oldRef.get() : null; @@ -212,11 +234,16 @@ public class RepositoryCache { oldDb.close(); } - private void unregisterRepository(final Key location) { + private Repository unregisterRepository(final Key location) { Reference oldRef = cacheMap.remove(location); - Repository oldDb = oldRef != null ? oldRef.get() : null; - if (oldDb != null) + return oldRef != null ? oldRef.get() : null; + } + + private void unregisterAndCloseRepository(final Key location) { + Repository oldDb = unregisterRepository(location); + if (oldDb != null) { oldDb.close(); + } } private Collection getKeys() {