AsyncJob.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
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.
7  */
8 
9 /* DEBUG: section 93 ICAP (RFC 3507) Client */
10 
11 #include "squid.h"
12 #include "base/AsyncCall.h"
13 #include "base/AsyncJob.h"
14 #include "base/AsyncJobCalls.h"
15 #include "base/TextException.h"
16 #include "cbdata.h"
17 #include "MemBuf.h"
18 
19 #include <ostream>
20 
22 
23 void
25 {
26  CallJobHere(93, 5, job, AsyncJob, start);
27  job->started_ = true; // it is the attempt that counts
28 }
29 
30 AsyncJob::AsyncJob(const char *aTypeName) :
31  stopReason(NULL), typeName(aTypeName), inCall(NULL)
32 {
33  debugs(93,5, "AsyncJob constructed, this=" << this <<
34  " type=" << typeName << " [" << id << ']');
35 }
36 
38 {
39  debugs(93,5, "AsyncJob destructed, this=" << this <<
40  " type=" << typeName << " [" << id << ']');
42 }
43 
45 {
46 }
47 
48 // XXX: temporary code to replace calls to "delete this" in jobs-in-transition.
49 // Will be replaced with calls to mustStop() when transition is complete.
50 void AsyncJob::deleteThis(const char *aReason)
51 {
52  Must(aReason);
53  stopReason = aReason;
54  if (inCall != NULL) {
55  // if we are in-call, then the call wrapper will delete us
56  debugs(93, 4, typeName << " will NOT delete in-call job, reason: " << stopReason);
57  return;
58  }
59 
60  // there is no call wrapper waiting for our return, so we fake it
61  debugs(93, 5, typeName << " will delete this, reason: " << stopReason);
62  CbcPointer<AsyncJob> self(this);
63  AsyncCall::Pointer fakeCall = asyncCall(93,4, "FAKE-deleteThis",
64  JobMemFun(self, &AsyncJob::deleteThis, aReason));
65  inCall = fakeCall;
66  callEnd();
67 // delete fakeCall;
68 }
69 
70 void AsyncJob::mustStop(const char *aReason)
71 {
72  // XXX: temporary code to catch cases where mustStop is called outside
73  // of an async call context. Will be removed when that becomes impossible.
74  // Until then, this will cause memory leaks and possibly other problems.
75  if (!inCall) {
76  stopReason = aReason;
77  debugs(93, 5, typeName << " will STALL, reason: " << stopReason);
78  return;
79  }
80 
81  Must(inCall != NULL); // otherwise nobody will delete us if we are done()
82  Must(aReason);
83  if (!stopReason) {
84  stopReason = aReason;
85  debugs(93, 5, typeName << " will stop, reason: " << stopReason);
86  } else {
87  debugs(93, 5, typeName << " will stop, another reason: " << aReason);
88  }
89 }
90 
91 bool AsyncJob::done() const
92 {
93  // stopReason, set in mustStop(), overwrites all other conditions
94  return stopReason != NULL || doneAll();
95 }
96 
97 bool AsyncJob::doneAll() const
98 {
99  return true; // so that it is safe for kids to use
100 }
101 
103 {
104  if (inCall != NULL) {
105  // This may happen when we have bugs or some module is not calling
106  // us asynchronously (comm used to do that).
107  debugs(93, 5, HERE << inCall << " is in progress; " <<
108  call << " cannot reenter the job.");
109  return call.cancel("reentrant job call");
110  }
111 
112  return true;
113 }
114 
116 {
117  // we must be called asynchronously and hence, the caller must lock us
119 
120  Must(!inCall); // see AsyncJob::canBeCalled
121 
122  inCall = &call; // XXX: ugly, but safe if callStart/callEnd,Ex are paired
124  typeName << " status in:" << status());
125 }
126 
127 void
128 AsyncJob::callException(const std::exception &ex)
129 {
130  debugs(93, 2, ex.what());
131  // we must be called asynchronously and hence, the caller must lock us
133 
134  mustStop("exception");
135 }
136 
138 {
139  if (done()) {
140  debugs(93, 5, *inCall << " ends job" << status());
141 
142  AsyncCall::Pointer inCallSaved = inCall;
143  void *thisSaved = this;
144 
145  // TODO: Swallow swanSong() exceptions to reduce memory leaks.
146 
147  // Job callback invariant: swanSong() is (only) called for started jobs.
148  // Here to detect violations in kids that forgot to call our swanSong().
149  assert(started_);
150 
151  swanSang_ = true; // it is the attempt that counts
152  swanSong();
153 
154  delete this; // this is the only place where a started job is deleted
155 
156  // careful: this object does not exist any more
157  debugs(93, 6, HERE << *inCallSaved << " ended " << thisSaved);
158  return;
159  }
160 
162  typeName << " status out:" << status());
163  inCall = NULL;
164 }
165 
166 // returns a temporary string depicting transaction status, for debugging
167 const char *AsyncJob::status() const
168 {
169  static MemBuf buf;
170  buf.reset();
171 
172  buf.append(" [", 2);
173  if (stopReason != NULL) {
174  buf.appendf("Stopped, reason:%s", stopReason);
175  }
176  buf.appendf(" %s%u]", id.prefix(), id.value);
177  buf.terminate();
178 
179  return buf.content();
180 }
181 
bool cancel(const char *reason)
Definition: AsyncCall.cc:56
void terminate()
Definition: MemBuf.cc:250
bool canBeCalled(AsyncCall &call) const
whether we can be called
Definition: AsyncJob.cc:102
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
bool started_
Start() has finished successfully.
Definition: AsyncJob.h:83
AsyncCall::Pointer inCall
the asynchronous call being handled, if any
Definition: AsyncJob.h:81
virtual void callEnd()
called right after the called job method
Definition: AsyncJob.cc:137
virtual void swanSong()
Definition: AsyncJob.h:59
const char * stopReason
reason for forcing done() to be true
Definition: AsyncJob.h:79
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:216
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:398
AsyncJob(const char *aTypeName)
Definition: AsyncJob.cc:30
virtual void * toCbdata()=0
#define NULL
Definition: types.h:166
virtual bool doneAll() const
whether positive goal has been reached
Definition: AsyncJob.cc:97
const int debugLevel
Definition: AsyncCall.h:78
virtual ~AsyncJob()
Definition: AsyncJob.cc:37
void mustStop(const char *aReason)
Definition: AsyncJob.cc:70
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
Definition: MemBuf.h:24
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:152
const int debugSection
Definition: AsyncCall.h:77
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:58
NullaryMemFunT< C > JobMemFun(const CbcPointer< C > &job, typename NullaryMemFunT< C >::Method method)
#define assert(EX)
Definition: assert.h:19
bool swanSang_
swanSong() was called
Definition: AsyncJob.h:84
InstanceIdDefinitions(AsyncJob, "job")
const char * typeName
kid (leaf) class name, for debugging
Definition: AsyncJob.h:80
bool done() const
the job is destroyed in callEnd() when done()
Definition: AsyncJob.cc:91
virtual const char * status() const
internal cleanup; do not call directly
Definition: AsyncJob.cc:167
void deleteThis(const char *aReason)
Definition: AsyncJob.cc:50
void callStart(AsyncCall &call)
Definition: AsyncJob.cc:115
char * content()
start of the added data
Definition: MemBuf.h:41
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:44
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:73
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void reset()
Definition: MemBuf.cc:132
virtual void callException(const std::exception &e)
called when the job throws during an async call
Definition: AsyncJob.cc:128
static void Start(const Pointer &job)
Definition: AsyncJob.cc:24

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors