]> git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/Initiate.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / adaptation / Initiate.cc
1 /*
2 * DEBUG: section 93 ICAP (RFC 3507) Client
3 */
4
5 #include "squid.h"
6 #include "adaptation/Answer.h"
7 #include "adaptation/Initiate.h"
8 #include "adaptation/Initiator.h"
9 #include "base/AsyncJobCalls.h"
10 #include "HttpMsg.h"
11
12 namespace Adaptation
13 {
14 typedef UnaryMemFunT<Initiator, Answer, const Answer &> AnswerDialer;
15 /// Calls expectNoConsumption() if noteAdaptationAnswer async call is
16 /// scheduled but never fired (e.g., because the HTTP transaction aborts).
17 class AnswerCall: public AsyncCallT<AnswerDialer>
18 {
19 public:
20 AnswerCall(const char *aName, const AnswerDialer &aDialer) :
21 AsyncCallT<AnswerDialer>(93, 5, aName, aDialer), fired(false) {}
22 virtual void fire() {
23 fired = true;
24 AsyncCallT<AnswerDialer>::fire();
25 }
26 virtual ~AnswerCall() {
27 if (!fired && dialer.arg1.message != NULL && dialer.arg1.message->body_pipe != NULL)
28 dialer.arg1.message->body_pipe->expectNoConsumption();
29 }
30
31 private:
32 bool fired; ///< whether we fired the call
33 };
34 }
35
36 Adaptation::Initiate::Initiate(const char *aTypeName): AsyncJob(aTypeName)
37 {
38 }
39
40 Adaptation::Initiate::~Initiate()
41 {
42 // TODO: we cannot assert(!theInitiator) because that fails if a child
43 // constructor fails. AsyncJob should have wasStarted flag so that we
44 // can assert(!(wasStarted && theInitiator)).
45 }
46
47 void
48 Adaptation::Initiate::initiator(const CbcPointer<Initiator> &i)
49 {
50 Must(!theInitiator);
51 Must(i.valid());
52 theInitiator = i;
53 }
54
55 // internal cleanup
56 void Adaptation::Initiate::swanSong()
57 {
58 debugs(93, 5, HERE << "swan sings" << status());
59
60 if (theInitiator.set()) {
61 debugs(93, 3, HERE << "fatal failure; sending abort notification");
62 tellQueryAborted(true); // final by default
63 }
64
65 debugs(93, 5, HERE << "swan sang" << status());
66 }
67
68 void Adaptation::Initiate::clearInitiator()
69 {
70 theInitiator.clear();
71 }
72
73 void Adaptation::Initiate::sendAnswer(const Answer &answer)
74 {
75 AsyncCall::Pointer call = new AnswerCall("Initiator::noteAdaptationAnswer",
76 AnswerDialer(theInitiator, &Initiator::noteAdaptationAnswer, answer));
77 ScheduleCallHere(call);
78 clearInitiator();
79 }
80
81 void Adaptation::Initiate::tellQueryAborted(bool final)
82 {
83 sendAnswer(Answer::Error(final));
84 }
85
86 const char *Adaptation::Initiate::status() const
87 {
88 return AsyncJob::status(); // for now
89 }