carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostclaim
2
3import (
4 "errors"
5 "fmt"
6)
7
8var (
9 ErrStaleOp = errors.New("hostclaim: the claim is under a different operation")
10 ErrWrongState = errors.New("hostclaim: transition not legal from the claim's state")
11 ErrPendingChore = errors.New("hostclaim: an obligation is pending in a location this operation writes")
12 // ErrRelocationFinishing is the completion barrier's refusal: the
13 // serving op journals a completed relocation that its box has not yet
14 // discharged. It is always returned wrapped with ErrPendingChore, so a
15 // caller that only knows ErrPendingChore refuses it the same way; the
16 // move door tells the two apart for its sentence.
17 ErrRelocationFinishing = errors.New("hostclaim: a completed relocation is not yet discharged")
18)
19
20func RequireOp(id string) func(*Claim) error {
21 return func(c *Claim) error {
22 if id == "" || c.Op.ID != id {
23 return fmt.Errorf("%w: have %q, want %q", ErrStaleOp, c.Op.ID, id)
24 }
25 return nil
26 }
27}
28
29// StartGuard is §4: one operation at a time, started from serving, and
30// CC11: never over a chore in a region or box the operation will write.
31// Region HA N13 (ruling 77): nor while a completed relocation's box has
32// not discharged its participation (completionBarrier). fencedCompletion
33// is completionBarrier's fencedSource (ruling 86): a box whose termination
34// fence the caller has verified (VerifyFence, under a FenceAuthority) for
35// this start, as a failover's start passes its source. "" when there is
36// no verified fence: never a box the caller has not verified, and never
37// one inferred from a missing fence.
38func StartGuard(c *Claim, regions, boxes []string, fencedCompletion string) error {
39 if c.Holder == nil || c.Op.Kind != KindServing {
40 return fmt.Errorf("%w: kind %q", ErrWrongState, c.Op.Kind)
41 }
42 if err := completionBarrier(c, fencedCompletion); err != nil {
43 return err
44 }
45 inR, inB := set(regions), set(boxes)
46 for _, o := range c.Obligations {
47 if (o.Region != "" && inR[o.Region]) || (o.Box != "" && inB[o.Box]) {
48 return fmt.Errorf("%w: %s %s%s", ErrPendingChore, o.Kind, o.Region, o.Box)
49 }
50 }
51 return nil
52}
53
54func set(xs []string) map[string]bool {
55 m := make(map[string]bool, len(xs))
56 for _, x := range xs {
57 m[x] = true
58 }
59 return m
60}
61