carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package registry
2
3import (
4 "database/sql"
5 "errors"
6 "time"
7)
8
9// The box's fence generation source. The activator's fences live in the
10// agent's memory and die with it, but a generation outlives the process:
11// the import journal stores the one its rollback fences under
12// (CloseImportGate), and a resumed rollback recognises and lifts its fence
13// by that number. A generation handed out after a restart must therefore
14// never equal one handed out before it, or the resumed rollback could take
15// another operation's fence for its own, or lift it.
16//
17// Each generation is the later of the wall clock in nanoseconds (the space
18// the layout pass and the moves cut draw theirs from) and one past the
19// last generation this registry handed out, which is stored before it is
20// returned. The stored floor survives a restart, so a clock that went back
21// cannot repeat a number; the clock covers a registry restored from an
22// older snapshot.
23
24func (r *Registry) migrateFenceGenerations() error {
25 _, err := r.sql.Exec(`CREATE TABLE IF NOT EXISTS fence_generation (
26 id INTEGER PRIMARY KEY CHECK (id = 1),
27 last INTEGER NOT NULL
28);`)
29 return err
30}
31
32// NextFenceGeneration hands out a fence generation no earlier call on this
33// registry file returned, across restarts: never 0, and above every
34// generation it handed out before. now is the wall clock.
35func (r *Registry) NextFenceGeneration(now time.Time) (uint64, error) {
36 var next int64
37 err := r.inTx(func(tx txer) error {
38 var last int64
39 err := tx.QueryRow(`SELECT last FROM fence_generation WHERE id = 1`).Scan(&last)
40 if err != nil && !errors.Is(err, sql.ErrNoRows) {
41 return err
42 }
43 next = max(now.UnixNano(), last+1, 1)
44 _, err = tx.Exec(`INSERT INTO fence_generation (id, last) VALUES (1, ?)
45ON CONFLICT(id) DO UPDATE SET last = excluded.last`, next)
46 return err
47 })
48 if err != nil {
49 return 0, err
50 }
51 return uint64(next), nil
52}
53