Merge branch 'master' into stable-4.3

* master:
  Remove repository from cache when it's closed
  Fix RefDirectory not closing resources
  Fix repository cache never closing repository

Change-Id: I9dc9d017806cba25125f69b53812cc3e062ef975
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
This commit is contained in:
Matthias Sohn 2016-04-07 13:06:14 +02:00
commit 27d06cb8d5
4 changed files with 79 additions and 15 deletions

View File

@ -173,4 +173,39 @@ public void testUnregister() {
assertEquals(0, RepositoryCache.getRegisteredKeys().size()); 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());
}
} }

View File

@ -203,10 +203,10 @@ public void create() throws IOException {
@Override @Override
public void close() { public void close() {
// We have no resources to close. clearReferences();
} }
void rescan() { private void clearReferences() {
looseRefs.set(RefList.<LooseRef> emptyList()); looseRefs.set(RefList.<LooseRef> emptyList());
packedRefs.set(PackedRefList.NO_PACKED_REFS); packedRefs.set(PackedRefList.NO_PACKED_REFS);
} }
@ -214,7 +214,7 @@ void rescan() {
@Override @Override
public void refresh() { public void refresh() {
super.refresh(); super.refresh();
rescan(); clearReferences();
} }
@Override @Override

View File

@ -110,7 +110,8 @@ public static ListenerList getGlobalListenerList() {
return globalListeners; 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. */ /** Metadata directory holding the repository's critical files. */
private final File gitDir; private final File gitDir;
@ -864,6 +865,7 @@ public void incrementOpen() {
public void close() { public void close() {
if (useCnt.decrementAndGet() == 0) { if (useCnt.decrementAndGet() == 0) {
doClose(); doClose();
RepositoryCache.unregister(this);
} }
} }

View File

@ -130,10 +130,10 @@ public static void register(final Repository db) {
} }
/** /**
* Remove a repository from the cache. * Close and remove a repository from the cache.
* <p> * <p>
* Removes a repository from the cache, if it is still registered here, * Removes a repository from the cache, if it is still registered here, and
* permitting it to close. * close it.
* *
* @param db * @param db
* repository to unregister. * repository to unregister.
@ -141,15 +141,35 @@ public static void register(final Repository db) {
public static void close(final Repository db) { public static void close(final Repository db) {
if (db.getDirectory() != null) { if (db.getDirectory() != null) {
FileKey key = FileKey.exact(db.getDirectory(), db.getFS()); FileKey key = FileKey.exact(db.getDirectory(), db.getFS());
cache.unregisterRepository(key); cache.unregisterAndCloseRepository(key);
} }
} }
/** /**
* Remove a repository from the cache. * Remove a repository from the cache.
* <p> * <p>
* Removes a repository from the cache, if it is still registered here, * Removes a repository from the cache, if it is still registered here. This
* permitting it to close. * 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.
* <p>
* 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 * @param location
* location of the repository to remove. * location of the repository to remove.
@ -196,15 +216,17 @@ private Repository openRepository(final Key location,
db = location.open(mustExist); db = location.open(mustExist);
ref = new SoftReference<Repository>(db); ref = new SoftReference<Repository>(db);
cacheMap.put(location, ref); cacheMap.put(location, ref);
} } else {
}
}
db.incrementOpen(); db.incrementOpen();
}
}
} else {
db.incrementOpen();
}
return db; return db;
} }
private void registerRepository(final Key location, final Repository db) { private void registerRepository(final Key location, final Repository db) {
db.incrementOpen();
SoftReference<Repository> newRef = new SoftReference<Repository>(db); SoftReference<Repository> newRef = new SoftReference<Repository>(db);
Reference<Repository> oldRef = cacheMap.put(location, newRef); Reference<Repository> oldRef = cacheMap.put(location, newRef);
Repository oldDb = oldRef != null ? oldRef.get() : null; Repository oldDb = oldRef != null ? oldRef.get() : null;
@ -212,12 +234,17 @@ private void registerRepository(final Key location, final Repository db) {
oldDb.close(); oldDb.close();
} }
private void unregisterRepository(final Key location) { private Repository unregisterRepository(final Key location) {
Reference<Repository> oldRef = cacheMap.remove(location); Reference<Repository> oldRef = cacheMap.remove(location);
Repository oldDb = oldRef != null ? oldRef.get() : null; return oldRef != null ? oldRef.get() : null;
if (oldDb != null) }
private void unregisterAndCloseRepository(final Key location) {
Repository oldDb = unregisterRepository(location);
if (oldDb != null) {
oldDb.close(); oldDb.close();
} }
}
private Collection<Key> getKeys() { private Collection<Key> getKeys() {
return new ArrayList<Key>(cacheMap.keySet()); return new ArrayList<Key>(cacheMap.keySet());