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

 

Introduction

Documentation

Support

Miscellaneous