]>
Commit | Line | Data |
---|---|---|
51ea0904 | 1 | /* |
bf95c10a | 2 | * Copyright (C) 1996-2022 The Squid Software Foundation and contributors |
51ea0904 | 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. | |
51ea0904 CT |
7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 54 Interprocess Communication */ |
10 | ||
f7f3304a | 11 | #include "squid.h" |
51ea0904 CT |
12 | #include "base/AsyncJobCalls.h" |
13 | #include "base/TextException.h" | |
1b76e6c1 AJ |
14 | #include "errorpage.h" |
15 | #include "HttpReply.h" | |
16 | #include "HttpRequest.h" | |
51ea0904 CT |
17 | #include "ipc/Forwarder.h" |
18 | #include "ipc/Port.h" | |
4c218615 | 19 | #include "ipc/RequestId.h" |
51ea0904 CT |
20 | #include "ipc/TypedMsgHdr.h" |
21 | ||
51ea0904 CT |
22 | CBDATA_NAMESPACED_CLASS_INIT(Ipc, Forwarder); |
23 | ||
24 | Ipc::Forwarder::RequestsMap Ipc::Forwarder::TheRequestsMap; | |
4c218615 | 25 | Ipc::RequestId::Index Ipc::Forwarder::LastRequestId = 0; |
51ea0904 CT |
26 | |
27 | Ipc::Forwarder::Forwarder(Request::Pointer aRequest, double aTimeout): | |
f53969cc | 28 | AsyncJob("Ipc::Forwarder"), |
87388f15 | 29 | codeContext(CodeContext::Current()), |
f53969cc | 30 | request(aRequest), timeout(aTimeout) |
51ea0904 | 31 | { |
51ea0904 CT |
32 | } |
33 | ||
34 | Ipc::Forwarder::~Forwarder() | |
35 | { | |
ebaabe74 AR |
36 | SWALLOW_EXCEPTIONS({ |
37 | Must(request->requestId == 0); | |
38 | }); | |
51ea0904 CT |
39 | } |
40 | ||
41 | void | |
42 | Ipc::Forwarder::start() | |
43 | { | |
bf95c10a | 44 | debugs(54, 3, MYNAME); |
51ea0904 CT |
45 | |
46 | typedef NullaryMemFunT<Forwarder> Dialer; | |
933a6aed | 47 | AsyncCall::Pointer callback = JobCallback(54, 5, Dialer, this, Forwarder::handleRemoteAck); |
51ea0904 CT |
48 | if (++LastRequestId == 0) // don't use zero value as request->requestId |
49 | ++LastRequestId; | |
50 | request->requestId = LastRequestId; | |
51 | TheRequestsMap[request->requestId] = callback; | |
52 | TypedMsgHdr message; | |
53 | ||
54 | try { | |
55 | request->pack(message); | |
56 | } catch (...) { | |
57 | // assume the pack() call failed because the message did not fit | |
58 | // TODO: add a more specific exception? | |
59 | handleError(); | |
a7ba2ec1 | 60 | return; |
51ea0904 CT |
61 | } |
62 | ||
1ee292b7 | 63 | SendMessage(Ipc::Port::CoordinatorAddr(), message); |
51ea0904 CT |
64 | eventAdd("Ipc::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut, |
65 | this, timeout, 0, false); | |
66 | } | |
67 | ||
68 | void | |
69 | Ipc::Forwarder::swanSong() | |
70 | { | |
bf95c10a | 71 | debugs(54, 5, MYNAME); |
51ea0904 CT |
72 | removeTimeoutEvent(); |
73 | if (request->requestId > 0) { | |
74 | DequeueRequest(request->requestId); | |
75 | request->requestId = 0; | |
76 | } | |
51ea0904 CT |
77 | } |
78 | ||
79 | bool | |
80 | Ipc::Forwarder::doneAll() const | |
81 | { | |
bf95c10a | 82 | debugs(54, 5, MYNAME); |
51ea0904 CT |
83 | return request->requestId == 0; |
84 | } | |
85 | ||
86 | /// called when Coordinator starts processing the request | |
87 | void | |
88 | Ipc::Forwarder::handleRemoteAck() | |
89 | { | |
bf95c10a | 90 | debugs(54, 3, MYNAME); |
51ea0904 | 91 | request->requestId = 0; |
70eb3fde EB |
92 | // Do not do entry->complete() because it will trigger our client side |
93 | // processing when we no longer own the client-Squid connection. | |
94 | // Let job cleanup close the client-Squid connection that Coordinator | |
95 | // now owns. | |
51ea0904 CT |
96 | } |
97 | ||
98 | /// Ipc::Forwarder::requestTimedOut wrapper | |
99 | void | |
100 | Ipc::Forwarder::RequestTimedOut(void* param) | |
101 | { | |
bf95c10a | 102 | debugs(54, 3, MYNAME); |
aee3523a | 103 | Must(param != nullptr); |
51ea0904 CT |
104 | Forwarder* fwdr = static_cast<Forwarder*>(param); |
105 | // use async call to enable job call protection that time events lack | |
87388f15 EB |
106 | |
107 | CallBack(fwdr->codeContext, [&fwdr] { | |
108 | CallJobHere(54, 5, fwdr, Forwarder, requestTimedOut); | |
109 | }); | |
51ea0904 CT |
110 | } |
111 | ||
112 | /// called when Coordinator fails to start processing the request [in time] | |
113 | void | |
114 | Ipc::Forwarder::requestTimedOut() | |
115 | { | |
bf95c10a | 116 | debugs(54, 3, MYNAME); |
51ea0904 CT |
117 | handleTimeout(); |
118 | } | |
119 | ||
120 | void | |
121 | Ipc::Forwarder::handleError() | |
122 | { | |
123 | mustStop("error"); | |
124 | } | |
125 | ||
126 | void | |
127 | Ipc::Forwarder::handleTimeout() | |
128 | { | |
129 | mustStop("timeout"); | |
130 | } | |
131 | ||
132 | /// terminate with an error | |
133 | void | |
134 | Ipc::Forwarder::handleException(const std::exception& e) | |
135 | { | |
bf95c10a | 136 | debugs(54, 3, e.what()); |
51ea0904 CT |
137 | mustStop("exception"); |
138 | } | |
139 | ||
140 | void | |
141 | Ipc::Forwarder::callException(const std::exception& e) | |
142 | { | |
143 | try { | |
144 | handleException(e); | |
145 | } catch (const std::exception& ex) { | |
bf95c10a | 146 | debugs(54, DBG_CRITICAL, ex.what()); |
51ea0904 CT |
147 | } |
148 | AsyncJob::callException(e); | |
149 | } | |
150 | ||
151 | /// returns and forgets the right Forwarder callback for the request | |
152 | AsyncCall::Pointer | |
4c218615 | 153 | Ipc::Forwarder::DequeueRequest(const RequestId::Index requestId) |
51ea0904 | 154 | { |
bf95c10a | 155 | debugs(54, 3, MYNAME); |
51ea0904 CT |
156 | Must(requestId != 0); |
157 | AsyncCall::Pointer call; | |
158 | RequestsMap::iterator request = TheRequestsMap.find(requestId); | |
159 | if (request != TheRequestsMap.end()) { | |
160 | call = request->second; | |
aee3523a | 161 | Must(call != nullptr); |
51ea0904 CT |
162 | TheRequestsMap.erase(request); |
163 | } | |
164 | return call; | |
165 | } | |
166 | ||
167 | /// called when we are no longer waiting for Coordinator to respond | |
168 | void | |
169 | Ipc::Forwarder::removeTimeoutEvent() | |
170 | { | |
171 | if (eventFind(&Forwarder::RequestTimedOut, this)) | |
172 | eventDelete(&Forwarder::RequestTimedOut, this); | |
173 | } | |
174 | ||
175 | void | |
4c218615 | 176 | Ipc::Forwarder::HandleRemoteAck(const RequestId requestId) |
51ea0904 | 177 | { |
bf95c10a | 178 | debugs(54, 3, MYNAME); |
51ea0904 CT |
179 | Must(requestId != 0); |
180 | ||
181 | AsyncCall::Pointer call = DequeueRequest(requestId); | |
aee3523a | 182 | if (call != nullptr) |
51ea0904 CT |
183 | ScheduleCallHere(call); |
184 | } | |
f53969cc | 185 |