2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SRC_ADAPTATION_ICAP_SERVICEREP_H
10 #define SQUID_SRC_ADAPTATION_ICAP_SERVICEREP_H
12 #include "adaptation/forward.h"
13 #include "adaptation/icap/Elements.h"
14 #include "adaptation/Initiator.h"
15 #include "adaptation/Service.h"
16 #include "base/AsyncJobCalls.h"
19 #include "FadingCounter.h"
31 /* The ICAP service representative maintains information about a single ICAP
32 service that Squid communicates with. The representative initiates OPTIONS
33 requests to the service to keep cached options fresh. One ICAP server may
34 host many ICAP services. */
37 * A service with a fresh cached OPTIONS response and without many failures
38 * is an "up" service. All other services are "down". A service is "probed"
39 * if we tried to get an OPTIONS response from it and succeeded or failed.
40 * A probed down service is called "broken".
42 * The number of failures required to bring an up service down is determined
43 * by icap_service_failure_limit in squid.conf.
45 * As a bootstrapping mechanism, ICAP transactions wait for an unprobed
46 * service to get a fresh OPTIONS response (see the callWhenReady method).
47 * The waiting callback is called when the OPTIONS transaction completes,
48 * even if the service is now broken.
50 * We do not initiate ICAP transactions with a broken service, but will
51 * eventually retry to fetch its options in hope to bring the service up.
53 * A service that should no longer be used after Squid reconfiguration is
54 * treated as if it does not have a fresh cached OPTIONS response. We do
55 * not try to fetch fresh options for such a service. It should be
56 * auto-destroyed by refcounting when no longer used.
59 class ServiceRep
: public RefCountable
, public Adaptation::Service
,
60 public Adaptation::Initiator
62 CBDATA_CHILD(ServiceRep
);
65 typedef RefCount
<ServiceRep
> Pointer
;
68 explicit ServiceRep(const ServiceConfigPointer
&aConfig
);
69 ~ServiceRep() override
;
71 void finalize() override
;
73 bool probed() const override
; // see comments above
74 bool up() const override
; // see comments above
75 bool availableForNew() const; ///< a new transaction may start communicating with the service
76 bool availableForOld() const; ///< a transaction notified about connection slot availability may start communicating with the service
78 Initiate
*makeXactLauncher(Http::Message
*virginHeader
, HttpRequest
*virginCause
, AccessLogEntry::Pointer
&alp
) override
;
80 void callWhenAvailable(AsyncCall::Pointer
&cb
, bool priority
= false);
81 void callWhenReady(AsyncCall::Pointer
&cb
);
83 // the methods below can only be called on an up() service
84 bool wantsUrl(const SBuf
&urlPath
) const override
;
85 bool wantsPreview(const SBuf
&urlPath
, size_t &wantedSize
) const;
86 bool allows204() const;
87 bool allows206() const;
88 /// \returns an idle persistent ICAP connection or nil
89 Comm::ConnectionPointer
getIdleConnection(bool isRetriable
);
90 void putConnection(const Comm::ConnectionPointer
&conn
, bool isReusable
, bool sendReset
, const char *comment
);
91 void noteConnectionUse(const Comm::ConnectionPointer
&conn
);
92 void noteConnectionFailed(const char *comment
);
94 void noteFailure() override
; // called by transactions to report service failure
96 void noteNewWaiter() {theAllWaiters
++;} ///< New xaction waiting for service to be up or available
97 void noteGoneWaiter(); ///< An xaction is not waiting any more for service to be available
98 bool existWaiters() const {return (theAllWaiters
> 0);} ///< if there are xactions waiting for the service to be available
100 //AsyncJob virtual methods
101 bool doneAll() const override
{ return Adaptation::Initiator::doneAll() && false;}
102 void callException(const std::exception
&e
) override
;
104 void detach() override
;
105 bool detached() const override
;
107 public: // treat these as private, they are for callbacks only
108 void noteTimeToUpdate();
109 void noteTimeToNotify();
111 // receive either an ICAP OPTIONS response header or an abort message
112 void noteAdaptationAnswer(const Answer
&answer
) override
;
114 Security::ContextPointer sslContext
;
115 // TODO: Remove sslContext above when FuturePeerContext below becomes PeerContext
116 Security::FuturePeerContext tlsContext
;
117 Security::SessionStatePointer sslSession
;
120 // stores Prepare() callback info
123 Pointer service
; // one for each client to preserve service
124 AsyncCall::Pointer callback
;
127 typedef std::vector
<Client
> Clients
;
128 // TODO: rename to theUpWaiters
129 Clients theClients
; // all clients waiting for a call back
132 CbcPointer
<Adaptation::Initiate
> theOptionsFetcher
; // pending ICAP OPTIONS transaction
133 time_t theLastUpdate
; // time the options were last updated
135 /// FIFO queue of xactions waiting for a connection slot and not yet notified
136 /// about it; xaction is removed when notification is scheduled
137 std::deque
<Client
> theNotificationWaiters
;
138 int theBusyConns
; ///< number of connections given to active transactions
139 /// number of xactions waiting for a connection slot (notified and not)
140 /// the number is decreased after the xaction receives notification
142 int theMaxConnections
; ///< the maximum allowed connections to the service
143 // TODO: use a better type like the FadingCounter for connOverloadReported
144 mutable bool connOverloadReported
; ///< whether we reported exceeding theMaxConnections
145 IdleConnList
*theIdleConns
; ///< idle persistent connection pool
147 FadingCounter theSessionFailures
;
148 const char *isSuspended
; // also stores suspension reason for debugging
150 bool notifying
; // may be true in any state except for the initial
151 bool updateScheduled
; // time-based options update has been scheduled
154 ICAP::Method
parseMethod(const char *) const;
155 ICAP::VectPoint
parseVectPoint(const char *) const;
157 void suspend(const char *reason
);
159 bool hasOptions() const;
160 bool needNewOptions() const;
161 time_t optionsFetchTime() const;
163 void scheduleUpdate(time_t when
);
164 void scheduleNotification();
166 void startGettingOptions();
167 void handleNewOptions(Options
*newOptions
);
168 void changeOptions(Options
*newOptions
);
171 void announceStatusChange(const char *downPhrase
, bool important
) const;
173 /// Set the maximum allowed connections for the service
174 void setMaxConnections();
175 /// The number of connections which excess the Max-Connections limit
176 int excessConnections() const;
178 * The available connections slots to the ICAP server
179 \return the available slots, or -1 if there is no limit on allowed connections
181 int availableConnections() const;
183 * If there are xactions waiting for the service to be available, notify
184 * as many xactions as the available connections slots.
186 void busyCheckpoint();
188 const char *status() const override
;
190 mutable bool wasAnnouncedUp
; // prevent sequential same-state announcements
195 /// Custom dialer to call Service::noteNewWaiter and noteGoneWaiter
196 /// to maintain Service idea of waiting and being-notified transactions.
197 class ConnWaiterDialer
: public NullaryMemFunT
<ModXact
>
200 typedef NullaryMemFunT
<ModXact
> Parent
;
201 ServiceRep::Pointer theService
;
202 ConnWaiterDialer(const CbcPointer
<Adaptation::Icap::ModXact
> &xact
, Adaptation::Icap::ConnWaiterDialer::Parent::Method aHandler
);
203 ConnWaiterDialer(const Adaptation::Icap::ConnWaiterDialer
&aConnWaiter
);
204 ~ConnWaiterDialer() override
;
208 } // namespace Adaptation
210 #endif /* SQUID_SRC_ADAPTATION_ICAP_SERVICEREP_H */