summaryrefslogtreecommitdiff
path: root/clientserver/src/mill/clientserver/Client.scala
blob: 5e1af0aaa4ae0b0ba949260f36efb4255ee200a3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package mill.clientserver

import java.io._

import org.scalasbt.ipcsocket.UnixDomainSocket

object Client{
  def WithLock[T](index: Int)(f: String => T): T = {
    val lockBase = "out/mill-worker-" + index
    new java.io.File(lockBase).mkdirs()
    val lockFile = new RandomAccessFile(lockBase+ "/clientLock", "rw")
    val channel = lockFile.getChannel
    channel.tryLock() match{
      case null =>
        lockFile.close()
        channel.close()
        if (index < 5) WithLock(index + 1)(f)
        else throw new Exception("Reached max process limit: " + 5)
      case locked =>
        try f(lockBase)
        finally{
          locked.release()
          lockFile.close()
          channel.close()
        }
    }
  }
}

class Client(lockBase: String,
             initServer: () => Unit,
             locks: Locks,
             stdin: InputStream,
             stdout: OutputStream,
             stderr: OutputStream) extends ClientServer(lockBase){
  def run(args: Array[String]): Int = {
    val f = new FileOutputStream(runFile)
    ClientServer.writeArgs(System.console() != null, args, f)
    f.close()
    if (locks.processLock.probe()) initServer()
    while(locks.processLock.probe()) Thread.sleep(3)

    val ioSocket = ClientServer.retry(1000, new UnixDomainSocket(ioPath))

    val outErr = ioSocket.getInputStream
    val in = ioSocket.getOutputStream
    val outPump = new ClientOutputPumper(outErr, stdout, stderr)
    val inPump = new ClientInputPumper(stdin, in)
    val outThread = new Thread(outPump)
    outThread.setDaemon(true)
    val inThread = new Thread(inPump)
    inThread.setDaemon(true)
    outThread.start()
    inThread.start()

    locks.serverLock.await()

    try{
      new BufferedReader(
        new InputStreamReader(
          new FileInputStream(exitCodePath)
        )
      ).readLine().toInt
    } catch{case e: Throwable => 1}
  }
}