]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/Inquirer.cc
2 * Copyright (C) 1996-2017 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 unsigned int 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 request(aRequest
), strands(coords
), pos(strands
.begin()), timeout(aTimeout
)
40 // order by ascending kid IDs; useful for non-aggregatable stats
41 std::sort(strands
.begin(), strands
.end(), LesserStrandByKidId
);
44 Ipc::Inquirer::~Inquirer()
51 Ipc::Inquirer::cleanup()
56 Ipc::Inquirer::start()
58 request
->requestId
= 0;
62 Ipc::Inquirer::inquire()
64 if (pos
== strands
.end()) {
69 Must(request
->requestId
== 0);
70 AsyncCall::Pointer callback
= asyncCall(54, 5, "Mgr::Inquirer::handleRemoteAck",
71 HandleAckDialer(this, &Inquirer::handleRemoteAck
, NULL
));
72 if (++LastRequestId
== 0) // don't use zero value as request->requestId
74 request
->requestId
= LastRequestId
;
75 const int kidId
= pos
->kidId
;
76 debugs(54, 4, HERE
<< "inquire kid: " << kidId
<< status());
77 TheRequestsMap
[request
->requestId
] = callback
;
79 request
->pack(message
);
80 SendMessage(Port::MakeAddr(strandAddrLabel
, kidId
), message
);
81 eventAdd("Ipc::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut
,
82 this, timeout
, 0, false);
85 /// called when a strand is done writing its output
87 Ipc::Inquirer::handleRemoteAck(Response::Pointer response
)
89 debugs(54, 4, HERE
<< status());
90 request
->requestId
= 0;
92 if (aggregate(response
)) {
93 Must(!done()); // or we should not be called
94 ++pos
; // advance after a successful inquiry
102 Ipc::Inquirer::swanSong()
105 removeTimeoutEvent();
106 if (request
->requestId
> 0) {
107 DequeueRequest(request
->requestId
);
108 request
->requestId
= 0;
115 Ipc::Inquirer::doneAll() const
117 return pos
== strands
.end();
121 Ipc::Inquirer::handleException(const std::exception
& e
)
123 debugs(54, 3, HERE
<< e
.what());
124 mustStop("exception");
128 Ipc::Inquirer::callException(const std::exception
& e
)
133 } catch (const std::exception
& ex
) {
134 debugs(54, DBG_CRITICAL
, HERE
<< ex
.what());
136 AsyncJob::callException(e
);
139 /// returns and forgets the right Inquirer callback for strand request
141 Ipc::Inquirer::DequeueRequest(unsigned int requestId
)
143 debugs(54, 3, HERE
<< " requestId " << requestId
);
144 Must(requestId
!= 0);
145 AsyncCall::Pointer call
;
146 RequestsMap::iterator request
= TheRequestsMap
.find(requestId
);
147 if (request
!= TheRequestsMap
.end()) {
148 call
= request
->second
;
150 TheRequestsMap
.erase(request
);
156 Ipc::Inquirer::HandleRemoteAck(const Response
& response
)
158 Must(response
.requestId
!= 0);
159 AsyncCall::Pointer call
= DequeueRequest(response
.requestId
);
161 HandleAckDialer
* dialer
= dynamic_cast<HandleAckDialer
*>(call
->getDialer());
163 dialer
->arg1
= response
.clone();
164 ScheduleCallHere(call
);
168 /// called when we are no longer waiting for the strand to respond
170 Ipc::Inquirer::removeTimeoutEvent()
172 if (eventFind(&Inquirer::RequestTimedOut
, this))
173 eventDelete(&Inquirer::RequestTimedOut
, this);
176 /// Ipc::Inquirer::requestTimedOut wrapper
178 Ipc::Inquirer::RequestTimedOut(void* param
)
182 Inquirer
* cmi
= static_cast<Inquirer
*>(param
);
183 // use async call to enable job call protection that time events lack
184 CallJobHere(54, 5, cmi
, Inquirer
, requestTimedOut
);
187 /// called when the strand failed to respond (or finish responding) in time
189 Ipc::Inquirer::requestTimedOut()
192 if (request
->requestId
!= 0) {
193 DequeueRequest(request
->requestId
);
194 request
->requestId
= 0;
195 Must(!done()); // or we should not be called
196 ++pos
; // advance after a failed inquiry
202 Ipc::Inquirer::status() const
206 buf
.appendf(" [request->requestId %u]", request
->requestId
);
208 return buf
.content();