summaryrefslogtreecommitdiff
path: root/indra/llcorehttp
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2014-06-23 18:45:12 -0400
committerMonty Brandenberg <monty@lindenlab.com>2014-06-23 18:45:12 -0400
commitc49ac5ded1168baf3f52586b961f7ed35a8bb999 (patch)
treece5531ee2d2044efbb6a3b382764f16c8b276d9b /indra/llcorehttp
parent053f436413c01e237accabace4dc5ff1eccca837 (diff)
parent5cca78e718f15522cc3db9aec76aa910dd696aa8 (diff)
Automated merge with ssh://bitbucket.org/monty_linden/viewer-library-refresh
Diffstat (limited to 'indra/llcorehttp')
-rwxr-xr-xindra/llcorehttp/_httpinternal.h5
-rwxr-xr-xindra/llcorehttp/_httplibcurl.cpp69
-rwxr-xr-xindra/llcorehttp/_httppolicy.cpp11
-rwxr-xr-xindra/llcorehttp/_httppolicyclass.cpp8
-rwxr-xr-xindra/llcorehttp/httprequest.h35
5 files changed, 114 insertions, 14 deletions
diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h
index f80d7f60f5..a2a60ca056 100755
--- a/indra/llcorehttp/_httpinternal.h
+++ b/indra/llcorehttp/_httpinternal.h
@@ -145,8 +145,11 @@ const int HTTP_CONNECTION_LIMIT_DEFAULT = 8;
const int HTTP_CONNECTION_LIMIT_MIN = 1;
const int HTTP_CONNECTION_LIMIT_MAX = 256;
-// Miscellaneous defaults
+// Pipelining limits
const long HTTP_PIPELINING_DEFAULT = 0L;
+const long HTTP_PIPELINING_MAX = 20L;
+
+// Miscellaneous defaults
const bool HTTP_USE_RETRY_AFTER_DEFAULT = true;
const long HTTP_THROTTLE_RATE_DEFAULT = 0L;
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index e56bc84174..fb907f6318 100755
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012-2013, Linden Research, Inc.
+ * Copyright (C) 2012-2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -33,6 +33,15 @@
#include "llhttpconstants.h"
+namespace
+{
+
+// Error testing and reporting for libcurl status codes
+void check_curl_multi_code(CURLMcode code);
+void check_curl_multi_code(CURLMcode code, int curl_setopt_option);
+
+} // end anonymous namespace
+
namespace LLCore
{
@@ -92,14 +101,44 @@ void HttpLibcurl::start(int policy_count)
llassert_always(policy_count <= HTTP_POLICY_CLASS_LIMIT);
llassert_always(! mMultiHandles); // One-time call only
+ HttpPolicy & policy(mService->getPolicy());
mPolicyCount = policy_count;
mMultiHandles = new CURLM * [mPolicyCount];
mActiveHandles = new int [mPolicyCount];
for (int policy_class(0); policy_class < mPolicyCount; ++policy_class)
{
- mMultiHandles[policy_class] = curl_multi_init();
+ HttpPolicyClass & options(policy.getClassOptions(policy_class));
+
mActiveHandles[policy_class] = 0;
+ if (NULL == (mMultiHandles[policy_class] = curl_multi_init()))
+ {
+ LL_ERRS("CoreHttp") << "Failed to allocate multi handle in libcurl."
+ << LL_ENDL;
+ }
+
+ if (options.mPipelining > 1)
+ {
+ CURLMcode code;
+
+ // We'll try to do pipelining on this multihandle
+ code = curl_multi_setopt(mMultiHandles[policy_class],
+ CURLMOPT_PIPELINING,
+ 1L);
+ check_curl_multi_code(code, CURLMOPT_PIPELINING);
+ code = curl_multi_setopt(mMultiHandles[policy_class],
+ CURLMOPT_MAX_PIPELINE_LENGTH,
+ long(options.mPipelining));
+ check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH);
+ code = curl_multi_setopt(mMultiHandles[policy_class],
+ CURLMOPT_MAX_HOST_CONNECTIONS,
+ long(options.mPerHostConnectionLimit));
+ check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS);
+ code = curl_multi_setopt(mMultiHandles[policy_class],
+ CURLMOPT_MAX_TOTAL_CONNECTIONS,
+ long(options.mConnectionLimit));
+ check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);
+ }
}
}
@@ -376,3 +415,29 @@ struct curl_slist * append_headers_to_slist(const HttpHeaders * headers, struct
} // end namespace LLCore
+
+
+namespace
+{
+
+void check_curl_multi_code(CURLMcode code, int curl_setopt_option)
+{
+ if (CURLM_OK != code)
+ {
+ LL_WARNS("CoreHttp") << "libcurl multi error detected: " << curl_multi_strerror(code)
+ << ", curl_multi_setopt option: " << curl_setopt_option
+ << LL_ENDL;
+ }
+}
+
+
+void check_curl_multi_code(CURLMcode code)
+{
+ if (CURLM_OK != code)
+ {
+ LL_WARNS("CoreHttp") << "libcurl multi error detected: " << curl_multi_strerror(code)
+ << LL_ENDL;
+ }
+}
+
+} // end anonymous namespace
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index fd5a93e192..bb7959b578 100755
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012-2013, Linden Research, Inc.
+ * Copyright (C) 2012-2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -128,7 +128,8 @@ void HttpPolicy::shutdown()
void HttpPolicy::start()
-{}
+{
+}
void HttpPolicy::addOp(HttpOpRequest * op)
@@ -234,7 +235,11 @@ HttpService::ELoopSpeed HttpPolicy::processReadyQueue()
}
int active(transport.getActiveCountInClass(policy_class));
- int needed(state.mOptions.mConnectionLimit - active); // Expect negatives here
+ int active_limit(state.mOptions.mPipelining > 1L
+ ? (state.mOptions.mPerHostConnectionLimit
+ * state.mOptions.mPipelining)
+ : state.mOptions.mConnectionLimit);
+ int needed(active_limit - active); // Expect negatives here
if (needed > 0)
{
diff --git a/indra/llcorehttp/_httppolicyclass.cpp b/indra/llcorehttp/_httppolicyclass.cpp
index f34a8e9f1e..2c0f650155 100755
--- a/indra/llcorehttp/_httppolicyclass.cpp
+++ b/indra/llcorehttp/_httppolicyclass.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012-2013, Linden Research, Inc.
+ * Copyright (C) 2012-2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -78,8 +78,8 @@ HttpStatus HttpPolicyClass::set(HttpRequest::EPolicyOption opt, long value)
mPerHostConnectionLimit = llclamp(value, long(HTTP_CONNECTION_LIMIT_MIN), mConnectionLimit);
break;
- case HttpRequest::PO_ENABLE_PIPELINING:
- mPipelining = llclamp(value, 0L, 1L);
+ case HttpRequest::PO_PIPELINING_DEPTH:
+ mPipelining = llclamp(value, 0L, HTTP_PIPELINING_MAX);
break;
case HttpRequest::PO_THROTTLE_RATE:
@@ -106,7 +106,7 @@ HttpStatus HttpPolicyClass::get(HttpRequest::EPolicyOption opt, long * value) co
*value = mPerHostConnectionLimit;
break;
- case HttpRequest::PO_ENABLE_PIPELINING:
+ case HttpRequest::PO_PIPELINING_DEPTH:
*value = mPipelining;
break;
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index 651654844a..7f23723b0b 100755
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012-2013, Linden Research, Inc.
+ * Copyright (C) 2012-2014, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -183,11 +183,38 @@ public:
/// Global only
PO_TRACE,
- /// Suitable requests are allowed to pipeline on their
- /// connections when they ask for it.
+ /// If greater than 1, suitable requests are allowed to
+ /// pipeline on their connections when they ask for it.
+ /// Value gives the maximum number of outstanding requests
+ /// on a connection.
+ ///
+ /// There is some interaction between PO_CONNECTION_LIMIT,
+ /// PO_PER_HOST_CONNECTION_LIMIT, and PO_PIPELINING_DEPTH.
+ /// When PIPELINING_DEPTH is 0 or 1 (no pipelining), this
+ /// library manages connection lifecycle and honors the
+ /// PO_CONNECTION_LIMIT setting as the maximum in-flight
+ /// request limit. Libcurl itself may be caching additional
+ /// connections under its connection cache policy.
+ ///
+ /// When PIPELINING_DEPTH is 2 or more, libcurl performs
+ /// connection management and both PO_CONNECTION_LIMIT and
+ /// PO_PER_HOST_CONNECTION_LIMIT should be set and non-zero.
+ /// In this case (as of libcurl 7.37.0), libcurl will
+ /// open new connections in preference to pipelining, up
+ /// to the above limits at which time pipelining begins.
+ /// And as usual, an additional cache of open but inactive
+ /// connections may still be maintained within libcurl.
+ /// For SL, a good rule-of-thumb is to set
+ /// PO_PER_HOST_CONNECTION_LIMIT to the user-visible
+ /// concurrency value and PO_CONNECTION_LIMIT to twice
+ /// that for baked texture loads and region crossings where
+ /// additional connection load will be tolerated. If
+ /// either limit is 0, libcurl will prefer pipelining
+ /// over connection creation, which is still interesting,
+ /// but won't be pursued at this time.
///
/// Per-class only
- PO_ENABLE_PIPELINING,
+ PO_PIPELINING_DEPTH,
/// Controls whether client-side throttling should be
/// performed on this policy class. Positive values