package link import "strconv" // The order of a node's facts (novox/hq ADR 0539 §9, to-be 45 §6, ADR 0227 rule 2). // // A node-engine says its facts (profile, firewall found, reachable, tunnel, witness, rollbacks, rekey, health) in a report // on the bus, and orders them itself: `epoch` and `sequence` are the node-engine's own (Writer `node-engine`), and // `report_sequence` numbers each report it makes. The controller keeps the newest account of a machine and refuses an older // one, said and counted (rule 2): by epoch, then sequence, then report sequence, each compared only where both claim one. // Zero is "no order claimed", never "first". The controller sends a machine no declaration to be ordered by: the order here // is only ever the machine's own. // Order is where a node-engine's account stands among its own: the epoch and sequence the node-engine counts. Zero in either // claims none. type Order struct { Epoch int64 `json:"epoch,omitempty"` Sequence int64 `json:"sequence,omitempty"` } // Words is an order as a person reads it in a log line. Not String: Report embeds Order, and a Stringer // promoted onto every report would print each one as its order alone. func (o Order) Words() string { switch { case o.Epoch > 0: return "epoch " + strconv.FormatInt(o.Epoch, 10) + ", sequence " + strconv.FormatInt(o.Sequence, 10) case o.Sequence > 0: return "sequence " + strconv.FormatInt(o.Sequence, 10) + ", no epoch" } return "no order" } // Account is the order of one account of a machine — a report about a declaration: that declaration's // order and the node-engine's own number for the report. type Account struct { Order ReportSequence int64 } // AccountOf is a report's account order. func AccountOf(r Report) Account { return Account{Order: r.Order, ReportSequence: r.ReportSequence} } // Ordered says a report comes from a node-engine that orders its reports: it carries a report sequence. // Such a report is judged by its order (OlderThan); one without is judged by the digest it names, as // before (issue 267). func (r Report) Ordered() bool { return r.ReportSequence > 0 } // OlderThan is the controller's rule (to-be 45 §6): whether this account is older than the one kept for // the machine — **by epoch, then sequence, then report sequence**, each compared only where both claim // one. An account of a declaration of an older epoch is refused; of an older sequence, refused; an older // report of the same declaration (a reconcile's, overtaken by the apply's — issue 267), refused. Equal is // the same report again, redelivered, and is not refused. func (a Account) OlderThan(kept Account) bool { if a.Epoch > 0 && kept.Epoch > 0 && a.Epoch != kept.Epoch { return a.Epoch < kept.Epoch } if a.Sequence > 0 && kept.Sequence > 0 && a.Sequence != kept.Sequence { return a.Sequence < kept.Sequence } return a.ReportSequence > 0 && kept.ReportSequence > 0 && a.ReportSequence < kept.ReportSequence }