Moved and extended AICurlInterface::Stats

Moved AICurlPrivate::Stats to AICurlInterface::Stats and added several
counters to keep track of the number of existing instances of
respectively AICurlEasyRequest, AICurlEasyRequestStateMachine,
BufferedCurlEasyRequest, ResponderBase and
ThreadSafeBufferedCurlEasyRequest.
This commit is contained in:
Aleric Inglewood
2012-11-07 02:15:23 +01:00
parent 1a43bc8abf
commit cb52e82a60
6 changed files with 87 additions and 42 deletions

View File

@@ -289,6 +289,20 @@ static unsigned int encoded_version(int major, int minor, int patch)
namespace AICurlInterface {
//static
LLAtomicU32 Stats::easy_calls;
LLAtomicU32 Stats::easy_errors;
LLAtomicU32 Stats::easy_init_calls;
LLAtomicU32 Stats::easy_init_errors;
LLAtomicU32 Stats::easy_cleanup_calls;
LLAtomicU32 Stats::multi_calls;
LLAtomicU32 Stats::multi_errors;
LLAtomicU32 Stats::AICurlEasyRequest_count;
LLAtomicU32 Stats::AICurlEasyRequestStateMachine_count;
LLAtomicU32 Stats::BufferedCurlEasyRequest_count;
LLAtomicU32 Stats::ResponderBase_count;
LLAtomicU32 Stats::ThreadSafeBufferedCurlEasyRequest_count;
// MAIN-THREAD
void initCurl(void)
{
@@ -417,6 +431,39 @@ void setCAPath(std::string const& path)
CertificateAuthority_w->path = path;
}
//static
void Stats::print(void)
{
int const easy_handles = easy_init_calls - easy_init_errors - easy_cleanup_calls;
llinfos_nf << "============ CURL STATS ============" << llendl;
llinfos_nf << " Curl multi errors/calls : " << std::dec << multi_errors << "/" << multi_calls << llendl;
llinfos_nf << " Curl easy errors/calls : " << std::dec << easy_errors << "/" << easy_calls << llendl;
llinfos_nf << " curl_easy_init() errors/calls : " << std::dec << easy_init_errors << "/" << easy_init_calls << llendl;
llinfos_nf << " Current number of curl easy handles: " << std::dec << easy_handles << llendl;
#ifdef DEBUG_CURLIO
llinfos_nf << " Current number of BufferedCurlEasyRequest objects: " << BufferedCurlEasyRequest_count << llendl;
llinfos_nf << " Current number of ThreadSafeBufferedCurlEasyRequest objects: " << ThreadSafeBufferedCurlEasyRequest_count << llendl;
llinfos_nf << " Current number of AICurlEasyRequest objects: " << AICurlEasyRequest_count << llendl;
llinfos_nf << " Current number of AICurlEasyRequestStateMachine objects: " << AICurlEasyRequestStateMachine_count << llendl;
#endif
llinfos_nf << " Current number of Responders: " << ResponderBase_count << llendl;
llinfos_nf << "========= END OF CURL STATS =========" << llendl;
// Leak tests.
// There is one easy handle per CurlEasyHandle, and BufferedCurlEasyRequest is derived from that.
// It is not allowed to create CurlEasyHandle (or CurlEasyRequest) directly, only by creating a BufferedCurlEasyRequest,
// therefore the number of existing easy handles must equal the number of BufferedCurlEasyRequest objects.
llassert(easy_handles == BufferedCurlEasyRequest_count);
// Even more strict, BufferedCurlEasyRequest may not be created directly either, only as
// base class of ThreadSafeBufferedCurlEasyRequest.
llassert(BufferedCurlEasyRequest_count == ThreadSafeBufferedCurlEasyRequest_count);
// Each AICurlEasyRequestStateMachine is responsible for exactly one easy handle.
llassert(easy_handles >= AICurlEasyRequest_count);
// Each AICurlEasyRequestStateMachine has one AICurlEasyRequest member.
llassert(AICurlEasyRequest_count >= AICurlEasyRequestStateMachine_count);
// AIFIXME: is this really always the case? And why?
llassert(easy_handles <= ResponderBase_count);
}
} // namespace AICurlInterface
//==================================================================================
@@ -426,31 +473,13 @@ void setCAPath(std::string const& path)
namespace AICurlPrivate {
using AICurlInterface::Stats;
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
// CURLOPT_DEBUGFUNCTION function.
extern int debug_callback(CURL*, curl_infotype infotype, char* buf, size_t size, void* user_ptr);
#endif
//static
LLAtomicU32 Stats::easy_calls;
LLAtomicU32 Stats::easy_errors;
LLAtomicU32 Stats::easy_init_calls;
LLAtomicU32 Stats::easy_init_errors;
LLAtomicU32 Stats::easy_cleanup_calls;
LLAtomicU32 Stats::multi_calls;
LLAtomicU32 Stats::multi_errors;
//static
void Stats::print(void)
{
llinfos_nf << "============ CURL STATS ============" << llendl;
llinfos_nf << " Curl multi errors/calls : " << std::dec << multi_errors << "/" << multi_calls << llendl;
llinfos_nf << " Curl easy errors/calls : " << std::dec << easy_errors << "/" << easy_calls << llendl;
llinfos_nf << " curl_easy_init() errors/calls : " << std::dec << easy_init_errors << "/" << easy_init_calls << llendl;
llinfos_nf << " Current number of curl easy handles: " << std::dec << (easy_init_calls - easy_init_errors - easy_cleanup_calls) << llendl;
llinfos_nf << "========= END OF CURL STATS =========" << llendl;
}
// THREAD-SAFE
void handle_multi_error(CURLMcode code)
{
@@ -1175,6 +1204,7 @@ LLChannelDescriptors const BufferedCurlEasyRequest::sChannels;
BufferedCurlEasyRequest::BufferedCurlEasyRequest() : mRequestTransferedBytes(0), mResponseTransferedBytes(0), mBufferEventsTarget(NULL)
{
AICurlInterface::Stats::BufferedCurlEasyRequest_count++;
}
#define llmaybeerrs lllog(LLApp::isRunning() ? LLError::LEVEL_ERROR : LLError::LEVEL_WARN, NULL, NULL, false, true)
@@ -1202,6 +1232,7 @@ BufferedCurlEasyRequest::~BufferedCurlEasyRequest()
timed_out();
}
}
--AICurlInterface::Stats::BufferedCurlEasyRequest_count;
}
void BufferedCurlEasyRequest::timed_out(void)

