From 94b8fb5a1980e493e52fd56c9b97147f89be8689 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Wed, 14 Oct 2009 18:05:53 -0400 Subject: [PATCH] Fix global lock implementation for ComponentManager --- ivy/ComponentManager.scala | 27 +++++-------------- ivy/IvyCache.scala | 2 +- ivy/src/test/scala/ComponentManagerTest.scala | 2 +- 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/ivy/ComponentManager.scala b/ivy/ComponentManager.scala index 483a0bb31..0056ace7a 100644 --- a/ivy/ComponentManager.scala +++ b/ivy/ComponentManager.scala @@ -1,7 +1,7 @@ package xsbt import java.io.{File,FileOutputStream} -import ComponentManager.lock +import java.util.concurrent.Callable /** A component manager provides access to the pieces of xsbt that are distributed as components. * There are two types of components. The first type is compiled subproject jars with their dependencies. @@ -12,7 +12,7 @@ import ComponentManager.lock * This is used for compiled source jars so that the compilation need not be repeated for other projects on the same * machine. */ -class ComponentManager(provider: xsbti.ComponentProvider, val log: IvyLogger) extends NotNull +class ComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentProvider, val log: IvyLogger) extends NotNull { /** Get all of the files for component 'id', throwing an exception if no files exist for the component. */ def files(id: String)(ifMissing: IfMissing): Iterable[File] = @@ -36,11 +36,12 @@ class ComponentManager(provider: xsbti.ComponentProvider, val log: IvyLogger) ex if(d.cache) cache(id) getOrElse(notFound) } - + lockLocalCache { getOrElse(fromGlobal) } } - private def lockLocalCache[T](action: => T): T = lock("local cache", provider.lockFile, log) ( action ) - private def lockGlobalCache[T](action: => T): T = lock("global cache", IvyCache.lockFile, log)( action ) + private def lockLocalCache[T](action: => T): T = lock(provider.lockFile)( action ) + private def lockGlobalCache[T](action: => T): T = lock(IvyCache.lockFile)( action ) + private def lock[T](file: File)(action: => T): T = globalLock(file, new Callable[T] { def call = action }) /** Get the file for component 'id', throwing an exception if no files or multiple files exist for the component. */ def file(id: String)(ifMissing: IfMissing): File = files(id)(ifMissing).toList match { @@ -68,20 +69,4 @@ object IfMissing { object Fail extends IfMissing final class Define(val cache: Boolean, define: => Unit) extends IfMissing { def apply() = define } -} -object ComponentManager -{ - def lock[T](label: String, file: File, log: IvyLogger)(action: => T): T = - { - synchronized { - val channel = new FileOutputStream(file).getChannel - try { - val freeLock = channel.tryLock - val lock = if(freeLock eq null) { log.info("Waiting for " + label + " to be available..."); channel.lock } else freeLock - try { action } - finally { lock.release() } - } - finally { channel.close() } - } - } } \ No newline at end of file diff --git a/ivy/IvyCache.scala b/ivy/IvyCache.scala index 74c27e3e8..e3f0044bc 100644 --- a/ivy/IvyCache.scala +++ b/ivy/IvyCache.scala @@ -27,7 +27,7 @@ private object NotInCache /** Provides methods for working at the level of a single jar file with the default Ivy cache.*/ object IvyCache { - def lockFile = new File(System.getProperty("temp.dir"), "sbt.cache.lock") + def lockFile = new File(System.getProperty("java.io.tmpdir"), "sbt.cache.lock") /** Caches the given 'file' with the given ID. It may be retrieved or cleared using this ID.*/ def cacheJar(moduleID: ModuleID, file: File, log: IvyLogger) { diff --git a/ivy/src/test/scala/ComponentManagerTest.scala b/ivy/src/test/scala/ComponentManagerTest.scala index 90613ce1e..446cec24e 100644 --- a/ivy/src/test/scala/ComponentManagerTest.scala +++ b/ivy/src/test/scala/ComponentManagerTest.scala @@ -77,5 +77,5 @@ object ComponentManagerTest extends Specification private def writeRandomContent(file: File) = FileUtilities.write(file, randomString) private def randomString = "asdf" private def withManager[T](f: ComponentManager => T): T = - TestIvyLogger( logger => withTemporaryDirectory { temp => f(new ComponentManager(new xsbt.boot.ComponentProvider(temp), logger)) } ) + TestIvyLogger( logger => withTemporaryDirectory { temp => f(new ComponentManager(xsbt.boot.Locks, new xsbt.boot.ComponentProvider(temp), logger)) } ) } \ No newline at end of file