summaryrefslogtreecommitdiff
path: root/indra/llcorehttp/_httplibcurl.cpp
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2012-06-08 20:21:54 -0400
committerMonty Brandenberg <monty@lindenlab.com>2012-06-08 20:21:54 -0400
commit28a04400b4160dd34166483ddcf0c12637bcc363 (patch)
treee43ca202df6ed9bc8cbcc4a97d354e4798b7aa62 /indra/llcorehttp/_httplibcurl.cpp
parent1e3d05329f2e823191c7c91926bee5ec9e5dc4d7 (diff)
Implemented HTTP retry for requests. Went in rather easily which
surprised me. Added a retry queue similar to ready queue to the policy object which is sorted by retry time. Currently do five retries (after the initial try) delayed by .25, .5, 1, 2 and 5 seconds. Removed the retry logic from the lltexturefetch module. Upped the waiting time in the unit test for the retries. People won't like this but tough, need tests.
Diffstat (limited to 'indra/llcorehttp/_httplibcurl.cpp')
-rw-r--r--indra/llcorehttp/_httplibcurl.cpp58
1 files changed, 50 insertions, 8 deletions
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 5272c391e8..05b2c2be69 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -29,6 +29,7 @@
#include "httpheaders.h"
#include "bufferarray.h"
#include "_httpoprequest.h"
+#include "_httppolicy.h"
namespace LLCore
@@ -85,6 +86,8 @@ void HttpLibcurl::term()
HttpService::ELoopSpeed HttpLibcurl::processTransport()
{
+ HttpService::ELoopSpeed ret(HttpService::REQUEST_SLEEP);
+
// Give libcurl some cycles to do I/O & callbacks
for (int policy_class(0); policy_class < HttpRequest::POLICY_CLASS_LIMIT; ++policy_class)
{
@@ -110,7 +113,8 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
CURL * handle(msg->easy_handle);
CURLcode result(msg->data.result);
- completeRequest(mMultiHandles[policy_class], handle, result);
+ HttpService::ELoopSpeed speed(completeRequest(mMultiHandles[policy_class], handle, result));
+ ret = (std::min)(ret, speed);
handle = NULL; // No longer valid on return
}
else if (CURLMSG_NONE == msg->msg)
@@ -127,7 +131,11 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
}
}
- return mActiveOps.empty() ? HttpService::REQUEST_SLEEP : HttpService::NORMAL;
+ if (! mActiveOps.empty())
+ {
+ ret = (std::min)(ret, HttpService::NORMAL);
+ }
+ return ret;
}
@@ -153,8 +161,12 @@ void HttpLibcurl::addOp(HttpOpRequest * op)
}
-void HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status)
+HttpService::ELoopSpeed HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode status)
{
+ static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
+ static const HttpStatus cant_res_proxy(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_PROXY);
+ static const HttpStatus cant_res_host(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_HOST);
+
HttpOpRequest * op(NULL);
curl_easy_getinfo(handle, CURLINFO_PRIVATE, &op);
// *FIXME: check the pointer
@@ -190,10 +202,7 @@ void HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode
int http_status(200);
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_status);
- op->mStatus = LLCore::HttpStatus(http_status,
- (http_status >= 200 && http_status <= 299
- ? HE_SUCCESS
- : HE_REPLY_ERROR));
+ op->mStatus = LLCore::HttpStatus(http_status);
}
// Detach from multi and recycle handle
@@ -201,9 +210,42 @@ void HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode
curl_easy_cleanup(handle);
op->mCurlHandle = NULL;
- // Deliver to reply queue and release
+ // Retry or finalize
+ if (! op->mStatus)
+ {
+ // If this failed, we might want to retry. Have to inspect
+ // the status a little more deeply for those reasons worth retrying...
+ if (op->mPolicyRetries < op->mPolicyRetryLimit &&
+ ((op->mStatus.isHttpStatus() && op->mStatus.mType >= 499 && op->mStatus.mType <= 599) ||
+ cant_connect == op->mStatus ||
+ cant_res_proxy == op->mStatus ||
+ cant_res_host == op->mStatus))
+ {
+ // Okay, worth a retry. We include 499 in this test as
+ // it's the old 'who knows?' error from many grid services...
+ HttpPolicy & policy(mService->getPolicy());
+
+ policy.retryOp(op);
+ return HttpService::NORMAL; // Having pushed to retry, keep things running
+ }
+ }
+
+ // This op is done, finalize it delivering it to the reply queue...
+ if (! op->mStatus)
+ {
+ LL_WARNS("CoreHttp") << "URL op failed after " << op->mPolicyRetries
+ << " retries. Reason: " << op->mStatus.toString()
+ << LL_ENDL;
+ }
+ else if (op->mPolicyRetries)
+ {
+ LL_WARNS("CoreHttp") << "URL op succeeded after " << op->mPolicyRetries << " retries."
+ << LL_ENDL;
+ }
+
op->stageFromActive(mService);
op->release();
+ return HttpService::REQUEST_SLEEP;
}