diff -r 6e85d866251f -r 465f43a9f780 src/Doc/System/Server.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Doc/System/Server.thy Mon Mar 19 19:24:45 2018 +0100 @@ -0,0 +1,354 @@ +(*:maxLineLen=78:*) + +theory Server +imports Base +begin + +chapter \The Isabelle server\ + +text \ + An Isabelle session requires at least two processes, which are both rather + heavy: Isabelle/Scala for the system infrastructure and Isabelle/ML for the + logic session (e.g.\ HOL). In principle, these processes can be invoked + directly on the command-line, e.g.\ via @{tool java}, @{tool scala}, @{tool + process}, @{tool console}, but this approach is inadequate for reactive + applications that require quick responses from the prover. + + In contrast, the Isabelle server exposes Isabelle/Scala as a + ``terminate-stay-resident'' application that manages multiple logic + \<^emph>\sessions\ and concurrent tasks to use \<^emph>\theories\. This provides an + analogous to @{ML Thy_Info.use_theories} in Isabelle/ML, but with full + concurrency and Isabelle/PIDE markup. + + The client/server arrangement via TCP sockets also opens possibilities for + remote Isabelle services that are accessed by local applications, e.g.\ via + an SSH tunnel. +\ + + +section \Command-line tools\ + +subsection \Server \label{sec:tool-server}\ + +text \ + The @{tool_def server} tool manages resident server processes: + @{verbatim [display] +\Usage: isabelle server [OPTIONS] + + Options are: + -L FILE logging on FILE + -c console interaction with specified server + -l list servers (alternative operation) + -n NAME explicit server name (default: isabelle) + -p PORT explicit server port + -s assume existing server, no implicit startup + -x exit specified server (alternative operation) + + Manage resident Isabelle servers.\} + + The main operation of \<^verbatim>\isabelle server\ is to ensure that a named server is + running, either by finding an already running process (according to the + central database file @{path "$ISABELLE_HOME_USER/servers.db"}) or by + becoming itself a new server that accepts connections on a particular TCP + socket. The server name and its address are printed as initial output line. + If another server instance is already running, the current + \<^verbatim>\isabelle server\ process will terminate; otherwise, it keeps running as a + new server process until an explicit \<^verbatim>\shutdown\ command is received. + Further details of the server socket protocol are explained in + \secref{sec:server-protocol}. + + Other server management operations are invoked via options \<^verbatim>\-l\ and \<^verbatim>\-x\ + (see below). + + \<^medskip> + Option \<^verbatim>\-n\ specifies an alternative server name: at most one process for + each name may run, but each server instance supports multiple connections + and logic sessions. + + \<^medskip> + Option \<^verbatim>\-p\ specifies an explicit TCP port for the server socket (which is + always on \<^verbatim>\localhost\): the default is to let the operating system assign a + free port number. + + \<^medskip> + Option \<^verbatim>\-s\ strictly assumes that the specified server process is already + running, skipping the optional server startup phase. + + \<^medskip> + Option \<^verbatim>\-c\ connects the console in/out channels after the initial check + for a suitable server process. Note that the @{tool client} tool + (\secref{sec:tool-client}) provides a more convenient way to do this + interactively, together with command-line editor support. + + \<^medskip> + Option \<^verbatim>\-l\ lists all active server processes with their connection + details. + + \<^medskip> + Option \<^verbatim>\-x\ exits the specified server process by sending it a \<^verbatim>\shutdown\ + command. + + \<^medskip> + Option \<^verbatim>\-L\ specifies a log file for exceptional output of internal server + and session operations. +\ + + +subsection \Client \label{sec:tool-client}\ + +text \ + The @{tool_def client} provides console interaction for Isabelle servers: + @{verbatim [display] +\Usage: isabelle client [OPTIONS] + + Options are: + -n NAME explicit server name + -p PORT explicit server port + + Console interaction for Isabelle server (with line-editor).\} + + This is a convenient wrapper to \<^verbatim>\isabelle server -s -c\ for interactive + experimentation, wrapped into @{setting ISABELLE_LINE_EDITOR} if available. + The server name is sufficient for identification, as the client can + determine the connection details from the local database of active servers. + + \<^medskip> + Option \<^verbatim>\-n\ specifies an explicit server name as in @{tool server}. + + \<^medskip> + Option \<^verbatim>\-p\ specifies an explicit server port as in @{tool server}. +\ + + +subsection \Examples\ + +text \ + Ensure that a particular server instance is running in the background: + @{verbatim [display] \isabelle server -n test &\} + + Here the first line of output presents the connection details:\<^footnote>\This + information may be used in an independent TCP client, while the + Isabelle/Scala tool merely needs the server name to access the database of + servers.\ + @{verbatim [display] \server "test" = 127.0.0.1:4711 (password "XYZ")\} + + \<^medskip> + List available server processes: + @{verbatim [display] \isabelle server -l\} + + \<^medskip> + Connect the command-line client to the above test server: + @{verbatim [display] \isabelle client -n test\} + + Interaction now works on a line-by-line basis, with commands like \<^verbatim>\help\ or + \<^verbatim>\echo\. For example, some JSON values may be echoed like this: + + @{verbatim [display] +\echo 42 +echo [1, 2, 3] +echo {"a": "text", "b": true, "c": 42}\} + + Closing the connection (via CTRL-D) leaves the server running: it is + possible to reconnect again, and have multiple connections at the same time. + + \<^medskip> + Finally, exit the named server on the command-line: + @{verbatim [display] \isabelle server -n test -x\} +\ + + +section \Protocol messages \label{sec:server-protocol}\ + +text \ + The Isabelle server listens on a regular TCP socket, using a line-oriented + protocol of structured messages: input \<^emph>\commands\ and output \<^emph>\results\ + (via \<^verbatim>\OK\ or \<^verbatim>\ERROR\) are strictly alternating on the toplevel, but + commands may also return a \<^emph>\task\ identifier to indicate an ongoing + asynchronous process that is joined later (via \<^verbatim>\FINISHED\ or \<^verbatim>\FAILED\). + Asynchronous \<^verbatim>\NOTE\ messages may occur at any time: they are independent of + the main command-reply protocol. + + For example, the synchronous \<^verbatim>\echo\ command immediately returns its + argument as \<^verbatim>\OK\ result. In contrast, the asynchronous \<^verbatim>\session_build\ + command returns \<^verbatim>\OK {"task":\\id\\<^verbatim>\}\ and continues in the background. It + will eventually produce \<^verbatim>\FINISHED {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ or + \<^verbatim>\FAILED {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ with the final result. Intermediately, it + may emit asynchronous messages of the form \<^verbatim>\NOTE {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ + to inform about its progress. Due to the explicit task identifier, the + client can show these messages in the proper context, e.g.\ a GUI window for + the session build job. + + \medskip Subsequently, the protocol message formats are described in further + detail. +\ + + +subsection \Byte messages\ + +text \ + The client-server connection is a raw byte-channel for bidirectional + communication, but the Isabelle server always works with messages of a + particular length. Messages are written as a single chunk that is flushed + immediately. + + The message boundary is determined as follows: + + \<^item> A \<^emph>\short message\ consists of a single line: it is a sequence of + arbitrary bytes excluding CR (13) and LF (10), and terminated by CR-LF or + just LF. + + \<^item> A \<^emph>\long message\ starts with a single line as above, which consists + only of decimal digits: that is interpreted as length of the subsequent + block of arbitrary bytes. A final line-terminator may be included here, + but is not required. + + Messages in JSON format (see below) always fit on a single line, due to + escaping of newline characters within string literals. This is convenient + for interactive experimentation, but it can impact performance for very long + messages. If the message byte-length is given on the preceding line, the + server can read the message efficiently as a single block. +\ + + +subsection \Text messages\ + +text \ + Messages are read and written as byte streams (with byte lengths), but the + content is always interpreted as plain text in terms of the UTF-8 + encoding.\<^footnote>\See also the ``UTF-8 Everywhere Manifesto'' + \<^url>\http://utf8everywhere.org\.\ + + Note that line-endings and other formatting characters are invariant wrt. + UTF-8 representation of text: thus implementations are free to determine the + overall message structure before or after applying the text encoding. +\ + + +subsection \Input and output messages\ + +text \ + Server input and output messages have a uniform format as follows: + + \<^item> \name argument\ such that: + + \<^item> \name\ is the longest prefix consisting of ASCII letters, digits, + ``\<^verbatim>\_\'' (underscore), or ``\<^verbatim>\.\'' (dot), + + \<^item> the separator between \name\ and \argument\ is the longest possible + sequence of ASCII blanks (it could be empty, e.g.\ when the argument + starts with a quote or bracket), + + \<^item> \argument\ is the rest of the message without the line terminator. + + \<^medskip> + Input messages are sent from the client to the server. Here the \name\ + specifies a \<^emph>\server command\: the list of known commands may be + retrieved via the \<^verbatim>\help\ command. + + \<^medskip> + Output messages are sent from the server to the client. Here the \name\ + specifies the \<^emph>\server reply\, which always has a specific meaning as + follows: + + \<^item> synchronous results: \<^verbatim>\OK\ or \<^verbatim>\ERROR\ + \<^item> asynchronous results: \<^verbatim>\FINISHED\ or \<^verbatim>\FAILED\ + \<^item> intermediate notifications: \<^verbatim>\NOTE\ + + \<^medskip> + The \argument\ format is uniform for both input and output messages: + + \<^item> empty argument (Scala type \<^verbatim>\Unit\) + \<^item> XML element in YXML notation (Scala type \<^verbatim>\XML.Elem\) + \<^item> JSON value (Scala type \<^verbatim>\JSON.T\) + + JSON values may consist of objects (records), arrays (lists), strings, + numbers, bools, null.\<^footnote>\See also the official specification + \<^url>\https://www.json.org\ and unofficial explorations ``Parsing JSON is a + Minefield'' \<^url>\http://seriot.ch/parsing_json.php\.\ Since JSON requires + explicit quotes and backslash-escapes to represent arbitrary text, the YXML + notation for XML trees (\secref{sec:yxml-vs-xml}) works better + for large messages with a lot of PIDE markup. + + Nonetheless, the most common commands use JSON by default: big chunks of + text (theory sources etc.) are taken from the underlying file-system and + results are pre-formatted for plain-text output, without PIDE markup + information. This is a concession to simplicity: the server imitates the + appearance of command-line tools on top of the Isabelle/PIDE infrastructure. +\ + + +subsection \Initial password exchange\ + +text \ + Whenever a new client opens the server socket, the initial message needs to + be its unique password. The server replies either with \<^verbatim>\OK\ (and some + information about the Isabelle version) or by silent disconnection of what + is considered an illegal connection attempt. + + Server passwords are created as Universally Unique Identifier (UUID) in + Isabelle/Scala and stored in a per-user database, with restricted + file-system access only for the current user. The Isabelle/Scala server + implementation is careful to expose the password only on private output + channels, and not on a process command-line (which is accessible to other + users, e.g.\ via the \<^verbatim>\ps\ command). +\ + + +subsection \Synchronous commands\ + +text \ + A \<^emph>\synchronous command\ corresponds to regular function application in + Isabelle/Scala, with single argument and result (regular or error). Both the + argument and the result may consist of type \<^verbatim>\Unit\, \<^verbatim>\XML.Elem\, \<^verbatim>\JSON.T\. + An error result typically consists of a JSON object with error message and + potentially further fields (this resembles exceptions in Scala). + + These are the protocol exchanges for both cases of command execution: + \begin{center} + \begin{tabular}{rl} + \<^bold>\input:\ & \command argument\ \\ + (a) regular \<^bold>\output:\ & \<^verbatim>\OK\ \result\ \\ + (b) error \<^bold>\output:\ & \<^verbatim>\ERROR\ \result\ \\ + \end{tabular} + \end{center} +\ + + +subsection \Asynchronous commands\ + +text \ + An \<^emph>\asynchronous command\ corresponds to an ongoing process that finishes + or fails eventually, while emitting arbitrary notifications intermediately. + Formally, it starts as synchronous command with immediate result \<^verbatim>\OK\ and + the \<^verbatim>\task\ identifier, or an immediate \<^verbatim>\ERROR\ that indicates bad command + syntax. For a running task, the termination is indicated later by + \<^verbatim>\FINISHED\ or \<^verbatim>\FAILED\, together with its ultimate result. + + These are the protocol exchanges for various cases of command task + execution: + + \begin{center} + \begin{tabular}{rl} + \<^bold>\input:\ & \command argument\ \\ + immediate \<^bold>\output:\ & \<^verbatim>\OK {"task":\\id\\<^verbatim>\}\ \\ + intermediate \<^bold>\output:\ & \<^verbatim>\NOTE {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ \\ + intermediate \<^bold>\output:\ & \<^verbatim>\NOTE {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ \\ + (a) regular \<^bold>\output:\ & \<^verbatim>\FINISHED {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ \\ + (b) error \<^bold>\output:\ & \<^verbatim>\FAILED {"task":\\id\\<^verbatim>\,\\\\\<^verbatim>\}\ \\[3ex] + \<^bold>\input:\ & \command argument\ \\ + immediate \<^bold>\output:\ & \<^verbatim>\ERROR\~\\\ \\ + \end{tabular} + \end{center} + + All asynchronous messages are decorated with the task identifier that was + revealed in the immediate (synchronous) result. Thus it is possible to emit + further asynchronous commands and dispatch the mingled stream of + asynchronous messages properly. + + The synchronous command \<^verbatim>\cancel\~\id\ tells the specified task to terminate + prematurely: usually causing a \<^verbatim>\FAILED\ result with error message + \<^verbatim>\Interrupt\, but this is not guaranteed: the cancel event may come too + late or the task may just ignore it. +\ + +end