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