PeerPoolMgr.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 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 "AccessLogEntry.h"
11 #include "base/AsyncJobCalls.h"
12 #include "base/RunnersRegistry.h"
13 #include "CachePeer.h"
14 #include "comm/Connection.h"
15 #include "comm/ConnOpener.h"
16 #include "Debug.h"
17 #include "fd.h"
18 #include "FwdState.h"
19 #include "globals.h"
20 #include "HttpRequest.h"
21 #include "MasterXaction.h"
22 #include "neighbors.h"
23 #include "pconn.h"
24 #include "PeerPoolMgr.h"
26 #include "SquidConfig.h"
27 #include "SquidTime.h"
28 
30 
32 class MyAnswerDialer: public UnaryMemFunT<PeerPoolMgr, Security::EncryptorAnswer, Security::EncryptorAnswer&>,
34 {
35 public:
36  MyAnswerDialer(const JobPointer &aJob, Method aMethod):
37  UnaryMemFunT<PeerPoolMgr, Security::EncryptorAnswer, Security::EncryptorAnswer&>(aJob, aMethod, Security::EncryptorAnswer()) {}
38 
39  /* Security::PeerConnector::CbDialer API */
40  virtual Security::EncryptorAnswer &answer() { return arg1; }
41 };
42 
44  peer(cbdataReference(aPeer)),
45  request(),
46  transportWait(),
47  encryptionWait(),
48  addrUsed(0)
49 {
50 }
51 
53 {
55 }
56 
57 void
59 {
61 
63  // ErrorState, getOutgoingAddress(), and other APIs may require a request.
64  // We fake one. TODO: Optionally send this request to peers?
67 
68  checkpoint("peer initialized");
69 }
70 
71 void
73 {
75 }
76 
77 bool
79 {
81 }
82 
83 bool
85 {
86  return !(validPeer() && peer->standby.limit) && AsyncJob::doneAll();
87 }
88 
89 void
91 {
92  transportWait.finish();
93 
94  if (!validPeer()) {
95  debugs(48, 3, "peer gone");
96  if (params.conn != NULL)
97  params.conn->close();
98  return;
99  }
100 
101  if (params.flag != Comm::OK) {
103  checkpoint("conn opening failure"); // may retry
104  return;
105  }
106 
107  Must(params.conn != NULL);
108 
109  // Handle TLS peers.
111  // XXX: Exceptions orphan params.conn
112  AsyncCall::Pointer callback = asyncCall(48, 4, "PeerPoolMgr::handleSecuredPeer",
114 
115  const auto peerTimeout = peer->connectTimeout();
116  const int timeUsed = squid_curtime - params.conn->startTime();
117  // Use positive timeout when less than one second is left for conn.
118  const int timeLeft = positiveTimeout(peerTimeout - timeUsed);
119  const auto connector = new Security::BlindPeerConnector(request, params.conn, callback, nullptr, timeLeft);
120  encryptionWait.start(connector, callback);
121  return;
122  }
123 
124  pushNewConnection(params.conn);
125 }
126 
127 void
129 {
130  Must(validPeer());
132  peer->standby.pool->push(conn, NULL /* domain */);
133  // push() will trigger a checkpoint()
134 }
135 
136 void
138 {
139  encryptionWait.finish();
140 
141  if (!validPeer()) {
142  debugs(48, 3, "peer gone");
143  if (answer.conn != NULL)
144  answer.conn->close();
145  return;
146  }
147 
148  assert(!answer.tunneled);
149  if (answer.error.get()) {
150  assert(!answer.conn);
151  // PeerConnector calls peerConnectFailed() for us;
152  checkpoint("conn securing failure"); // may retry
153  return;
154  }
155 
156  assert(answer.conn);
157 
158  // The socket could get closed while our callback was queued. Sync
159  // Connection. XXX: Connection::fd may already be stale/invalid here.
160  if (answer.conn->isOpen() && fd_table[answer.conn->fd].closing()) {
161  answer.conn->noteClosure();
162  checkpoint("external connection closure"); // may retry
163  return;
164  }
165 
166  pushNewConnection(answer.conn);
167 }
168 
169 void
171 {
172  // KISS: Do nothing else when we are already doing something.
174  debugs(48, 7, "busy: " << transportWait << '|' << encryptionWait << '|' << shutting_down);
175  return; // there will be another checkpoint when we are done opening/securing
176  }
177 
178  // Do not talk to a peer until it is ready.
179  if (!neighborUp(peer)) // provides debugging
180  return; // there will be another checkpoint when peer is up
181 
182  // Do not violate peer limits.
183  if (!peerCanOpenMore(peer)) { // provides debugging
184  peer->standby.waitingForClose = true; // may already be true
185  return; // there will be another checkpoint when a peer conn closes
186  }
187 
188  // Do not violate global restrictions.
189  if (fdUsageHigh()) {
190  debugs(48, 7, "overwhelmed");
191  peer->standby.waitingForClose = true; // may already be true
192  // There will be another checkpoint when a peer conn closes OR when
193  // a future pop() fails due to an empty pool. See PconnPool::pop().
194  return;
195  }
196 
197  peer->standby.waitingForClose = false;
198 
200  Must(peer->n_addresses); // guaranteed by neighborUp() above
201  // cycle through all available IP addresses
202  conn->remote = peer->addresses[addrUsed++ % peer->n_addresses];
203  conn->remote.port(peer->http_port);
204  conn->peerType = STANDBY_POOL; // should be reset by peerSelect()
205  conn->setPeer(peer);
208 
209  const auto ctimeout = peer->connectTimeout();
211  AsyncCall::Pointer callback = JobCallback(48, 5, Dialer, this, PeerPoolMgr::handleOpenedConnection);
212  const auto cs = new Comm::ConnOpener(conn, callback, ctimeout);
213  transportWait.start(cs, callback);
214 }
215 
216 void
218 {
219  debugs(48, 8, howMany);
220  peer->standby.pool->closeN(howMany);
221 }
222 
223 void
224 PeerPoolMgr::checkpoint(const char *reason)
225 {
226  if (!validPeer()) {
227  debugs(48, 3, reason << " and peer gone");
228  return; // nothing to do after our owner dies; the job will quit
229  }
230 
231  const int count = peer->standby.pool->count();
232  const int limit = peer->standby.limit;
233  debugs(48, 7, reason << " with " << count << " ? " << limit);
234 
235  if (count < limit)
237  else if (count > limit)
238  closeOldConnections(count - limit);
239 }
240 
241 void
242 PeerPoolMgr::Checkpoint(const Pointer &mgr, const char *reason)
243 {
244  CallJobHere1(48, 5, mgr, PeerPoolMgr, checkpoint, reason);
245 }
246 
249 {
250 public:
251  /* RegisteredRunner API */
252  virtual void useConfig() { syncConfig(); }
253  virtual void syncConfig();
254 };
255 
257 
258 void
260 {
261  for (CachePeer *p = Config.peers; p; p = p->next) {
262  // On reconfigure, Squid deletes the old config (and old peers in it),
263  // so should always be dealing with a brand new configuration.
264  assert(!p->standby.mgr);
265  assert(!p->standby.pool);
266  if (p->standby.limit) {
267  p->standby.mgr = new PeerPoolMgr(p);
268  p->standby.pool = new PconnPool(p->name, p->standby.mgr);
269  AsyncJob::Start(p->standby.mgr.get());
270  }
271  }
272 }
273 
bool waitingForClose
a conn must close before we open a standby conn
Definition: CachePeer.h:184
void handleSecuredPeer(Security::EncryptorAnswer &answer)
Security::PeerConnector callback.
Definition: PeerPoolMgr.cc:137
Maintains an fixed-size "standby" PconnPool for a single CachePeer.
Definition: PeerPoolMgr.h:23
void closeN(int n)
closes any n connections, regardless of their destination
Definition: pconn.cc:507
Ip::Address addresses[10]
Definition: CachePeer.h:150
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
bool tunneled
whether we spliced the connections instead of negotiating encryption
JobWait< Security::BlindPeerConnector > encryptionWait
waits for the established transport connection to be secured/encrypted
Definition: PeerPoolMgr.h:69
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1299
virtual void swanSong()
Definition: AsyncJob.h:59
CbcPointer< ErrorState > error
problem details (nil on success)
int fdUsageHigh(void)
Definition: fd.cc:302
PconnPool * pool
idle connection pool for this peer
Definition: CachePeer.h:181
@ initPeerPool
PeerPool manager.
void handleOpenedConnection(const CommConnectCbParams &params)
Comm::ConnOpener calls this when done opening a connection for us.
Definition: PeerPoolMgr.cc:90
@ STANDBY_POOL
Definition: hier_code.h:37
struct CachePeer::@35 standby
optional "cache_peer standby=limit" feature
JobWait< Comm::ConnOpener > transportWait
waits for a transport connection to the peer to be established/opened
Definition: PeerPoolMgr.h:66
Gives Security::PeerConnector access to Answer in the PeerPoolMgr callback dialer.
Definition: PeerPoolMgr.cc:34
C * getRaw() const
Definition: RefCount.h:80
time_t startTime() const
Definition: Connection.h:118
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:398
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
@ OK
Definition: Flag.h:16
virtual void syncConfig()
Definition: PeerPoolMgr.cc:259
int limit
the limit itself
Definition: CachePeer.h:183
time_t connectTimeout() const
Definition: CachePeer.cc:51
#define cbdataReference(var)
Definition: cbdata.h:341
virtual void swanSong()
Definition: PeerPoolMgr.cc:72
CachePeer * peer
the owner of the pool we manage
Definition: PeerPoolMgr.h:62
@ METHOD_OPTIONS
Definition: MethodType.h:31
void getOutgoingAddress(HttpRequest *request, const Comm::ConnectionPointer &conn)
Definition: FwdState.cc:1509
unsigned int addrUsed
counter for cycling through peer addresses
Definition: PeerPoolMgr.h:71
MyAnswerDialer(const JobPointer &aJob, Method aMethod)
Definition: PeerPoolMgr.cc:36
Comm::ConnectionPointer conn
peer connection (secured on success)
bool validPeer() const
whether the peer is still out there and in a valid state we can safely use
Definition: PeerPoolMgr.cc:78
#define NULL
Definition: types.h:166
virtual bool doneAll() const
whether positive goal has been reached
Definition: AsyncJob.cc:97
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
launches PeerPoolMgrs for peers configured with standby.limit
Definition: PeerPoolMgr.cc:249
int n_addresses
Definition: CachePeer.h:151
void count(int uses)
void push(const Comm::ConnectionPointer &serverConn, const char *domain)
Definition: pconn.cc:412
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:57
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
int conn
the current server connection FD
Definition: Transport.cc:26
#define assert(EX)
Definition: assert.h:19
SSL Connection
Definition: Session.h:45
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:87
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
Definition: AsyncJobCalls.h:69
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
bool peerCanOpenMore(const CachePeer *p)
Whether we can open new connections to the peer (e.g., despite max-conn)
Definition: neighbors.cc:224
time_t squid_curtime
Definition: stub_time.cc:17
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: PeerPoolMgr.cc:40
A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
#define fd_table
Definition: fde.h:189
void start(const JobPointer &aJob, const AsyncCall::Pointer &aCallback)
starts waiting for the given job to call the given callback
Definition: JobWait.h:69
time_t positiveTimeout(const time_t timeout)
Definition: neighbors.cc:1196
void openNewConnection()
starts the process of opening a new standby connection (if possible)
Definition: PeerPoolMgr.cc:170
@ PROTO_HTTP
Definition: ProtocolType.h:25
char * host
Definition: CachePeer.h:40
RunnerRegistrationEntry(PeerPoolMgrsRr)
PeerPoolMgr(CachePeer *aPeer)
Definition: PeerPoolMgr.cc:43
void checkpoint(const char *reason)
Definition: PeerPoolMgr.cc:224
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:44
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:73
int neighborUp(const CachePeer *p)
Definition: neighbors.cc:1164
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
CachePeer * peers
Definition: SquidConfig.h:252
virtual void start()
called by AsyncStart; do not call directly
Definition: PeerPoolMgr.cc:58
int shutting_down
virtual ~PeerPoolMgr()
Definition: PeerPoolMgr.cc:52
bool encryptTransport
whether transport encryption (TLS/SSL) is to be used on connections to the peer
Definition: PeerOptions.h:145
virtual void useConfig()
Definition: PeerPoolMgr.cc:252
bool isOpen() const
Definition: Connection.h:99
CachePeer * next
Definition: CachePeer.h:153
void pushNewConnection(const Comm::ConnectionPointer &conn)
the final step in connection opening (and, optionally, securing) sequence
Definition: PeerPoolMgr.cc:128
static void Checkpoint(const Pointer &mgr, const char *reason)
Definition: PeerPoolMgr.cc:242
Network/connection security abstraction layer.
Definition: Connection.h:34
Security::PeerOptions secure
security settings for peer connection
Definition: CachePeer.h:190
void host(const char *src)
Definition: Uri.cc:98
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
unsigned short http_port
Definition: CachePeer.h:77
virtual bool doneAll() const
whether positive goal has been reached
Definition: PeerPoolMgr.cc:84
void closeOldConnections(const int howMany)
closes 'howMany' standby connections
Definition: PeerPoolMgr.cc:217
class SquidConfig Config
Definition: SquidConfig.cc:12
void GetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1588
RefCount< HttpRequest > request
fake HTTP request for conn opening code
Definition: PeerPoolMgr.h:63
static void Start(const Pointer &job)
Definition: AsyncJob.cc:24
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:63

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors