]>
Commit | Line | Data |
---|---|---|
c824c43b | 1 | /* |
b510f3a1 | 2 | * DEBUG: section 93 ICAP (RFC 3507) Client |
c824c43b | 3 | */ |
4 | ||
5 | #include "squid.h" | |
3ff65596 | 6 | #include "acl/FilledChecklist.h" |
26cc52cb AR |
7 | #include "adaptation/icap/Launcher.h" |
8 | #include "adaptation/icap/Xaction.h" | |
9 | #include "adaptation/icap/ServiceRep.h" | |
3ff65596 | 10 | #include "adaptation/icap/Config.h" |
3d93a84d AJ |
11 | #include "base/TextException.h" |
12 | #include "HttpMsg.h" | |
13 | #include "HttpRequest.h" | |
14 | #include "HttpReply.h" | |
c824c43b | 15 | |
16 | ||
26cc52cb | 17 | Adaptation::Icap::Launcher::Launcher(const char *aTypeName, |
af6a12ee | 18 | Adaptation::Initiator *anInitiator, Adaptation::ServicePointer &aService): |
26ac0430 | 19 | AsyncJob(aTypeName), |
a22e6cd3 AR |
20 | Adaptation::Initiate(aTypeName, anInitiator), |
21 | theService(aService), theXaction(0), theLaunches(0) | |
c824c43b | 22 | { |
23 | } | |
24 | ||
26cc52cb | 25 | Adaptation::Icap::Launcher::~Launcher() |
c824c43b | 26 | { |
27 | assert(!theXaction); | |
28 | } | |
29 | ||
26cc52cb | 30 | void Adaptation::Icap::Launcher::start() |
c824c43b | 31 | { |
0bef8dd7 | 32 | Adaptation::Initiate::start(); |
c824c43b | 33 | |
34 | Must(theInitiator); | |
3ff65596 | 35 | launchXaction("first"); |
c824c43b | 36 | } |
37 | ||
3ff65596 | 38 | void Adaptation::Icap::Launcher::launchXaction(const char *xkind) |
c824c43b | 39 | { |
40 | Must(!theXaction); | |
41 | ++theLaunches; | |
3ff65596 | 42 | debugs(93,4, HERE << "launching " << xkind << " xaction #" << theLaunches); |
26cc52cb | 43 | Adaptation::Icap::Xaction *x = createXaction(); |
3ff65596 AR |
44 | x->attempts = theLaunches; |
45 | if (theLaunches > 1) | |
c824c43b | 46 | x->disableRetries(); |
3ff65596 AR |
47 | if (theLaunches >= TheConfig.repeat_limit) |
48 | x->disableRepeats("over icap_retry_limit"); | |
0bef8dd7 | 49 | theXaction = initiateAdaptation(x); |
c824c43b | 50 | Must(theXaction); |
51 | } | |
52 | ||
26cc52cb | 53 | void Adaptation::Icap::Launcher::noteAdaptationAnswer(HttpMsg *message) |
c824c43b | 54 | { |
c824c43b | 55 | sendAnswer(message); |
0bef8dd7 | 56 | clearAdaptation(theXaction); |
c824c43b | 57 | Must(done()); |
26cc52cb | 58 | debugs(93,3, HERE << "Adaptation::Icap::Launcher::noteAdaptationAnswer exiting "); |
c824c43b | 59 | } |
60 | ||
26cc52cb | 61 | void Adaptation::Icap::Launcher::noteInitiatorAborted() |
c824c43b | 62 | { |
c824c43b | 63 | |
64 | announceInitiatorAbort(theXaction); // propogate to the transaction | |
65 | clearInitiator(); | |
66 | Must(done()); // should be nothing else to do | |
67 | ||
c824c43b | 68 | } |
69 | ||
3ff65596 | 70 | // XXX: this call is unused by ICAPXaction in favor of ICAPLauncher::noteXactAbort |
26cc52cb | 71 | void Adaptation::Icap::Launcher::noteAdaptationQueryAbort(bool final) |
c824c43b | 72 | { |
3ff65596 | 73 | debugs(93,5, HERE << "launches: " << theLaunches << "; final: " << final); |
0bef8dd7 | 74 | clearAdaptation(theXaction); |
e1381638 | 75 | |
3ff65596 AR |
76 | Must(done()); // swanSong will notify the initiator |
77 | } | |
78 | ||
79 | void Adaptation::Icap::Launcher::noteXactAbort(XactAbortInfo &info) | |
80 | { | |
81 | debugs(93,5, HERE << "theXaction:" << theXaction << " launches: " << theLaunches); | |
c824c43b | 82 | |
e1381638 | 83 | // TODO: add more checks from FwdState::checkRetry()? |
3ff65596 AR |
84 | if (canRetry(info)) { |
85 | clearAdaptation(theXaction); | |
86 | launchXaction("retry"); | |
e1381638 | 87 | } else if (canRepeat(info)) { |
3ff65596 AR |
88 | clearAdaptation(theXaction); |
89 | launchXaction("repeat"); | |
c824c43b | 90 | } else { |
3ff65596 AR |
91 | debugs(93,3, HERE << "cannot retry or repeat a failed transaction"); |
92 | clearAdaptation(theXaction); | |
a22e6cd3 AR |
93 | tellQueryAborted(false); // caller decides based on bypass, consumption |
94 | Must(done()); | |
e1381638 | 95 | } |
c824c43b | 96 | } |
97 | ||
26cc52cb | 98 | bool Adaptation::Icap::Launcher::doneAll() const |
26ac0430 | 99 | { |
0bef8dd7 | 100 | return (!theInitiator || !theXaction) && Adaptation::Initiate::doneAll(); |
c824c43b | 101 | } |
102 | ||
26cc52cb | 103 | void Adaptation::Icap::Launcher::swanSong() |
c824c43b | 104 | { |
105 | if (theInitiator) | |
a22e6cd3 | 106 | tellQueryAborted(true); // always final here because abnormal |
c824c43b | 107 | |
108 | if (theXaction) | |
0bef8dd7 | 109 | clearAdaptation(theXaction); |
c824c43b | 110 | |
0bef8dd7 | 111 | Adaptation::Initiate::swanSong(); |
c824c43b | 112 | } |
3ff65596 AR |
113 | |
114 | bool Adaptation::Icap::Launcher::canRetry(Adaptation::Icap::XactAbortInfo &info) const | |
115 | { | |
116 | // We do not check and can exceed zero repeat limit when retrying. | |
117 | // This is by design as the limit does not apply to pconn retrying. | |
118 | return !shutting_down && info.isRetriable; | |
119 | } | |
120 | ||
121 | bool Adaptation::Icap::Launcher::canRepeat(Adaptation::Icap::XactAbortInfo &info) const | |
122 | { | |
123 | debugs(93,9, HERE << shutting_down); | |
124 | if (theLaunches >= TheConfig.repeat_limit || shutting_down) | |
125 | return false; | |
126 | ||
127 | debugs(93,9, HERE << info.isRepeatable); // TODO: update and use status() | |
128 | if (!info.isRepeatable) | |
129 | return false; | |
130 | ||
131 | debugs(93,9, HERE << info.icapReply); | |
132 | if (!info.icapReply) // did not get to read an ICAP reply; a timeout? | |
133 | return true; | |
e1381638 | 134 | |
3ff65596 AR |
135 | debugs(93,9, HERE << info.icapReply->sline.status); |
136 | if (!info.icapReply->sline.status) // failed to parse the reply; I/O err | |
137 | return true; | |
e1381638 | 138 | |
3ff65596 AR |
139 | ACLFilledChecklist *cl = |
140 | new ACLFilledChecklist(TheConfig.repeat, info.icapRequest, dash_str); | |
141 | cl->reply = HTTPMSGLOCK(info.icapReply); | |
e1381638 | 142 | |
3ff65596 AR |
143 | const bool result = cl->fastCheck(); |
144 | delete cl; | |
145 | return result; | |
146 | } | |
147 | ||
148 | /* ICAPXactAbortInfo */ | |
149 | ||
150 | Adaptation::Icap::XactAbortInfo::XactAbortInfo(HttpRequest *anIcapRequest, | |
e1381638 AJ |
151 | HttpReply *anIcapReply, bool beRetriable, bool beRepeatable): |
152 | icapRequest(anIcapRequest ? HTTPMSGLOCK(anIcapRequest) : NULL), | |
153 | icapReply(anIcapReply ? HTTPMSGLOCK(anIcapReply) : NULL), | |
154 | isRetriable(beRetriable), isRepeatable(beRepeatable) | |
3ff65596 AR |
155 | { |
156 | } | |
157 | ||
158 | Adaptation::Icap::XactAbortInfo::XactAbortInfo(const Adaptation::Icap::XactAbortInfo &i): | |
e1381638 AJ |
159 | icapRequest(i.icapRequest ? HTTPMSGLOCK(i.icapRequest) : NULL), |
160 | icapReply(i.icapReply ? HTTPMSGLOCK(i.icapReply) : NULL), | |
161 | isRetriable(i.isRetriable), isRepeatable(i.isRepeatable) | |
3ff65596 AR |
162 | { |
163 | } | |
164 | ||
165 | Adaptation::Icap::XactAbortInfo::~XactAbortInfo() | |
166 | { | |
167 | HTTPMSGUNLOCK(icapRequest); | |
168 | HTTPMSGUNLOCK(icapReply); | |
169 | } |