src/main/java/com/gitblit/manager/GitblitManager.java
@@ -1099,4 +1099,19 @@ public boolean deletePendingFederationProposal(FederationProposal proposal) { return federationManager.deletePendingFederationProposal(proposal); } @Override public void closeAll() { repositoryManager.closeAll(); } @Override public void close(String repository) { repositoryManager.close(repository); } @Override public boolean isIdle(Repository repository) { return repositoryManager.isIdle(repository); } } src/main/java/com/gitblit/manager/IRepositoryManager.java
@@ -393,4 +393,23 @@ */ boolean isCollectingGarbage(String repositoryName); /** * Ensures that all cached repositories are completely closed and their resources * are properly released. */ void closeAll(); /** * Ensures that a cached repository is completely closed and it's resources * are properly released. */ void close(String repository); /** * Returns true if the repository is idle (not being accessed). * * @param repository * @return true if the repository is idle */ boolean isIdle(Repository repository); } src/main/java/com/gitblit/manager/RepositoryManager.java
@@ -169,6 +169,7 @@ gcExecutor.close(); mirrorExecutor.close(); closeAll(); return this; } @@ -1084,12 +1085,49 @@ } /** * Returns true if the repository is idle (not being accessed). * * @param repository * @return true if the repository is idle */ @Override public boolean isIdle(Repository repository) { try { // Read the use count. // An idle use count is 2: // +1 for being in the cache // +1 for the repository parameter in this method Field useCnt = Repository.class.getDeclaredField("useCnt"); useCnt.setAccessible(true); int useCount = ((AtomicInteger) useCnt.get(repository)).get(); return useCount == 2; } catch (Exception e) { logger.warn(MessageFormat .format("Failed to reflectively determine use count for repository {0}", repository.getDirectory().getPath()), e); } return false; } /** * Ensures that all cached repository are completely closed and their resources * are properly released. */ @Override public void closeAll() { for (String repository : getRepositoryList()) { close(repository); } } /** * Ensure that a cached repository is completely closed and its resources * are properly released. * * @param repositoryName */ private void closeRepository(String repositoryName) { @Override public void close(String repositoryName) { Repository repository = getRepository(repositoryName); if (repository == null) { return; @@ -1114,7 +1152,7 @@ repositoryName), e); } if (uses > 0) { logger.info(MessageFormat logger.debug(MessageFormat .format("{0}.useCnt={1}, calling close() {2} time(s) to close object and ref databases", repositoryName, uses, uses)); for (int i = 0; i < uses; i++) { @@ -1252,7 +1290,7 @@ "Failed to rename ''{0}'' because ''{1}'' already exists.", repositoryName, repository.name)); } closeRepository(repositoryName); close(repositoryName); File folder = new File(repositoriesFolder, repositoryName); File destFolder = new File(repositoriesFolder, repository.name); if (destFolder.exists()) { @@ -1477,7 +1515,7 @@ @Override public boolean deleteRepository(String repositoryName) { try { closeRepository(repositoryName); close(repositoryName); // clear the repository cache clearRepositoryMetadataCache(repositoryName); src/main/java/com/gitblit/service/GarbageCollectorService.java
@@ -15,7 +15,6 @@ */ package com.gitblit.service; import java.lang.reflect.Field; import java.text.MessageFormat; import java.util.Calendar; import java.util.Date; @@ -23,7 +22,6 @@ import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jgit.api.GarbageCollectCommand; import org.eclipse.jgit.api.Git; @@ -33,7 +31,6 @@ import com.gitblit.IStoredSettings; import com.gitblit.Keys; import com.gitblit.Keys.git; import com.gitblit.manager.IRepositoryManager; import com.gitblit.models.RepositoryModel; import com.gitblit.utils.FileUtils; @@ -160,7 +157,7 @@ continue; } if (!isRepositoryIdle(repository)) { if (!repositoryManager.isIdle(repository)) { logger.debug(MessageFormat.format("GCExecutor is skipping {0} because it is not idle", repositoryName)); continue; } @@ -227,23 +224,5 @@ } running.set(false); } private boolean isRepositoryIdle(Repository repository) { try { // Read the use count. // An idle use count is 2: // +1 for being in the cache // +1 for the repository parameter in this method Field useCnt = Repository.class.getDeclaredField("useCnt"); useCnt.setAccessible(true); int useCount = ((AtomicInteger) useCnt.get(repository)).get(); return useCount == 2; } catch (Exception e) { logger.warn(MessageFormat .format("Failed to reflectively determine use count for repository {0}", repository.getDirectory().getPath()), e); } return false; } }