ResolvedPeers.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
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.
7 */
8
9#include "squid.h"
10#include "CachePeer.h"
11#include "comm/Connection.h"
12#include "comm/ConnOpener.h"
13#include "ResolvedPeers.h"
14#include "SquidConfig.h"
15
17{
20}
21
22void
24{
25 debugs(17, 4, path);
26 assert(path);
27
28 const auto pos = path.position_;
29 assert(pos < paths_.size());
30
31 assert(!paths_[pos].available);
32 paths_[pos].available = true;
34
35 // if we restored availability of a path that we used to skip, update
36 const auto pathsToTheLeft = pos;
37 if (pathsToTheLeft < pathsToSkip) {
38 pathsToSkip = pathsToTheLeft;
39 } else {
40 // *found was unavailable so pathsToSkip could not end at it
41 Must(pathsToTheLeft != pathsToSkip);
42 }
43}
44
45void
47{
48 paths_.emplace_back(path);
49 Must(paths_.back().available); // no pathsToSkip updates are needed
51}
52
54ResolvedPeers::Paths::iterator
56{
57 Must(pathsToSkip <= paths_.size());
58 return paths_.begin() + pathsToSkip; // may return end()
59}
60
63ResolvedPeers::makeFinding(const Paths::iterator &path, bool foundOther)
64{
65 return std::make_pair((foundOther ? paths_.end() : path), foundOther);
66}
67
71{
72 const auto path = start();
73 const auto foundNextOrSpare = path != paths_.end() &&
74 (currentPeer.getPeer() != path->connection->getPeer() || // next peer
75 ConnectionFamily(currentPeer) != ConnectionFamily(*path->connection));
76 return makeFinding(path, foundNextOrSpare);
77}
78
82{
83 const auto primeFamily = ConnectionFamily(currentPeer);
84 const auto primePeer = currentPeer.getPeer();
85 const auto path = std::find_if(start(), paths_.end(),
86 [primeFamily, primePeer](const ResolvedPeerPath &candidate) {
87 if (!candidate.available)
88 return false;
89 if (primePeer != candidate.connection->getPeer())
90 return true; // found next peer
91 if (primeFamily != ConnectionFamily(*candidate.connection))
92 return true; // found spare
93 return false;
94 });
95 const auto foundNext = path != paths_.end() &&
96 primePeer != path->connection->getPeer();
97 return makeFinding(path, foundNext);
98}
99
103{
104 const auto path = start();
105 const auto foundNext = path != paths_.end() &&
106 currentPeer.getPeer() != path->connection->getPeer();
107 return makeFinding(path, foundNext);
108}
109
112{
113 Must(!empty());
114 return extractFound("first: ", start());
115}
116
119{
120 const auto found = findPrime(currentPeer).first;
121 if (found != paths_.end())
122 return extractFound("same-peer same-family match: ", found);
123
124 debugs(17, 7, "no same-peer same-family paths");
125 return nullptr;
126}
127
130{
131 const auto found = findSpare(currentPeer).first;
132 if (found != paths_.end())
133 return extractFound("same-peer different-family match: ", found);
134
135 debugs(17, 7, "no same-peer different-family paths");
136 return nullptr;
137}
138
141ResolvedPeers::extractFound(const char *description, const Paths::iterator &found)
142{
143 auto &path = *found;
144 debugs(17, 7, description << path.connection);
145 assert(path.available);
146 path.available = false;
148
149 // if we extracted the left-most available path, find the next one
150 if (static_cast<size_type>(found - paths_.begin()) == pathsToSkip) {
151 while (++pathsToSkip < paths_.size() && !paths_[pathsToSkip].available) {}
152 }
153
154 const auto cleanPath = path.connection->cloneProfile();
155 return PeerConnectionPointer(cleanPath, found - paths_.begin());
156}
157
158bool
160{
161 return findSpare(currentPeer).first != paths_.end();
162}
163
166bool
167ResolvedPeers::doneWith(const Finding &findings) const
168{
169 if (findings.first != paths_.end())
170 return false; // not done because the caller found a viable path X
171
172 // The caller did not find any path X. If the caller found any "other"
173 // paths, then we are done with paths X. If there are no "other" paths,
174 // then destinationsFinalized is the answer.
175 return findings.second ? true : destinationsFinalized;
176}
177
178bool
180{
181 return doneWith(findSpare(currentPeer));
182}
183
184bool
186{
187 return doneWith(findPrime(currentPeer));
188}
189
190bool
192{
193 return doneWith(findPeer(currentPeer));
194}
195
196int
198{
199 return conn.remote.isIPv4() ? AF_INET : AF_INET6;
200}
201
203void
205{
207 assert(availablePaths <= paths_.size());
208}
209
211void
213{
216}
217
218std::ostream &
219operator <<(std::ostream &os, const ResolvedPeers &peers)
220{
221 if (peers.empty())
222 return os << "[no paths]";
223 return os << peers.size() << (peers.destinationsFinalized ? "" : "+") << " paths";
224}
225
226/* PeerConnectionPointer */
227
228void
229PeerConnectionPointer::print(std::ostream &os) const
230{
231 // We should see no combinations of a nil connection and a set position
232 // because assigning nullptr (to our smart pointer) naturally erases both
233 // fields. We report such unexpected combinations for debugging sake, but do
234 // not complicate this code to report them beautifully.
235
236 if (connection_)
237 os << connection_;
238
239 if (position_ != npos)
240 os << " @" << position_;
241}
242
std::ostream & operator<<(std::ostream &os, const ResolvedPeers &peers)
summarized ResolvedPeers (for debugging)
class SquidConfig Config
Definition: SquidConfig.cc:12
#define Must(condition)
Definition: TextException.h:71
int conn
the current server connection FD
Definition: Transport.cc:26
#define assert(EX)
Definition: assert.h:17
CachePeer * getPeer() const
Definition: Connection.cc:124
Comm::ConnectionPointer connection_
half-baked, open, failed, or closed Comm::Connection (or nil)
void print(std::ostream &) const
debugging dump
static constexpr auto npos
non-existent position for nil connection
size_type position_
ResolvedPeers-maintained membership index (or npos)
Finding makeFinding(const Paths::iterator &found, bool foundOther)
finalizes the iterator part of the given preliminary find*() result
Paths paths_
resolved addresses in (peer, family) order
PeerConnectionPointer extractFront()
extracts and returns the first queued address
bool doneWith(const Finding &findings) const
size_type pathsToSkip
bool haveSpare(const Comm::Connection &currentPeer)
whether extractSpare() would return a non-nil path right now
Finding findPrime(const Comm::Connection &currentPeer)
void increaseAvailability()
increments the number of available paths
Finding findSpare(const Comm::Connection &currentPeer)
Paths::iterator start()
size_type availablePaths
the total number of currently available elements in paths_
static int ConnectionFamily(const Comm::Connection &conn)
The protocol family of the given path, AF_INET or AF_INET6.
bool doneWithPrimes(const Comm::Connection &currentPeer)
whether extractPrime() returns and will continue to return nil
std::pair< Paths::iterator, bool > Finding
Definition: ResolvedPeers.h:89
bool doneWithPeer(const Comm::Connection &currentPeer)
whether doneWithPrimes() and doneWithSpares() are true for currentPeer
void reinstatePath(const PeerConnectionPointer &)
size_type size() const
the current number of candidate paths
Definition: ResolvedPeers.h:78
PeerConnectionPointer extractFound(const char *description, const Paths::iterator &found)
convenience method to finish a successful extract*() call
Paths::size_type size_type
Definition: ResolvedPeers.h:39
PeerConnectionPointer extractSpare(const Comm::Connection &currentPeer)
void decreaseAvailability()
decrements the number of available paths
bool empty() const
whether we lack any known candidate paths
Definition: ResolvedPeers.h:45
bool destinationsFinalized
whether all of the available candidate paths received from DNS
Definition: ResolvedPeers.h:81
void addPath(const Comm::ConnectionPointer &)
add a candidate path to try after all the existing paths
Finding findPeer(const Comm::Connection &currentPeer)
PeerConnectionPointer extractPrime(const Comm::Connection &currentPeer)
bool doneWithSpares(const Comm::Connection &currentPeer)
whether extractSpare() returns and will continue to return nil
int forward_max_tries
Definition: SquidConfig.h:349
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:193

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors