]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/icap/ServiceRep.h
51a22f01e2c8aafd880b18c9aef3705c3869714a
[thirdparty/squid.git] / src / adaptation / icap / ServiceRep.h
1 /*
2 * Copyright (C) 1996-2015 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 #ifndef SQUID_ICAPSERVICEREP_H
10 #define SQUID_ICAPSERVICEREP_H
11
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"
17 #include "cbdata.h"
18 #include "comm.h"
19 #include "FadingCounter.h"
20 #include "pconn.h"
21 #include <deque>
22
23 namespace Adaptation
24 {
25 namespace Icap
26 {
27
28 class Options;
29 class OptXact;
30
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. */
35
36 /*
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".
41 *
42 * The number of failures required to bring an up service down is determined
43 * by icap_service_failure_limit in squid.conf.
44 *
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.
49 *
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.
52 *
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.
57 */
58
59 class ServiceRep : public RefCountable, public Adaptation::Service,
60 public Adaptation::Initiator
61 {
62 CBDATA_CLASS(ServiceRep);
63
64 public:
65 typedef RefCount<ServiceRep> Pointer;
66
67 public:
68 explicit ServiceRep(const ServiceConfigPointer &aConfig);
69 virtual ~ServiceRep();
70
71 virtual void finalize();
72
73 virtual bool probed() const; // see comments above
74 virtual bool up() const; // 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
77
78 virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp);
79
80 void callWhenAvailable(AsyncCall::Pointer &cb, bool priority = false);
81 void callWhenReady(AsyncCall::Pointer &cb);
82
83 // the methods below can only be called on an up() service
84 bool wantsUrl(const SBuf &urlPath) const;
85 bool wantsPreview(const SBuf &urlPath, size_t &wantedSize) const;
86 bool allows204() const;
87 bool allows206() const;
88 Comm::ConnectionPointer getConnection(bool isRetriable, bool &isReused);
89 void putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment);
90 void noteConnectionUse(const Comm::ConnectionPointer &conn);
91 void noteConnectionFailed(const char *comment);
92
93 void noteFailure(); // called by transactions to report service failure
94
95 void noteNewWaiter() {theAllWaiters++;} ///< New xaction waiting for service to be up or available
96 void noteGoneWaiter(); ///< An xaction is not waiting any more for service to be available
97 bool existWaiters() const {return (theAllWaiters > 0);} ///< if there are xactions waiting for the service to be available
98
99 //AsyncJob virtual methods
100 virtual bool doneAll() const { return Adaptation::Initiator::doneAll() && false;}
101 virtual void callException(const std::exception &e);
102
103 virtual void detach();
104 virtual bool detached() const;
105
106 public: // treat these as private, they are for callbacks only
107 void noteTimeToUpdate();
108 void noteTimeToNotify();
109
110 // receive either an ICAP OPTIONS response header or an abort message
111 virtual void noteAdaptationAnswer(const Answer &answer);
112
113 Security::ContextPtr sslContext;
114 #if USE_OPENSSL
115 SSL_SESSION *sslSession;
116 #endif
117
118 private:
119 // stores Prepare() callback info
120
121 struct Client {
122 Pointer service; // one for each client to preserve service
123 AsyncCall::Pointer callback;
124 };
125
126 typedef std::vector<Client> Clients;
127 // TODO: rename to theUpWaiters
128 Clients theClients; // all clients waiting for a call back
129
130 Options *theOptions;
131 CbcPointer<Adaptation::Initiate> theOptionsFetcher; // pending ICAP OPTIONS transaction
132 time_t theLastUpdate; // time the options were last updated
133
134 /// FIFO queue of xactions waiting for a connection slot and not yet notified
135 /// about it; xaction is removed when notification is scheduled
136 std::deque<Client> theNotificationWaiters;
137 int theBusyConns; ///< number of connections given to active transactions
138 /// number of xactions waiting for a connection slot (notified and not)
139 /// the number is decreased after the xaction receives notification
140 int theAllWaiters;
141 int theMaxConnections; ///< the maximum allowed connections to the service
142 // TODO: use a better type like the FadingCounter for connOverloadReported
143 mutable bool connOverloadReported; ///< whether we reported exceeding theMaxConnections
144 IdleConnList *theIdleConns; ///< idle persistent connection pool
145
146 FadingCounter theSessionFailures;
147 const char *isSuspended; // also stores suspension reason for debugging
148
149 bool notifying; // may be true in any state except for the initial
150 bool updateScheduled; // time-based options update has been scheduled
151
152 private:
153 ICAP::Method parseMethod(const char *) const;
154 ICAP::VectPoint parseVectPoint(const char *) const;
155
156 void suspend(const char *reason);
157
158 bool hasOptions() const;
159 bool needNewOptions() const;
160 time_t optionsFetchTime() const;
161
162 void scheduleUpdate(time_t when);
163 void scheduleNotification();
164
165 void startGettingOptions();
166 void handleNewOptions(Options *newOptions);
167 void changeOptions(Options *newOptions);
168 void checkOptions();
169
170 void announceStatusChange(const char *downPhrase, bool important) const;
171
172 /// Set the maximum allowed connections for the service
173 void setMaxConnections();
174 /// The number of connections which excess the Max-Connections limit
175 int excessConnections() const;
176 /**
177 * The available connections slots to the ICAP server
178 \return the available slots, or -1 if there is no limit on allowed connections
179 */
180 int availableConnections() const;
181 /**
182 * If there are xactions waiting for the service to be available, notify
183 * as many xactions as the available connections slots.
184 */
185 void busyCheckpoint();
186
187 const char *status() const;
188
189 mutable bool wasAnnouncedUp; // prevent sequential same-state announcements
190 bool isDetached;
191 };
192
193 class ModXact;
194 /// Custom dialer to call Service::noteNewWaiter and noteGoneWaiter
195 /// to maintain Service idea of waiting and being-notified transactions.
196 class ConnWaiterDialer: public NullaryMemFunT<ModXact>
197 {
198 public:
199 typedef NullaryMemFunT<ModXact> Parent;
200 ServiceRep::Pointer theService;
201 ConnWaiterDialer(const CbcPointer<Adaptation::Icap::ModXact> &xact, Adaptation::Icap::ConnWaiterDialer::Parent::Method aHandler);
202 ConnWaiterDialer(const Adaptation::Icap::ConnWaiterDialer &aConnWaiter);
203 ~ConnWaiterDialer();
204 };
205
206 } // namespace Icap
207 } // namespace Adaptation
208
209 #endif /* SQUID_ICAPSERVICEREP_H */
210