ResolvedPeers.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2020 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 {
18  if (Config.forward_max_tries > 0)
20 }
21 
22 void
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 
45 void
47 {
48  paths_.emplace_back(path);
49  Must(paths_.back().available); // no pathsToSkip updates are needed
51 }
52 
54 ResolvedPeers::Paths::iterator
56 {
57  Must(pathsToSkip <= paths_.size());
58  return paths_.begin() + pathsToSkip; // may return end()
59 }
60 
63 ResolvedPeers::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 
141 ResolvedPeers::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->cloneDestinationDetails();
155  return PeerConnectionPointer(cleanPath, found - paths_.begin());
156 }
157 
158 bool
160 {
161  return findSpare(currentPeer).first != paths_.end();
162 }
163 
166 bool
167 ResolvedPeers::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 
178 bool
180 {
181  return doneWith(findSpare(currentPeer));
182 }
183 
184 bool
186 {
187  return doneWith(findPrime(currentPeer));
188 }
189 
190 bool
192 {
193  return doneWith(findPeer(currentPeer));
194 }
195 
196 int
198 {
199  return conn.remote.isIPv4() ? AF_INET : AF_INET6;
200 }
201 
203 void
205 {
206  ++availablePaths;
207  assert(availablePaths <= paths_.size());
208 }
209 
211 void
213 {
214  assert(availablePaths > 0);
215  --availablePaths;
216 }
217 
218 std::ostream &
219 operator <<(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 
228 void
229 PeerConnectionPointer::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 }
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:81
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)
Finding findPeer(const Comm::Connection &currentPeer)
Paths::size_type size_type
Definition: ResolvedPeers.h:39
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:45
static constexpr auto npos
non-existent position for nil connection
std::pair< Paths::iterator, bool > Finding
Definition: ResolvedPeers.h:89
bool haveSpare(const Comm::Connection &currentPeer)
whether extractSpare() would return a non-nil path right now
PeerConnectionPointer extractPrime(const Comm::Connection &currentPeer)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:128
void decreaseAvailability()
decrements the number of available paths
#define true
Definition: GnuRegex.c:234
PeerConnectionPointer extractFound(const char *description, const Paths::iterator &found)
convenience method to finish a successful extract*() call
CachePeer * getPeer() const
Definition: Connection.cc:105
Paths::iterator start()
Paths paths_
resolved addresses in (peer, family) order
size_type pathsToSkip
int conn
the current server connection FD
Definition: Transport.cc:26
#define assert(EX)
Definition: assert.h:19
PeerConnectionPointer extractSpare(const Comm::Connection &currentPeer)
size_type size() const
the current number of candidate paths
Definition: ResolvedPeers.h:78
bool doneWithPeer(const Comm::Connection &currentPeer)
whether doneWithPrimes() and doneWithSpares() are true for currentPeer
void reinstatePath(const PeerConnectionPointer &)
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
int forward_max_tries
Definition: SquidConfig.h:355
void increaseAvailability()
increments the number of available paths
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

Web Site Translations

Mirrors