carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package rootparticipation
2
3import (
4 "context"
5 "errors"
6 "os"
7 "sync"
8
9 "github.com/carlosframework/platform/internal/hostwrite"
10
11 "github.com/carlosframework/platform/internal/rootstate"
12)
13
14var launchVerifier struct {
15 sync.RWMutex
16 verify func(context.Context, uint64) error
17 exclude func(context.Context, func(context.Context) error) error
18}
19
20// RegisterLaunchVerifier binds E2's root reservation and kernel census reader.
21// It runs under participation exclusion and must not call the agent or broker.
22func RegisterLaunchVerifier(verify func(context.Context, uint64) error, exclude func(context.Context, func(context.Context) error) error) error {
23 launchVerifier.Lock()
24 defer launchVerifier.Unlock()
25 if verify == nil || exclude == nil || launchVerifier.verify != nil {
26 return ErrUnavailable
27 }
28 launchVerifier.verify = verify
29 launchVerifier.exclude = exclude
30 return nil
31}
32
33func Open() (Ledger, error) {
34 state, err := rootstate.Open(Namespace, false, false)
35 if err != nil {
36 return Ledger{}, err
37 }
38 launchVerifier.RLock()
39 verify, exclude := launchVerifier.verify, launchVerifier.exclude
40 launchVerifier.RUnlock()
41 return Ledger{State: state, VerifyLaunches: verify, ExcludeLaunches: exclude}, nil
42}
43
44func VerifyLaunchCensus(ctx context.Context, revision uint64) error {
45 launchVerifier.RLock()
46 verify := launchVerifier.verify
47 launchVerifier.RUnlock()
48 if verify == nil {
49 return ErrUnavailable
50 }
51 return verify(ctx, revision)
52}
53
54// UpdateRequired keeps a retained census authoritative after claims are disabled.
55// Only an absent census with the flag off selects the legacy update protocol.
56func (l Ledger) UpdateRequired() (bool, error) {
57 if hostwrite.Enabled(os.Getenv) {
58 return true, nil
59 }
60 if l.State == nil {
61 return false, ErrUnavailable
62 }
63 _, err := l.State.Read("census.json")
64 if errors.Is(err, os.ErrNotExist) {
65 return false, nil
66 }
67 return true, err
68}
69
70func OpenForUpdate() (Ledger, bool, error) {
71 l, err := Open()
72 if errors.Is(err, os.ErrNotExist) {
73 return Ledger{}, false, nil
74 }
75 if err != nil {
76 return Ledger{}, false, err
77 }
78 _, err = l.State.Read("census.json")
79 if errors.Is(err, os.ErrNotExist) {
80 l.State.Close()
81 return Ledger{}, false, nil
82 }
83 required, err := l.UpdateRequired()
84 if err != nil {
85 l.State.Close()
86 return Ledger{}, false, err
87 }
88 return l, required, nil
89}
90
91func (l Ledger) ActivationReady(ctx context.Context) error {
92 c, err := l.Census()
93 if err != nil {
94 return err
95 }
96 if l.VerifyLaunches == nil {
97 return ErrUnavailable
98 }
99 return l.VerifyLaunches(ctx, c.LaunchRevision)
100}
101
102func WithLaunchExclusion(ctx context.Context, fn func(context.Context) error) error {
103 launchVerifier.RLock()
104 exclude := launchVerifier.exclude
105 launchVerifier.RUnlock()
106 if exclude == nil {
107 return ErrUnavailable
108 }
109 return exclude(ctx, fn)
110}
111
112func (l Ledger) WithLaunchExclusion(ctx context.Context, fn func(context.Context) error) error {
113 if l.ExcludeLaunches == nil {
114 return ErrUnavailable
115 }
116 return l.ExcludeLaunches(ctx, fn)
117}
118