Mercurial > hg > mercurial
changeset 372:2869f49b9211
TW-17252 handle mercurial caches correctly
author | Dmitry Neverov <dmitry.neverov@jetbrains.com> |
---|---|
date | Thu, 09 Feb 2012 12:58:53 +0400 |
parents | 24d926f22e85 |
children | 1350f99b43bc |
files | mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerImpl.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialResetCacheHandler.java mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialResetCacheHandlerTest.java mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java mercurial-tests/src/testng.xml |
diffstat | 6 files changed, 208 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerImpl.java Wed Feb 08 16:45:14 2012 +0400 +++ b/mercurial-common/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MirrorManagerImpl.java Thu Feb 09 12:58:53 2012 +0400 @@ -77,14 +77,19 @@ @NotNull public Map<String, File> getMappings() { - return new HashMap<String, File>(myMirrors); + myLock.readLock().lock(); + try { + return new HashMap<String, File>(myMirrors); + } finally { + myLock.readLock().unlock(); + } } public void lockDir(@NotNull final File dir) { lockFor(dir).lock(); } - public void unlockDir(@NotNull File dir) { + public void unlockDir(@NotNull final File dir) { lockFor(dir).unlock(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialResetCacheHandler.java Thu Feb 09 12:58:53 2012 +0400 @@ -0,0 +1,88 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import com.intellij.openapi.diagnostic.Logger; +import jetbrains.buildServer.util.cache.ResetCacheHandler; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; + +import static com.intellij.openapi.util.io.FileUtil.delete; +import static java.util.Collections.singletonList; + +/** + * @author dmitry.neverov + */ +public class MercurialResetCacheHandler implements ResetCacheHandler { + + private static Logger LOG = Logger.getInstance(MercurialResetCacheHandler.class.getName()); + private static final String MERCURIAL_CACHE_NAME = "mercurial"; + + private final MirrorManager myMirrorManager; + private AtomicBoolean myResetRunning = new AtomicBoolean(false); + + public MercurialResetCacheHandler(@NotNull MirrorManager mirrorManager) { + myMirrorManager = mirrorManager; + } + + @NotNull + public List<String> listCaches() { + return singletonList(MERCURIAL_CACHE_NAME); + } + + public boolean isEmpty(@NotNull final String cache) { + return myMirrorManager.getMappings().isEmpty(); + } + + public void resetCache(@NotNull final String cache) { + boolean started = startReset(); + if (!started) { + LOG.info("Mercurial mirrors reset is already running"); + return; + } + resetAllMirrors(); + finishReset(); + } + + private boolean startReset() { + return myResetRunning.compareAndSet(false, true); + } + + private void finishReset() { + myResetRunning.set(false); + } + + private void resetAllMirrors() { + LOG.info("Start reseting mercurial caches"); + for (Map.Entry<String, File> entry : myMirrorManager.getMappings().entrySet()) { + String url = entry.getKey(); + File mirror = entry.getValue(); + try { + lockMirror(url, mirror); + resetMirror(mirror); + } finally { + unlockMirror(url, mirror); + } + } + LOG.info("Mercurial caches reseted"); + } + + private void lockMirror(@NotNull final String url, @NotNull final File mirror) { + LOG.debug("Lock mirror of " + url); + myMirrorManager.lockDir(mirror); + LOG.debug("Mirror of " + url + " is locked"); + } + + private void resetMirror(@NotNull final File mirror) { + LOG.debug("Reset mercurial mirror " + mirror.getAbsolutePath()); + myMirrorManager.forgetDir(mirror); + delete(mirror); + LOG.debug("Mercurial mirror " + mirror.getAbsolutePath() + " reseted"); + } + + private void unlockMirror(@NotNull final String url, @NotNull final File mirror) { + myMirrorManager.unlockDir(mirror); + LOG.debug("Mirror of " + url + " is unlocked"); + } +}
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Wed Feb 08 16:45:14 2012 +0400 +++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialVcsSupport.java Thu Feb 09 12:58:53 2012 +0400 @@ -24,6 +24,7 @@ import jetbrains.buildServer.util.EventDispatcher; import jetbrains.buildServer.util.FileUtil; import jetbrains.buildServer.util.StringUtil; +import jetbrains.buildServer.util.cache.ResetCacheRegister; import jetbrains.buildServer.vcs.*; import jetbrains.buildServer.vcs.impl.VcsRootImpl; import jetbrains.buildServer.vcs.patches.PatchBuilder; @@ -63,6 +64,7 @@ public MercurialVcsSupport(@NotNull final VcsManager vcsManager, @NotNull final SBuildServer server, @NotNull final EventDispatcher<BuildServerListener> dispatcher, + @NotNull final ResetCacheRegister resetCacheHandlerManager, @NotNull final ServerPluginConfig config, @NotNull final HgPathProvider hgPathProvider, @NotNull final CommandFactory commandFactory, @@ -73,6 +75,7 @@ myMirrorManager = mirrorManager; myHgPathProvider = hgPathProvider; myCommandFactory = commandFactory; + resetCacheHandlerManager.registerHandler(new MercurialResetCacheHandler(myMirrorManager)); dispatcher.addListener(new BuildServerAdapter() { @Override public void cleanupFinished() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialResetCacheHandlerTest.java Thu Feb 09 12:58:53 2012 +0400 @@ -0,0 +1,107 @@ +package jetbrains.buildServer.buildTriggers.vcs.mercurial; + +import jetbrains.buildServer.TempFiles; +import jetbrains.buildServer.util.cache.ResetCacheHandler; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.jmock.States; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Arrays.asList; +import static java.util.Collections.emptyMap; +import static org.testng.AssertJUnit.*; + +/** + * @author dmitry.neverov + */ +@Test +public class MercurialResetCacheHandlerTest { + + private Mockery myContext; + private TempFiles myTempFiles; + private File myCachesDir; + private MirrorManager myMirrorManager; + private ResetCacheHandler myCacheHandler; + + @BeforeMethod + public void setUp() throws IOException { + myContext = new Mockery(); + myTempFiles = new TempFiles(); + myCachesDir = myTempFiles.createTempDir(); + myMirrorManager = myContext.mock(MirrorManager.class); + myCacheHandler = new MercurialResetCacheHandler(myMirrorManager); + } + + @AfterMethod + public void tearDown() { + myTempFiles.cleanup(); + } + + + public void cache_list_should_contains_entry_for_mercurial_in_general() { + assertEquals(asList("mercurial"), myCacheHandler.listCaches()); + } + + + public void mercurial_cache_is_empty_when_there_are_no_mirrors() { + myContext.checking(new Expectations() {{ + atLeast(1).of(myMirrorManager).getMappings(); will(returnValue(emptyMap())); + }}); + + assertTrue(myCacheHandler.isEmpty("mercurial")); + myContext.assertIsSatisfied(); + } + + + public void mercurial_cache_is_not_empty_when_mirrors_exist() { + final Map<String, File> mapping = new HashMap<String, File>() {{ + put("http://some.org/repository1", new File(myCachesDir, "a")); + put("http://some.org/repository2", new File(myCachesDir, "b")); + }}; + myContext.checking(new Expectations() {{ + atLeast(1).of(myMirrorManager).getMappings(); will(returnValue(mapping)); + }}); + + assertFalse(myCacheHandler.isEmpty("mercurial")); + myContext.assertIsSatisfied(); + } + + + public void reset_cache_should_reset_caches_for_all_mirrors() { + final String url1 = "http://some.org/repository1"; + final String url2 = "http://some.org/repository2"; + final File mirror1 = new File(myCachesDir, "a"); + final File mirror2 = new File(myCachesDir, "b"); + mirror1.mkdirs(); + mirror2.mkdirs(); + final Map<String, File> mapping = new HashMap<String, File>() {{ + put(url1, mirror1); + put(url2, mirror2); + }}; + final States stateOfMirror1 = myContext.states("mirror1").startsAs("initial"); + final States stateOfMirror2 = myContext.states("mirror2").startsAs("initial"); + myContext.checking(new Expectations() {{ + atLeast(1).of(myMirrorManager).getMappings(); will(returnValue(mapping)); + + one(myMirrorManager).lockDir(mirror1); when(stateOfMirror1.is("initial")); then(stateOfMirror1.is("locked")); + one(myMirrorManager).lockDir(mirror2); when(stateOfMirror2.is("initial")); then(stateOfMirror2.is("locked")); + + one(myMirrorManager).forgetDir(mirror1); when(stateOfMirror1.is("locked")); then(stateOfMirror1.is("reseted")); + one(myMirrorManager).forgetDir(mirror2); when(stateOfMirror2.is("locked")); then(stateOfMirror2.is("reseted")); + + one(myMirrorManager).unlockDir(mirror1); when(stateOfMirror1.is("reseted")); + one(myMirrorManager).unlockDir(mirror2); when(stateOfMirror2.is("reseted")); + }}); + + myCacheHandler.resetCache("mercurial"); + myContext.assertIsSatisfied(); + assertTrue(myCachesDir.listFiles().length == 0); + } +}
--- a/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java Wed Feb 08 16:45:14 2012 +0400 +++ b/mercurial-tests/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/Util.java Thu Feb 09 12:58:53 2012 +0400 @@ -3,6 +3,7 @@ import jetbrains.buildServer.serverSide.BuildServerListener; import jetbrains.buildServer.serverSide.SBuildServer; import jetbrains.buildServer.util.EventDispatcher; +import jetbrains.buildServer.util.cache.ResetCacheRegister; import jetbrains.buildServer.vcs.VcsManager; import org.jetbrains.annotations.NotNull; import org.jmock.Expectations; @@ -43,6 +44,6 @@ allowing(server).getExecutor(); will(returnValue(executor)); }}); EventDispatcher<BuildServerListener> dispatcher = EventDispatcher.create(BuildServerListener.class); - return new MercurialVcsSupport(vcsManager, server, dispatcher, config, new ServerHgPathProvider(config), commandFactory, new MirrorManagerImpl(config)); + return new MercurialVcsSupport(vcsManager, server, dispatcher, new ResetCacheRegister(), config, new ServerHgPathProvider(config), commandFactory, new MirrorManagerImpl(config)); } }
--- a/mercurial-tests/src/testng.xml Wed Feb 08 16:45:14 2012 +0400 +++ b/mercurial-tests/src/testng.xml Thu Feb 09 12:58:53 2012 +0400 @@ -21,6 +21,7 @@ <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.DagFeaturesTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.UnrelatedResitoriesTest"/> <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.CleanupTest"/> + <class name="jetbrains.buildServer.buildTriggers.vcs.mercurial.MercurialResetCacheHandlerTest"/> </classes> </test> </suite>