diff options
author | Paul Phillips <paulp@improving.org> | 2009-08-24 01:07:45 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-08-24 01:07:45 +0000 |
commit | db8c41b53586961f10c2ba3a48ad14fa622d507f (patch) | |
tree | d3bb02c75e0e4eb3b63e6a1c97450c8e23d818c1 | |
parent | 0f7296a008e0e4090e69b489c23a492df26fd4f6 (diff) | |
download | scala-db8c41b53586961f10c2ba3a48ad14fa622d507f.tar.gz scala-db8c41b53586961f10c2ba3a48ad14fa622d507f.tar.bz2 scala-db8c41b53586961f10c2ba3a48ad14fa622d507f.zip |
Taking a little more advantage of some recent a...
Taking a little more advantage of some recent abstractions.
-rw-r--r-- | src/compiler/scala/tools/nsc/CompileServer.scala | 50 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/CompileSocket.scala | 48 | ||||
-rw-r--r-- | src/compiler/scala/tools/util/SocketServer.scala | 77 | ||||
-rw-r--r-- | src/library/scala/io/File.scala | 7 |
4 files changed, 96 insertions, 86 deletions
diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index 010d183bc8..7cd4be214a 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -6,10 +6,9 @@ package scala.tools.nsc -import java.io.{BufferedOutputStream, File, FileOutputStream, PrintStream} -import java.lang.{Runtime, System, Thread} +import java.io.{ BufferedOutputStream, FileOutputStream, PrintStream, File => JFile } +import scala.io.File -import scala.concurrent.ops.spawn import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import scala.tools.nsc.util.FakePos //Position import scala.tools.util.SocketServer @@ -22,7 +21,8 @@ import scala.tools.util.SocketServer * @author Martin Odersky * @version 1.0 */ -class StandardCompileServer extends SocketServer { +class StandardCompileServer extends SocketServer +{ def compileSocket: CompileSocket = CompileSocket // todo: make this a lazy val val versionMsg = "Fast Scala compiler " + @@ -44,6 +44,7 @@ class StandardCompileServer extends SocketServer { } private val runtime = Runtime.getRuntime() + import runtime.{ totalMemory, freeMemory, maxMemory } var reporter: ConsoleReporter = _ @@ -54,24 +55,31 @@ class StandardCompileServer extends SocketServer { } override def timeout() { - if (!compileSocket.portFile(port).exists()) + if (!compileSocket.portFile(port).file.exists()) fatal("port file no longer exists; skipping cleanup") } + def printMemoryStats() { + System.out.println("New session, total memory = %s, max memory = %s, free memory = %s".format( + totalMemory, maxMemory, freeMemory)) + System.out.flush() + } + + def isMemoryFullEnough() = { + runtime.gc() + (totalMemory - freeMemory).toDouble / maxMemory.toDouble > MaxCharge + } + protected def newOfflineCompilerCommand( arguments: List[String], settings: Settings, error: String => Unit, - interactive: Boolean) - = new OfflineCompilerCommand(arguments, settings, error, interactive) + interactive: Boolean + ) = new OfflineCompilerCommand(arguments, settings, error, interactive) def session() { - System.out.println("New session" + - ", total memory = "+ runtime.totalMemory() + - ", max memory = " + runtime.maxMemory() + - ", free memory = " + runtime.freeMemory) - System.out.flush() - val password = compileSocket.getPassword(port) + printMemoryStats() + val password = compileSocket getPassword port val guessedPassword = in.readLine() val input = in.readLine() if ((input ne null) && password == guessedPassword) { @@ -127,24 +135,18 @@ class StandardCompileServer extends SocketServer { shutDown = true } reporter.printSummary() - runtime.gc() - if ((runtime.totalMemory() - runtime.freeMemory()).toDouble / - runtime.maxMemory().toDouble > MaxCharge) compiler = null + if (isMemoryFullEnough) + compiler = null } } } /** A directory holding redirected output */ - private val redirectDir = new File(compileSocket.tmpDir, "output-redirects") + private val redirectDir = File(compileSocket.tmpDir) / "output-redirects" redirectDir.mkdirs - private def redirect(setter: PrintStream => Unit, filename: String) { - setter( - new PrintStream( - new BufferedOutputStream( - new FileOutputStream( - new File(redirectDir, filename))))) - } + private def redirect(setter: PrintStream => Unit, filename: String): Unit = + setter(new PrintStream(redirectDir / filename bufferedOutput())) def main(args: Array[String]) { redirect(System.setOut, "scala-compile-server-out.log") diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala index 42b91a59ad..fb4d4c50dc 100644 --- a/src/compiler/scala/tools/nsc/CompileSocket.scala +++ b/src/compiler/scala/tools/nsc/CompileSocket.scala @@ -6,10 +6,16 @@ package scala.tools.nsc -import java.io.{ File, IOException, FileNotFoundException, PrintWriter, FileOutputStream } +import java.io.{ IOException, FileNotFoundException, PrintWriter, FileOutputStream } import java.io.{ BufferedReader, FileReader } import java.util.regex.Pattern import java.net._ +import java.security.SecureRandom + +import scala.io.File +import scala.util.control.Exception.catching + +// class CompileChannel { } /** This class manages sockets for the fsc offline compiler. */ class CompileSocket { @@ -26,7 +32,7 @@ class CompileSocket { protected val vmCommand = Properties.scalaHome match { case null => cmdName case dirname => - val trial = scala.io.File(dirname) / "bin" / cmdName + val trial = File(dirname) / "bin" / cmdName if (trial.canRead) trial.path else cmdName } @@ -53,7 +59,7 @@ class CompileSocket { /** A temporary directory to use */ val tmpDir = { val udir = Option(Properties.userName) getOrElse "shared" - val f = (scala.io.File(Properties.tmpDir) / "scala-devel" / udir).file + val f = (File(Properties.tmpDir) / "scala-devel" / udir).file f.mkdirs() if (f.isDirectory && f.canWrite) { @@ -64,7 +70,7 @@ class CompileSocket { } /* A directory holding port identification files */ - val portsDir = new File(tmpDir, dirName) + val portsDir = File(tmpDir) / dirName portsDir.mkdirs /** Maximum number of polls for an available port */ @@ -97,24 +103,16 @@ class CompileSocket { } /** The port identification file */ - def portFile(port: Int) = new File(portsDir, port.toString()) + def portFile(port: Int) = portsDir / port.toString /** Poll for a server port number; return -1 if none exists yet */ - private def pollPort(): Int = { - val hits = portsDir.listFiles() - if (hits.length == 0) -1 - else - try { - for (i <- 1 until hits.length) hits(i).delete() - hits(0).getName.toInt - } catch { - case ex: NumberFormatException => - fatal(ex.toString() + - "\nbad file in temp directory: " + - hits(0).getAbsolutePath() + - "\nplease remove the file and try again") - } - } + private def pollPort(): Int = + portsDir.iterator.toList match { + case Nil => -1 + case p :: xs => + xs forall (_.delete()) + p.name.toInt + } /** Get the port number to which a scala compile server is connected; * If no server is running yet, then create one. @@ -138,8 +136,8 @@ class CompileSocket { /** Set the port number to which a scala compile server is connected */ def setPort(port: Int) { - val file = scala.io.File(portFile(port)) - val secret = new java.security.SecureRandom().nextInt.toString + val file = portFile(port) + val secret = new SecureRandom().nextInt.toString try file writeAll List(secret) catch { case e @ (_: FileNotFoundException | _: SecurityException) => @@ -148,7 +146,7 @@ class CompileSocket { } /** Delete the port number to which a scala compile server was connected */ - def deletePort(port: Int) { portFile(port).delete() } + def deletePort(port: Int) = portFile(port).delete() /** Get a socket connected to a daemon. If create is true, then * create a new daemon if necessary. Returns null if the connection @@ -210,8 +208,8 @@ class CompileSocket { } def getPassword(port: Int): String = { - val ff = scala.io.File(portFile(port)) - val f = ff.bufferedReader() + val ff = portFile(port) + val f = ff.bufferedReader() // allow some time for the server to start up def check = { diff --git a/src/compiler/scala/tools/util/SocketServer.scala b/src/compiler/scala/tools/util/SocketServer.scala index 1a1815f02a..00180f7659 100644 --- a/src/compiler/scala/tools/util/SocketServer.scala +++ b/src/compiler/scala/tools/util/SocketServer.scala @@ -10,12 +10,22 @@ package scala.tools.util -import java.lang.System -import java.io.PrintWriter -import java.io.BufferedOutputStream -import java.io.{BufferedReader, InputStreamReader} -import java.io.IOException -import java.net.{ServerSocket, SocketException, SocketTimeoutException} +import java.io.{ PrintWriter, BufferedOutputStream, BufferedReader, InputStreamReader, IOException } +import java.net.{ Socket, ServerSocket, SocketException, SocketTimeoutException } + +object SocketServer +{ + // After 30 idle minutes, politely exit. + // Should the port file disappear, and the clients + // therefore unable to contact this server instance, + // the process will just eventually terminate by itself. + val IdleTimeout = 1800000 + val BufferSize = 10240 + + def bufferedReader(s: Socket) = new BufferedReader(new InputStreamReader(s.getInputStream())) + def bufferedOutput(s: Socket) = new BufferedOutputStream(s.getOutputStream, BufferSize) +} +import SocketServer._ /** The abstract class <code>SocketServer</code> implements the server * communication for the fast Scala compiler. @@ -23,8 +33,8 @@ import java.net.{ServerSocket, SocketException, SocketTimeoutException} * @author Martin Odersky * @version 1.0 */ -abstract class SocketServer { - +abstract class SocketServer +{ def shutDown: Boolean def session() @@ -51,41 +61,38 @@ abstract class SocketServer { val port: Int = serverSocket.getLocalPort() + // @todo: this is going to be a prime candidate for ARM + def doSession(clientSocket: Socket) = { + out = new PrintWriter(clientSocket.getOutputStream(), true) + in = bufferedReader(clientSocket) + val bufout = bufferedOutput(clientSocket) + + scala.Console.withOut(bufout) { session() } + + bufout.close() + out.close() + in.close() + } + def run() { - try { - // After 30 idle minutes, politely exit. - // Should the port file disappear, and the clients - // therefore unable to contact this server instance, - // the process will just eventually terminate by itself. - serverSocket.setSoTimeout(1800000) - } catch { - case e: SocketException => - fatal("Could not set timeout on port: " + port + "; exiting.") + def fail(s: String) = fatal(s format port) + + try serverSocket setSoTimeout IdleTimeout catch { + case e: SocketException => fail("Could not set timeout on port: %d; exiting.") } + try { while (!shutDown) { - val clientSocket = try { - serverSocket.accept() - } catch { - case e: IOException => - fatal("Accept on port " + port + " failed; exiting.") + val clientSocket = try serverSocket.accept() catch { + case e: IOException => fail("Accept on port %d failed; exiting.") } - - out = new PrintWriter(clientSocket.getOutputStream(), true) - in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())) - val bufout = new BufferedOutputStream(clientSocket.getOutputStream, 10240) - - scala.Console.withOut(bufout) { - session() - } - bufout.close() - out.close() - in.close() + doSession(clientSocket) clientSocket.close() } - } catch { + } + catch { case e: SocketTimeoutException => - warn("Timeout elapsed with no requests from clients on port " + port + "; exiting") + warn("Timeout elapsed with no requests from clients on port %d; exiting" format port) timeout() } serverSocket.close() diff --git a/src/library/scala/io/File.scala b/src/library/scala/io/File.scala index 98b76b24bf..f1cdb452dc 100644 --- a/src/library/scala/io/File.scala +++ b/src/library/scala/io/File.scala @@ -12,7 +12,7 @@ package scala.io import java.io.{ FileInputStream, FileOutputStream, BufferedReader, BufferedWriter, InputStreamReader, OutputStreamWriter, - BufferedInputStream, File => JFile } + BufferedInputStream, BufferedOutputStream, File => JFile } import collection.Traversable object File @@ -56,6 +56,7 @@ import File._ */ class File(val file: JFile)(implicit val codec: Codec = Codec.default) extends collection.Iterable[File] { + def name = file.getName() def path = file.getPath() def absolutePath = file.getAbsolutePath() def delete() = file.delete() @@ -82,7 +83,7 @@ class File(val file: JFile)(implicit val codec: Codec = Codec.default) extends c * you can map (_.toByte) if you would really prefer Bytes. */ def bytes(): Iterator[Int] = { - val in = new BufferedInputStream(inputStream()) + val in = bufferedInput() Iterator continually in.read() takeWhile (_ != -1) } @@ -104,9 +105,11 @@ class File(val file: JFile)(implicit val codec: Codec = Codec.default) extends c /** Obtains an InputStream. */ def inputStream() = new FileInputStream(file) + def bufferedInput() = new BufferedInputStream(inputStream()) /** Obtains a OutputStream. */ def outputStream(append: Boolean = false) = new FileOutputStream(file, append) + def bufferedOutput(append: Boolean = false) = new BufferedOutputStream(outputStream(append)) /** Obtains an InputStreamReader wrapped around a FileInputStream. */ |