]> git.ipfire.org Git - thirdparty/squid.git/blob - src/helper.h
Merged from trunk
[thirdparty/squid.git] / src / helper.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 /* DEBUG: section 84 Helper process maintenance */
10
11 #ifndef SQUID_HELPER_H
12 #define SQUID_HELPER_H
13
14 #include "base/AsyncCall.h"
15 #include "base/InstanceId.h"
16 #include "cbdata.h"
17 #include "comm/forward.h"
18 #include "dlink.h"
19 #include "helper/ChildConfig.h"
20 #include "helper/forward.h"
21 #include "ip/Address.h"
22 #include "SBuf.h"
23
24 #include <list>
25 #include <map>
26
27 class Packable;
28
29 /**
30 * Managers a set of individual helper processes with a common queue of requests.
31 *
32 * With respect to load, a helper goes through these states (roughly):
33 * idle: no processes are working on requests (and no requests are queued);
34 * normal: some, but not all processes are working (and no requests are queued);
35 * busy: all processes are working (and some requests are possibly queued);
36 * full: all processes are working and at least 2*#processes requests are queued.
37 *
38 * A "busy" helper queues new requests and issues a WARNING every 10 minutes or so.
39 * A "full" helper either drops new requests or keeps queuing them, depending on
40 * whether the caller can handle dropped requests (trySubmit vs helperSubmit APIs).
41 * An attempt to use a "full" helper that has been "full" for 3+ minutes kills worker.
42 * Given enough load, all helpers except for external ACL will make such attempts.
43 */
44 class helper
45 {
46 CBDATA_CLASS(helper);
47
48 public:
49 inline helper(const char *name) :
50 cmdline(NULL),
51 id_name(name),
52 ipc_type(0),
53 full_time(0),
54 last_queue_warn(0),
55 last_restart(0),
56 timeout(0),
57 retryTimedOut(false),
58 retryBrokenHelper(false),
59 eom('\n') {
60 memset(&stats, 0, sizeof(stats));
61 }
62 ~helper();
63
64 ///< whether at least one more request can be successfully submitted
65 bool queueFull() const;
66
67 ///< If not full, submit request. Otherwise, either kill Squid or return false.
68 bool trySubmit(const char *buf, HLPCB * callback, void *data);
69
70 /// Submits a request to the helper or add it to the queue if none of
71 /// the servers is available.
72 void submitRequest(Helper::Request *r);
73
74 /// Dump some stats about the helper state to a Packable object
75 void packStatsInto(Packable *p, const char *label = NULL) const;
76
77 public:
78 wordlist *cmdline;
79 dlink_list servers;
80 dlink_list queue;
81 const char *id_name;
82 Helper::ChildConfig childs; ///< Configuration settings for number running.
83 int ipc_type;
84 Ip::Address addr;
85 time_t full_time; ///< when a full helper became full (zero for non-full helpers)
86 time_t last_queue_warn;
87 time_t last_restart;
88 time_t timeout; ///< Requests timeout
89 bool retryTimedOut; ///< Whether the timed-out requests must retried
90 bool retryBrokenHelper; ///< Whether the requests must retried on BH replies
91 SBuf onTimedOutResponse; ///< The response to use when helper response timedout
92 char eom; ///< The char which marks the end of (response) message, normally '\n'
93
94 struct _stats {
95 int requests;
96 int replies;
97 int timedout;
98 int queue_size;
99 int avg_svc_time;
100 } stats;
101
102 protected:
103 friend void helperSubmit(helper * hlp, const char *buf, HLPCB * callback, void *data);
104 void prepSubmit();
105 void submit(const char *buf, HLPCB * callback, void *data);
106 };
107
108 class statefulhelper : public helper
109 {
110 CBDATA_CLASS(statefulhelper);
111
112 public:
113 inline statefulhelper(const char *name) : helper(name), datapool(NULL), IsAvailable(NULL), OnEmptyQueue(NULL) {}
114 inline ~statefulhelper() {}
115
116 public:
117 MemAllocator *datapool;
118 HLPSAVAIL *IsAvailable;
119 HLPSONEQ *OnEmptyQueue;
120
121 private:
122 friend void helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPCB * callback, void *data, helper_stateful_server * lastserver);
123 void submit(const char *buf, HLPCB * callback, void *data, helper_stateful_server *lastserver);
124 };
125
126 /**
127 * Fields shared between stateless and stateful helper servers.
128 */
129 class HelperServerBase
130 {
131 public:
132 /** Closes pipes to the helper safely.
133 * Handles the case where the read and write pipes are the same FD.
134 *
135 * \param name displayed for the helper being shutdown if logging an error
136 */
137 void closePipesSafely(const char *name);
138
139 /** Closes the reading pipe.
140 * If the read and write sockets are the same the write pipe will
141 * also be closed. Otherwise its left open for later handling.
142 *
143 * \param name displayed for the helper being shutdown if logging an error
144 */
145 void closeWritePipeSafely(const char *name);
146
147 public:
148 /// Helper program identifier; does not change when contents do,
149 /// including during assignment
150 const InstanceId<HelperServerBase> index;
151 int pid;
152 Ip::Address addr;
153 Comm::ConnectionPointer readPipe;
154 Comm::ConnectionPointer writePipe;
155 void *hIpc;
156
157 char *rbuf;
158 size_t rbuf_sz;
159 size_t roffset;
160
161 struct timeval dispatch_time;
162 struct timeval answer_time;
163
164 dlink_node link;
165
166 struct _helper_flags {
167 bool writing;
168 bool closing;
169 bool shutdown;
170 bool reserved;
171 } flags;
172
173 typedef std::list<Helper::Request *> Requests;
174 Requests requests; ///< requests in order of submission/expiration
175
176 struct {
177 uint64_t uses; //< requests sent to this helper
178 uint64_t replies; //< replies received from this helper
179 uint64_t pending; //< queued lookups waiting to be sent to this helper
180 uint64_t releases; //< times release() has been called on this helper (if stateful)
181 uint64_t timedout; //< requests which timed-out
182 } stats;
183 void initStats();
184 };
185
186 class MemBuf;
187 class CommTimeoutCbParams;
188
189 class helper_server : public HelperServerBase
190 {
191 CBDATA_CLASS(helper_server);
192
193 public:
194 uint64_t nextRequestId;
195
196 MemBuf *wqueue;
197 MemBuf *writebuf;
198
199 helper *parent;
200
201 // STL says storing std::list iterators is safe when changing the list
202 typedef std::map<uint64_t, Requests::iterator> RequestIndex;
203 RequestIndex requestsIndex; ///< maps request IDs to requests
204
205 /// Run over the active requests lists and forces a retry, or timedout reply
206 /// or the configured "on timeout response" for timedout requests.
207 void checkForTimedOutRequests(bool const retry);
208
209 /// Read timeout handler
210 static void requestTimeout(const CommTimeoutCbParams &io);
211 };
212
213 class helper_stateful_server : public HelperServerBase
214 {
215 CBDATA_CLASS(helper_stateful_server);
216
217 public:
218 /* MemBuf wqueue; */
219 /* MemBuf writebuf; */
220
221 statefulhelper *parent;
222
223 void *data; /* State data used by the calling routines */
224 };
225
226 /* helper.c */
227 void helperOpenServers(helper * hlp);
228 void helperStatefulOpenServers(statefulhelper * hlp);
229 void helperSubmit(helper * hlp, const char *buf, HLPCB * callback, void *data);
230 void helperStatefulSubmit(statefulhelper * hlp, const char *buf, HLPCB * callback, void *data, helper_stateful_server * lastserver);
231 void helperShutdown(helper * hlp);
232 void helperStatefulShutdown(statefulhelper * hlp);
233 void helperStatefulReleaseServer(helper_stateful_server * srv);
234 void *helperStatefulServerGetData(helper_stateful_server * srv);
235
236 #endif /* SQUID_HELPER_H */
237