src/Pure/Build/database_progress.scala
author Fabian Huch <huch@in.tum.de>
Thu, 06 Jun 2024 14:51:28 +0200
changeset 80261 e3f472221f8f
parent 79887 17220dc05991
permissions -rw-r--r--
add triggers to ci jobs: on commit vs timed;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
79873
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/Build/database_progress.scala
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     3
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     4
System progress backed by shared database: local SQLite or remote PostgreSQL.
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     5
*/
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     6
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     7
package isabelle
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     8
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
     9
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    10
import scala.collection.immutable.SortedMap
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    11
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    12
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    13
object Database_Progress {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    14
  /* SQL data model */
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    15
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    16
  object private_data extends SQL.Data("isabelle_progress") {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    17
    val database: Path = Path.explode("$ISABELLE_HOME_USER/progress.db")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    18
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    19
    override lazy val tables: SQL.Tables =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    20
      SQL.Tables(Base.table, Agents.table, Messages.table)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    21
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    22
    object Base {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    23
      val context_uuid = SQL.Column.string("context_uuid").make_primary_key
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    24
      val context = SQL.Column.long("context").make_primary_key
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    25
      val stopped = SQL.Column.bool("stopped")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    26
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    27
      val table = make_table(List(context_uuid, context, stopped))
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    28
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    29
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    30
    object Agents {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    31
      val agent_uuid = SQL.Column.string("agent_uuid").make_primary_key
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    32
      val context_uuid = SQL.Column.string("context_uuid").make_primary_key
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    33
      val kind = SQL.Column.string("kind")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    34
      val hostname = SQL.Column.string("hostname")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    35
      val java_pid = SQL.Column.long("java_pid")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    36
      val java_start = SQL.Column.date("java_start")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    37
      val start = SQL.Column.date("start")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    38
      val stamp = SQL.Column.date("stamp")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    39
      val stop = SQL.Column.date("stop")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    40
      val seen = SQL.Column.long("seen")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    41
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    42
      val table =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    43
        make_table(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    44
          List(agent_uuid, context_uuid, kind, hostname, java_pid, java_start,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    45
            start, stamp, stop, seen),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    46
          name = "agents")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    47
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    48
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    49
    object Messages {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    50
      type T = SortedMap[Long, Progress.Message]
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    51
      val empty: T = SortedMap.empty
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    52
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    53
      val context = SQL.Column.long("context").make_primary_key
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    54
      val serial = SQL.Column.long("serial").make_primary_key
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    55
      val kind = SQL.Column.int("kind")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    56
      val text = SQL.Column.string("text")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    57
      val verbose = SQL.Column.bool("verbose")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    58
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    59
      val table = make_table(List(context, serial, kind, text, verbose), name = "messages")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    60
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    61
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    62
    val channel: String = Base.table.name
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    63
    val channel_ping: SQL.Notification = SQL.Notification(channel, payload = "ping")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    64
    val channel_output: SQL.Notification = SQL.Notification(channel, payload = "output")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    65
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    66
    def read_progress_context(db: SQL.Database, context_uuid: String): Option[Long] =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    67
      db.execute_query_statementO(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    68
        Base.table.select(List(Base.context),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    69
          sql = Base.context_uuid.where_equal(context_uuid)), _.long(Base.context))
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    70
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    71
    def next_progress_context(db: SQL.Database): Long =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    72
      db.execute_query_statementO(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    73
        Base.table.select(List(Base.context.max)), _.long(Base.context)).getOrElse(0L) + 1L
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    74
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    75
    def read_progress_stopped(db: SQL.Database, context: Long): Boolean =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    76
      db.execute_query_statementO(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    77
        Base.table.select(List(Base.stopped), sql = Base.context.where_equal(context)),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    78
        _.bool(Base.stopped)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    79
      ).getOrElse(false)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    80
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    81
    def write_progress_stopped(db: SQL.Database, context: Long, stopped: Boolean): Unit =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    82
      db.execute_statement(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    83
        Base.table.update(List(Base.stopped), sql = Base.context.where_equal(context)),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    84
          body = { stmt => stmt.bool(1) = stopped })
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    85
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    86
    def update_agent(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    87
      db: SQL.Database,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    88
      agent_uuid: String,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    89
      seen: Long,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    90
      stop_now: Boolean = false
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    91
    ): Unit = {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    92
      val sql = Agents.agent_uuid.where_equal(agent_uuid)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    93
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    94
      val stop =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    95
        db.execute_query_statementO(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    96
          Agents.table.select(List(Agents.stop), sql = sql), _.get_date(Agents.stop)).flatten
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    97
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    98
      db.execute_statement(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
    99
        Agents.table.update(List(Agents.stamp, Agents.stop, Agents.seen), sql = sql),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   100
        body = { stmt =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   101
          val now = db.now()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   102
          stmt.date(1) = now
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   103
          stmt.date(2) = if (stop_now) Some(now) else stop
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   104
          stmt.long(3) = seen
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   105
        })
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   106
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   107
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   108
    def read_messages_serial(db: SQL.Database, context: Long): Long =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   109
      db.execute_query_statementO(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   110
        Messages.table.select(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   111
          List(Messages.serial.max), sql = Base.context.where_equal(context)),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   112
        _.long(Messages.serial)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   113
      ).getOrElse(0L)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   114
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   115
    def read_messages(db: SQL.Database, context: Long, seen: Long = 0): Messages.T =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   116
      db.execute_query_statement(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   117
        Messages.table.select(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   118
          List(Messages.serial, Messages.kind, Messages.text, Messages.verbose),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   119
          sql =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   120
            SQL.where_and(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   121
              Messages.context.ident + " = " + context,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   122
              if (seen <= 0) "" else Messages.serial.ident + " > " + seen)),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   123
        SortedMap.from[Long, Progress.Message],
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   124
        { res =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   125
          val serial = res.long(Messages.serial)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   126
          val kind = Progress.Kind.fromOrdinal(res.int(Messages.kind))
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   127
          val text = res.string(Messages.text)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   128
          val verbose = res.bool(Messages.verbose)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   129
          serial -> Progress.Message(kind, text, verbose = verbose)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   130
        }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   131
      )
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   132
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   133
    def write_messages(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   134
      db: SQL.Database,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   135
      context: Long,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   136
      messages: List[(Long, Progress.Message)]
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   137
    ): Unit = {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   138
      db.execute_batch_statement(Messages.table.insert(), batch =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   139
        for ((serial, message) <- messages) yield { (stmt: SQL.Statement) =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   140
          stmt.long(1) = context
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   141
          stmt.long(2) = serial
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   142
          stmt.int(3) = message.kind.ordinal
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   143
          stmt.string(4) = message.text
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   144
          stmt.bool(5) = message.verbose
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   145
        })
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   146
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   147
  }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   148
}
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   149
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   150
class Database_Progress(
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   151
  db: SQL.Database,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   152
  base_progress: Progress,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   153
  input_messages: Boolean = false,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   154
  kind: String = "progress",
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   155
  hostname: String = Isabelle_System.hostname(),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   156
  context_uuid: String = UUID.random_string(),
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   157
  timeout: Option[Time] = None,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   158
  tick_expire: Int = 50)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   159
extends Progress {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   160
  database_progress =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   161
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   162
  override def now(): Date = db.now()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   163
  override val start: Date = now()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   164
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   165
  if (UUID.unapply(context_uuid).isEmpty) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   166
    error("Bad Database_Progress.context_uuid: " + quote(context_uuid))
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   167
  }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   168
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   169
  private var _tick: Long = 0
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   170
  private var _agent_uuid: String = ""
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   171
  private var _context: Long = -1
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   172
  private var _serial: Long = 0
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   173
  private var _consumer: Consumer_Thread[Progress.Output] = null
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   174
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   175
  def agent_uuid: String = synchronized { _agent_uuid }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   176
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   177
  private def init(): Unit = synchronized {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   178
    db.listen(Database_Progress.private_data.channel)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   179
    Database_Progress.private_data.transaction_lock(db,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   180
      create = true,
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   181
      label = "Database_Progress.init"
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   182
    ) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   183
      Database_Progress.private_data.read_progress_context(db, context_uuid) match {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   184
        case Some(context) =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   185
          _context = context
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   186
          _agent_uuid = UUID.random_string()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   187
        case None =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   188
          _context = Database_Progress.private_data.next_progress_context(db)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   189
          _agent_uuid = context_uuid
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   190
          db.execute_statement(Database_Progress.private_data.Base.table.insert(), { stmt =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   191
            stmt.string(1) = context_uuid
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   192
            stmt.long(2) = _context
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   193
            stmt.bool(3) = false
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   194
          })
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   195
      }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   196
      db.execute_statement(Database_Progress.private_data.Agents.table.insert(), { stmt =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   197
        val java = ProcessHandle.current()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   198
        val java_pid = java.pid
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   199
        val java_start = Date.instant(java.info.startInstant.get)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   200
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   201
        stmt.string(1) = _agent_uuid
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   202
        stmt.string(2) = context_uuid
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   203
        stmt.string(3) = kind
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   204
        stmt.string(4) = hostname
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   205
        stmt.long(5) = java_pid
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   206
        stmt.date(6) = java_start
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   207
        stmt.date(7) = start
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   208
        stmt.date(8) = start
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   209
        stmt.date(9) = None
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   210
        stmt.long(10) = 0L
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   211
      })
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   212
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   213
    if (context_uuid == _agent_uuid) db.vacuum(Database_Progress.private_data.tables.list)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   214
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   215
    def consume(bulk_output: List[Progress.Output]): List[Exn.Result[Unit]] = {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   216
      val expired = synchronized { _tick += 1; _tick % tick_expire == 0 }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   217
      val received = db.receive(n => n.channel == Database_Progress.private_data.channel)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   218
      val ok =
79887
17220dc05991 revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
wenzelm
parents: 79884
diff changeset
   219
        bulk_output.nonEmpty || expired || base_progress.stopped ||
79873
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   220
        received.isEmpty ||
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   221
        received.get.contains(Database_Progress.private_data.channel_ping) ||
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   222
        input_messages && received.get.contains(Database_Progress.private_data.channel_output)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   223
      if (ok) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   224
        sync_database {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   225
          if (bulk_output.nonEmpty) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   226
            for (out <- bulk_output) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   227
              out match {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   228
                case message: Progress.Message =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   229
                  if (do_output(message)) base_progress.output(message)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   230
                case theory: Progress.Theory => base_progress.theory(theory)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   231
              }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   232
            }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   233
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   234
            val messages =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   235
              for ((out, i) <- bulk_output.zipWithIndex)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   236
                yield (_serial + i + 1) -> out.message
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   237
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   238
            Database_Progress.private_data.write_messages(db, _context, messages)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   239
            _serial = messages.last._1
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   240
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   241
            db.send(Database_Progress.private_data.channel_output)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   242
          }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   243
          bulk_output.map(_ => Exn.Res(()))
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   244
        }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   245
      }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   246
      else Nil
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   247
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   248
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   249
    _consumer = Consumer_Thread.fork_bulk[Progress.Output](name = "Database_Progress.consumer")(
79884
caf61c098754 tuned whitespace;
wenzelm
parents: 79873
diff changeset
   250
      bulk = _ => true,
caf61c098754 tuned whitespace;
wenzelm
parents: 79873
diff changeset
   251
      timeout = timeout,
79873
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   252
      consume = { bulk_output =>
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   253
        val results =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   254
          if (bulk_output.isEmpty) consume(Nil)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   255
          else bulk_output.grouped(200).toList.flatMap(consume)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   256
        (results, true) })
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   257
  }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   258
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   259
  def close(): Unit = synchronized {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   260
    if (_context > 0) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   261
      _consumer.shutdown()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   262
      _consumer = null
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   263
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   264
      Database_Progress.private_data.transaction_lock(db, label = "Database_Progress.exit") {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   265
        Database_Progress.private_data.update_agent(db, _agent_uuid, _serial, stop_now = true)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   266
      }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   267
      _context = 0
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   268
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   269
    db.close()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   270
  }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   271
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   272
  private def sync_context[A](body: => A): A = synchronized {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   273
    if (_context < 0) throw new IllegalStateException("Database_Progress before init")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   274
    if (_context == 0) throw new IllegalStateException("Database_Progress after exit")
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   275
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   276
    body
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   277
  }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   278
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   279
  private def sync_database[A](body: => A): A = synchronized {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   280
    Database_Progress.private_data.transaction_lock(db, label = "Database_Progress.sync_database") {
79887
17220dc05991 revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
wenzelm
parents: 79884
diff changeset
   281
      val stopped_db = Database_Progress.private_data.read_progress_stopped(db, _context)
79873
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   282
79887
17220dc05991 revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
wenzelm
parents: 79884
diff changeset
   283
      if (stopped_db && !base_progress.stopped) base_progress.stop()
17220dc05991 revert most parts of 0e79fa88cab6: somewhat ambitious attempt to move towards "editing" builds via added/canceled workers;
wenzelm
parents: 79884
diff changeset
   284
      if (!stopped_db && base_progress.stopped) {
79873
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   285
        Database_Progress.private_data.write_progress_stopped(db, _context, true)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   286
        db.send(Database_Progress.private_data.channel_ping)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   287
      }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   288
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   289
      val serial0 = _serial
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   290
      if (input_messages) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   291
        val messages = Database_Progress.private_data.read_messages(db, _context, seen = _serial)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   292
        for ((message_serial, message) <- messages) {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   293
          if (base_progress.do_output(message)) base_progress.output(message)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   294
          _serial = _serial max message_serial
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   295
        }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   296
      }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   297
      else {
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   298
        _serial = _serial max Database_Progress.private_data.read_messages_serial(db, _context)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   299
      }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   300
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   301
      val res = body
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   302
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   303
      if (_serial != serial0) Database_Progress.private_data.update_agent(db, _agent_uuid, _serial)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   304
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   305
      res
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   306
    }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   307
  }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   308
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   309
  private def sync(): Unit = sync_database {}
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   310
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   311
  override def output(message: Progress.Message): Unit = sync_context { _consumer.send(message) }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   312
  override def theory(theory: Progress.Theory): Unit = sync_context { _consumer.send(theory) }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   313
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   314
  override def nodes_status(nodes_status: Document_Status.Nodes_Status): Unit =
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   315
    base_progress.nodes_status(nodes_status)
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   316
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   317
  override def verbose: Boolean = base_progress.verbose
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   318
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   319
  override def stop(): Unit = sync_context { base_progress.stop(); sync() }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   320
  override def stopped: Boolean = sync_context { base_progress.stopped }
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   321
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   322
  override def toString: String = super.toString + ": database " + db
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   323
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   324
  init()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   325
  sync()
6c19c29ddcbe clarified modules;
wenzelm
parents:
diff changeset
   326
}