diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-02-19 20:05:29 -0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-02-19 20:05:29 -0800 |
commit | 8febd3f0e98c428eff52ec73f7708c2042a5cfb1 (patch) | |
tree | 1b8792fbacd74a84bed95bb728424d00ff6dc4fb /main | |
parent | fb8c75c01f86f41a62e549eb03953789658f7cae (diff) | |
download | mill-8febd3f0e98c428eff52ec73f7708c2042a5cfb1.tar.gz mill-8febd3f0e98c428eff52ec73f7708c2042a5cfb1.tar.bz2 mill-8febd3f0e98c428eff52ec73f7708c2042a5cfb1.zip |
Basic working server-client model based on flat files communications
Diffstat (limited to 'main')
-rw-r--r-- | main/src/mill/Main.scala | 17 | ||||
-rw-r--r-- | main/src/mill/ServerClient.scala | 128 |
2 files changed, 137 insertions, 8 deletions
diff --git a/main/src/mill/Main.scala b/main/src/mill/Main.scala index 203f92e1..9f95c3c2 100644 --- a/main/src/mill/Main.scala +++ b/main/src/mill/Main.scala @@ -12,6 +12,10 @@ object Main { watch: Boolean = false) def main(args: Array[String]): Unit = { + val result = main0(args) + System.exit(if(result) 0 else 1) + } + def main0(args: Array[String]): Boolean = { import ammonite.main.Cli @@ -24,7 +28,7 @@ object Main { ) match{ case Left(msg) => System.err.println(msg) - System.exit(1) + false case Right((cliConfig, _)) if cliConfig.help => val leftMargin = millArgSignature.map(ammonite.main.Cli.showArg(_).length).max + 2 System.out.println( @@ -33,7 +37,7 @@ object Main { | |${formatBlock(millArgSignature, leftMargin).mkString(Util.newLine)}""".stripMargin ) - System.exit(0) + true case Right((cliConfig, leftoverArgs)) => val repl = leftoverArgs.isEmpty @@ -61,13 +65,10 @@ object Main { ) if (repl){ runner.printInfo("Loading...") - runner.runRepl() + runner.watchLoop(isRepl = true, printing = false, _.run()) } else { - val result = runner.runScript(pwd / "build.sc", leftoverArgs) - System.exit(if(result) 0 else 1) + runner.runScript(pwd / "build.sc", leftoverArgs) } } } -} - - +}
\ No newline at end of file diff --git a/main/src/mill/ServerClient.scala b/main/src/mill/ServerClient.scala new file mode 100644 index 00000000..a1816c55 --- /dev/null +++ b/main/src/mill/ServerClient.scala @@ -0,0 +1,128 @@ +package mill + +import java.io.{InputStream, OutputStream, PrintStream, RandomAccessFile} +import java.nio.file.{Files, Path, Paths} +import java.util +object Client{ + def WithLock[T](index: Int)(f: Path => T): T = { + val lockFile = Paths.get("out/mill-worker-" + index + "/lock") + Files.createDirectories(lockFile.getParent) + val raf = new RandomAccessFile(lockFile.toFile, "rw") + val channel = raf.getChannel + channel.tryLock() match{ + case null => + raf.close() + channel.close() + if (index < 5) WithLock(index + 1)(f) + else throw new Exception("Reached max process limit: " + 5) + case locked => + try f(lockFile.getParent) + finally{ + locked.release() + raf.close() + channel.close() + } + } + } + + def main(args: Array[String]): Unit = { + WithLock(1) { lockBase => + val inFile = lockBase.resolve("stdin") + val outFile = lockBase.resolve("stdout") + val errFile = lockBase.resolve("stderr") + val runFile = lockBase.resolve("run") + val tmpRunFile = lockBase.resolve("run-tmp") + + Files.createFile(outFile) + Files.createFile(errFile) + + Files.write(tmpRunFile, java.util.Arrays.asList(args:_*)) + Files.move(tmpRunFile, runFile) + val start = System.currentTimeMillis() + val in = Files.newOutputStream(inFile) + val out = Files.newInputStream(outFile) + val err = Files.newInputStream(errFile) + if (!Files.exists(lockBase.resolve("pid"))){ + val selfJar = getClass.getProtectionDomain.getCodeSource.getLocation.toURI.getPath + + val l = new java.util.ArrayList[String] + l.add("java") + val props = System.getProperties + val keys = props.stringPropertyNames().iterator() + while(keys.hasNext){ + val k = keys.next() + if (k.startsWith("MILL_")) l.add("-D" + k + "=" + props.getProperty(k)) + } + l.add("-cp") + l.add(selfJar) + l.add("mill.Server") + l.add(lockBase.toString) + + new java.lang.ProcessBuilder() + .command(l) + .redirectInput(inFile.toFile) + .redirectOutput(outFile.toFile) + .redirectError(errFile.toFile) + .start() + } + + + val buffer = new Array[Byte](1024) + while({ + Thread.sleep(1) + forward(buffer, out, System.out) | + forward(buffer, err, System.err) | + forward(buffer, System.in, in) | + Files.exists(runFile) + })() + println("DELTA: " + (System.currentTimeMillis() - start)) + + Files.delete(inFile) + Files.delete(outFile) + Files.delete(errFile) + + } + } + + def forward(buffer: Array[Byte], src: InputStream, dest: OutputStream) = { + if (src.available() != 0){ + val n = src.read(buffer) + dest.write(buffer, 0, n) + true + }else false + } +} + + +object Server{ + def main(args: Array[String]): Unit = { + val lockBase = Paths.get(args(0)) + val runFile = lockBase.resolve("run") + var lastRun = System.currentTimeMillis() + val pidFile = lockBase.resolve("pid") + Files.createFile(pidFile) + try { + while (System.currentTimeMillis() - lastRun < 60000) { + if (!Files.exists(runFile)) Thread.sleep(10) + else { + val in = Files.newInputStream(lockBase.resolve("stdin")) + val out = Files.newOutputStream(lockBase.resolve("stdout")) + val err = Files.newOutputStream(lockBase.resolve("stderr")) + val args = new String(Files.readAllBytes(runFile)).split('\n') + try { + System.setOut(new PrintStream(out)) + System.setErr(new PrintStream(err)) + System.setIn(in) + mill.Main.main0(args) + } finally { + Files.delete(runFile) + lastRun = System.currentTimeMillis() + } + } + } + }finally{ + Files.delete(pidFile) + } + } +} + |