src/Pure/Build/build_cluster.scala
author wenzelm
Thu, 22 Feb 2024 17:24:43 +0100
changeset 79704 512d701d0df9
parent 79681 df1059ea8846
child 79948 8fe1ed4b5705
permissions -rw-r--r--
tuned signature;
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
79637
wenzelm
parents: 79636
diff changeset
   126
    def ssh_host: String = proper_string(host.hostname) getOrElse host.name
78925
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,
79637
wenzelm
parents: 79636
diff changeset
   153
        user = host.user, user_home = host.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
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   174
    val build_cluster_identifier: String = options.string("build_cluster_identifier")
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   175
    val build_cluster_root: Path = Path.explode(options.string("build_cluster_root"))
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   176
    val built_cluster_isabelle_home: Path = build_cluster_root + Path.explode("isabelle")
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   177
    val build_cluster_afp_root: Option[Path] =
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   178
      if (build_context.afp_root.isEmpty) None
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   179
      else Some(built_cluster_isabelle_home + Path.explode("AFP"))
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   180
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   181
    lazy val build_cluster_isabelle: Other_Isabelle =
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   182
      Other_Isabelle(built_cluster_isabelle_home,
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   183
        isabelle_identifier = build_cluster_identifier, ssh = ssh)
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   184
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   185
    def sync(): Other_Isabelle = {
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   186
      Sync.sync(options, Rsync.Context(ssh = ssh), built_cluster_isabelle_home,
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   187
        afp_root = build_context.afp_root,
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   188
        purge_heaps = true,
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   189
        preserve_jars = true)
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   190
      build_cluster_isabelle
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   191
    }
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   192
79681
df1059ea8846 propagate property "isabelle.debug", notably for Java/Scala exception trace;
wenzelm
parents: 79637
diff changeset
   193
    def init(): Unit =
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   194
      build_cluster_isabelle.init(other_settings =
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   195
        build_cluster_isabelle.init_components() ::: build_cluster_isabelle.debug_settings())
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   196
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
    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
   198
      val script =
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   199
        Build_Benchmark.benchmark_command(host, ssh = ssh, isabelle_home = built_cluster_isabelle_home)
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   200
      build_cluster_isabelle.bash(script).check
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
   201
    }
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
   202
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
   203
    def start(): Process_Result = {
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   204
      val build_cluster_ml_platform = build_cluster_isabelle.getenv("ML_PLATFORM")
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   205
      if (build_cluster_ml_platform != build_context.ml_platform) {
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   206
        error("Bad ML_PLATFORM: found " + build_cluster_ml_platform +
78572
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   207
          ", but expected " + build_context.ml_platform)
11cf77478d3e more explicit check;
wenzelm
parents: 78567
diff changeset
   208
      }
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   209
      val build_options =
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
   210
        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
   211
      val script =
78558
ca0fe2802123 tuned signature;
wenzelm
parents: 78556
diff changeset
   212
        Build.build_worker_command(host,
78556
20360824863a more robust command options;
wenzelm
parents: 78508
diff changeset
   213
          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
   214
          build_options = build_options.toList,
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   215
          build_id = build_context.build_uuid,
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   216
          isabelle_home = built_cluster_isabelle_home,
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   217
          afp_root = build_cluster_afp_root,
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   218
          dirs = Path.split(host.dirs).map(build_cluster_isabelle.expand_path),
78638
28a2c55648d5 prefer quiet mode: potentially more robust ssh connection, e.g. when master closes;
wenzelm
parents: 78584
diff changeset
   219
          quiet = true)
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   220
      build_cluster_isabelle.bash(script).check
78430
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
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   223
    override def close(): Unit = ssh.close()
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   224
  }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   225
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   226
  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
   227
    def rc: Int = Process_Result.RC(process_result)
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   228
    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
   229
  }
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
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
   231
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
   232
  /* 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
   233
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   234
  object none extends Build_Cluster {
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   235
    override def toString: String = "Build_Cluster.none"
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   236
  }
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
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
  def make(build_context: Build.Context, progress: Progress = new Progress): Build_Cluster = {
79619
50ec6a68d36f tuned signature;
wenzelm
parents: 79526
diff changeset
   239
    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
   240
    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
   241
    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
   242
  }
78398
ea5adf7acc2d support for management of build cluster;
wenzelm
parents:
diff changeset
   243
}
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   244
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
   245
// 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
   246
trait Build_Cluster extends AutoCloseable {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   247
  def rc: Int = Process_Result.RC.ok
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   248
  def ok: Boolean = rc == Process_Result.RC.ok
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   249
  def return_code(rc: Int): Unit = ()
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   250
  def return_code(res: Process_Result): Unit = return_code(res.rc)
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   251
  def return_code(exn: Throwable): Unit = return_code(Process_Result.RC(exn))
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   252
  def open(): Build_Cluster = this
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   253
  def init(): Build_Cluster = this
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   254
  def benchmark(): Build_Cluster = this
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   255
  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
   256
  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
   257
  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
   258
  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
   259
  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
   260
}
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
   261
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
   262
class Remote_Build_Cluster(
78436
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   263
  val build_context: Build.Context,
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   264
  val remote_hosts: List[Build_Cluster.Host],
5f5f909206bb clarified signature: more "object-oriented" style;
wenzelm
parents: 78434
diff changeset
   265
  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
   266
) extends Build_Cluster {
79619
50ec6a68d36f tuned signature;
wenzelm
parents: 79526
diff changeset
   267
  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
   268
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
   269
  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
   270
    remote_hosts.iterator.map(_.name).mkString("Build_Cluster(", ", ", ")")
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   271
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   272
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   273
  /* cumulative return code */
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   274
78581
1384593459b4 tuned: prefer explicit types;
wenzelm
parents: 78580
diff changeset
   275
  private val _rc = Synchronized(Process_Result.RC.ok)
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   276
78581
1384593459b4 tuned: prefer explicit types;
wenzelm
parents: 78580
diff changeset
   277
  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
   278
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
   279
  override def return_code(rc: Int): Unit =
78581
1384593459b4 tuned: prefer explicit types;
wenzelm
parents: 78580
diff changeset
   280
    _rc.change(rc0 => Process_Result.RC.merge(rc0, rc))
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   281
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   282
  def capture[A](host: Build_Cluster.Host, op: String)(
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   283
    e: => A,
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   284
    msg: String = host.message(op + " ..."),
78506
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   285
    err: Throwable => String = { exn =>
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   286
      return_code(exn)
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   287
      host.message("failed to " + op + "\n" + Exn.print(exn))
14da1177d1c3 more informative error;
wenzelm
parents: 78505
diff changeset
   288
    }
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   289
  ): Exn.Result[A] = {
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   290
    progress.capture(e, msg = msg, err = err)
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   291
  }
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   292
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   293
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   294
  /* open remote sessions */
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   295
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   296
  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
   297
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   298
  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
   299
    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
   300
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   301
    val attempts =
78433
872f10c80810 tuned signature;
wenzelm
parents: 78430
diff changeset
   302
      Par_List.map((host: Build_Cluster.Host) =>
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   303
        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
   304
        remote_hosts, thread = true)
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   305
78674
88f47c70187a clarified signature;
wenzelm
parents: 78643
diff changeset
   306
    if (attempts.forall(Exn.is_res)) {
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   307
      _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
   308
      _sessions
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   309
    }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   310
    else {
78592
fdfe9b91d96e misc tuning: support "scalac -source 3.3";
wenzelm
parents: 78584
diff changeset
   311
      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
   312
      error("Failed to connect build cluster")
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   313
    }
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   314
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   315
    this
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   316
  }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   317
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   318
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
   319
  /* init and benchmark remote Isabelle distributions */
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   320
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   321
  private var _init = List.empty[Future[Unit]]
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   322
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   323
  override def init(): Build_Cluster = synchronized {
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   324
    require(_sessions.nonEmpty, "build cluster not yet open")
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   325
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   326
    if (_init.isEmpty) {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   327
      _init =
78567
db99a70f8531 support hosts with shared directory (e.g. NFS);
wenzelm
parents: 78560
diff changeset
   328
        for (session <- _sessions if !session.host.shared) yield {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   329
          Future.thread(session.host.message("session")) {
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   330
            capture(session.host, "sync") { session.sync() }
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   331
            capture(session.host, "init") { session.init() }
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   332
          }
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   333
        }
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   334
    }
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   335
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   336
    this
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   337
  }
79704
512d701d0df9 tuned signature;
wenzelm
parents: 79681
diff changeset
   338
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   339
  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
   340
    _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
   341
    _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
   342
      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
   343
        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
   344
          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
   345
        }
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
   346
      }
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
    _init.foreach(_.join)
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   348
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   349
    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
   350
  }
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   351
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   352
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   353
  /* workers */
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   354
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
   355
  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
   356
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
  override def active(): Boolean = synchronized { _workers.nonEmpty }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   358
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   359
  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
   360
    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
   361
    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
   362
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   363
    init()
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   364
    _init.foreach(_.join)
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   365
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   366
    _workers =
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   367
      for (session <- _sessions) yield {
78582
63f06b935a1f tuned messages (again);
wenzelm
parents: 78581
diff changeset
   368
        Future.thread(session.host.message("work")) {
63f06b935a1f tuned messages (again);
wenzelm
parents: 78581
diff changeset
   369
          Exn.release(capture(session.host, "work") { session.start() })
78444
3d1746a716fa clarified signature: Build_Cluster.Session.build_context;
wenzelm
parents: 78443
diff changeset
   370
        }
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   371
      }
79627
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   372
0f01c575ff3e clarified signature;
wenzelm
parents: 79626
diff changeset
   373
    this
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   374
  }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   375
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
   376
  override def join: List[Build_Cluster.Result] = synchronized {
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   377
    _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
   378
    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
   379
    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
   380
      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
   381
      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
   382
        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
   383
    }
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   384
  }
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   385
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   386
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
   387
  /* close */
78430
0461fc9d43e8 more build_cluster management: open SSH connections in parallel, but synchronously;
wenzelm
parents: 78427
diff changeset
   388
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
  override def close(): Unit = synchronized {
78441
3153311f0f6c more robust;
wenzelm
parents: 78440
diff changeset
   390
    _init.foreach(_.join)
78639
ca56952b7322 proper stop of build_process shutdown, despite errors on workers;
wenzelm
parents: 78638
diff changeset
   391
    _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
   392
    _sessions.foreach(_.close())
78440
126a12483c67 support for Build_Cluster.Session.init (rsync + Admin/init);
wenzelm
parents: 78436
diff changeset
   393
78443
a8e1d9202dd9 clarified exception handling and return_code;
wenzelm
parents: 78441
diff changeset
   394
    _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
   395
    _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
   396
    _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
   397
  }
78413
6f3066a9b609 more pro-forma support for Build_Cluster;
wenzelm
parents: 78408
diff changeset
   398
}