clientConn(client),
start_t(squid_curtime),
n_tries(0),
+ waitingForDispatched(false),
destinations(new ResolvedPeers()),
pconnRace(raceImpossible),
storedWholeReply_(nullptr)
logReplyStatus(n_tries, replyStatus);
+ // will already be false if complete() was called before/without dispatch()
+ waitingForDispatched = false;
+
if (reforward()) {
debugs(17, 3, "re-forwarding " << replyStatus << " " << entry->url());
}
}
+/// Whether a forwarding attempt to some selected destination X is in progress
+/// (after successfully opening/reusing a transport connection to X).
+/// See also: transportWait
bool
-FwdState::usingDestination() const
+FwdState::transporting() const
{
- return encryptionWait || peerWait || Comm::IsConnOpen(serverConn);
+ return peerWait || encryptionWait || waitingForDispatched;
}
void
destinations->addPath(path);
- if (usingDestination()) {
- // We are already using a previously opened connection, so we cannot be
- // waiting for it. We still receive destinations for backup.
- Must(!transportWait);
- return;
- }
-
if (transportWait) {
+ assert(!transporting());
notifyConnOpener();
return; // and continue to wait for FwdState::noteConnection() callback
}
+ if (transporting())
+ return; // and continue to receive destinations for backup
+
// This is the first path candidate we have seen. Use it.
useDestinations();
}
// if all of them fail, forwarding as whole will fail
Must(!selectionError); // finding at least one path means selection succeeded
- if (usingDestination()) {
- // We are already using a previously opened connection, so we cannot be
- // waiting for it. We were receiving destinations for backup.
- Must(!transportWait);
- return;
+ if (transportWait) {
+ assert(!transporting());
+ notifyConnOpener();
+ return; // and continue to wait for FwdState::noteConnection() callback
}
- Must(transportWait); // or we would be stuck with nothing to do or wait for
- notifyConnOpener();
- // and continue to wait for FwdState::noteConnection() callback
+ Must(transporting()); // or we would be stuck with nothing to do or wait for
}
/// makes sure connection opener knows that the destinations have changed
serverConn = nullptr;
closeHandler = nullptr;
destinationReceipt = nullptr;
+
+ // will already be false if this closure happened before/without dispatch()
+ waitingForDispatched = false;
+
retryOrBail();
}
assert(!Comm::IsConnOpen(serverConn));
serverConn = nullptr;
destinationReceipt = nullptr;
+
+ // might already be false due to uncertainties documented in serverClosed()
+ waitingForDispatched = false;
+
retryOrBail();
}
Must(!request->pinnedConnection());
assert(!destinations->empty());
- assert(!usingDestination());
+ assert(!transporting());
// Ditch error page if it was created before.
// A new one will be created if there's another problem
*/
assert(Comm::IsConnOpen(serverConn));
+ assert(!waitingForDispatched);
+ waitingForDispatched = true;
+
fd_note(serverConnection()->fd, entry->url());
fd_table[serverConnection()->fd].noteUse();
/* PeerSelectionInitiator API */
virtual void noteDestination(Comm::ConnectionPointer conn) override;
virtual void noteDestinationsEnd(ErrorState *selectionError) override;
- /// whether the successfully selected path destination or the established
- /// server connection is still in use
- bool usingDestination() const;
+
+ bool transporting() const;
void noteConnection(HappyConnOpenerAnswer &);
/// over the (encrypted, if needed) transport connection to that cache_peer
JobWait<Http::Tunneler> peerWait;
+ /// whether we are waiting for the last dispatch()ed activity to end
+ bool waitingForDispatched;
+
ResolvedPeersPointer destinations; ///< paths for forwarding the request
Comm::ConnectionPointer serverConn; ///< a successfully opened connection to a server.
PeerConnectionPointer destinationReceipt; ///< peer selection result (or nil)