| 1 | package hostguard |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "github.com/carlosframework/platform/internal/hostclaim" |
| 6 | ) |
| 7 | |
| 8 | // AdmissionFenced reports whether the host's admission is closed for the |
| 9 | // installation and session captured names on claim c. It is With's own |
| 10 | // reading of the record (record.admits), exposed for region HA §5.3's row |
| 11 | // decision ("the source in releasing until its admission fence closes"): |
| 12 | // closed whenever With would refuse on the record, so a stop root that |
| 13 | // began (ActiveFence) or completed (a FenceJournal receipt) for that |
| 14 | // session, and also an inactive or retired installation, a stamp that is |
| 15 | // not the active one, or another incarnation on the record. Absence is |
| 16 | // never evidence: a retired fenced installation still reads closed. With's |
| 17 | // other refusals (no record, a malformed record, a claim for another host |
| 18 | // or incarnation) are errors, never "open". It takes no lock: the record |
| 19 | // is replaced atomically, and callers already hold the host lock |
| 20 | // (Activate's reader, WithLocal) or need no lock for one consistent read. |
| 21 | // The claim is the caller's fresh read. It grants nothing. |
| 22 | func (g Guard) AdmissionFenced(host string, c *hostclaim.Claim, captured Captured) (bool, error) { |
| 23 | if c == nil || c.Holder == nil { |
| 24 | return false, ErrNoHolder |
| 25 | } |
| 26 | if c.Host != host || c.Holder.Incarnation == "" { |
| 27 | return false, ErrMalformedClaim |
| 28 | } |
| 29 | if c.Holder.Incarnation != captured.Incarnation { |
| 30 | return false, ErrClaimIncarnation |
| 31 | } |
| 32 | if g.Root != nil { |
| 33 | r, err := g.Root.read(host) |
| 34 | if err != nil { |
| 35 | return false, err |
| 36 | } |
| 37 | return r.admits(c, captured) != nil, nil |
| 38 | } |
| 39 | if g.FenceView != nil { |
| 40 | v, err := g.FenceView(context.Background(), host, captured) |
| 41 | if err != nil { |
| 42 | return false, err |
| 43 | } |
| 44 | if err := v.validate(host, captured); err != nil { |
| 45 | return false, err |
| 46 | } |
| 47 | if v.admit(host, captured, c.Holder.Session) != nil { |
| 48 | return true, nil |
| 49 | } |
| 50 | } |
| 51 | r, err := readRecord(g.DataDir, host) |
| 52 | if err != nil { |
| 53 | return false, err |
| 54 | } |
| 55 | // Every refusal admits gives is a record state, never a read failure. |
| 56 | return r.admits(c, captured) != nil, nil |
| 57 | } |
| 58 | |