CURLIO (and libcwd): add number of established connections to http console.
I need to parse the debug output of libcurl for this, and choose to not do that for a Release build - at which point it makes little sense to even do it for a Debug build, since also the Alpha release are 'Release'. Even though it would probably have no impact on FPS, there would be like two persons looking at that number and understanding it.
This commit is contained in:
@@ -977,6 +977,7 @@ void CurlEasyRequest::resetState(void)
|
||||
mTimeoutPolicy = NULL;
|
||||
mTimeout = NULL;
|
||||
mHandleEventsTarget = NULL;
|
||||
mResult = CURLE_FAILED_INIT;
|
||||
applyDefaultOptions();
|
||||
}
|
||||
|
||||
@@ -1322,6 +1323,34 @@ void BufferedCurlEasyRequest::bad_socket(void)
|
||||
mResponder = NULL;
|
||||
}
|
||||
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
static AIPerServicePtr sConnections[64];
|
||||
|
||||
void BufferedCurlEasyRequest::connection_established(int connectionnr)
|
||||
{
|
||||
PerService_rat per_service_r(*mPerServicePtr);
|
||||
int n = per_service_r->connection_established();
|
||||
llassert(sConnections[connectionnr] == NULL); // Only one service can use a connection at a time.
|
||||
llassert_always(connectionnr < 64);
|
||||
sConnections[connectionnr] = mPerServicePtr;
|
||||
Dout(dc::curlio, (void*)get_lockobj() << " Connection established (#" << connectionnr << "). Now " << n << " connections [" << (void*)&*per_service_r << "].");
|
||||
llassert(sConnections[connectionnr] != NULL);
|
||||
}
|
||||
|
||||
void BufferedCurlEasyRequest::connection_closed(int connectionnr)
|
||||
{
|
||||
if (sConnections[connectionnr] == NULL)
|
||||
{
|
||||
Dout(dc::curlio, "Closing connection that never connected (#" << connectionnr << ").");
|
||||
return;
|
||||
}
|
||||
PerService_rat per_service_r(*sConnections[connectionnr]);
|
||||
int n = per_service_r->connection_closed();
|
||||
sConnections[connectionnr] = NULL;
|
||||
Dout(dc::curlio, (void*)get_lockobj() << " Connection closed (#" << connectionnr << "); " << n << " connections remaining [" << (void*)&*per_service_r << "].");
|
||||
}
|
||||
#endif
|
||||
|
||||
void BufferedCurlEasyRequest::resetState(void)
|
||||
{
|
||||
llassert(!mResponder);
|
||||
|
||||
@@ -75,6 +75,7 @@ AIPerService::AIPerService(void) :
|
||||
mConcurrentConnections(CurlConcurrentConnectionsPerService),
|
||||
mApprovedRequests(0),
|
||||
mTotalAdded(0),
|
||||
mEstablishedConnections(0),
|
||||
mUsedCT(0),
|
||||
mCTInUse(0)
|
||||
{
|
||||
@@ -230,6 +231,7 @@ AIPerServicePtr AIPerService::instance(std::string const& servicename)
|
||||
if (iter == instance_map_w->end())
|
||||
{
|
||||
iter = instance_map_w->insert(instance_map_type::value_type(servicename, new RefCountedThreadSafePerService)).first;
|
||||
Dout(dc::curlio, "Created new service \"" << servicename << "\" [" << (void*)&*PerService_rat(*iter->second) << "]");
|
||||
}
|
||||
// Note: the creation of AIPerServicePtr MUST be protected by the lock on sInstanceMap (see release()).
|
||||
return iter->second;
|
||||
|
||||
@@ -169,6 +169,7 @@ class AIPerService {
|
||||
int mConcurrentConnections; // The maximum number of allowed concurrent connections to this service.
|
||||
int mApprovedRequests; // The number of approved requests for this service by approveHTTPRequestFor that were not added to the command queue yet.
|
||||
int mTotalAdded; // Number of active easy handles with this service.
|
||||
int mEstablishedConnections; // Number of connected sockets to this service.
|
||||
|
||||
U32 mUsedCT; // Bit mask with one bit per capability type. A '1' means the capability was in use since the last resetUsedCT().
|
||||
U32 mCTInUse; // Bit mask with one bit per capability type. A '1' means the capability is in use right now.
|
||||
@@ -203,6 +204,9 @@ class AIPerService {
|
||||
}
|
||||
}
|
||||
public:
|
||||
int connection_established(void) { mEstablishedConnections++; return mEstablishedConnections; }
|
||||
int connection_closed(void) { mEstablishedConnections--; return mEstablishedConnections; }
|
||||
|
||||
static bool is_approved(AICapabilityType capability_type) { return (((U32)1 << capability_type) & approved_mask); }
|
||||
static U32 CT2mask(AICapabilityType capability_type) { return (U32)1 << capability_type; }
|
||||
void resetUsedCt(void) { mUsedCT = mCTInUse; }
|
||||
|
||||
@@ -457,6 +457,9 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
|
||||
// So far the only such error I've seen is HTTP_BAD_REQUEST.
|
||||
bool upload_error_status(void) const { return mStatus == HTTP_BAD_REQUEST; }
|
||||
|
||||
// Returns true if the request was a success.
|
||||
bool success(void) const { return mResult == CURLE_OK && mStatus >= 200 && mStatus < 400; }
|
||||
|
||||
// Return true when prepRequest was already called and the object has not been
|
||||
// invalidated as a result of calling timed_out().
|
||||
bool isValid(void) const { return mResponder; }
|
||||
@@ -466,6 +469,12 @@ class BufferedCurlEasyRequest : public CurlEasyRequest {
|
||||
|
||||
// Return true if any data was received.
|
||||
bool received_data(void) const { return mTotalRawBytes > 0; }
|
||||
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
// Connection accounting for debug purposes.
|
||||
void connection_established(int connectionnr);
|
||||
void connection_closed(int connectionnr);
|
||||
#endif
|
||||
};
|
||||
|
||||
inline ThreadSafeBufferedCurlEasyRequest* CurlEasyRequest::get_lockobj(void)
|
||||
|
||||
@@ -1845,12 +1845,11 @@ CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator cons
|
||||
{
|
||||
AICurlEasyRequest_wat curl_easy_request_w(**iter);
|
||||
bool downloaded_something = curl_easy_request_w->received_data();
|
||||
bool success = curl_easy_request_w->success();
|
||||
res = curl_easy_request_w->remove_handle_from_multi(curl_easy_request_w, mMultiHandle);
|
||||
capability_type = curl_easy_request_w->capability_type();
|
||||
per_service = curl_easy_request_w->getPerServicePtr();
|
||||
CURLcode code;
|
||||
curl_easy_request_w->getResult(&code, NULL);
|
||||
PerService_wat(*per_service)->removed_from_multi_handle(capability_type, downloaded_something, code == CURLE_OK); // (About to be) removed from mAddedEasyRequests.
|
||||
PerService_wat(*per_service)->removed_from_multi_handle(capability_type, downloaded_something, success); // (About to be) removed from mAddedEasyRequests.
|
||||
#ifdef SHOW_ASSERT
|
||||
curl_easy_request_w->mRemovedPerCommand = as_per_command;
|
||||
#endif
|
||||
@@ -2356,6 +2355,58 @@ int debug_callback(CURL* handle, curl_infotype infotype, char* buf, size_t size,
|
||||
{
|
||||
request->mDebugIsHeadOrGetMethod = true;
|
||||
}
|
||||
if (infotype == CURLINFO_TEXT)
|
||||
{
|
||||
if (!strncmp(buf, "STATE: WAITCONNECT => ", 22))
|
||||
{
|
||||
if (buf[22] == 'P' || buf[22] == 'D') // PROTOCONNECT or DO.
|
||||
{
|
||||
int n = size - 1;
|
||||
while (buf[n] != ')')
|
||||
{
|
||||
llassert(n > 56);
|
||||
--n;
|
||||
}
|
||||
int connectionnr = 0;
|
||||
int factor = 1;
|
||||
do
|
||||
{
|
||||
llassert(n > 56);
|
||||
--n;
|
||||
connectionnr += factor * (buf[n] - '0');
|
||||
factor *= 10;
|
||||
}
|
||||
while(buf[n - 1] != '#');
|
||||
// A new connection was established.
|
||||
request->connection_established(connectionnr);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(buf[22] == 'C'); // COMPLETED (connection failure).
|
||||
}
|
||||
}
|
||||
else if (!strncmp(buf, "Closing connection", 18))
|
||||
{
|
||||
int n = size - 1;
|
||||
while (!std::isdigit(buf[n]))
|
||||
{
|
||||
llassert(n > 20);
|
||||
--n;
|
||||
}
|
||||
int connectionnr = 0;
|
||||
int factor = 1;
|
||||
do
|
||||
{
|
||||
llassert(n > 19);
|
||||
connectionnr += factor * (buf[n] - '0');
|
||||
factor *= 10;
|
||||
--n;
|
||||
}
|
||||
while(buf[n] != '#');
|
||||
// A connection was closed.
|
||||
request->connection_closed(connectionnr);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CURLIO
|
||||
if (!debug_curl_print_debug(handle))
|
||||
|
||||
@@ -80,6 +80,7 @@ void AIServiceBar::draw()
|
||||
U32 is_used;
|
||||
U32 is_inuse;
|
||||
int total_added;
|
||||
int established_connections;
|
||||
int concurrent_connections;
|
||||
size_t bandwidth;
|
||||
{
|
||||
@@ -87,6 +88,7 @@ void AIServiceBar::draw()
|
||||
is_used = per_service_r->is_used();
|
||||
is_inuse = per_service_r->is_inuse();
|
||||
total_added = per_service_r->mTotalAdded;
|
||||
established_connections = per_service_r->mEstablishedConnections;
|
||||
concurrent_connections = per_service_r->mConcurrentConnections;
|
||||
bandwidth = per_service_r->bandwidth().truncateData(AIHTTPView::getTime_40ms());
|
||||
cts = per_service_r->mCapabilityType; // Not thread-safe, but we're only reading from it and only using the results to show in a debug console.
|
||||
@@ -145,7 +147,11 @@ void AIServiceBar::draw()
|
||||
start += LLFontGL::getFontMonospace()->getWidth(text);
|
||||
}
|
||||
start = mHTTPView->updateColumn(mc_col, start);
|
||||
#if defined(CWDEBUG) || defined(DEBUG_CURLIO)
|
||||
text = llformat(" | %d,%d/%d", total_added, established_connections, concurrent_connections);
|
||||
#else
|
||||
text = llformat(" | %d/%d", total_added, concurrent_connections);
|
||||
#endif
|
||||
LLFontGL::getFontMonospace()->renderUTF8(text, 0, start, height, text_color, LLFontGL::LEFT, LLFontGL::TOP);
|
||||
start += LLFontGL::getFontMonospace()->getWidth(text);
|
||||
start = mHTTPView->updateColumn(bw_col, start);
|
||||
|
||||
Reference in New Issue
Block a user