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