diff --git a/indra/llmessage/aicurl.h b/indra/llmessage/aicurl.h index 26491da67..2402da224 100644 --- a/indra/llmessage/aicurl.h +++ b/indra/llmessage/aicurl.h @@ -99,7 +99,7 @@ struct TransferInfo { void initCurl(void (*)(void) = NULL); // Called once at start of application (from LLAppViewer::initThreads), starts AICurlThread. -void startCurlThread(void); +void startCurlThread(U32 CurlConcurrentConnections); // Called once at end of application (from newview/llappviewer.cpp by main thread), // with purpose to stop curl threads, free curl resources and deinitialize curl. diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 71302accb..a75b1f0a0 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -1440,18 +1440,27 @@ CURLMsg const* MultiHandle::info_read(int* msgs_in_queue) const return ret; } -CURLMcode MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request) +static U32 curl_concurrent_connections = 8; // Initialized on start up by startCurlThread(). + +void MultiHandle::add_easy_request(AICurlEasyRequest const& easy_request) { - std::pair res = mAddedEasyRequests.insert(easy_request); - llassert(res.second); // May not have been added before. - CURLMcode ret; + if (mAddedEasyRequests.size() < curl_concurrent_connections) // Not throttled? { - AICurlEasyRequest_wat curl_easy_request_w(*easy_request); - ret = curl_easy_request_w->add_handle_to_multi(curl_easy_request_w, mMultiHandle); + CURLMcode ret; + { + AICurlEasyRequest_wat curl_easy_request_w(*easy_request); + ret = curl_easy_request_w->add_handle_to_multi(curl_easy_request_w, mMultiHandle); + } + if (ret == CURLM_OK) + { + mHandleAddedOrRemoved = true; + std::pair res = mAddedEasyRequests.insert(easy_request); + llassert(res.second); // May not have been added before. + Dout(dc::curl, "MultiHandle::add_easy_request: Added AICurlEasyRequest " << (void*)easy_request.get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); + return; + } } - mHandleAddedOrRemoved = true; - Dout(dc::curl, "MultiHandle::add_easy_request: Added AICurlEasyRequest " << (void*)easy_request.get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); - return ret; + mQueuedRequests.push_back(easy_request); } CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request, bool as_per_command) @@ -1470,6 +1479,14 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request mAddedEasyRequests.erase(iter); mHandleAddedOrRemoved = true; Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)easy_request.get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); + + // Attempt to add a queued request, if any. + if (!mQueuedRequests.empty()) + { + add_easy_request(mQueuedRequests.front()); + mQueuedRequests.pop_front(); + } + return res; } @@ -1697,11 +1714,12 @@ void AICurlEasyRequest::removeRequest(void) namespace AICurlInterface { -void startCurlThread(void) +void startCurlThread(U32 CurlConcurrentConnections) { using namespace AICurlPrivate::curlthread; llassert(is_main_thread()); + curl_concurrent_connections = CurlConcurrentConnections; // Debug Setting. AICurlThread::sInstance = new AICurlThread; AICurlThread::sInstance->start(); } diff --git a/indra/llmessage/aicurlthread.h b/indra/llmessage/aicurlthread.h index a2bd36352..839c8339e 100644 --- a/indra/llmessage/aicurlthread.h +++ b/indra/llmessage/aicurlthread.h @@ -33,6 +33,7 @@ #include "aicurl.h" #include +#include #undef AICurlPrivate @@ -59,7 +60,7 @@ class MultiHandle : public CurlMultiHandle ~MultiHandle(); // Add/remove an easy handle to/from a multi session. - CURLMcode add_easy_request(AICurlEasyRequest const& easy_request); + void add_easy_request(AICurlEasyRequest const& easy_request); CURLMcode remove_easy_request(AICurlEasyRequest const& easy_request, bool as_per_command = false); // Reads/writes available data from a particular socket (non-blocking). @@ -100,6 +101,10 @@ class MultiHandle : public CurlMultiHandle PollSet* mReadPollSet; PollSet* mWritePollSet; + + private: + // Temporary throttling hack. + std::deque mQueuedRequests; // Waiting (throttled) requests. }; } // namespace curlthread diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c0ec36c53..7d9482424 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4205,6 +4205,17 @@ Value 0 + CurlConcurrentConnections + + Comment + Maximum number of simultaneous curl connections (requires restart) + Persist + 1 + Type + U32 + Value + 16 + CurlMaximumNumberOfHandles Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2fcf37fdb..0e55784cc 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1817,7 +1817,7 @@ bool LLAppViewer::initThreads() LLWatchdog::getInstance()->init(watchdog_killer_callback); } - AICurlInterface::startCurlThread(); + AICurlInterface::startCurlThread(gSavedSettings.getU32("CurlConcurrentConnections")); LLImage::initClass();