]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/Inquirer.cc
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 54 Interprocess Communication */
12 #include "base/TextException.h"
14 #include "comm/Write.h"
15 #include "ipc/Inquirer.h"
17 #include "ipc/TypedMsgHdr.h"
21 CBDATA_NAMESPACED_CLASS_INIT(Ipc
, Inquirer
);
23 Ipc::Inquirer::RequestsMap
Ipc::Inquirer::TheRequestsMap
;
24 Ipc::RequestId::Index
Ipc::Inquirer::LastRequestId
= 0;
26 /// compare Ipc::StrandCoord using kidId, for std::sort() below
28 LesserStrandByKidId(const Ipc::StrandCoord
&c1
, const Ipc::StrandCoord
&c2
)
30 return c1
.kidId
< c2
.kidId
;
33 Ipc::Inquirer::Inquirer(Request::Pointer aRequest
, const StrandCoords
& coords
,
35 AsyncJob("Ipc::Inquirer"),
36 codeContext(CodeContext::Current()),
37 request(aRequest
), strands(coords
), pos(strands
.begin()), timeout(aTimeout
)
39 debugs(54, 5, MYNAME
);
41 // order by ascending kid IDs; useful for non-aggregatable stats
42 std::sort(strands
.begin(), strands
.end(), LesserStrandByKidId
);
45 Ipc::Inquirer::~Inquirer()
47 debugs(54, 5, MYNAME
);
52 Ipc::Inquirer::cleanup()
57 Ipc::Inquirer::start()
59 request
->requestId
= 0;
63 Ipc::Inquirer::inquire()
65 if (pos
== strands
.end()) {
70 Must(request
->requestId
== 0);
71 AsyncCall::Pointer callback
= asyncCall(54, 5, "Mgr::Inquirer::handleRemoteAck",
72 HandleAckDialer(this, &Inquirer::handleRemoteAck
, nullptr));
73 if (++LastRequestId
== 0) // don't use zero value as request->requestId
75 request
->requestId
= LastRequestId
;
76 const int kidId
= pos
->kidId
;
77 debugs(54, 4, "inquire kid: " << kidId
<< status());
78 TheRequestsMap
[request
->requestId
] = callback
;
80 request
->pack(message
);
81 SendMessage(Port::MakeAddr(strandAddrLabel
, kidId
), message
);
82 eventAdd("Ipc::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut
,
83 this, timeout
, 0, false);
86 /// called when a strand is done writing its output
88 Ipc::Inquirer::handleRemoteAck(Response::Pointer response
)
90 debugs(54, 4, status());
91 request
->requestId
= 0;
93 if (aggregate(response
)) {
94 Must(!done()); // or we should not be called
95 ++pos
; // advance after a successful inquiry
103 Ipc::Inquirer::swanSong()
105 debugs(54, 5, MYNAME
);
106 removeTimeoutEvent();
107 if (request
->requestId
> 0) {
108 DequeueRequest(request
->requestId
);
109 request
->requestId
= 0;
116 Ipc::Inquirer::doneAll() const
118 return pos
== strands
.end();
122 Ipc::Inquirer::handleException(const std::exception
& e
)
124 debugs(54, 3, e
.what());
125 mustStop("exception");
129 Ipc::Inquirer::callException(const std::exception
& e
)
131 debugs(54, 3, MYNAME
);
134 } catch (const std::exception
& ex
) {
135 debugs(54, DBG_CRITICAL
, ex
.what());
137 AsyncJob::callException(e
);
140 /// returns and forgets the right Inquirer callback for strand request
142 Ipc::Inquirer::DequeueRequest(const RequestId::Index requestId
)
144 debugs(54, 3, " requestId " << requestId
);
145 Must(requestId
!= 0);
146 AsyncCall::Pointer call
;
147 RequestsMap::iterator request
= TheRequestsMap
.find(requestId
);
148 if (request
!= TheRequestsMap
.end()) {
149 call
= request
->second
;
150 Must(call
!= nullptr);
151 TheRequestsMap
.erase(request
);
157 Ipc::Inquirer::HandleRemoteAck(const Response
& response
)
159 Must(response
.requestId
!= 0);
160 AsyncCall::Pointer call
= DequeueRequest(response
.requestId
);
161 if (call
!= nullptr) {
162 HandleAckDialer
* dialer
= dynamic_cast<HandleAckDialer
*>(call
->getDialer());
164 dialer
->arg1
= response
.clone();
165 ScheduleCallHere(call
);
169 /// called when we are no longer waiting for the strand to respond
171 Ipc::Inquirer::removeTimeoutEvent()
173 if (eventFind(&Inquirer::RequestTimedOut
, this))
174 eventDelete(&Inquirer::RequestTimedOut
, this);
177 /// Ipc::Inquirer::requestTimedOut wrapper
179 Ipc::Inquirer::RequestTimedOut(void* param
)
181 debugs(54, 3, MYNAME
);
182 Must(param
!= nullptr);
183 Inquirer
* cmi
= static_cast<Inquirer
*>(param
);
184 // use async call to enable job call protection that time events lack
185 CallBack(cmi
->codeContext
, [&cmi
] {
186 CallJobHere(54, 5, cmi
, Inquirer
, requestTimedOut
);
190 /// called when the strand failed to respond (or finish responding) in time
192 Ipc::Inquirer::requestTimedOut()
194 debugs(54, 3, MYNAME
);
195 if (request
->requestId
!= 0) {
196 DequeueRequest(request
->requestId
);
197 request
->requestId
= 0;
198 Must(!done()); // or we should not be called
199 ++pos
; // advance after a failed inquiry
205 Ipc::Inquirer::status() const
209 buf
.appendf(" [requestId %u]", request
->requestId
.index());
211 return buf
.content();