45027
|
1 |
/* Title: Pure/System/system_channel.scala
|
|
2 |
Author: Makarius
|
|
3 |
|
45028
|
4 |
Portable system channel for inter-process communication, based on
|
|
5 |
named pipes or sockets.
|
45027
|
6 |
*/
|
|
7 |
|
|
8 |
package isabelle
|
|
9 |
|
|
10 |
|
|
11 |
import java.io.{InputStream, OutputStream, File, FileInputStream, FileOutputStream, IOException}
|
45028
|
12 |
import java.net.{ServerSocket, InetAddress}
|
45027
|
13 |
|
|
14 |
|
|
15 |
object System_Channel
|
|
16 |
{
|
|
17 |
def apply(): System_Channel = new Fifo_Channel
|
|
18 |
}
|
|
19 |
|
|
20 |
abstract class System_Channel
|
|
21 |
{
|
|
22 |
def isabelle_args: List[String]
|
|
23 |
def rendezvous(): (OutputStream, InputStream)
|
|
24 |
def accepted(): Unit
|
|
25 |
}
|
|
26 |
|
|
27 |
|
45028
|
28 |
/** named pipes **/
|
|
29 |
|
45027
|
30 |
object Fifo_Channel
|
|
31 |
{
|
|
32 |
private val next_fifo = new Counter
|
|
33 |
}
|
|
34 |
|
|
35 |
class Fifo_Channel extends System_Channel
|
|
36 |
{
|
|
37 |
private def mk_fifo(): String =
|
|
38 |
{
|
|
39 |
val i = Fifo_Channel.next_fifo()
|
|
40 |
val script =
|
|
41 |
"FIFO=\"/tmp/isabelle-fifo-${PPID}-$$" + i + "\"\n" +
|
|
42 |
"echo -n \"$FIFO\"\n" +
|
|
43 |
"mkfifo -m 600 \"$FIFO\"\n"
|
|
44 |
val (out, err, rc) = Isabelle_System.bash(script)
|
|
45 |
if (rc == 0) out else error(err.trim)
|
|
46 |
}
|
|
47 |
|
|
48 |
private def rm_fifo(fifo: String): Boolean =
|
|
49 |
Isabelle_System.platform_file(
|
|
50 |
Path.explode(if (Platform.is_windows) fifo + ".lnk" else fifo)).delete
|
|
51 |
|
|
52 |
private def fifo_input_stream(fifo: String): InputStream =
|
|
53 |
{
|
|
54 |
if (Platform.is_windows) { // Cygwin fifo as Windows/Java input stream
|
|
55 |
val proc =
|
|
56 |
Isabelle_System.execute(false,
|
|
57 |
Isabelle_System.standard_path(Path.explode("~~/lib/scripts/raw_dump")), fifo, "-")
|
|
58 |
proc.getOutputStream.close
|
|
59 |
proc.getErrorStream.close
|
|
60 |
proc.getInputStream
|
|
61 |
}
|
|
62 |
else new FileInputStream(fifo)
|
|
63 |
}
|
|
64 |
|
|
65 |
private def fifo_output_stream(fifo: String): OutputStream =
|
|
66 |
{
|
|
67 |
if (Platform.is_windows) { // Cygwin fifo as Windows/Java output stream
|
|
68 |
val proc =
|
|
69 |
Isabelle_System.execute(false,
|
|
70 |
Isabelle_System.standard_path(Path.explode("~~/lib/scripts/raw_dump")), "-", fifo)
|
|
71 |
proc.getInputStream.close
|
|
72 |
proc.getErrorStream.close
|
|
73 |
val out = proc.getOutputStream
|
|
74 |
new OutputStream {
|
|
75 |
override def close() { out.close(); proc.waitFor() }
|
|
76 |
override def flush() { out.flush() }
|
|
77 |
override def write(b: Array[Byte]) { out.write(b) }
|
|
78 |
override def write(b: Array[Byte], off: Int, len: Int) { out.write(b, off, len) }
|
|
79 |
override def write(b: Int) { out.write(b) }
|
|
80 |
}
|
|
81 |
}
|
|
82 |
else new FileOutputStream(fifo)
|
|
83 |
}
|
|
84 |
|
|
85 |
|
|
86 |
private val fifo1 = mk_fifo()
|
|
87 |
private val fifo2 = mk_fifo()
|
|
88 |
|
|
89 |
val isabelle_args: List[String] = List ("-W", fifo1 + ":" + fifo2)
|
|
90 |
|
|
91 |
def rendezvous(): (OutputStream, InputStream) =
|
|
92 |
{
|
|
93 |
val output_stream = fifo_output_stream(fifo1)
|
|
94 |
val input_stream = fifo_input_stream(fifo2)
|
|
95 |
(output_stream, input_stream)
|
|
96 |
}
|
|
97 |
|
|
98 |
def accepted() { rm_fifo(fifo1); rm_fifo(fifo2) }
|
|
99 |
}
|
45028
|
100 |
|
|
101 |
|
|
102 |
/** sockets **/
|
|
103 |
|
|
104 |
class Socket_Channel extends System_Channel
|
|
105 |
{
|
|
106 |
private val server = new ServerSocket(0, 2, InetAddress.getByName("127.0.0.1"))
|
|
107 |
|
|
108 |
def isabelle_args: List[String] = List("-T", "127.0.0.1:" + server.getLocalPort)
|
|
109 |
|
|
110 |
def rendezvous(): (OutputStream, InputStream) =
|
|
111 |
{
|
|
112 |
val socket = server.accept
|
|
113 |
(socket.getOutputStream, socket.getInputStream)
|
|
114 |
}
|
|
115 |
|
|
116 |
def accepted() { server.close }
|
|
117 |
}
|