]>
Commit | Line | Data |
---|---|---|
c824c43b | 1 | /* |
ef57eb7b | 2 | * Copyright (C) 1996-2016 The Squid Software Foundation and contributors |
bbc27441 AJ |
3 | * |
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. | |
c824c43b | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 93 ICAP (RFC 3507) Client */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
3d93a84d AJ |
12 | #include "base/AsyncCall.h" |
13 | #include "base/AsyncJob.h" | |
4299f876 | 14 | #include "base/AsyncJobCalls.h" |
3d93a84d | 15 | #include "base/TextException.h" |
c824c43b | 16 | #include "cbdata.h" |
3e5c8cf4 | 17 | #include "MemBuf.h" |
c824c43b | 18 | |
d977f933 AJ |
19 | #include <ostream> |
20 | ||
52ed047a | 21 | InstanceIdDefinitions(AsyncJob, "job"); |
3e5c8cf4 | 22 | |
4299f876 | 23 | AsyncJob::Pointer AsyncJob::Start(AsyncJob *j) |
26ac0430 | 24 | { |
4299f876 AR |
25 | AsyncJob::Pointer job(j); |
26 | CallJobHere(93, 5, job, AsyncJob, start); | |
c824c43b | 27 | return job; |
28 | } | |
29 | ||
c9568681 | 30 | AsyncJob::AsyncJob(const char *aTypeName) : |
f53969cc | 31 | stopReason(NULL), typeName(aTypeName), inCall(NULL) |
c824c43b | 32 | { |
5dfc3258 | 33 | debugs(93,5, "AsyncJob constructed, this=" << this << |
52ed047a | 34 | " type=" << typeName << " [" << id << ']'); |
c824c43b | 35 | } |
36 | ||
37 | AsyncJob::~AsyncJob() | |
38 | { | |
5dfc3258 | 39 | debugs(93,5, "AsyncJob destructed, this=" << this << |
52ed047a | 40 | " type=" << typeName << " [" << id << ']'); |
c824c43b | 41 | } |
42 | ||
c824c43b | 43 | void AsyncJob::start() |
44 | { | |
3e5c8cf4 | 45 | } |
46 | ||
47 | // XXX: temporary code to replace calls to "delete this" in jobs-in-transition. | |
48 | // Will be replaced with calls to mustStop() when transition is complete. | |
49 | void AsyncJob::deleteThis(const char *aReason) | |
50 | { | |
51 | Must(aReason); | |
52 | stopReason = aReason; | |
53 | if (inCall != NULL) { | |
54 | // if we are in-call, then the call wrapper will delete us | |
55 | debugs(93, 4, typeName << " will NOT delete in-call job, reason: " << stopReason); | |
56 | return; | |
26ac0430 AJ |
57 | } |
58 | ||
3e5c8cf4 | 59 | // there is no call wrapper waiting for our return, so we fake it |
60 | debugs(93, 5, typeName << " will delete this, reason: " << stopReason); | |
4299f876 | 61 | CbcPointer<AsyncJob> self(this); |
3e5c8cf4 | 62 | AsyncCall::Pointer fakeCall = asyncCall(93,4, "FAKE-deleteThis", |
4cb2536f | 63 | JobMemFun(self, &AsyncJob::deleteThis, aReason)); |
3e5c8cf4 | 64 | inCall = fakeCall; |
65 | callEnd(); | |
66 | // delete fakeCall; | |
c824c43b | 67 | } |
68 | ||
69 | void AsyncJob::mustStop(const char *aReason) | |
70 | { | |
3e5c8cf4 | 71 | // XXX: temporary code to catch cases where mustStop is called outside |
72 | // of an async call context. Will be removed when that becomes impossible. | |
73 | // Until then, this will cause memory leaks and possibly other problems. | |
26ac0430 | 74 | if (!inCall) { |
3e5c8cf4 | 75 | stopReason = aReason; |
76 | debugs(93, 5, typeName << " will STALL, reason: " << stopReason); | |
77 | return; | |
26ac0430 | 78 | } |
3e5c8cf4 | 79 | |
80 | Must(inCall != NULL); // otherwise nobody will delete us if we are done() | |
c824c43b | 81 | Must(aReason); |
82 | if (!stopReason) { | |
83 | stopReason = aReason; | |
84 | debugs(93, 5, typeName << " will stop, reason: " << stopReason); | |
85 | } else { | |
86 | debugs(93, 5, typeName << " will stop, another reason: " << aReason); | |
87 | } | |
88 | } | |
89 | ||
90 | bool AsyncJob::done() const | |
91 | { | |
92 | // stopReason, set in mustStop(), overwrites all other conditions | |
93 | return stopReason != NULL || doneAll(); | |
94 | } | |
95 | ||
96 | bool AsyncJob::doneAll() const | |
97 | { | |
98 | return true; // so that it is safe for kids to use | |
99 | } | |
100 | ||
3e5c8cf4 | 101 | bool AsyncJob::canBeCalled(AsyncCall &call) const |
c824c43b | 102 | { |
3e5c8cf4 | 103 | if (inCall != NULL) { |
104 | // This may happen when we have bugs or some module is not calling | |
105 | // us asynchronously (comm used to do that). | |
26ac0430 AJ |
106 | debugs(93, 5, HERE << inCall << " is in progress; " << |
107 | call << " canot reenter the job."); | |
3e5c8cf4 | 108 | return call.cancel("reentrant job call"); |
c824c43b | 109 | } |
110 | ||
c824c43b | 111 | return true; |
112 | } | |
113 | ||
3e5c8cf4 | 114 | void AsyncJob::callStart(AsyncCall &call) |
115 | { | |
116 | // we must be called asynchronously and hence, the caller must lock us | |
117 | Must(cbdataReferenceValid(toCbdata())); | |
118 | ||
119 | Must(!inCall); // see AsyncJob::canBeCalled | |
120 | ||
121 | inCall = &call; // XXX: ugly, but safe if callStart/callEnd,Ex are paired | |
122 | debugs(inCall->debugSection, inCall->debugLevel, | |
26ac0430 | 123 | typeName << " status in:" << status()); |
3e5c8cf4 | 124 | } |
125 | ||
ced8def3 AJ |
126 | void |
127 | AsyncJob::callException(const std::exception &) | |
c824c43b | 128 | { |
3e5c8cf4 | 129 | // we must be called asynchronously and hence, the caller must lock us |
130 | Must(cbdataReferenceValid(toCbdata())); | |
c824c43b | 131 | |
132 | mustStop("exception"); | |
133 | } | |
134 | ||
135 | void AsyncJob::callEnd() | |
136 | { | |
137 | if (done()) { | |
3e5c8cf4 | 138 | debugs(93, 5, *inCall << " ends job" << status()); |
c824c43b | 139 | |
3e5c8cf4 | 140 | AsyncCall::Pointer inCallSaved = inCall; |
c824c43b | 141 | void *thisSaved = this; |
142 | ||
143 | swanSong(); | |
144 | ||
c824c43b | 145 | delete this; // this is the only place where the object is deleted |
c824c43b | 146 | |
147 | // careful: this object does not exist any more | |
3e5c8cf4 | 148 | debugs(93, 6, HERE << *inCallSaved << " ended " << thisSaved); |
c824c43b | 149 | return; |
150 | } | |
151 | ||
3e5c8cf4 | 152 | debugs(inCall->debugSection, inCall->debugLevel, |
26ac0430 | 153 | typeName << " status out:" << status()); |
c824c43b | 154 | inCall = NULL; |
155 | } | |
156 | ||
3e5c8cf4 | 157 | // returns a temporary string depicting transaction status, for debugging |
158 | const char *AsyncJob::status() const | |
159 | { | |
160 | static MemBuf buf; | |
161 | buf.reset(); | |
162 | ||
163 | buf.append(" [", 2); | |
26ac0430 | 164 | if (stopReason != NULL) { |
4391cd15 | 165 | buf.appendf("Stopped, reason:%s", stopReason); |
3e5c8cf4 | 166 | } |
4391cd15 | 167 | buf.appendf(" %s%u]", id.Prefix, id.value); |
3e5c8cf4 | 168 | buf.terminate(); |
169 | ||
170 | return buf.content(); | |
171 | } | |
172 |