2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 #ifndef SQUID_RESOLVEDPEERS_H
10 #define SQUID_RESOLVEDPEERS_H
12 #include "base/RefCount.h"
13 #include "comm/forward.h"
19 class ResolvedPeerPath
22 explicit ResolvedPeerPath(const Comm::ConnectionPointer
&conn
) : connection(conn
), available(true) {}
24 Comm::ConnectionPointer connection
; ///< (the address of) a path
25 bool available
; ///< whether this path may be used (i.e., has not been tried already)
28 class PeerConnectionPointer
;
30 /// cache_peer and origin server addresses (a.k.a. paths)
31 /// selected and resolved by the peering code
32 class ResolvedPeers
: public RefCountable
34 MEMPROXY_CLASS(ResolvedPeers
);
37 // ResolvedPeerPaths in addPath() call order
38 typedef std::vector
<ResolvedPeerPath
> Paths
;
39 using size_type
= Paths::size_type
;
40 typedef RefCount
<ResolvedPeers
> Pointer
;
44 /// whether we lack any known candidate paths
45 bool empty() const { return !availablePaths
; }
47 /// add a candidate path to try after all the existing paths
48 void addPath(const Comm::ConnectionPointer
&);
50 /// makes the previously extracted path available for extraction at its
52 void reinstatePath(const PeerConnectionPointer
&);
54 /// extracts and returns the first queued address
55 PeerConnectionPointer
extractFront();
57 /// extracts and returns the first same-peer same-family address
58 /// \returns nil if it cannot find the requested address
59 PeerConnectionPointer
extractPrime(const Comm::Connection
¤tPeer
);
61 /// extracts and returns the first same-peer different-family address
62 /// \returns nil if it cannot find the requested address
63 PeerConnectionPointer
extractSpare(const Comm::Connection
¤tPeer
);
65 /// whether extractSpare() would return a non-nil path right now
66 bool haveSpare(const Comm::Connection
¤tPeer
);
68 /// whether extractPrime() returns and will continue to return nil
69 bool doneWithPrimes(const Comm::Connection
¤tPeer
);
71 /// whether extractSpare() returns and will continue to return nil
72 bool doneWithSpares(const Comm::Connection
¤tPeer
);
74 /// whether doneWithPrimes() and doneWithSpares() are true for currentPeer
75 bool doneWithPeer(const Comm::Connection
¤tPeer
);
77 /// the current number of candidate paths
78 size_type
size() const { return availablePaths
; }
80 /// whether all of the available candidate paths received from DNS
81 bool destinationsFinalized
= false;
83 /// whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
84 bool notificationPending
= false;
87 /// A find*() result: An iterator of the found path (or paths_.end()) and
88 /// whether the "other" path was found instead.
89 typedef std::pair
<Paths::iterator
, bool> Finding
;
91 /// The protocol family of the given path, AF_INET or AF_INET6
92 static int ConnectionFamily(const Comm::Connection
&conn
);
94 Paths::iterator
start();
95 Finding
findSpare(const Comm::Connection
¤tPeer
);
96 Finding
findPrime(const Comm::Connection
¤tPeer
);
97 Finding
findPeer(const Comm::Connection
¤tPeer
);
98 PeerConnectionPointer
extractFound(const char *description
, const Paths::iterator
&found
);
99 Finding
makeFinding(const Paths::iterator
&found
, bool foundOther
);
101 bool doneWith(const Finding
&findings
) const;
103 void increaseAvailability();
104 void decreaseAvailability();
106 Paths paths_
; ///< resolved addresses in (peer, family) order
108 /// the number of leading paths_ elements that are all currently unavailable
109 /// i.e. the size of the front paths_ segment comprised of unavailable items
110 /// i.e. the position of the first available path (or paths_.size())
111 size_type pathsToSkip
= 0;
113 /// the total number of currently available elements in paths_
114 size_type availablePaths
= 0;
117 /// An invasive reference-counting Comm::Connection pointer that also keeps an
118 /// (optional) ResolvedPeers position for the ResolvedPeers::reinstatePath() usage.
119 /// Reference counting mechanism is compatible with Comm::ConnectionPointer.
120 class PeerConnectionPointer
123 using size_type
= ResolvedPeers::size_type
;
125 PeerConnectionPointer() = default;
126 PeerConnectionPointer(std::nullptr_t
): PeerConnectionPointer() {} ///< implicit nullptr conversion
127 PeerConnectionPointer(const Comm::ConnectionPointer
&conn
, const size_type pos
): connection_(conn
), position_(pos
) {}
129 /* read-only pointer API; for Connection assignment, see finalize() */
130 explicit operator bool() const { return static_cast<bool>(connection_
); }
131 Comm::Connection
*operator->() const { assert(connection_
); return connection_
.getRaw(); }
132 Comm::Connection
&operator *() const { assert(connection_
); return *connection_
; }
134 /// convenience conversion to Comm::ConnectionPointer
135 operator const Comm::ConnectionPointer
&() const { return connection_
; }
137 /// upgrade stored peer selection details with a matching actual connection
138 void finalize(const Comm::ConnectionPointer
&conn
) { connection_
= conn
; }
141 void print(std::ostream
&) const;
144 /// non-existent position for nil connection
145 static constexpr auto npos
= std::numeric_limits
<size_type
>::max();
147 /// half-baked, open, failed, or closed Comm::Connection (or nil)
148 Comm::ConnectionPointer connection_
;
150 /// ResolvedPeers-maintained membership index (or npos)
151 size_type position_
= npos
;
152 friend class ResolvedPeers
;
155 /// summarized ResolvedPeers (for debugging)
156 std::ostream
&operator <<(std::ostream
&, const ResolvedPeers
&);
158 inline std::ostream
&
159 operator <<(std::ostream
&os
, const PeerConnectionPointer
&dest
)
165 #endif /* SQUID_RESOLVEDPEERS_H */