]> git.ipfire.org Git - thirdparty/squid.git/blame - src/helper.h
mkrelease: allow two digits for minor release numbers (#1837)
[thirdparty/squid.git] / src / helper.h
CommitLineData
51ee7c82 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
51ee7c82 3 *
bbc27441
AJ
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.
51ee7c82 7 */
8
bbc27441
AJ
9/* DEBUG: section 84 Helper process maintenance */
10
ff9d9458
FC
11#ifndef SQUID_SRC_HELPER_H
12#define SQUID_SRC_HELPER_H
51ee7c82 13
37dedc58 14#include "base/AsyncCall.h"
e237d339 15#include "base/InstanceId.h"
3bd118d6 16#include "base/RefCount.h"
aa839030 17#include "cbdata.h"
e0d28505 18#include "comm/forward.h"
582c2af2 19#include "dlink.h"
76d9b994 20#include "helper/ChildConfig.h"
24438ec5 21#include "helper/forward.h"
ddc77a2e 22#include "helper/Reply.h"
c8f9dea2 23#include "helper/Request.h"
a56fcf0b 24#include "helper/ReservationId.h"
602d9612 25#include "ip/Address.h"
65e41a45 26#include "sbuf/SBuf.h"
32fd6d8a
CT
27
28#include <list>
a8067a2e 29#include <map>
6215dc18 30#include <queue>
a8067a2e 31#include <unordered_map>
aa839030 32
e05a9d51
EB
33class CommTimeoutCbParams;
34class MemBuf;
bf3e8d5a 35class Packable;
541b581e 36class wordlist;
bf3e8d5a 37
ddc77a2e
CT
38namespace Helper
39{
40/// Holds the required data to serve a helper request.
41class Xaction {
42 MEMPROXY_CLASS(Helper::Xaction);
43public:
44 Xaction(HLPCB *c, void *d, const char *b): request(c, d, b) {}
45 Helper::Request request;
46 Helper::Reply reply;
47};
ddc77a2e 48
e05a9d51
EB
49class SessionBase;
50
6825b101
CT
51/**
52 * Managers a set of individual helper processes with a common queue of requests.
53 *
54 * With respect to load, a helper goes through these states (roughly):
55 * idle: no processes are working on requests (and no requests are queued);
56 * normal: some, but not all processes are working (and no requests are queued);
57 * busy: all processes are working (and some requests are possibly queued);
6082a0e2 58 * overloaded: a busy helper with more than queue-size requests in the queue.
6825b101 59 *
6082a0e2
EB
60 * A busy helper queues new requests and issues a WARNING every 10 minutes or so.
61 * An overloaded helper either drops new requests or keeps queuing them, depending on
6825b101 62 * whether the caller can handle dropped requests (trySubmit vs helperSubmit APIs).
6082a0e2
EB
63 * If an overloaded helper has been overloaded for 3+ minutes, an attempt to use
64 * it results in on-persistent-overload action, which may kill worker.
6825b101 65 */
e05a9d51 66class Client: public RefCountable
10044c9b 67{
48d54e4d 68public:
e05a9d51 69 using Pointer = RefCount<Client>;
3bd118d6 70
e05a9d51 71 /// \returns a newly created instance of the named helper client
91ce75c9 72 /// \param name admin-visible helper category (with this process lifetime)
3bd118d6
EB
73 static Pointer Make(const char *name);
74
e05a9d51 75 virtual ~Client();
48d54e4d 76
6215dc18 77 /// \returns next request in the queue, or nil.
e05a9d51 78 Xaction *nextRequest();
6215dc18 79
6082a0e2 80 /// If possible, submit request. Otherwise, either kill Squid or return false.
6825b101
CT
81 bool trySubmit(const char *buf, HLPCB * callback, void *data);
82
f53969cc 83 /// Submits a request to the helper or add it to the queue if none of
32fd6d8a 84 /// the servers is available.
e05a9d51 85 void submitRequest(Xaction *);
bf3e8d5a
AJ
86
87 /// Dump some stats about the helper state to a Packable object
aee3523a 88 void packStatsInto(Packable *p, const char *label = nullptr) const;
6082a0e2
EB
89 /// whether the helper will be in "overloaded" state after one more request
90 /// already overloaded helpers return true
91 bool willOverload() const;
bf3e8d5a 92
e05a9d51 93 /// Updates internal statistics and starts new helper processes after
a56fcf0b 94 /// an unexpected server exit
569605b9 95 void handleKilledServer(SessionBase *);
a56fcf0b 96
e05a9d51
EB
97 /// Reacts to unexpected helper process death(s), including a failure to start helper(s)
98 /// and an unexpected exit of a previously started helper. \sa handleKilledServer()
99 /// \param madeProgress whether the died helper(s) responded to any requests
654835f0
EB
100 void handleFewerServers(bool madeProgress);
101
569605b9
EB
102 /// satisfies all queued requests with a Helper::Unknown answer
103 /// \prec no existing servers will be able to process queued requests
104 /// \sa SessionBase::dropQueued()
105 void dropQueued();
106
26b6afaf
EB
107 /// sends transaction response to the transaction initiator
108 void callBack(Xaction &);
109
bd71920d
EB
110 /// Starts required helper process(es).
111 /// The caller is responsible for checking that new processes are needed.
112 virtual void openSessions();
113
48d54e4d 114public:
3bd118d6 115 wordlist *cmdline = nullptr;
aa839030 116 dlink_list servers;
e05a9d51 117 std::queue<Xaction *> queue;
3bd118d6 118 const char *id_name = nullptr;
e05a9d51 119 ChildConfig childs; ///< Configuration settings for number running.
3bd118d6 120 int ipc_type = 0;
b7ac5457 121 Ip::Address addr;
3bd118d6
EB
122 unsigned int droppedRequests = 0; ///< requests not sent during helper overload
123 time_t overloadStart = 0; ///< when the helper became overloaded (zero if it is not)
124 time_t last_queue_warn = 0;
125 time_t last_restart = 0;
126 time_t timeout = 0; ///< Requests timeout
127 bool retryTimedOut = false; ///< Whether the timed-out requests must retried
128 bool retryBrokenHelper = false; ///< Whether the requests must retried on BH replies
895dba0a 129 SBuf onTimedOutResponse; ///< The response to use when helper response timedout
3bd118d6 130 char eom = '\n'; ///< The char which marks the end of (response) message, normally '\n'
aa839030 131
48d54e4d 132 struct _stats {
3bd118d6
EB
133 int requests = 0;
134 int replies = 0;
135 int timedout = 0;
136 int queue_size = 0;
137 int avg_svc_time = 0;
2fadd50d 138 } stats;
6825b101
CT
139
140protected:
3bd118d6 141 /// \param name admin-visible helper category (with this process lifetime)
e05a9d51 142 explicit Client(const char * const name): id_name(name) {}
3bd118d6 143
6082a0e2
EB
144 bool queueFull() const;
145 bool overloaded() const;
146 void syncQueueStats();
147 bool prepSubmit();
6825b101 148 void submit(const char *buf, HLPCB * callback, void *data);
aa839030 149};
150
e05a9d51
EB
151} // namespace Helper
152
153// TODO: Rename to a *Client.
154class statefulhelper: public Helper::Client
10044c9b 155{
48d54e4d 156public:
3bd118d6 157 using Pointer = RefCount<statefulhelper>;
a56fcf0b
CT
158 typedef std::unordered_map<Helper::ReservationId, helper_stateful_server *> Reservations;
159
e05a9d51 160 ~statefulhelper() override = default;
48d54e4d 161
3bd118d6
EB
162 static Pointer Make(const char *name);
163
a56fcf0b
CT
164 /// reserve the given server
165 void reserveServer(helper_stateful_server * srv);
166
167 /// undo reserveServer(), clear the reservation and kick the queue
168 void cancelReservation(const Helper::ReservationId reservation);
169
bd71920d
EB
170 /* Helper::Client API */
171 void openSessions() override;
172
6825b101 173private:
3bd118d6
EB
174 friend void helperStatefulSubmit(const statefulhelper::Pointer &, const char *buf, HLPCB *, void *cbData, const Helper::ReservationId &);
175
e05a9d51 176 explicit statefulhelper(const char * const name): Helper::Client(name) {}
a56fcf0b
CT
177
178 /// \return the previously reserved server (if the reservation is still valid) or nil
179 helper_stateful_server *findServer(const Helper::ReservationId & reservation);
180
181 void submit(const char *buf, HLPCB * callback, void *data, const Helper::ReservationId & reservation);
182 bool trySubmit(const char *buf, HLPCB * callback, void *data, const Helper::ReservationId & reservation);
183
895dba0a 184 ///< reserved servers indexed by reservation IDs
a56fcf0b 185 Reservations reservations;
aa839030 186};
187
e05a9d51
EB
188namespace Helper
189{
190
191/// represents a single helper process
192class SessionBase: public CbdataParent
10044c9b 193{
e0d28505 194public:
e05a9d51
EB
195 ~SessionBase() override;
196
0a958e42
EB
197 /// close handler to handle exited server processes
198 static void HelperServerClosed(SessionBase *);
199
e0d28505
AJ
200 /** Closes pipes to the helper safely.
201 * Handles the case where the read and write pipes are the same FD.
202 */
0a958e42 203 void closePipesSafely();
e0d28505
AJ
204
205 /** Closes the reading pipe.
206 * If the read and write sockets are the same the write pipe will
207 * also be closed. Otherwise its left open for later handling.
208 */
0a958e42 209 void closeWritePipeSafely();
e0d28505 210
a56fcf0b
CT
211 // TODO: Teach each child to report its child-specific state instead.
212 /// whether the server is locked for exclusive use by a client
213 virtual bool reserved() = 0;
214
0a958e42
EB
215 /// our creator (parent) object
216 virtual Client &helper() const = 0;
217
e05a9d51 218 /// dequeues and sends an Unknown answer to all queued requests
0a958e42 219 virtual void dropQueued();
a56fcf0b 220
48d54e4d 221public:
e237d339
AJ
222 /// Helper program identifier; does not change when contents do,
223 /// including during assignment
e05a9d51
EB
224 const InstanceId<SessionBase> index;
225
895dba0a 226 int pid;
b7ac5457 227 Ip::Address addr;
e0d28505
AJ
228 Comm::ConnectionPointer readPipe;
229 Comm::ConnectionPointer writePipe;
895dba0a 230 void *hIpc;
48d54e4d 231
895dba0a
CT
232 char *rbuf;
233 size_t rbuf_sz;
234 size_t roffset;
aa839030 235
236 struct timeval dispatch_time;
aa839030 237 struct timeval answer_time;
238
239 dlink_node link;
e0d28505
AJ
240
241 struct _helper_flags {
895dba0a
CT
242 bool writing;
243 bool closing;
244 bool shutdown;
e0d28505
AJ
245 } flags;
246
e05a9d51 247 using Requests = std::list<Xaction *>;
bf3e8d5a
AJ
248 Requests requests; ///< requests in order of submission/expiration
249
1f7ba0b4 250 struct {
895dba0a
CT
251 uint64_t uses; //< requests sent to this helper
252 uint64_t replies; //< replies received from this helper
253 uint64_t pending; //< queued lookups waiting to be sent to this helper
254 uint64_t releases; //< times release() has been called on this helper (if stateful)
255 uint64_t timedout; //< requests which timed-out
1f7ba0b4 256 } stats;
895dba0a 257 void initStats();
48d54e4d
AJ
258};
259
e05a9d51
EB
260/// represents a single "stateless helper" process;
261/// supports concurrent helper requests
262class Session: public SessionBase
10044c9b 263{
e05a9d51 264 CBDATA_CHILD(Session);
5c2f68b7 265
48d54e4d 266public:
895dba0a 267 uint64_t nextRequestId;
017a2d1f 268
895dba0a
CT
269 MemBuf *wqueue;
270 MemBuf *writebuf;
32fd6d8a 271
e05a9d51 272 Client::Pointer parent;
32fd6d8a 273
ddc77a2e
CT
274 /// The helper request Xaction object for the current reply .
275 /// A helper reply may be distributed to more than one of the retrieved
276 /// packets from helper. This member stores the Xaction object as long as
277 /// the end-of-message for current reply is not retrieved.
e05a9d51 278 Xaction *replyXaction;
ddc77a2e 279
1176e456 280 /// Whether to ignore current message, because it is timed-out or other reason
895dba0a 281 bool ignoreToEom;
1176e456 282
32fd6d8a
CT
283 // STL says storing std::list iterators is safe when changing the list
284 typedef std::map<uint64_t, Requests::iterator> RequestIndex;
285 RequestIndex requestsIndex; ///< maps request IDs to requests
286
e05a9d51
EB
287 ~Session() override;
288
ddc77a2e
CT
289 /// Search in queue for the request with requestId, return the related
290 /// Xaction object and remove it from queue.
291 /// If concurrency is disabled then the requestId is ignored and the
292 /// Xaction of the next request in queue is retrieved.
e05a9d51 293 Xaction *popRequest(int requestId);
ddc77a2e 294
32fd6d8a
CT
295 /// Run over the active requests lists and forces a retry, or timedout reply
296 /// or the configured "on timeout response" for timedout requests.
297 void checkForTimedOutRequests(bool const retry);
298
e05a9d51 299 /* SessionBase API */
337b9aa4 300 bool reserved() override {return false;}
0a958e42
EB
301 void dropQueued() override;
302 Client &helper() const override { return *parent; }
a56fcf0b 303
f53969cc 304 /// Read timeout handler
32fd6d8a 305 static void requestTimeout(const CommTimeoutCbParams &io);
aa839030 306};
307
e05a9d51
EB
308} // namespace Helper
309
310// TODO: Rename to a *Session, matching renamed statefulhelper.
311/// represents a single "stateful helper" process;
312/// supports exclusive transaction reservations
313class helper_stateful_server: public Helper::SessionBase
10044c9b 314{
a56fcf0b 315 CBDATA_CHILD(helper_stateful_server);
5c2f68b7 316
48d54e4d 317public:
337b9aa4 318 ~helper_stateful_server() override;
a56fcf0b
CT
319 void reserve();
320 void clearReservation();
321
0a958e42 322 /* Helper::SessionBase API */
337b9aa4 323 bool reserved() override {return reservationId.reserved();}
0a958e42 324 Helper::Client &helper() const override { return *parent; }
a56fcf0b 325
3bd118d6 326 statefulhelper::Pointer parent;
a56fcf0b
CT
327
328 // Reservations temporary lock the server for an exclusive "client" use. The
329 // client keeps the reservation ID as a proof of her reservation. If a
330 // reservation expires, and the server is reserved for another client, then
331 // the reservation ID presented by the late client will not match ours.
332 Helper::ReservationId reservationId; ///< "confirmation ID" of the last
895dba0a 333 time_t reservationStart; ///< when the last `reservation` was made
aa839030 334};
51ee7c82 335
e05a9d51 336void helperSubmit(const Helper::Client::Pointer &, const char *buf, HLPCB *, void *cbData);
3bd118d6 337void helperStatefulSubmit(const statefulhelper::Pointer &, const char *buf, HLPCB *, void *cbData, uint64_t reservation);
e05a9d51 338void helperShutdown(const Helper::Client::Pointer &);
3bd118d6 339void helperStatefulShutdown(const statefulhelper::Pointer &);
aa839030 340
ff9d9458 341#endif /* SQUID_SRC_HELPER_H */
70ac5b29 342