src/Pure/Build/build_cluster.scala
author wenzelm
Fri, 16 Feb 2024 20:20:24 +0100
changeset 79636 b3febd2a4c73
parent 79634 432217a1e990
child 79637 a14497801192
permissions -rw-r--r--
more robust: check subclasses as well;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
79502
c7a98469c0e7 clarified directories;
wenzelm
parents: 78965
diff changeset
     1
/*  Title:      Pure/Build/build_cluster.scala
78398
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
     3
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
     4
Management of build cluster: independent ssh hosts with access to shared
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
     5
PostgreSQL server.
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
     6
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
     7
NB: extensible classes allow quite different implementations in user-space,
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
     8
via the service class Build.Engine and overridable methods
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
     9
Build.Engine.open_build_process(), Build_Process.open_build_cluster().
78398
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
    10
*/
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
    11
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
    12
package isabelle
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
    13
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
    14
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
    15
object Build_Cluster {
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
    16
  /* host specifications */
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
    17
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
    18
  object Host {
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    19
    private val rfc822_specials = """()<>@,;:\"[]"""
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    20
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    21
    private val HOSTNAME = "hostname"
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    22
    private val USER = "user"
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    23
    private val PORT = "port"
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    24
    private val JOBS = "jobs"
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    25
    private val NUMA = "numa"
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
    26
    private val DIRS = "dirs"
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
    27
    private val HOME = "home"
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
    28
    private val SHARED = "shared"
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    29
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    30
    val parameters: Options =
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    31
      Options.inline("""
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    32
        option hostname : string = "" -- "explicit SSH hostname"
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    33
        option user : string = ""     -- "explicit SSH user"
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    34
        option port : int = 0         -- "explicit SSH port"
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    35
        option jobs : int = 1         -- "maximum number of parallel jobs"
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    36
        option numa : bool = false    -- "cyclic shuffling of NUMA CPU nodes"
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    37
        option dirs : string = ""     -- "additional session directories (separated by colon)"
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
    38
        option home : string = ""     -- "alternative user home (via $USER_HOME)"
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
    39
        option shared : bool = false  -- "shared home directory: omit sync + init"
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    40
      """)
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    41
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    42
    def is_parameter(spec: Options.Spec): Boolean = parameters.defined(spec.name)
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    43
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    44
    lazy val test_options: Options = Options.init0()
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
    45
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
    46
    def apply(
78416
f26eba6281b1 tuned signature;
wenzelm
parents: 78413
diff changeset
    47
      name: String = "",
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    48
      hostname: String = parameters.string(HOSTNAME),
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    49
      user: String = parameters.string(USER),
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    50
      port: Int = parameters.int(PORT),
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    51
      jobs: Int = parameters.int(JOBS),
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    52
      numa: Boolean = parameters.bool(NUMA),
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
    53
      dirs: String = parameters.string(DIRS),
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
    54
      home: String = parameters.string(HOME),
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
    55
      shared: Boolean = parameters.bool(SHARED),
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
    56
      options: List[Options.Spec] = Nil
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
    57
    ): Host = {
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
    58
      new Host(name, hostname, user, port, jobs, numa, dirs, home, shared, options)
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
    59
    }
78401
822ddccda899 proforma support for remote build hosts;
wenzelm
parents: 78399
diff changeset
    60
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    61
    def parse(registry: Registry, str: String): List[Host] = {
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    62
      def err(msg: String): Nothing =
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    63
        cat_error(msg, "The error(s) above occurred in host specification " + quote(str))
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    64
78578
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
    65
      val names = str.takeWhile(c => !rfc822_specials.contains(c) || c == ',')
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    66
      val more_specs =
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    67
        try {
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    68
          val n = str.length
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    69
          val m = names.length
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    70
          val l =
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    71
            if (m == n) n
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    72
            else if (str(m) == ':') m + 1
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    73
            else error("Missing \":\" after host name")
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    74
          Options.Spec.parse(str.substring(l))
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    75
        }
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    76
        catch { case ERROR(msg) => err(msg) }
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    77
78965
890783dc4bc6 tuned signature;
wenzelm
parents: 78964
diff changeset
    78
      def get_registry(a: String): Registry.Cluster.Value =
78964
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    79
        Registry.Cluster.try_unqualify(a) match {
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    80
          case Some(b) => Registry.Cluster.get(registry, b)
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    81
          case None => List(a -> Registry.Host.get(registry, a))
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    82
        }
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    83
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    84
      for (name <- space_explode(',', names); (host, host_specs) <- get_registry(name))
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    85
      yield {
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    86
        val (params, options) =
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    87
          try {
78964
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    88
            val (specs1, specs2) = (host_specs ::: more_specs).partition(is_parameter)
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    89
            (parameters ++ specs1, { test_options ++ specs2; specs2 })
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
    90
          }
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    91
          catch { case ERROR(msg) => err(msg) }
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
    92
78964
a2de1f6ff94e support for "cluster" table with "hosts" array, and params/options as for "host" table;
wenzelm
parents: 78963
diff changeset
    93
        apply(name = host,
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
    94
          hostname = params.string(HOSTNAME),
78578
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
    95
          user = params.string(USER),
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
    96
          port = params.int(PORT),
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
    97
          jobs = params.int(JOBS),
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
    98
          numa = params.bool(NUMA),
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
    99
          dirs = params.string(DIRS),
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
   100
          home = params.string(HOME),
78578
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
   101
          shared = params.bool(SHARED),
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
   102
          options = options)
5ccf921a2c3d support multiple host names;
wenzelm
parents: 78572
diff changeset
   103
      }
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
   104
    }
78943
bc89bdc65f29 clarified signature: more operations;
wenzelm
parents: 78926
diff changeset
   105
78945
73162a487f94 build cluster host specifications are based on registry entries (table prefix "host");
wenzelm
parents: 78943
diff changeset
   106
    def parse_single(registry: Registry, str: String): Host =
79626
73b8ac4b0492 tuned signature;
wenzelm
parents: 79620
diff changeset
   107
      Library.the_single(parse(registry, str), message = "Single host expected: " + quote(str))
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   108
  }
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   109
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   110
  class Host(
78427
5b7d1cb073db tuned signature;
wenzelm
parents: 78426
diff changeset
   111
    val name: String,
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
   112
    val hostname: String,
78427
5b7d1cb073db tuned signature;
wenzelm
parents: 78426
diff changeset
   113
    val user: String,
5b7d1cb073db tuned signature;
wenzelm
parents: 78426
diff changeset
   114
    val port: Int,
5b7d1cb073db tuned signature;
wenzelm
parents: 78426
diff changeset
   115
    val jobs: Int,
5b7d1cb073db tuned signature;
wenzelm
parents: 78426
diff changeset
   116
    val numa: Boolean,
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
   117
    val dirs: String,
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
   118
    val home: String,
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
   119
    val shared: Boolean,
78427
5b7d1cb073db tuned signature;
wenzelm
parents: 78426
diff changeset
   120
    val options: List[Options.Spec]
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   121
  ) {
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   122
    host =>
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   123
79636
b3febd2a4c73 more robust: check subclasses as well;
wenzelm
parents: 79634
diff changeset
   124
    Path.split(host.dirs)  // check
b3febd2a4c73 more robust: check subclasses as well;
wenzelm
parents: 79634
diff changeset
   125
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
   126
    def ssh_host: String = proper_string(hostname) getOrElse name
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
   127
    def is_local: Boolean = SSH.is_local(ssh_host)
79619
50ec6a68d36f tuned signature;
wenzelm
parents: 79526
diff changeset
   128
    def is_remote: Boolean = !is_local
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   129
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
   130
    override def toString: String = print
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   131
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   132
    def print: String = {
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
   133
      val params =
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   134
        List(
78925
b33a7c6b99c5 support for explicit SSH hostname;
wenzelm
parents: 78911
diff changeset
   135
          if (host.hostname.isEmpty) "" else Options.Spec.print(Host.HOSTNAME, host.hostname),
78560
39f6f180008d clarified signature;
wenzelm
parents: 78559
diff changeset
   136
          if (host.user.isEmpty) "" else Options.Spec.print(Host.USER, host.user),
39f6f180008d clarified signature;
wenzelm
parents: 78559
diff changeset
   137
          if (host.port == 0) "" else Options.Spec.print(Host.PORT, host.port.toString),
39f6f180008d clarified signature;
wenzelm
parents: 78559
diff changeset
   138
          if (host.jobs == 1) "" else Options.Spec.print(Host.JOBS, host.jobs.toString),
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
   139
          if_proper(host.numa, Host.NUMA),
79632
wenzelm
parents: 79627
diff changeset
   140
          if_proper(host.dirs, Options.Spec.print(Host.DIRS, host.dirs)),
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
   141
          if_proper(host.home, Options.Spec.print(Host.HOME, host.home)),
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
   142
          if_proper(host.shared, Host.SHARED)
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   143
        ).filter(_.nonEmpty)
78560
39f6f180008d clarified signature;
wenzelm
parents: 78559
diff changeset
   144
      val rest = (params ::: host.options.map(_.print)).mkString(",")
78408
092f1e435b3a proper Build_Cluster.Host.parse for parameters and system options;
wenzelm
parents: 78401
diff changeset
   145
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   146
      SSH.print_local(host.name) + if_proper(rest, ":" + rest)
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   147
    }
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   148
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   149
    def message(msg: String): String = "Host " + quote(host.name) + if_proper(msg, ": " + msg)
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   150
78926
35d42112301a clarified signature: more operations;
wenzelm
parents: 78925
diff changeset
   151
    def open_ssh(options: Options): SSH.System =
79634
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
   152
      SSH.open_system(options ++ host.options, ssh_host, port = host.port,
432217a1e990 support for alternative user home, e.g. to avoid slow NFS shares;
wenzelm
parents: 79632
diff changeset
   153
        user = host.user, user_home = home)
78926
35d42112301a clarified signature: more operations;
wenzelm
parents: 78925
diff changeset
   154
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   155
    def open_session(build_context: Build.Context, progress: Progress = new Progress): Session = {
78926
35d42112301a clarified signature: more operations;
wenzelm
parents: 78925
diff changeset
   156
      val ssh_options = build_context.build_options ++ host.options
35d42112301a clarified signature: more operations;
wenzelm
parents: 78925
diff changeset
   157
      val ssh = open_ssh(build_context.build_options)
35d42112301a clarified signature: more operations;
wenzelm
parents: 78925
diff changeset
   158
      new Session(build_context, host, ssh_options, ssh, progress)
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   159
    }
78399
facf1a324807 more operations;
wenzelm
parents: 78398
diff changeset
   160
  }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   161
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   162
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   163
  /* SSH sessions */
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   164
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   165
  class Session(
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   166
    val build_context: Build.Context,
78433
872f10c80810 tuned signature;
wenzelm
parents: 78430
diff changeset
   167
    val host: Host,
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   168
    val options: Options,
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   169
    val ssh: SSH.System,
78433
872f10c80810 tuned signature;
wenzelm
parents: 78430
diff changeset
   170
    val progress: Progress
872f10c80810 tuned signature;
wenzelm
parents: 78430
diff changeset
   171
  ) extends AutoCloseable {
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   172
    override def toString: String = ssh.toString
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   173
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   174
    val remote_identifier: String = options.string("build_cluster_identifier")
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   175
    val remote_root: Path = Path.explode(options.string("build_cluster_root"))
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   176
    val remote_isabelle_home: Path = remote_root + Path.explode("isabelle")
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   177
    val remote_afp_root: Option[Path] =
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   178
      if (build_context.afp_root.isEmpty) None
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   179
      else Some(remote_isabelle_home + Path.explode("AFP"))
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   180
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   181
    lazy val remote_isabelle: Other_Isabelle =
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   182
      Other_Isabelle(remote_isabelle_home, isabelle_identifier = remote_identifier, ssh = ssh)
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   183
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   184
    def sync(): Other_Isabelle = {
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   185
      Sync.sync(options, Rsync.Context(ssh = ssh), remote_isabelle_home,
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   186
        afp_root = build_context.afp_root,
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   187
        purge_heaps = true,
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   188
        preserve_jars = true)
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   189
      remote_isabelle
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   190
    }
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   191
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   192
    def init(): Unit = remote_isabelle.init()
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   193
78840
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   194
    def benchmark(): Unit = {
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   195
      val script =
79620
3914bca631b9 clarified directories;
wenzelm
parents: 79619
diff changeset
   196
        Build_Benchmark.benchmark_command(host, ssh = ssh, isabelle_home = remote_isabelle_home)
78840
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   197
      remote_isabelle.bash(script).check
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   198
    }
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   199
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   200
    def start(): Process_Result = {
78572
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   201
      val remote_ml_platform = remote_isabelle.getenv("ML_PLATFORM")
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   202
      if (remote_ml_platform != build_context.ml_platform) {
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   203
        error("Bad ML_PLATFORM: found " + remote_ml_platform +
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   204
          ", but expected " + build_context.ml_platform)
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   205
      }
79526
6e5397fcc41b add build_sync tag to sync certain options (e.g., build_engine) across build processes;
Fabian Huch <huch@in.tum.de>
parents: 79502
diff changeset
   206
      val build_options = 
6e5397fcc41b add build_sync tag to sync certain options (e.g., build_engine) across build processes;
Fabian Huch <huch@in.tum.de>
parents: 79502
diff changeset
   207
        for { option <- options.iterator if option.for_build_sync } yield options.spec(option.name)
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   208
      val script =
78558
ca0fe2802123 tuned signature;
wenzelm
parents: 78556
diff changeset
   209
        Build.build_worker_command(host,
78556
20360824863a more robust command options;
wenzelm
parents: 78508
diff changeset
   210
          ssh = ssh,
79526
6e5397fcc41b add build_sync tag to sync certain options (e.g., build_engine) across build processes;
Fabian Huch <huch@in.tum.de>
parents: 79502
diff changeset
   211
          build_options = build_options.toList,
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   212
          build_id = build_context.build_uuid,
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   213
          isabelle_home = remote_isabelle_home,
78580
c3a3db450c80 support for Host.dirs;
wenzelm
parents: 78579
diff changeset
   214
          afp_root = remote_afp_root,
78638
28a2c55648d5 prefer quiet mode: potentially more robust ssh connection, e.g. when master closes;
wenzelm
parents: 78584
diff changeset
   215
          dirs = Path.split(host.dirs).map(remote_isabelle.expand_path),
28a2c55648d5 prefer quiet mode: potentially more robust ssh connection, e.g. when master closes;
wenzelm
parents: 78584
diff changeset
   216
          quiet = true)
78584
92ef737f412c removed junk (following ab07d4cb7d1c, amending 8cd399b25dac);
wenzelm
parents: 78582
diff changeset
   217
      remote_isabelle.bash(script).check
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   218
    }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   219
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   220
    override def close(): Unit = ssh.close()
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   221
  }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   222
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   223
  class Result(val host: Host, val process_result: Exn.Result[Process_Result]) {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   224
    def rc: Int = Process_Result.RC(process_result)
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   225
    def ok: Boolean = rc == Process_Result.RC.ok
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   226
  }
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   227
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   228
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   229
  /* build clusters */
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   230
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   231
  object none extends Build_Cluster {
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   232
    override def toString: String = "Build_Cluster.none"
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   233
  }
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   234
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   235
  def make(build_context: Build.Context, progress: Progress = new Progress): Build_Cluster = {
79619
50ec6a68d36f tuned signature;
wenzelm
parents: 79526
diff changeset
   236
    val remote_hosts = build_context.build_hosts.filter(_.is_remote)
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   237
    if (remote_hosts.isEmpty) none
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   238
    else new Remote_Build_Cluster(build_context, remote_hosts, progress = progress)
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   239
  }
78398
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
   240
}
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   241
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   242
// NB: extensible via Build.Engine.build_process() and Build_Process.init_cluster()
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   243
trait Build_Cluster extends AutoCloseable {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   244
  def rc: Int = Process_Result.RC.ok
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   245
  def ok: Boolean = rc == Process_Result.RC.ok
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   246
  def return_code(rc: Int): Unit = ()
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   247
  def return_code(res: Process_Result): Unit = return_code(res.rc)
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   248
  def return_code(exn: Throwable): Unit = return_code(Process_Result.RC(exn))
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   249
  def open(): Build_Cluster = this
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   250
  def init(): Build_Cluster = this
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   251
  def benchmark(): Build_Cluster = this
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   252
  def start(): Build_Cluster = this
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   253
  def active(): Boolean = false
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   254
  def join: List[Build_Cluster.Result] = Nil
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   255
  def stop(): Unit = { join; close() }
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   256
  override def close(): Unit = ()
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   257
}
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   258
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   259
class Remote_Build_Cluster(
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   260
  val build_context: Build.Context,
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   261
  val remote_hosts: List[Build_Cluster.Host],
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   262
  val progress: Progress = new Progress
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   263
) extends Build_Cluster {
79619
50ec6a68d36f tuned signature;
wenzelm
parents: 79526
diff changeset
   264
  require(remote_hosts.nonEmpty && remote_hosts.forall(_.is_remote), "remote hosts required")
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   265
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   266
  override def toString: String =
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   267
    remote_hosts.iterator.map(_.name).mkString("Build_Cluster(", ", ", ")")
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   268
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   269
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   270
  /* cumulative return code */
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   271
78581
1384593459b4 tuned: prefer explicit types;
wenzelm
parents: 78580
diff changeset
   272
  private val _rc = Synchronized(Process_Result.RC.ok)
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   273
78581
1384593459b4 tuned: prefer explicit types;
wenzelm
parents: 78580
diff changeset
   274
  override def rc: Int = _rc.value
78499
a7dab3b8ebfe clarified synchronized regions: avoid deadlock of Build_Cluster operations on other thread vs. return_code(), notably via capture() error handling;
wenzelm
parents: 78447
diff changeset
   275
a7dab3b8ebfe clarified synchronized regions: avoid deadlock of Build_Cluster operations on other thread vs. return_code(), notably via capture() error handling;
wenzelm
parents: 78447
diff changeset
   276
  override def return_code(rc: Int): Unit =
78581
1384593459b4 tuned: prefer explicit types;
wenzelm
parents: 78580
diff changeset
   277
    _rc.change(rc0 => Process_Result.RC.merge(rc0, rc))
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   278
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   279
  def capture[A](host: Build_Cluster.Host, op: String)(
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   280
    e: => A,
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   281
    msg: String = host.message(op + " ..."),
78506
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   282
    err: Throwable => String = { exn =>
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   283
      return_code(exn)
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   284
      host.message("failed to " + op + "\n" + Exn.print(exn))
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   285
    }
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   286
  ): Exn.Result[A] = {
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   287
    progress.capture(e, msg = msg, err = err)
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   288
  }
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   289
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   290
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   291
  /* open remote sessions */
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   292
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   293
  private var _sessions = List.empty[Build_Cluster.Session]
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   294
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   295
  override def open(): Build_Cluster = synchronized {
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   296
    require(_sessions.isEmpty, "build cluster already open")
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   297
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   298
    val attempts =
78433
872f10c80810 tuned signature;
wenzelm
parents: 78430
diff changeset
   299
      Par_List.map((host: Build_Cluster.Host) =>
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   300
        capture(host, "open") { host.open_session(build_context, progress = progress) },
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   301
        remote_hosts, thread = true)
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   302
78674
88f47c70187a clarified signature;
wenzelm
parents: 78643
diff changeset
   303
    if (attempts.forall(Exn.is_res)) {
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   304
      _sessions = attempts.map(Exn.the_res)
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   305
      _sessions
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   306
    }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   307
    else {
78592
fdfe9b91d96e misc tuning: support "scalac -source 3.3";
wenzelm
parents: 78584
diff changeset
   308
      for (case Exn.Res(session) <- attempts) session.close()
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   309
      error("Failed to connect build cluster")
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   310
    }
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   311
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   312
    this
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   313
  }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   314
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   315
78840
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   316
  /* init and benchmark remote Isabelle distributions */
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   317
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   318
  private var _init = List.empty[Future[Unit]]
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   319
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   320
  override def init(): Build_Cluster = synchronized {
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   321
    require(_sessions.nonEmpty, "build cluster not yet open")
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   322
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   323
    if (_init.isEmpty) {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   324
      _init =
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
   325
        for (session <- _sessions if !session.host.shared) yield {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   326
          Future.thread(session.host.message("session")) {
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   327
            capture(session.host, "sync") { session.sync() }
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   328
            capture(session.host, "init") { session.init() }
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   329
          }
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   330
        }
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   331
    }
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   332
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   333
    this
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   334
  }
78840
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   335
  
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   336
  override def benchmark(): Build_Cluster = synchronized {
78840
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   337
    _init.foreach(_.join)
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   338
    _init =
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   339
      for (session <- _sessions if !session.host.shared) yield {
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   340
        Future.thread(session.host.message("session")) {
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   341
          capture(session.host, "benchmark") { session.benchmark() }
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   342
        }
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   343
      }
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   344
    _init.foreach(_.join)
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   345
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   346
    this
78840
4b528ca25573 added initial version of benchmark module, e.g., to compare performance of different hosts;
Fabian Huch <huch@in.tum.de>
parents: 78674
diff changeset
   347
  }
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   348
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   349
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   350
  /* workers */
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   351
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   352
  private var _workers = List.empty[Future[Process_Result]]
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   353
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   354
  override def active(): Boolean = synchronized { _workers.nonEmpty }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   355
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   356
  override def start(): Build_Cluster = synchronized {
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   357
    require(_sessions.nonEmpty, "build cluster not yet open")
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   358
    require(_workers.isEmpty, "build cluster already active")
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   359
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   360
    init()
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   361
    _init.foreach(_.join)
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   362
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   363
    _workers =
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   364
      for (session <- _sessions) yield {
78582
63f06b935a1f tuned messages (again);
wenzelm
parents: 78581
diff changeset
   365
        Future.thread(session.host.message("work")) {
63f06b935a1f tuned messages (again);
wenzelm
parents: 78581
diff changeset
   366
          Exn.release(capture(session.host, "work") { session.start() })
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   367
        }
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   368
      }
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   369
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   370
    this
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   371
  }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   372
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   373
  override def join: List[Build_Cluster.Result] = synchronized {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   374
    _init.foreach(_.join)
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   375
    if (_workers.isEmpty) Nil
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   376
    else {
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   377
      assert(_sessions.length == _workers.length)
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   378
      for ((session, worker) <- _sessions zip _workers)
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   379
        yield Build_Cluster.Result(session.host, worker.join_result)
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   380
    }
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   381
  }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   382
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   383
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   384
  /* close */
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   385
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   386
  override def close(): Unit = synchronized {
78441
3153311f0f6c more robust;
wenzelm
parents: 78440
diff changeset
   387
    _init.foreach(_.join)
78639
ca56952b7322 proper stop of build_process shutdown, despite errors on workers;
wenzelm
parents: 78638
diff changeset
   388
    _workers.foreach(_.join_result)
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   389
    _sessions.foreach(_.close())
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   390
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   391
    _init = Nil
78434
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   392
    _workers = Nil
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   393
    _sessions = Nil
b4ec7ea073da clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
wenzelm
parents: 78433
diff changeset
   394
  }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   395
}