View File

@@ -127,6 +127,23 @@ class AICurlNoBody : public AICurlError {
// Things defined in this namespace are called from elsewhere in the viewer code.
namespace AICurlInterface {
struct Stats {
static LLAtomicU32 easy_calls;
static LLAtomicU32 easy_errors;
static LLAtomicU32 easy_init_calls;
static LLAtomicU32 easy_init_errors;
static LLAtomicU32 easy_cleanup_calls;
static LLAtomicU32 multi_calls;
static LLAtomicU32 multi_errors;
static LLAtomicU32 AICurlEasyRequest_count;
static LLAtomicU32 AICurlEasyRequestStateMachine_count;
static LLAtomicU32 BufferedCurlEasyRequest_count;
static LLAtomicU32 ResponderBase_count;
static LLAtomicU32 ThreadSafeBufferedCurlEasyRequest_count;
static void print(void);
};
//-----------------------------------------------------------------------------
// Global functions.
@@ -221,11 +238,14 @@ class AICurlEasyRequest {
// 'new' never returned however and neither the constructor nor destructor of mBufferedCurlEasyRequest is called in this case.
// This might throw AICurlNoEasyHandle.
AICurlEasyRequest(void) :
mBufferedCurlEasyRequest(new AICurlPrivate::ThreadSafeBufferedCurlEasyRequest) { }
mBufferedCurlEasyRequest(new AICurlPrivate::ThreadSafeBufferedCurlEasyRequest) { AICurlInterface::Stats::AICurlEasyRequest_count++; }
public:
// Update stats.
~AICurlEasyRequest() { --AICurlInterface::Stats::AICurlEasyRequest_count; }
// Used for storing this object in a standard container (see MultiHandle::add_easy_request).
AICurlEasyRequest(AICurlEasyRequest const& orig) : mBufferedCurlEasyRequest(orig.mBufferedCurlEasyRequest) { }
AICurlEasyRequest(AICurlEasyRequest const& orig) : mBufferedCurlEasyRequest(orig.mBufferedCurlEasyRequest) { AICurlInterface::Stats::AICurlEasyRequest_count++; }
// For the rest, only allow read operations.
AIThreadSafeSimple<AICurlPrivate::BufferedCurlEasyRequest>& operator*(void) const { llassert(mBufferedCurlEasyRequest.get()); return *mBufferedCurlEasyRequest; }
@@ -271,11 +291,11 @@ class AICurlEasyRequest {
// then it's OK to construct a AICurlEasyRequest from it.
// Note that the external AICurlPrivate::BufferedCurlEasyRequestPtr needs its own locking, because
// it's not thread-safe in itself.
AICurlEasyRequest(AICurlPrivate::BufferedCurlEasyRequestPtr const& ptr) : mBufferedCurlEasyRequest(ptr) { }
AICurlEasyRequest(AICurlPrivate::BufferedCurlEasyRequestPtr const& ptr) : mBufferedCurlEasyRequest(ptr) { AICurlInterface::Stats::AICurlEasyRequest_count++; }
// This one is obviously dangerous. It's for use only in MultiHandle::check_msg_queue.
// See also the long comment in BufferedCurlEasyRequest::finalizeRequest with regard to CURLOPT_PRIVATE.
explicit AICurlEasyRequest(AICurlPrivate::ThreadSafeBufferedCurlEasyRequest* ptr) : mBufferedCurlEasyRequest(ptr) { }
explicit AICurlEasyRequest(AICurlPrivate::ThreadSafeBufferedCurlEasyRequest* ptr) : mBufferedCurlEasyRequest(ptr) { AICurlInterface::Stats::AICurlEasyRequest_count++; }
};
#define AICurlPrivate DONTUSE_AICurlPrivate

View File

@@ -249,6 +249,7 @@ AICurlEasyRequestStateMachine::AICurlEasyRequestStateMachine(void) :
mTimer(NULL), mTotalDelayTimeout(AIHTTPTimeoutPolicy::getDebugSettingsCurlTimeout().getTotalDelay())
{
Dout(dc::statemachine, "Calling AICurlEasyRequestStateMachine(void) [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
AICurlInterface::Stats::AICurlEasyRequestStateMachine_count++;
}
void AICurlEasyRequestStateMachine::setTotalDelayTimeout(F32 totalDelayTimeout)
@@ -259,5 +260,6 @@ void AICurlEasyRequestStateMachine::setTotalDelayTimeout(F32 totalDelayTimeout)
AICurlEasyRequestStateMachine::~AICurlEasyRequestStateMachine()
{
Dout(dc::statemachine, "Calling ~AICurlEasyRequestStateMachine() [" << (void*)this << "] [" << (void*)mCurlEasyRequest.get() << "]");
--AICurlInterface::Stats::AICurlEasyRequestStateMachine_count;
}

View File

@@ -111,20 +111,8 @@ class HTTPTimeout : public LLRefCount {
} // namespace curlthread
struct Stats {
static LLAtomicU32 easy_calls;
static LLAtomicU32 easy_errors;
static LLAtomicU32 easy_init_calls;
static LLAtomicU32 easy_init_errors;
static LLAtomicU32 easy_cleanup_calls;
static LLAtomicU32 multi_calls;
static LLAtomicU32 multi_errors;
static void print(void);
};
void handle_multi_error(CURLMcode code);
inline CURLMcode check_multi_code(CURLMcode code) { Stats::multi_calls++; if (code != CURLM_OK) handle_multi_error(code); return code; }
inline CURLMcode check_multi_code(CURLMcode code) { AICurlInterface::Stats::multi_calls++; if (code != CURLM_OK) handle_multi_error(code); return code; }
bool curlThreadIsRunning(void);
void wakeUpCurlThread(void);
@@ -248,7 +236,7 @@ class CurlEasyHandle : public boost::noncopyable, protected AICurlEasyHandleEven
// Always first call setErrorBuffer()!
static inline CURLcode check_easy_code(CURLcode code)
{
Stats::easy_calls++;
AICurlInterface::Stats::easy_calls++;
if (code != CURLE_OK)
handle_easy_error(code);
return code;
@@ -511,9 +499,11 @@ class ThreadSafeBufferedCurlEasyRequest : public AIThreadSafeSimple<BufferedCurl
// Throws AICurlNoEasyHandle.
ThreadSafeBufferedCurlEasyRequest(void) : mReferenceCount(0)
{ new (ptr()) BufferedCurlEasyRequest;
Dout(dc::curl, "Creating ThreadSafeBufferedCurlEasyRequest with this = " << (void*)this); }
virtual ~ThreadSafeBufferedCurlEasyRequest()
{ Dout(dc::curl, "Destructing ThreadSafeBufferedCurlEasyRequest with this = " << (void*)this); }
Dout(dc::curl, "Creating ThreadSafeBufferedCurlEasyRequest with this = " << (void*)this);
AICurlInterface::Stats::ThreadSafeBufferedCurlEasyRequest_count++; }
~ThreadSafeBufferedCurlEasyRequest()
{ Dout(dc::curl, "Destructing ThreadSafeBufferedCurlEasyRequest with this = " << (void*)this);
--AICurlInterface::Stats::ThreadSafeBufferedCurlEasyRequest_count; }
private:
LLAtomicU32 mReferenceCount;

View File

@@ -1527,7 +1527,7 @@ CURLMsg const* MultiHandle::info_read(int* msgs_in_queue) const
// never increment Stats::multi_errors. However, lets just increment multi_calls
// when it certainly wasn't an error...
if (ret)
Stats::multi_calls++;
AICurlInterface::Stats::multi_calls++;
return ret;
}

View File

@@ -265,12 +265,14 @@ void LLHTTPClient::get(std::string const& url, LLSD const& query, ResponderPtr r
LLHTTPClient::ResponderBase::ResponderBase(void) : mReferenceCount(0), mCode(CURLE_FAILED_INIT), mFinished(false)
{
DoutEntering(dc::curl, "AICurlInterface::Responder() with this = " << (void*)this);
AICurlInterface::Stats::ResponderBase_count++;
}
LLHTTPClient::ResponderBase::~ResponderBase()
{
DoutEntering(dc::curl, "AICurlInterface::ResponderBase::~ResponderBase() with this = " << (void*)this << "; mReferenceCount = " << mReferenceCount);
llassert(mReferenceCount == 0);
--AICurlInterface::Stats::ResponderBase_count;
}
void LLHTTPClient::ResponderBase::setURL(std::string const& url)