package checker import ( "sort" ) // Idempotent: rules and report both call it; both must see the same grouping. func deriveView(data *ResolverPropagationData) { if data == nil { return } for key, view := range data.RRsets { // Reset derived fields so repeated calls stay idempotent. view.Groups = nil view.ConsensusSig = "" view.Agreeing = nil view.Dissenting = nil view.MatchesExpected = false voteCount := map[string]int{} type group struct { rcode string records []string resolvers []string } groups := map[string]*group{} for _, rv := range data.Resolvers { p := rv.Probes[key] if p == nil || p.Error != "" { continue } g := groups[p.Signature] if g == nil { g = &group{rcode: p.Rcode, records: p.Records} groups[p.Signature] = g } g.resolvers = append(g.resolvers, rv.ID) if !rv.Filtered { voteCount[p.Signature]++ } } // Pick the winning signature, preferring NOERROR responses. var winSig string var winVotes int for sig, g := range groups { if g.rcode != "NOERROR" && winSig != "" { continue } if voteCount[sig] > winVotes { winSig = sig winVotes = voteCount[sig] } } if winSig == "" { for sig := range groups { winSig = sig break } } view.ConsensusSig = winSig type gEntry struct { sig string g *group } var entries []gEntry for s, g := range groups { sort.Strings(g.resolvers) entries = append(entries, gEntry{sig: s, g: g}) } sort.Slice(entries, func(i, j int) bool { return len(entries[i].g.resolvers) > len(entries[j].g.resolvers) }) for _, e := range entries { view.Groups = append(view.Groups, SignatureGroup{ Signature: e.sig, Records: e.g.records, Resolvers: e.g.resolvers, Rcode: e.g.rcode, }) if e.sig == winSig { view.Agreeing = append(view.Agreeing, e.g.resolvers...) } else { view.Dissenting = append(view.Dissenting, e.g.resolvers...) } } sort.Strings(view.Agreeing) sort.Strings(view.Dissenting) if view.Expected != "" { view.MatchesExpected = view.ConsensusSig == view.Expected } } // Recompute UnfilteredAgreeing from the consensus we just built. agree := 0 for _, rv := range data.Resolvers { if rv.Filtered || !rv.Reachable { continue } ok := true for key, p := range rv.Probes { if p == nil || p.Error != "" { continue } v := data.RRsets[key] if v == nil || v.ConsensusSig == "" { continue } if p.Signature != v.ConsensusSig { ok = false break } } if ok { agree++ } } data.Stats.UnfilteredAgreeing = agree }