91 os << (answer.
reused ?
"reused " :
"new ") << answer.
conn;
93 os <<
" after " << answer.
n_tries;
155 jobs_.emplace_back(&job);
175 while (!
jobs_.empty()) {
176 if (
const auto jobPtr =
jobs_.front().valid()) {
180 CallBack(job.spareWaiting.codeContext, [&] {
181 job.spareWaiting.callback = notify(jobPtr);
193 if (cfgTimeoutMsec <= 0)
199 const auto newWaitEnd = std::min(lastStart,
current_dtime) + tout;
335 prime(&
HappyConnOpener::notePrimeConnectDone,
"HappyConnOpener::notePrimeConnectDone"),
336 spare(&
HappyConnOpener::noteSpareConnectDone,
"HappyConnOpener::noteSpareConnectDone"),
423 os <<
"FD " << attempt.
path->
fd;
444 os <<
"prime:" <<
prime;
446 os <<
"spare:" <<
spare;
450 os <<
' ' <<
id <<
']';
501 debugs(17, 4, connKind <<
": " << conn);
503 answer->reused = reused;
527 assert(answer->error.valid());
549 const auto canReuseOld =
allowPconn_ && !bumpThroughPeer;
577#if URL_CHECKSUM_DEBUG
578 entry->mem_obj->checkUrlChecksum();
589 if (!conn->getPeer())
621 auto handledPath = attempt.
path;
632 debugs(17, 8, what <<
" failed: " << params.
conn);
693 debugs(17, 5,
"because " << reason);
828 debugs(17, 7,
"concurrent spares are prohibited");
834 debugs(17, 7,
"no happy_eyeballs_connect_timeout");
891 debugs(17, 5,
"maximum allowed tries exhausted");
897 debugs(17, 5,
"forwarding timeout");
906 callbackMethod(method),
907 callbackMethodName(methodName)
921 connWait.cancel(reason);
#define ScheduleCallHere(call)
RefCount< AsyncCallT< Dialer > > asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
#define CallJobHere(debugSection, debugLevel, job, Class, method)
void NoteOutgoingConnectionFailure(CachePeer *const peer)
void CallBack(const CodeContext::Pointer &callbackContext, Fun &&callback)
PconnPool * fwdPconnPool
a collection of previously used persistent Squid-to-peer HTTP(S) connections
void GetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
PrimeChanceGiver ThePrimeChanceGiver
SpareAllowanceGiver TheSpareAllowanceGiver
std::ostream & operator<<(std::ostream &os, const HappyConnOpenerAnswer &answer)
reports Answer details (for AsyncCall parameter debugging)
std::list< CbcPointer< HappyConnOpener > > HappySpareWaitList
A FIFO queue of HappyConnOpener jobs waiting to open a spare connection.
double HappyAbsoluteTime
absolute time in fractional seconds; compatible with current_timed
#define CBDATA_CLASS_INIT(type)
bool cancel(const char *reason)
a smart AsyncCall pointer for delivery of future results
bool done() const
the job is destroyed in callEnd() when done()
const char * stopReason
reason for forcing done() to be true
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
bool set() const
was set but may be invalid
static const Pointer & Current()
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Comm::Flag flag
comm layer result status.
Comm::ConnectionPointer conn
InstanceId< Connection, uint64_t > id
CachePeer * getPeer() const
time_t connectTimeout(const time_t fwdStart) const
ConnectionPointer cloneProfile() const
Create a new closed Connection with the same configuration as this one.
static time_t ForwardTimeout(const time_t fwdStart)
time left to finish the whole forwarding process (which started at fwdStart)
Final result (an open connection or an error) sent to the job initiator.
bool reused
whether conn was open earlier, by/for somebody else
PeerConnectionPointer conn
CbcPointer< ErrorState > error
problem details (nil on success)
a connection opening attempt in progress (or falsy)
void finish()
reacts to a natural attempt completion (successful or otherwise)
const char *const callbackMethodName
for callbackMethod debugging
void(HappyConnOpener::*)(const CommConnectCbParams &) CallbackMethod
HappyConnOpener method implementing a ConnOpener callback.
JobWait< Comm::ConnOpener > connWait
waits for a connection to the peer to be established/opened
void cancel(const char *reason)
aborts an in-progress attempt
const CallbackMethod callbackMethod
ConnOpener calls this method.
PeerConnectionPointer path
the destination we are connecting to
Attempt(const CallbackMethod method, const char *methodName)
bool doneAll() const override
whether positive goal has been reached
void noteSpareConnectDone(const CommConnectCbParams &)
Comm::ConnOpener callback for the spare connection attempt.
bool ignoreSpareRestrictions
whether spare connection attempts disregard happy_eyeballs_* settings
bool gotSpareAllowance
whether we have received a permission to open a spare while spares are limited
PeerConnectionPointer lastFailedConnection
nil if none has failed
void start() override
called by AsyncStart; do not call directly
void noteGavePrimeItsChance()
reacts to expired happy_eyeballs_connect_timeout
bool retriable_
whether we are opening connections for a request that may be resent
const char * status() const override
internal cleanup; do not call directly
void cancelAttempt(Attempt &, const char *reason)
cancels the in-progress attempt, making its path a future candidate
Comm::ConnectionPointer currentPeer
void maybeGivePrimeItsChance()
void setHost(const char *)
configures the origin server domain name
const char * ranOutOfTimeOrAttemptsEarlier_
Reason to ran out of time or attempts.
void sendSuccess(const PeerConnectionPointer &conn, bool reused, const char *connKind)
send a successful result to the initiator (if it still needs an answer)
HappyConnOpener(const ResolvedPeersPointer &, const AsyncCallback< Answer > &, const HttpRequestPointer &, time_t aFwdStart, int tries, const AccessLogEntryPointer &)
void updateSpareWaitAfterPrimeFailure()
reacts to a prime attempt failure
~HappyConnOpener() override
HttpRequestPointer cause
the request that needs a to-server connection
void stopGivingPrimeItsChance()
called when the prime attempt has used up its chance for a solo victory
AccessLogEntryPointer ale
transaction details
void maybeOpenSpareConnection()
if possible, starts a spare connection attempt
Answer * futureAnswer(const PeerConnectionPointer &)
const time_t fwdStart
requestor start time
void checkForNewConnection()
void handleConnOpenerAnswer(Attempt &, const CommConnectCbParams &, const char *connDescription)
prime/spare-agnostic processing of a Comm::ConnOpener result
bool ranOutOfTimeOrAttempts() const
Check for maximum connection tries and forwarding time restrictions.
void stopWaitingForSpareAllowance()
called when the spare attempt should no longer obey spare connection limits
ErrorState * makeError(const err_type type) const
void noteSpareAllowance()
reacts to satisfying happy_eyeballs_connect_gap and happy_eyeballs_connect_limit
HappySpareWait spareWaiting
preconditions for an attempt to open a spare connection
void sendFailure()
inform the initiator about our failure to connect (if needed)
ErrorState * lastError
last problem details (or nil)
bool reuseOldConnection(PeerConnectionPointer &)
void startConnecting(Attempt &, PeerConnectionPointer &)
starts opening (or reusing) a connection to the given destination
bool allowPconn_
whether persistent connections are allowed
const char * host_
origin server domain name (or equivalent)
Attempt spare
current connection opening attempt on the spare track (if any)
ResolvedPeersPointer destinations
Candidate paths. Shared with the initiator. May not be finalized yet.
HappyAbsoluteTime primeStart
the start of the first connection attempt for the currentPeer
void maybeOpenPrimeConnection()
starts a prime connection attempt if possible or does nothing otherwise
void openFreshConnection(Attempt &, PeerConnectionPointer &)
AsyncCallback< Answer > callback_
answer destination
void notePrimeConnectDone(const CommConnectCbParams &)
Comm::ConnOpener callback for the prime connection attempt.
void cancelSpareWait(const char *reason)
stops waiting for the right conditions to open a spare connection
void noteCandidatesChange()
reacts to changes in the destinations list
Attempt prime
current connection opening attempt on the prime track (if any)
const char *const name
waiting event name, for debugging
void dequeue(HappyConnOpener &)
stops managing the job's wait; cancels the pending callback, if any
void checkpoint()
resumes jobs that need resuming (if any)
bool startedWaiting(const HappyAbsoluteTime lastStart, const int cfgTimeoutMsec) const
static void NoteWaitOver(void *raw)
virtual AsyncCall::Pointer notify(const CbcPointer< HappyConnOpener > &)=0
virtual bool readyNow(const HappyConnOpener &) const =0
void enqueue(HappyConnOpener &)
starts managing the job's wait; the job should expect a call back
HappySpareWaitList jobs_
queued jobs waiting their turn
HappyOrderEnforcer(const char *aName)
HappyAbsoluteTime waitEnd_
expected NoteWaitOver() call time (or zero)
bool toGivePrimeItsChance
HappySpareWaitList::iterator position
CodeContext::Pointer codeContext
requestor's context
AsyncCall::Pointer callback
a pending noteGavePrimeItsChance() or noteSpareAllowance() call
void start(const JobPointer &aJob, const AsyncCall::Pointer &aCallback)
starts waiting for the given job to call the given callback
Comm::ConnectionPointer pop(const Comm::ConnectionPointer &dest, const char *domain, bool keepOpen)
void finalize(const Comm::ConnectionPointer &conn)
upgrade stored peer selection details with a matching actual connection
enforces happy_eyeballs_connect_timeout
bool readyNow(const HappyConnOpener &job) const override
AsyncCall::Pointer notify(const CbcPointer< HappyConnOpener > &) override
PeerConnectionPointer extractFront()
extracts and returns the first queued address
bool haveSpare(const Comm::Connection ¤tPeer)
whether extractSpare() would return a non-nil path right now
bool doneWithPrimes(const Comm::Connection ¤tPeer)
whether extractPrime() returns and will continue to return nil
bool doneWithPeer(const Comm::Connection ¤tPeer)
whether doneWithPrimes() and doneWithSpares() are true for currentPeer
void reinstatePath(const PeerConnectionPointer &)
PeerConnectionPointer extractSpare(const Comm::Connection ¤tPeer)
bool notificationPending
whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
bool empty() const
whether we lack any known candidate paths
bool destinationsFinalized
whether all of the available candidate paths received from DNS
PeerConnectionPointer extractPrime(const Comm::Connection ¤tPeer)
bool doneWithSpares(const Comm::Connection ¤tPeer)
whether extractSpare() returns and will continue to return nil
SBuf buf()
bytes written so far
enforces happy_eyeballs_connect_gap and happy_eyeballs_connect_limit
void jobGotInstantAllowance()
bool concurrencyLimitReached() const
whether opening a spare connection now would violate happy_eyeballs_connect_limit
bool readyNow(const HappyConnOpener &job) const override
void jobDroppedAllowance()
reacts to HappyConnOpener dropping its spare connection allowance
void recordAllowance()
account for the given allowance
HappyAbsoluteTime lastAllowanceStart
the time of the last noteSpareAllowance() call
AsyncCall::Pointer notify(const CbcPointer< HappyConnOpener > &) override
void jobUsedAllowance()
reacts to HappyConnOpener getting a spare connection opening result
struct SquidConfig::@101 happyEyeballs
#define debugs(SECTION, LEVEL, CONTENT)
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
double current_dtime
the current UNIX time in seconds (with microsecond precision)