PeerPoolMgr.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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  opener(),
47  securer(),
48  closer(),
49  addrUsed(0)
50 {
51 }
52 
54 {
56 }
57 
58 void
60 {
62 
64  // ErrorState, getOutgoingAddress(), and other APIs may require a request.
65  // We fake one. TODO: Optionally send this request to peers?
68 
69  checkpoint("peer initialized");
70 }
71 
72 void
74 {
76 }
77 
78 bool
80 {
82 }
83 
84 bool
86 {
87  return !(validPeer() && peer->standby.limit) && AsyncJob::doneAll();
88 }
89 
90 void
92 {
93  opener = NULL;
94 
95  if (!validPeer()) {
96  debugs(48, 3, "peer gone");
97  if (params.conn != NULL)
98  params.conn->close();
99  return;
100  }
101 
102  if (params.flag != Comm::OK) {
103  /* it might have been a timeout with a partially open link */
104  if (params.conn != NULL)
105  params.conn->close();
107  checkpoint("conn opening failure"); // may retry
108  return;
109  }
110 
111  Must(params.conn != NULL);
112 
113  // Handle TLS peers.
116  closer = JobCallback(48, 3, CloserDialer, this,
119 
120  securer = asyncCall(48, 4, "PeerPoolMgr::handleSecuredPeer",
122 
123  const int peerTimeout = peerConnectTimeout(peer);
124  const int timeUsed = squid_curtime - params.conn->startTime();
125  // Use positive timeout when less than one second is left for conn.
126  const int timeLeft = positiveTimeout(peerTimeout - timeUsed);
127  auto *connector = new Security::BlindPeerConnector(request, params.conn, securer, nullptr, timeLeft);
128  AsyncJob::Start(connector); // will call our callback
129  return;
130  }
131 
132  pushNewConnection(params.conn);
133 }
134 
135 void
137 {
138  Must(validPeer());
139  Must(Comm::IsConnOpen(conn));
140  peer->standby.pool->push(conn, NULL /* domain */);
141  // push() will trigger a checkpoint()
142 }
143 
144 void
146 {
147  Must(securer != NULL);
148  securer = NULL;
149 
150  if (closer != NULL) {
151  if (answer.conn != NULL)
153  else
154  closer->cancel("securing completed");
155  closer = NULL;
156  }
157 
158  if (!validPeer()) {
159  debugs(48, 3, "peer gone");
160  if (answer.conn != NULL)
161  answer.conn->close();
162  return;
163  }
164 
165  if (answer.error.get()) {
166  if (answer.conn != NULL)
167  answer.conn->close();
168  // PeerConnector calls peerConnectFailed() for us;
169  checkpoint("conn securing failure"); // may retry
170  return;
171  }
172 
173  pushNewConnection(answer.conn);
174 }
175 
176 void
178 {
179  Must(closer != NULL);
180  Must(securer != NULL);
181  securer->cancel("conn closed by a 3rd party");
182  securer = NULL;
183  closer = NULL;
184  // allow the closing connection to fully close before we check again
185  Checkpoint(this, "conn closure while securing");
186 }
187 
188 void
190 {
191  // KISS: Do nothing else when we are already doing something.
192  if (opener != NULL || securer != NULL || shutting_down) {
193  debugs(48, 7, "busy: " << opener << '|' << securer << '|' << shutting_down);
194  return; // there will be another checkpoint when we are done opening/securing
195  }
196 
197  // Do not talk to a peer until it is ready.
198  if (!neighborUp(peer)) // provides debugging
199  return; // there will be another checkpoint when peer is up
200 
201  // Do not violate peer limits.
202  if (!peerCanOpenMore(peer)) { // provides debugging
203  peer->standby.waitingForClose = true; // may already be true
204  return; // there will be another checkpoint when a peer conn closes
205  }
206 
207  // Do not violate global restrictions.
208  if (fdUsageHigh()) {
209  debugs(48, 7, "overwhelmed");
210  peer->standby.waitingForClose = true; // may already be true
211  // There will be another checkpoint when a peer conn closes OR when
212  // a future pop() fails due to an empty pool. See PconnPool::pop().
213  return;
214  }
215 
216  peer->standby.waitingForClose = false;
217 
219  Must(peer->n_addresses); // guaranteed by neighborUp() above
220  // cycle through all available IP addresses
221  conn->remote = peer->addresses[addrUsed++ % peer->n_addresses];
222  conn->remote.port(peer->http_port);
223  conn->peerType = STANDBY_POOL; // should be reset by peerSelect()
224  conn->setPeer(peer);
227 
228  const int ctimeout = peerConnectTimeout(peer);
231  Comm::ConnOpener *cs = new Comm::ConnOpener(conn, opener, ctimeout);
232  AsyncJob::Start(cs);
233 }
234 
235 void
237 {
238  debugs(48, 8, howMany);
239  peer->standby.pool->closeN(howMany);
240 }
241 
242 void
243 PeerPoolMgr::checkpoint(const char *reason)
244 {
245  if (!validPeer()) {
246  debugs(48, 3, reason << " and peer gone");
247  return; // nothing to do after our owner dies; the job will quit
248  }
249 
250  const int count = peer->standby.pool->count();
251  const int limit = peer->standby.limit;
252  debugs(48, 7, reason << " with " << count << " ? " << limit);
253 
254  if (count < limit)
256  else if (count > limit)
257  closeOldConnections(count - limit);
258 }
259 
260 void
261 PeerPoolMgr::Checkpoint(const Pointer &mgr, const char *reason)
262 {
263  CallJobHere1(48, 5, mgr, PeerPoolMgr, checkpoint, reason);
264 }
265 
268 {
269 public:
270  /* RegisteredRunner API */
271  virtual void useConfig() { syncConfig(); }
272  virtual void syncConfig();
273 };
274 
276 
277 void
279 {
280  for (CachePeer *p = Config.peers; p; p = p->next) {
281  // On reconfigure, Squid deletes the old config (and old peers in it),
282  // so should always be dealing with a brand new configuration.
283  assert(!p->standby.mgr);
284  assert(!p->standby.pool);
285  if (p->standby.limit) {
286  p->standby.mgr = new PeerPoolMgr(p);
287  p->standby.pool = new PconnPool(p->name, p->standby.mgr);
288  AsyncJob::Start(p->standby.mgr.get());
289  }
290  }
291 }
292 
int n_addresses
Definition: CachePeer.h:152
void getOutgoingAddress(HttpRequest *request, Comm::ConnectionPointer conn)
Definition: FwdState.cc:1293
int fdUsageHigh(void)
Definition: fd.cc:306
virtual bool doneAll() const
whether positive goal has been reached
Definition: AsyncJob.cc:96
virtual bool doneAll() const
whether positive goal has been reached
Definition: PeerPoolMgr.cc:85
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
Definition: AsyncJobCalls.h:68
void closeN(int n)
closes any n connections, regardless of their destination
Definition: pconn.cc:478
#define assert(EX)
Definition: assert.h:17
bool waitingForClose
a conn must close before we open a standby conn
Definition: CachePeer.h:185
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
CbcPointer< ErrorState > error
problem details (nil on success)
PeerPoolMgr(CachePeer *aPeer)
Definition: PeerPoolMgr.cc:43
void openNewConnection()
starts the process of opening a new standby connection (if possible)
Definition: PeerPoolMgr.cc:189
time_t peerConnectTimeout(const CachePeer *peer)
Definition: neighbors.cc:1164
CachePeer * peers
Definition: SquidConfig.h:243
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
Gives Security::PeerConnector access to Answer in the PeerPoolMgr callback dialer.
Definition: PeerPoolMgr.cc:32
bool encryptTransport
whether transport encryption (TLS/SSL) is to be used on connections to the peer
Definition: PeerOptions.h:124
virtual void useConfig()
Definition: PeerPoolMgr.cc:271
Definition: Flag.h:16
AsyncCall::Pointer opener
whether we are opening a connection
Definition: PeerPoolMgr.h:66
bool cancel(const char *reason)
Definition: AsyncCall.cc:52
char * p
Definition: membanger.c:43
static void Checkpoint(const Pointer &mgr, const char *reason)
Definition: PeerPoolMgr.cc:261
int conn
the current server connection FD
Definition: Transport.cc:26
virtual void start()
called by AsyncStart; do not call directly
Definition: PeerPoolMgr.cc:59
virtual ~PeerPoolMgr()
Definition: PeerPoolMgr.cc:53
void count(int uses)
time_t squid_curtime
Definition: stub_time.cc:17
void host(const char *src)
Definition: url.cc:47
AsyncCall::Pointer closer
monitors conn while we are securing it
Definition: PeerPoolMgr.h:68
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void GetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Sets initial TOS value and Netfilter for the future outgoing connection.
Definition: FwdState.cc:1358
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
void push(const Comm::ConnectionPointer &serverConn, const char *domain)
Definition: pconn.cc:407
int shutting_down
Definition: testAddress.cc:36
struct CachePeer::@36 standby
optional "cache_peer standby=limit" feature
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1274
bool validPeer() const
whether the peer is still out there and in a valid state we can safely use
Definition: PeerPoolMgr.cc:79
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define cbdataReference(var)
Definition: cbdata.h:341
void closeOldConnections(const int howMany)
closes 'howMany' standby connections
Definition: PeerPoolMgr.cc:236
void checkpoint(const char *reason)
Definition: PeerPoolMgr.cc:243
RefCount< HttpRequest > request
fake HTTP request for conn opening code
Definition: PeerPoolMgr.h:65
void handleSecureClosure(const CommCloseCbParams &params)
called when the connection we are trying to secure is closed by a 3rd party
Definition: PeerPoolMgr.cc:177
virtual void swanSong()
Definition: AsyncJob.h:55
void pushNewConnection(const Comm::ConnectionPointer &conn)
the final step in connection opening (and, optionally, securing) sequence
Definition: PeerPoolMgr.cc:136
bool peerCanOpenMore(const CachePeer *p)
Whether we can open new connections to the peer (e.g., despite max-conn)
Definition: neighbors.cc:213
MyAnswerDialer(const JobPointer &aJob, Method aMethod)
Definition: PeerPoolMgr.cc:36
PconnPool * pool
idle connection pool for this peer
Definition: CachePeer.h:182
Security::PeerOptions secure
security settings for peer connection
Definition: CachePeer.h:191
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:62
void handleSecuredPeer(Security::EncryptorAnswer &answer)
Security::PeerConnector callback.
Definition: PeerPoolMgr.cc:145
virtual void syncConfig()
Definition: PeerPoolMgr.cc:278
URL url
the request URI
Definition: HttpRequest.h:103
unsigned short port() const
Definition: Address.cc:786
#define Must(cond)
Definition: TextException.h:89
time_t positiveTimeout(const time_t timeout)
Definition: neighbors.cc:1171
Ip::Address addresses[10]
Definition: CachePeer.h:151
AsyncCall::Pointer securer
whether we are securing a connection
Definition: PeerPoolMgr.h:67
RunnerRegistrationEntry(PeerPoolMgrsRr)
void setPeer(CachePeer *p)
Definition: Connection.cc:106
Ip::Address remote
Definition: Connection.h:138
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: PeerPoolMgr.cc:40
unsigned int addrUsed
counter for cycling through peer addresses
Definition: PeerPoolMgr.h:69
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
int limit
the limit itself
Definition: CachePeer.h:184
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:87
A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:69
virtual void swanSong()
Definition: PeerPoolMgr.cc:73
hier_code peerType
Definition: Connection.h:141
CachePeer * peer
the owner of the pool we manage
Definition: PeerPoolMgr.h:64
Comm::ConnectionPointer conn
peer connection (secured on success)
unsigned short http_port
Definition: CachePeer.h:78
Maintains an fixed-size "standby" PconnPool for a single CachePeer.
Definition: PeerPoolMgr.h:21
void handleOpenedConnection(const CommConnectCbParams &params)
Comm::ConnOpener calls this when done opening a connection for us.
Definition: PeerPoolMgr.cc:91
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:412
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:961
int neighborUp(const CachePeer *p)
Definition: neighbors.cc:1123
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:43
time_t startTime() const
Definition: Connection.h:106
void comm_remove_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:988
launches PeerPoolMgrs for peers configured with standby.limit
Definition: PeerPoolMgr.cc:267
C * getRaw() const
Definition: RefCount.h:74
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
char * host
Definition: CachePeer.h:41

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors