@@ -24,6 +24,7 @@ type MHMap struct {
2424 uniq map [* MH ]struct {}
2525 byIpp map [netip.AddrPort ]* MH // ip:port => MH
2626 byHostport map [string ]* MH // host:port => MH
27+ byAddr map [netip.Addr ]int // addr => refcount; for O(1) HasAddr
2728}
2829
2930func (m * MHMap ) All () (all []* MH ) {
@@ -57,6 +58,20 @@ func (m *MHMap) Endpoints() (all []string) {
5758 return
5859}
5960
61+ // HasAddr returns true if any endpoint in this map contains the given address.
62+ // It looks up byIpp directly for efficiency rather than iterating through all MHs.
63+ // HasAddr returns true if any endpoint in this map contains the given address.
64+ // Uses the byAddr index for O(1) lookup.
65+ func (m * MHMap ) HasAddr (addr netip.Addr ) bool {
66+ if m == nil || ! addr .IsValid () {
67+ return false
68+ }
69+ m .RLock ()
70+ defer m .RUnlock ()
71+ _ , ok := m .byAddr [addr ]
72+ return ok
73+ }
74+
6075func (m * MHMap ) Get (hostOrIpport string ) (h * MH , _ error ) {
6176 if m == nil {
6277 return nil , errMhNotFound
@@ -116,6 +131,8 @@ func (m *MHMap) putLocked(h *MH) (ok bool) {
116131 m .uniq [h ] = struct {}{}
117132 for _ , ipp := range ipps {
118133 m .byIpp [ipp ] = h
134+ // increment refcount for each unique addr (ignore port)
135+ m .byAddr [ipp .Addr ()]++
119136 }
120137 for _ , name := range names {
121138 m .byHostport [name ] = h
@@ -149,6 +166,13 @@ func (m *MHMap) delLocked(h *MH) (ok bool) {
149166 for _ , ip := range ipps {
150167 if x := m .byIpp [ip ]; x == h {
151168 delete (m .byIpp , ip )
169+ // decrement refcount for each unique addr (ignore port)
170+ a := ip .Addr ()
171+ if m .byAddr [a ] <= 1 {
172+ delete (m .byAddr , a )
173+ } else {
174+ m .byAddr [a ]--
175+ }
152176 }
153177 }
154178 for _ , name := range names {
@@ -263,5 +287,6 @@ func NewMap(id string) *MHMap {
263287 uniq : make (map [* MH ]struct {}),
264288 byIpp : make (map [netip.AddrPort ]* MH ),
265289 byHostport : make (map [string ]* MH ),
290+ byAddr : make (map [netip.Addr ]int ),
266291 }
267292}
0 commit comments