]> git.ipfire.org Git - thirdparty/squid.git/blame - src/base/AsyncJob.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / base / AsyncJob.cc
CommitLineData
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 21InstanceIdDefinitions(AsyncJob, "job");
3e5c8cf4 22
4299f876 23AsyncJob::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 30AsyncJob::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
37AsyncJob::~AsyncJob()
38{
5dfc3258 39 debugs(93,5, "AsyncJob destructed, this=" << this <<
52ed047a 40 " type=" << typeName << " [" << id << ']');
c824c43b 41}
42
c824c43b 43void 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.
49void 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
69void 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
90bool AsyncJob::done() const
91{
92 // stopReason, set in mustStop(), overwrites all other conditions
93 return stopReason != NULL || doneAll();
94}
95
96bool AsyncJob::doneAll() const
97{
98 return true; // so that it is safe for kids to use
99}
100
3e5c8cf4 101bool 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 114void 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
126void
127AsyncJob::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
135void 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
158const 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