summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2012-07-23 23:40:07 +0000
committerMonty Brandenberg <monty@lindenlab.com>2012-07-23 23:40:07 +0000
commit85e69b043b098dbe5a09f2eac6ff541123089f13 (patch)
treee0f5cc824c41563ea8b780cc4ba0cdb8c701c3f8
parent334ce2556f0d51c38a76d655084ae1d4671f6aec (diff)
Big comment and naming cleanup. Ready for prime-time.
Add to-do list to _httpinternal.h to guide anyone who wants to pitch in and help.
-rw-r--r--indra/llcorehttp/_httpinternal.h93
-rw-r--r--indra/llcorehttp/_httplibcurl.cpp13
-rw-r--r--indra/llcorehttp/_httplibcurl.h27
-rw-r--r--indra/llcorehttp/_httpopcancel.cpp7
-rw-r--r--indra/llcorehttp/_httpopcancel.h5
-rw-r--r--indra/llcorehttp/_httpoperation.cpp8
-rw-r--r--indra/llcorehttp/_httpoperation.h77
-rw-r--r--indra/llcorehttp/_httpoprequest.cpp47
-rw-r--r--indra/llcorehttp/_httpoprequest.h26
-rw-r--r--indra/llcorehttp/_httpopsetget.cpp8
-rw-r--r--indra/llcorehttp/_httpopsetget.h3
-rw-r--r--indra/llcorehttp/_httppolicy.cpp12
-rw-r--r--indra/llcorehttp/_httppolicy.h39
-rw-r--r--indra/llcorehttp/_httppolicyclass.cpp8
-rw-r--r--indra/llcorehttp/_httppolicyglobal.cpp8
-rw-r--r--indra/llcorehttp/_httpreadyqueue.h10
-rw-r--r--indra/llcorehttp/_httpservice.cpp24
-rw-r--r--indra/llcorehttp/_httpservice.h6
-rw-r--r--indra/llcorehttp/httpcommon.h18
-rw-r--r--indra/llcorehttp/httpoptions.cpp6
20 files changed, 313 insertions, 132 deletions
diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h
index 97ec5ee1d6..465e2036b3 100644
--- a/indra/llcorehttp/_httpinternal.h
+++ b/indra/llcorehttp/_httpinternal.h
@@ -32,12 +32,65 @@
// something wrong is probably happening.
+// --------------------------------------------------------------------
+// General library to-do list
+//
+// - Implement policy classes. Structure is mostly there just didn't
+// need it for the first consumer.
+// - Consider Removing 'priority' from the request interface. Its use
+// in an always active class can lead to starvation of low-priority
+// requests. Requires coodination of priority values across all
+// components that share a class. Changing priority across threads
+// is slightly expensive (relative to gain) and hasn't been completely
+// implemented. And the major user of priority, texture fetches,
+// may not really need it.
+// - Set/get for global policy and policy classes is clumsy. Rework
+// it heading in a direction that allows for more dynamic behavior.
+// - Move HttpOpRequest::prepareRequest() to HttpLibcurl for the
+// pedantic.
+// - Update downloader and other long-duration services are going to
+// need a progress notification. Initial idea is to introduce a
+// 'repeating request' which can piggyback on another request and
+// persist until canceled or carrier completes. Current queue
+// structures allow an HttpOperation object to be enqueued
+// repeatedly, so...
+// - Investigate making c-ares' re-implementation of a resolver library
+// more resilient or more intelligent on Mac. Part of the DNS failure
+// lies in here. The mechanism also looks a little less dynamic
+// than needed in an environments where networking is changing.
+// - Global optimizations: 'borrowing' connections from other classes,
+// HTTP pipelining.
+// - Dynamic/control system stuff: detect problems and self-adjust.
+// This won't help in the face of the router problems we've looked
+// at, however. Detect starvation due to UDP activity and provide
+// feedback to it.
+//
+// Integration to-do list
+// - LLTextureFetch still needs a major refactor. The use of
+// LLQueuedThread makes it hard to inspect workers and do the
+// resource waiting we're now doing. Rebuild along simpler lines
+// some of which are suggested in new commentary at the top of
+// the main source file.
+// - Expand areas of usage eventually leading to the removal of LLCurl.
+// Rough order of expansion:
+// . Mesh fetch
+// . Avatar names
+// . Group membership lists
+// . Caps access in general
+// . 'The rest'
+// - Adapt texture cache, image decode and other image consumers to
+// the BufferArray model to reduce data copying. Alternatively,
+// adapt this library to something else.
+//
+// --------------------------------------------------------------------
+
+
// If '1', internal ready queues will not order ready
// requests by priority, instead it's first-come-first-served.
// Reprioritization requests have the side-effect of then
// putting the modified request at the back of the ready queue.
-#define LLCORE_READY_QUEUE_IGNORES_PRIORITY 1
+#define LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY 1
namespace LLCore
@@ -45,48 +98,48 @@ namespace LLCore
// Maxium number of policy classes that can be defined.
// *TODO: Currently limited to the default class, extend.
-const int POLICY_CLASS_LIMIT = 1;
+const int HTTP_POLICY_CLASS_LIMIT = 1;
// Debug/informational tracing. Used both
// as a global option and in per-request traces.
-const int TRACE_OFF = 0;
-const int TRACE_LOW = 1;
-const int TRACE_CURL_HEADERS = 2;
-const int TRACE_CURL_BODIES = 3;
+const int HTTP_TRACE_OFF = 0;
+const int HTTP_TRACE_LOW = 1;
+const int HTTP_TRACE_CURL_HEADERS = 2;
+const int HTTP_TRACE_CURL_BODIES = 3;
-const int TRACE_MIN = TRACE_OFF;
-const int TRACE_MAX = TRACE_CURL_BODIES;
+const int HTTP_TRACE_MIN = HTTP_TRACE_OFF;
+const int HTTP_TRACE_MAX = HTTP_TRACE_CURL_BODIES;
// Request retry limits
-const int DEFAULT_RETRY_COUNT = 5;
-const int LIMIT_RETRY_MIN = 0;
-const int LIMIT_RETRY_MAX = 100;
+const int HTTP_RETRY_COUNT_DEFAULT = 5;
+const int HTTP_RETRY_COUNT_MIN = 0;
+const int HTTP_RETRY_COUNT_MAX = 100;
-const int DEFAULT_HTTP_REDIRECTS = 10;
+const int HTTP_REDIRECTS_DEFAULT = 10;
// Timeout value used for both connect and protocol exchange.
// Retries and time-on-queue are not included and aren't
// accounted for.
-const long DEFAULT_TIMEOUT = 30L;
-const long LIMIT_TIMEOUT_MIN = 0L;
-const long LIMIT_TIMEOUT_MAX = 3600L;
+const long HTTP_REQUEST_TIMEOUT_DEFAULT = 30L;
+const long HTTP_REQUEST_TIMEOUT_MIN = 0L;
+const long HTTP_REQUEST_TIMEOUT_MAX = 3600L;
// Limits on connection counts
-const int DEFAULT_CONNECTIONS = 8;
-const int LIMIT_CONNECTIONS_MIN = 1;
-const int LIMIT_CONNECTIONS_MAX = 256;
+const int HTTP_CONNECTION_LIMIT_DEFAULT = 8;
+const int HTTP_CONNECTION_LIMIT_MIN = 1;
+const int HTTP_CONNECTION_LIMIT_MAX = 256;
// Tuning parameters
// Time worker thread sleeps after a pass through the
// request, ready and active queues.
-const int LOOP_SLEEP_NORMAL_MS = 2;
+const int HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS = 2;
// Block allocation size (a tuning parameter) is found
// in bufferarray.h.
// Compatibility controls
-const bool ENABLE_LINKSYS_WRT54G_V5_DNS_FIX = true;
+const bool HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX = true;
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index e031efbc91..4e2e3f0e0e 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -85,7 +85,7 @@ void HttpLibcurl::shutdown()
void HttpLibcurl::start(int policy_count)
{
- llassert_always(policy_count <= POLICY_CLASS_LIMIT);
+ llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT);
llassert_always(! mMultiHandles); // One-time call only
mPolicyCount = policy_count;
@@ -156,6 +156,7 @@ HttpService::ELoopSpeed HttpLibcurl::processTransport()
}
+// Caller has provided us with a ref count on op.
void HttpLibcurl::addOp(HttpOpRequest * op)
{
llassert_always(op->mReqPolicy < mPolicyCount);
@@ -165,7 +166,7 @@ void HttpLibcurl::addOp(HttpOpRequest * op)
if (! op->prepareRequest(mService))
{
// Couldn't issue request, fail with notification
- // *FIXME: Need failure path
+ // *TODO: Need failure path
return;
}
@@ -173,7 +174,7 @@ void HttpLibcurl::addOp(HttpOpRequest * op)
curl_multi_add_handle(mMultiHandles[op->mReqPolicy], op->mCurlHandle);
op->mCurlActive = true;
- if (op->mTracing > TRACE_OFF)
+ if (op->mTracing > HTTP_TRACE_OFF)
{
HttpPolicy & policy(mService->getPolicy());
@@ -215,7 +216,7 @@ bool HttpLibcurl::cancel(HttpHandle handle)
// *NOTE: cancelRequest logic parallels completeRequest logic.
// Keep them synchronized as necessary. Caller is expected to
-// remove to op from the active list and release the op *after*
+// remove the op from the active list and release the op *after*
// calling this method. It must be called first to deliver the
// op to the reply queue with refcount intact.
void HttpLibcurl::cancelRequest(HttpOpRequest * op)
@@ -229,7 +230,7 @@ void HttpLibcurl::cancelRequest(HttpOpRequest * op)
op->mCurlHandle = NULL;
// Tracing
- if (op->mTracing > TRACE_OFF)
+ if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS("CoreHttp") << "TRACE, RequestCanceled, Handle: "
<< static_cast<HttpHandle>(op)
@@ -305,7 +306,7 @@ bool HttpLibcurl::completeRequest(CURLM * multi_handle, CURL * handle, CURLcode
op->mCurlHandle = NULL;
// Tracing
- if (op->mTracing > TRACE_OFF)
+ if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS("CoreHttp") << "TRACE, RequestComplete, Handle: "
<< static_cast<HttpHandle>(op)
diff --git a/indra/llcorehttp/_httplibcurl.h b/indra/llcorehttp/_httplibcurl.h
index 53972b1ffa..611f029ef5 100644
--- a/indra/llcorehttp/_httplibcurl.h
+++ b/indra/llcorehttp/_httplibcurl.h
@@ -68,24 +68,41 @@ public:
/// Give cycles to libcurl to run active requests. Completed
/// operations (successful or failed) will be retried or handed
/// over to the reply queue as final responses.
+ ///
+ /// @return Indication of how long this method is
+ /// willing to wait for next service call.
HttpService::ELoopSpeed processTransport();
/// Add request to the active list. Caller is expected to have
- /// provided us with a reference count to hold the request. (No
- /// additional references will be added.)
+ /// provided us with a reference count on the op to hold the
+ /// request. (No additional references will be added.)
void addOp(HttpOpRequest * op);
/// One-time call to set the number of policy classes to be
/// serviced and to create the resources for each. Value
/// must agree with HttpPolicy::setPolicies() call.
void start(int policy_count);
-
+
+ /// Synchronously stop libcurl operations. All active requests
+ /// are canceled and removed from libcurl's handling. Easy
+ /// handles are detached from their multi handles and released.
+ /// Multi handles are also released. Canceled requests are
+ /// completed with canceled status and made available on their
+ /// respective reply queues.
+ ///
+ /// Can be restarted with a start() call.
void shutdown();
-
+
+ /// Return global and per-class counts of active requests.
int getActiveCount() const;
int getActiveCountInClass(int policy_class) const;
- // Shadows HttpService's method
+ /// Attempt to cancel a request identified by handle.
+ ///
+ /// Interface shadows HttpService's method.
+ ///
+ /// @return True if handle was found and operation canceled.
+ ///
bool cancel(HttpHandle handle);
protected:
diff --git a/indra/llcorehttp/_httpopcancel.cpp b/indra/llcorehttp/_httpopcancel.cpp
index 8e1105dc81..c1912eb3db 100644
--- a/indra/llcorehttp/_httpopcancel.cpp
+++ b/indra/llcorehttp/_httpopcancel.cpp
@@ -26,18 +26,11 @@
#include "_httpopcancel.h"
-#include <cstdio>
-#include <algorithm>
-
#include "httpcommon.h"
#include "httphandler.h"
#include "httpresponse.h"
-#include "_httprequestqueue.h"
-#include "_httpreplyqueue.h"
#include "_httpservice.h"
-#include "_httppolicy.h"
-#include "_httplibcurl.h"
namespace LLCore
diff --git a/indra/llcorehttp/_httpopcancel.h b/indra/llcorehttp/_httpopcancel.h
index 659d28955f..336dfdc573 100644
--- a/indra/llcorehttp/_httpopcancel.h
+++ b/indra/llcorehttp/_httpopcancel.h
@@ -46,11 +46,14 @@ namespace LLCore
/// be canceled, if possible. This includes active requests
/// that may be in the middle of an HTTP transaction. Any
/// completed request will not be canceled and will return
-/// its final status unchanged.
+/// its final status unchanged and *this* request will complete
+/// with an HE_HANDLE_NOT_FOUND error status.
class HttpOpCancel : public HttpOperation
{
public:
+ /// @param handle Handle of previously-issued request to
+ /// be canceled.
HttpOpCancel(HttpHandle handle);
protected:
diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp
index 910dbf1f2f..5cf5bc5930 100644
--- a/indra/llcorehttp/_httpoperation.cpp
+++ b/indra/llcorehttp/_httpoperation.cpp
@@ -94,7 +94,7 @@ void HttpOperation::stageFromRequest(HttpService *)
// Default implementation should never be called. This
// indicates an operation making a transition that isn't
// defined.
- LL_ERRS("HttpCore") << "Default stateFromRequest method may not be called."
+ LL_ERRS("HttpCore") << "Default stageFromRequest method may not be called."
<< LL_ENDL;
}
@@ -104,7 +104,7 @@ void HttpOperation::stageFromReady(HttpService *)
// Default implementation should never be called. This
// indicates an operation making a transition that isn't
// defined.
- LL_ERRS("HttpCore") << "Default stateFromReady method may not be called."
+ LL_ERRS("HttpCore") << "Default stageFromReady method may not be called."
<< LL_ENDL;
}
@@ -114,7 +114,7 @@ void HttpOperation::stageFromActive(HttpService *)
// Default implementation should never be called. This
// indicates an operation making a transition that isn't
// defined.
- LL_ERRS("HttpCore") << "Default stateFromActive method may not be called."
+ LL_ERRS("HttpCore") << "Default stageFromActive method may not be called."
<< LL_ENDL;
}
@@ -143,7 +143,7 @@ HttpStatus HttpOperation::cancel()
void HttpOperation::addAsReply()
{
- if (mTracing > TRACE_OFF)
+ if (mTracing > HTTP_TRACE_OFF)
{
LL_INFOS("CoreHttp") << "TRACE, ToReplyQueue, Handle: "
<< static_cast<HttpHandle>(this)
diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h
index 717a9b0d72..914627fad0 100644
--- a/indra/llcorehttp/_httpoperation.h
+++ b/indra/llcorehttp/_httpoperation.h
@@ -72,9 +72,11 @@ class HttpService;
class HttpOperation : public LLCoreInt::RefCounted
{
public:
+ /// Threading: called by a consumer/application thread.
HttpOperation();
protected:
+ /// Threading: called by any thread.
virtual ~HttpOperation(); // Use release()
private:
@@ -82,28 +84,87 @@ private:
void operator=(const HttpOperation &); // Not defined
public:
+ /// Register a reply queue and a handler for completion notifications.
+ ///
+ /// Invokers of operations that want to receive notification that an
+ /// operation has been completed do so by binding a reply queue and
+ /// a handler object to the request.
+ ///
+ /// @param reply_queue Pointer to the reply queue where completion
+ /// notifications are to be queued (typically
+ /// by addAsReply()). This will typically be
+ /// the reply queue referenced by the request
+ /// object. This method will increment the
+ /// refcount on the queue holding the queue
+ /// until delivery is complete. Using a reply_queue
+ /// even if the handler is NULL has some benefits
+ /// for memory deallocation by keeping it in the
+ /// originating thread.
+ ///
+ /// @param handler Possibly NULL pointer to a non-refcounted
+ //// handler object to be invoked (onCompleted)
+ /// when the operation is finished. Note that
+ /// the handler object is never dereferenced
+ /// by the worker thread. This is passible data
+ /// until notification is performed.
+ ///
+ /// Threading: called by application thread.
+ ///
void setReplyPath(HttpReplyQueue * reply_queue,
HttpHandler * handler);
- HttpHandler * getUserHandler() const
- {
- return mUserHandler;
- }
-
+ /// The three possible staging steps in an operation's lifecycle.
+ /// Asynchronous requests like HTTP operations move from the
+ /// request queue to the ready queue via stageFromRequest. Then
+ /// from the ready queue to the active queue by stageFromReady. And
+ /// when complete, to the reply queue via stageFromActive and the
+ /// addAsReply utility.
+ ///
+ /// Immediate mode operations (everything else) move from the
+ /// request queue to the reply queue directly via stageFromRequest
+ /// and addAsReply with no existence on the ready or active queues.
+ ///
+ /// These methods will take out a reference count on the request,
+ /// caller only needs to dispose of its reference when done with
+ /// the request.
+ ///
+ /// Threading: called by worker thread.
+ ///
virtual void stageFromRequest(HttpService *);
virtual void stageFromReady(HttpService *);
virtual void stageFromActive(HttpService *);
+ /// Delivers a notification to a handler object on completion.
+ ///
+ /// Once a request is complete and it has been removed from its
+ /// reply queue, a handler notification may be delivered by a
+ /// call to HttpRequest::update(). This method does the necessary
+ /// dispatching.
+ ///
+ /// Threading: called by application thread.
+ ///
virtual void visitNotifier(HttpRequest *);
-
+
+ /// Cancels the operation whether queued or active.
+ /// Final status of the request becomes canceled (an error) and
+ /// that will be delivered to caller via notification scheme.
+ ///
+ /// Threading: called by worker thread.
+ ///
virtual HttpStatus cancel();
protected:
+ /// Delivers request to reply queue on completion. After this
+ /// call, worker thread no longer accesses the object and it
+ /// is owned by the reply queue.
+ ///
+ /// Threading: called by worker thread.
+ ///
void addAsReply();
protected:
HttpReplyQueue * mReplyQueue; // Have refcount
- HttpHandler * mUserHandler;
+ HttpHandler * mUserHandler; // Naked pointer
public:
// Request Data
@@ -172,7 +233,7 @@ public:
/// HttpOpSpin is a test-only request that puts the worker
/// thread into a cpu spin. Used for unit tests and cleanup
-/// evaluation. You do not want to use this.
+/// evaluation. You do not want to use this in production.
class HttpOpSpin : public HttpOperation
{
public:
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index a18a164f0d..7db19b1841 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -111,10 +111,10 @@ HttpOpRequest::HttpOpRequest()
mReplyHeaders(NULL),
mPolicyRetries(0),
mPolicyRetryAt(HttpTime(0)),
- mPolicyRetryLimit(DEFAULT_RETRY_COUNT)
+ mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT)
{
// *NOTE: As members are added, retry initialization/cleanup
- // may need to be extended in @prepareRequest().
+ // may need to be extended in @see prepareRequest().
}
@@ -153,9 +153,6 @@ HttpOpRequest::~HttpOpRequest()
mCurlHeaders = NULL;
}
- mReplyOffset = 0;
- mReplyLength = 0;
- mReplyFullLength = 0;
if (mReplyBody)
{
mReplyBody->release();
@@ -215,8 +212,6 @@ void HttpOpRequest::stageFromActive(HttpService * service)
void HttpOpRequest::visitNotifier(HttpRequest * request)
{
- static const HttpStatus partial_content(HTTP_PARTIAL_CONTENT, HE_SUCCESS);
-
if (mUserHandler)
{
HttpResponse * response = new HttpResponse();
@@ -339,8 +334,8 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
mProcFlags |= PF_SAVE_HEADERS;
}
mPolicyRetryLimit = options->getRetries();
- mPolicyRetryLimit = llclamp(mPolicyRetryLimit, LIMIT_RETRY_MIN, LIMIT_RETRY_MAX);
- mTracing = (std::max)(mTracing, llclamp(options->getTrace(), TRACE_MIN, TRACE_MAX));
+ mPolicyRetryLimit = llclamp(mPolicyRetryLimit, HTTP_RETRY_COUNT_MIN, HTTP_RETRY_COUNT_MAX);
+ mTracing = (std::max)(mTracing, llclamp(options->getTrace(), HTTP_TRACE_MIN, HTTP_TRACE_MAX));
}
}
@@ -394,7 +389,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
- if (ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)
+ if (HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)
{
// The Linksys WRT54G V5 router has an issue with frequent
// DNS lookups from LAN machines. If they happen too often,
@@ -402,7 +397,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// about 700 or so requests and starts issuing TCP RSTs to
// new connections. Reuse the DNS lookups for even a few
// seconds and no RSTs.
- curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 10);
+ curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
}
else
{
@@ -414,7 +409,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
}
curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, DEFAULT_HTTP_REDIRECTS);
+ curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
@@ -434,7 +429,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
}
else if (policy.get(HttpRequest::GP_HTTP_PROXY, &opt_value))
{
- // *TODO: This is fine for now but get fuller socks/
+ // *TODO: This is fine for now but get fuller socks5/
// authentication thing going later....
curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, opt_value->c_str());
curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
@@ -497,7 +492,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
}
// Tracing
- if (mTracing >= TRACE_CURL_HEADERS)
+ if (mTracing >= HTTP_TRACE_CURL_HEADERS)
{
curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
@@ -528,11 +523,11 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
mCurlHeaders = curl_slist_append(mCurlHeaders, "Pragma:");
// Request options
- long timeout(DEFAULT_TIMEOUT);
+ long timeout(HTTP_REQUEST_TIMEOUT_DEFAULT);
if (mReqOptions)
{
timeout = mReqOptions->getTimeout();
- timeout = llclamp(timeout, LIMIT_TIMEOUT_MIN, LIMIT_TIMEOUT_MAX);
+ timeout = llclamp(timeout, HTTP_REQUEST_TIMEOUT_MIN, HTTP_REQUEST_TIMEOUT_MAX);
}
curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, timeout);
curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
@@ -605,12 +600,6 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
static const char con_ran_line[] = "content-range:";
static const size_t con_ran_line_len = sizeof(con_ran_line) - 1;
- static const char con_type_line[] = "content-type:";
- static const size_t con_type_line_len = sizeof(con_type_line) - 1;
-
- static const char con_enc_line[] = "content-encoding:";
- static const size_t con_enc_line_len = sizeof(con_enc_line) - 1;
-
HttpOpRequest * op(static_cast<HttpOpRequest *>(userdata));
const size_t hdr_size(size * nmemb);
@@ -705,7 +694,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
switch (info)
{
case CURLINFO_TEXT:
- if (op->mTracing >= TRACE_CURL_HEADERS)
+ if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "TEXT";
escape_libcurl_debug_data(buffer, len, true, safe_line);
@@ -714,7 +703,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
break;
case CURLINFO_HEADER_IN:
- if (op->mTracing >= TRACE_CURL_HEADERS)
+ if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "HEADERIN";
escape_libcurl_debug_data(buffer, len, true, safe_line);
@@ -723,7 +712,7 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
break;
case CURLINFO_HEADER_OUT:
- if (op->mTracing >= TRACE_CURL_HEADERS)
+ if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "HEADEROUT";
escape_libcurl_debug_data(buffer, 2 * len, true, safe_line); // Goes out as one line
@@ -732,11 +721,11 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
break;
case CURLINFO_DATA_IN:
- if (op->mTracing >= TRACE_CURL_HEADERS)
+ if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "DATAIN";
logit = true;
- if (op->mTracing >= TRACE_CURL_BODIES)
+ if (op->mTracing >= HTTP_TRACE_CURL_BODIES)
{
escape_libcurl_debug_data(buffer, len, false, safe_line);
}
@@ -750,11 +739,11 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
break;
case CURLINFO_DATA_OUT:
- if (op->mTracing >= TRACE_CURL_HEADERS)
+ if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
{
tag = "DATAOUT";
logit = true;
- if (op->mTracing >= TRACE_CURL_BODIES)
+ if (op->mTracing >= HTTP_TRACE_CURL_BODIES)
{
escape_libcurl_debug_data(buffer, len, false, safe_line);
}
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index 36dc5dc876..7b65d17783 100644
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -88,7 +88,14 @@ public:
virtual void visitNotifier(HttpRequest * request);
public:
- // Setup Methods
+ /// Setup Methods
+ ///
+ /// Basically an RPC setup for each type of HTTP method
+ /// invocation with one per method type. These are
+ /// generally invoked right after construction.
+ ///
+ /// Threading: called by application thread
+ ///
HttpStatus setupGet(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
@@ -116,19 +123,32 @@ public:
BufferArray * body,
HttpOptions * options,
HttpHeaders * headers);
-
+
+ // Internal method used to setup the libcurl options for a request.
+ // Does all the libcurl handle setup in one place.
+ //
+ // Threading: called by worker thread
+ //
HttpStatus prepareRequest(HttpService * service);
virtual HttpStatus cancel();
protected:
+ // Common setup for all the request methods.
+ //
+ // Threading: called by application thread
+ //
void setupCommon(HttpRequest::policy_t policy_id,
HttpRequest::priority_t priority,
const std::string & url,
BufferArray * body,
HttpOptions * options,
HttpHeaders * headers);
-
+
+ // libcurl operational callbacks
+ //
+ // Threading: called by worker thread
+ //
static size_t writeCallback(void * data, size_t size, size_t nmemb, void * userdata);
static size_t readCallback(void * data, size_t size, size_t nmemb, void * userdata);
static size_t headerCallback(void * data, size_t size, size_t nmemb, void * userdata);
diff --git a/indra/llcorehttp/_httpopsetget.cpp b/indra/llcorehttp/_httpopsetget.cpp
index c1357f9ae5..8198528a9b 100644
--- a/indra/llcorehttp/_httpopsetget.cpp
+++ b/indra/llcorehttp/_httpopsetget.cpp
@@ -26,18 +26,10 @@
#include "_httpopsetget.h"
-#include <cstdio>
-#include <algorithm>
-
#include "httpcommon.h"
-#include "httphandler.h"
-#include "httpresponse.h"
-#include "_httprequestqueue.h"
-#include "_httpreplyqueue.h"
#include "_httpservice.h"
#include "_httppolicy.h"
-#include "_httplibcurl.h"
namespace LLCore
diff --git a/indra/llcorehttp/_httpopsetget.h b/indra/llcorehttp/_httpopsetget.h
index efb24855c5..6966b9d94e 100644
--- a/indra/llcorehttp/_httpopsetget.h
+++ b/indra/llcorehttp/_httpopsetget.h
@@ -44,6 +44,8 @@ namespace LLCore
/// HttpOpSetGet requests dynamic changes to policy and
/// configuration settings.
+///
+/// *NOTE: Expect this to change. Don't really like it yet.
class HttpOpSetGet : public HttpOperation
{
@@ -58,6 +60,7 @@ private:
void operator=(const HttpOpSetGet &); // Not defined
public:
+ /// Threading: called by application thread
void setupGet(HttpRequest::EGlobalPolicy setting);
void setupSet(HttpRequest::EGlobalPolicy setting, const std::string & value);
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index 1e64924198..c7a69ad133 100644
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -40,12 +40,17 @@ namespace LLCore
{
+// Per-policy-class data for a running system.
+// Collection of queues, parameters, history, metrics, etc.
+// for a single policy class.
+//
+// Threading: accessed only by worker thread
struct HttpPolicy::State
{
public:
State()
- : mConnMax(DEFAULT_CONNECTIONS),
- mConnAt(DEFAULT_CONNECTIONS),
+ : mConnMax(HTTP_CONNECTION_LIMIT_DEFAULT),
+ mConnAt(HTTP_CONNECTION_LIMIT_DEFAULT),
mConnMin(1),
mNextSample(0),
mErrorCount(0),
@@ -298,6 +303,7 @@ bool HttpPolicy::cancel(HttpHandle handle)
return false;
}
+
bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
{
static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
@@ -345,7 +351,7 @@ bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
}
-int HttpPolicy::getReadyCount(HttpRequest::policy_t policy_class)
+int HttpPolicy::getReadyCount(HttpRequest::policy_t policy_class) const
{
if (policy_class < mActiveClasses)
{
diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h
index a02bf084c1..03d92c0b8e 100644
--- a/indra/llcorehttp/_httppolicy.h
+++ b/indra/llcorehttp/_httppolicy.h
@@ -63,22 +63,37 @@ public:
/// Cancel all ready and retry requests sending them to
/// their notification queues. Release state resources
/// making further request handling impossible.
+ ///
+ /// Threading: called by worker thread
void shutdown();
/// Deliver policy definitions and enable handling of
/// requests. One-time call invoked before starting
/// the worker thread.
+ ///
+ /// Threading: called by application thread
void start(const HttpPolicyGlobal & global,
const std::vector<HttpPolicyClass> & classes);
/// Give the policy layer some cycles to scan the ready
/// queue promoting higher-priority requests to active
/// as permited.
+ ///
+ /// @return Indication of how soon this method
+ /// should be called again.
+ ///
+ /// Threading: called by worker thread
HttpService::ELoopSpeed processReadyQueue();
/// Add request to a ready queue. Caller is expected to have
/// provided us with a reference count to hold the request. (No
/// additional references will be added.)
+ ///
+ /// OpRequest is owned by the request queue after this call
+ /// and should not be modified by anyone until retrieved
+ /// from queue.
+ ///
+ /// Threading: called by any thread
void addOp(HttpOpRequest *);
/// Similar to addOp, used when a caller wants to retry a
@@ -87,12 +102,20 @@ public:
/// handling is the same and retried operations are considered
/// before new ones but that doesn't guarantee completion
/// order.
+ ///
+ /// Threading: called by worker thread
void retryOp(HttpOpRequest *);
- // Shadows HttpService's method
+ /// Attempt to change the priority of an earlier request.
+ /// Request that Shadows HttpService's method
+ ///
+ /// Threading: called by worker thread
bool changePriority(HttpHandle handle, HttpRequest::priority_t priority);
- // Shadows HttpService's method as well
+ /// Attempt to cancel a previous request.
+ /// Shadows HttpService's method as well
+ ///
+ /// Threading: called by worker thread
bool cancel(HttpHandle handle);
/// When transport is finished with an op and takes it off the
@@ -103,17 +126,25 @@ public:
/// @return Returns true of the request is still active
/// or ready after staging, false if has been
/// sent on to the reply queue.
+ ///
+ /// Threading: called by worker thread
bool stageAfterCompletion(HttpOpRequest * op);
// Get pointer to global policy options. Caller is expected
// to do context checks like no setting once running.
+ ///
+ /// Threading: called by any thread *but* the object may
+ /// only be modified by the worker thread once running.
+ ///
HttpPolicyGlobal & getGlobalOptions()
{
return mGlobalOptions;
}
- // Get ready counts for a particular class
- int getReadyCount(HttpRequest::policy_t policy_class);
+ /// Get ready counts for a particular policy class
+ ///
+ /// Threading: called by worker thread
+ int getReadyCount(HttpRequest::policy_t policy_class) const;
protected:
struct State;
diff --git a/indra/llcorehttp/_httppolicyclass.cpp b/indra/llcorehttp/_httppolicyclass.cpp
index 8007468d3c..a23b81322c 100644
--- a/indra/llcorehttp/_httppolicyclass.cpp
+++ b/indra/llcorehttp/_httppolicyclass.cpp
@@ -35,8 +35,8 @@ namespace LLCore
HttpPolicyClass::HttpPolicyClass()
: mSetMask(0UL),
- mConnectionLimit(DEFAULT_CONNECTIONS),
- mPerHostConnectionLimit(DEFAULT_CONNECTIONS),
+ mConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
+ mPerHostConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
mPipelining(0)
{}
@@ -71,11 +71,11 @@ HttpStatus HttpPolicyClass::set(HttpRequest::EClassPolicy opt, long value)
switch (opt)
{
case HttpRequest::CP_CONNECTION_LIMIT:
- mConnectionLimit = llclamp(value, long(LIMIT_CONNECTIONS_MIN), long(LIMIT_CONNECTIONS_MAX));
+ mConnectionLimit = llclamp(value, long(HTTP_CONNECTION_LIMIT_MIN), long(HTTP_CONNECTION_LIMIT_MAX));
break;
case HttpRequest::CP_PER_HOST_CONNECTION_LIMIT:
- mPerHostConnectionLimit = llclamp(value, long(LIMIT_CONNECTIONS_MIN), mConnectionLimit);
+ mPerHostConnectionLimit = llclamp(value, long(HTTP_CONNECTION_LIMIT_MIN), mConnectionLimit);
break;
case HttpRequest::CP_ENABLE_PIPELINING:
diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp
index ca04839eaf..72f409d3b1 100644
--- a/indra/llcorehttp/_httppolicyglobal.cpp
+++ b/indra/llcorehttp/_httppolicyglobal.cpp
@@ -35,8 +35,8 @@ namespace LLCore
HttpPolicyGlobal::HttpPolicyGlobal()
: mSetMask(0UL),
- mConnectionLimit(DEFAULT_CONNECTIONS),
- mTrace(TRACE_OFF),
+ mConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
+ mTrace(HTTP_TRACE_OFF),
mUseLLProxy(0)
{}
@@ -66,11 +66,11 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, long value)
switch (opt)
{
case HttpRequest::GP_CONNECTION_LIMIT:
- mConnectionLimit = llclamp(value, long(LIMIT_CONNECTIONS_MIN), long(LIMIT_CONNECTIONS_MAX));
+ mConnectionLimit = llclamp(value, long(HTTP_CONNECTION_LIMIT_MIN), long(HTTP_CONNECTION_LIMIT_MAX));
break;
case HttpRequest::GP_TRACE:
- mTrace = llclamp(value, long(TRACE_MIN), long(TRACE_MAX));
+ mTrace = llclamp(value, long(HTTP_TRACE_MIN), long(HTTP_TRACE_MAX));
break;
case HttpRequest::GP_LLPROXY:
diff --git a/indra/llcorehttp/_httpreadyqueue.h b/indra/llcorehttp/_httpreadyqueue.h
index 9cf4b059a1..5f19a9c5f9 100644
--- a/indra/llcorehttp/_httpreadyqueue.h
+++ b/indra/llcorehttp/_httpreadyqueue.h
@@ -45,7 +45,7 @@ namespace LLCore
/// important of those rules is that any iterator becomes invalid
/// on element erasure. So pay attention.
///
-/// If LLCORE_READY_QUEUE_IGNORES_PRIORITY tests true, the class
+/// If LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY tests true, the class
/// implements a std::priority_queue interface but on std::deque
/// behavior to eliminate sensitivity to priority. In the future,
/// this will likely become the only behavior or it may become
@@ -54,7 +54,7 @@ namespace LLCore
/// Threading: not thread-safe. Expected to be used entirely by
/// a single thread, typically a worker thread of some sort.
-#if LLCORE_READY_QUEUE_IGNORES_PRIORITY
+#if LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY
typedef std::deque<HttpOpRequest *> HttpReadyQueueBase;
@@ -64,7 +64,7 @@ typedef std::priority_queue<HttpOpRequest *,
std::deque<HttpOpRequest *>,
LLCore::HttpOpRequestCompare> HttpReadyQueueBase;
-#endif // LLCORE_READY_QUEUE_IGNORES_PRIORITY
+#endif // LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY
class HttpReadyQueue : public HttpReadyQueueBase
{
@@ -82,7 +82,7 @@ protected:
public:
-#if LLCORE_READY_QUEUE_IGNORES_PRIORITY
+#if LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY
// Types and methods needed to make a std::deque look
// more like a std::priority_queue, at least for our
// purposes.
@@ -103,7 +103,7 @@ public:
push_back(v);
}
-#endif // LLCORE_READY_QUEUE_IGNORES_PRIORITY
+#endif // LLCORE_HTTP_READY_QUEUE_IGNORES_PRIORITY
const container_type & get_container() const
{
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index f7d9813db0..0825888d0f 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -55,8 +55,8 @@ HttpService::HttpService()
{
// Create the default policy class
HttpPolicyClass pol_class;
- pol_class.set(HttpRequest::CP_CONNECTION_LIMIT, DEFAULT_CONNECTIONS);
- pol_class.set(HttpRequest::CP_PER_HOST_CONNECTION_LIMIT, DEFAULT_CONNECTIONS);
+ pol_class.set(HttpRequest::CP_CONNECTION_LIMIT, HTTP_CONNECTION_LIMIT_DEFAULT);
+ pol_class.set(HttpRequest::CP_PER_HOST_CONNECTION_LIMIT, HTTP_CONNECTION_LIMIT_DEFAULT);
pol_class.set(HttpRequest::CP_ENABLE_PIPELINING, 0L);
mPolicyClasses.push_back(pol_class);
}
@@ -150,7 +150,7 @@ void HttpService::term()
HttpRequest::policy_t HttpService::createPolicyClass()
{
const HttpRequest::policy_t policy_class(mPolicyClasses.size());
- if (policy_class >= POLICY_CLASS_LIMIT)
+ if (policy_class >= HTTP_POLICY_CLASS_LIMIT)
{
return 0;
}
@@ -219,12 +219,12 @@ bool HttpService::changePriority(HttpHandle handle, HttpRequest::priority_t prio
}
- /// Try to find the given request handle on any of the request
- /// queues and cancel the operation.
- ///
- /// @return True if the request was canceled.
- ///
- /// Threading: callable by worker thread.
+/// Try to find the given request handle on any of the request
+/// queues and cancel the operation.
+///
+/// @return True if the request was canceled.
+///
+/// Threading: callable by worker thread.
bool HttpService::cancel(HttpHandle handle)
{
bool canceled(false);
@@ -297,7 +297,7 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
// Determine whether to spin, sleep briefly or sleep for next request
if (REQUEST_SLEEP != loop)
{
- ms_sleep(LOOP_SLEEP_NORMAL_MS);
+ ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS);
}
}
@@ -321,11 +321,11 @@ HttpService::ELoopSpeed HttpService::processRequestQueue(ELoopSpeed loop)
if (! mExitRequested)
{
// Setup for subsequent tracing
- long tracing(TRACE_OFF);
+ long tracing(HTTP_TRACE_OFF);
mPolicy->getGlobalOptions().get(HttpRequest::GP_TRACE, &tracing);
op->mTracing = (std::max)(op->mTracing, int(tracing));
- if (op->mTracing > TRACE_OFF)
+ if (op->mTracing > HTTP_TRACE_OFF)
{
LL_INFOS("CoreHttp") << "TRACE, FromRequestQueue, Handle: "
<< static_cast<HttpHandle>(op)
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index d24c497ca9..ffe0349d4d 100644
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -55,7 +55,7 @@ class HttpPolicy;
class HttpLibcurl;
-/// The HttpService class does the work behind the request queue. It
+/// The HttpService class does the work behind the request queue. It
/// oversees the HTTP workflow carrying out a number of tasks:
/// - Pulling requests from the global request queue
/// - Executing 'immediate' requests directly
@@ -76,7 +76,7 @@ class HttpLibcurl;
/// HttpPolicy and HttpLibcurl (transport). These always exist in a
/// 1:1:1 relationship with HttpService managing instances of the other
/// two. So, these classes do not use reference counting to refer
-/// to one-another, their lifecycles are always managed together.
+/// to one another, their lifecycles are always managed together.
class HttpService
{
@@ -206,7 +206,7 @@ protected:
// === shared data ===
static volatile EState sState;
- HttpRequestQueue * mRequestQueue;
+ HttpRequestQueue * mRequestQueue; // Refcounted
LLAtomicU32 mExitRequested;
LLCoreInt::HttpThread * mThread;
diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h
index dd5798edf9..c0d4ec5aad 100644
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -60,8 +60,10 @@
/// Using the library is fairly easy. Global setup needs a few
/// steps:
///
-/// - libcurl initialization with thread-safely callbacks for c-ares
-/// DNS lookups.
+/// - libcurl initialization including thread-safely callbacks for SSL:
+/// . curl_global_init(...)
+/// . CRYPTO_set_locking_callback(...)
+/// . CRYPTO_set_id_callback(...)
/// - HttpRequest::createService() called to instantiate singletons
/// and support objects.
///
@@ -90,8 +92,18 @@
/// - Do completion processing in your onCompletion() method.
///
/// Code fragments:
-/// <TBD>
+/// Rather than a poorly-maintained example in comments, look in the
+/// example subdirectory which is a minimal yet functional tool to do
+/// GET request performance testing. With four calls:
///
+/// init_curl();
+/// LLCore::HttpRequest::createService();
+/// LLCore::HttpRequest::startThread();
+/// LLCore::HttpRequest * hr = new LLCore::HttpRequest();
+///
+/// the program is basically ready to issue requests.
+///
+
#include "linden_common.h" // Modifies curl/curl.h interfaces
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index 68f7277ed3..1699d19f8d 100644
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -36,9 +36,9 @@ namespace LLCore
HttpOptions::HttpOptions()
: RefCounted(true),
mWantHeaders(false),
- mTracing(TRACE_OFF),
- mTimeout(DEFAULT_TIMEOUT),
- mRetries(DEFAULT_RETRY_COUNT)
+ mTracing(HTTP_TRACE_OFF),
+ mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
+ mRetries(HTTP_RETRY_COUNT_DEFAULT)
{}