summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindra/llcorehttp/_httpinternal.h3
-rwxr-xr-xindra/llcorehttp/_httpoprequest.cpp15
-rwxr-xr-xindra/llcorehttp/_httpoprequest.h3
-rwxr-xr-xindra/llcorehttp/_httppolicy.cpp6
-rwxr-xr-xindra/llcorehttp/httpoptions.cpp9
-rwxr-xr-xindra/llcorehttp/httpoptions.h9
-rwxr-xr-xindra/llcorehttp/httpresponse.cpp6
-rwxr-xr-xindra/llcorehttp/httpresponse.h17
-rwxr-xr-xindra/newview/llappcorehttp.cpp156
-rwxr-xr-xindra/newview/llappcorehttp.h36
-rwxr-xr-xindra/newview/llmeshrepository.cpp197
-rwxr-xr-xindra/newview/llmeshrepository.h21
-rwxr-xr-xindra/newview/lltexturefetch.cpp4
13 files changed, 301 insertions, 181 deletions
diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h
index 30b0905c12..d60996756f 100755
--- a/indra/llcorehttp/_httpinternal.h
+++ b/indra/llcorehttp/_httpinternal.h
@@ -98,7 +98,7 @@ namespace LLCore
// Maxium number of policy classes that can be defined.
// *TODO: Currently limited to the default class + 1, extend.
-const int HTTP_POLICY_CLASS_LIMIT = 2;
+const int HTTP_POLICY_CLASS_LIMIT = 4;
// Debug/informational tracing. Used both
// as a global option and in per-request traces.
@@ -129,6 +129,7 @@ const int HTTP_REDIRECTS_DEFAULT = 10;
// Retries and time-on-queue are not included and aren't
// accounted for.
const long HTTP_REQUEST_TIMEOUT_DEFAULT = 30L;
+const long HTTP_REQUEST_XFER_TIMEOUT_DEFAULT = 0L;
const long HTTP_REQUEST_TIMEOUT_MIN = 0L;
const long HTTP_REQUEST_TIMEOUT_MAX = 3600L;
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 51a8eaf998..d403b2d249 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -110,6 +110,7 @@ HttpOpRequest::HttpOpRequest()
mReplyFullLength(0),
mReplyHeaders(NULL),
mPolicyRetries(0),
+ mPolicy503Retries(0),
mPolicyRetryAt(HttpTime(0)),
mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT)
{
@@ -224,6 +225,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
response->setRange(mReplyOffset, mReplyLength, mReplyFullLength);
}
response->setContentType(mReplyConType);
+ response->setRetries(mPolicyRetries, mPolicy503Retries);
mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
@@ -524,12 +526,19 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// Request options
long timeout(HTTP_REQUEST_TIMEOUT_DEFAULT);
+ long xfer_timeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT);
if (mReqOptions)
- {
+ {
timeout = mReqOptions->getTimeout();
timeout = llclamp(timeout, HTTP_REQUEST_TIMEOUT_MIN, HTTP_REQUEST_TIMEOUT_MAX);
+ xfer_timeout = mReqOptions->getTransferTimeout();
+ xfer_timeout = llclamp(xfer_timeout, HTTP_REQUEST_TIMEOUT_MIN, HTTP_REQUEST_TIMEOUT_MAX);
+ }
+ if (xfer_timeout == 0L)
+ {
+ xfer_timeout = timeout;
}
- curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, timeout);
+ curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
// Request headers
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index 7b65d17783..831e5bebf7 100755
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -187,6 +187,7 @@ public:
// Policy data
int mPolicyRetries;
+ int mPolicy503Retries;
HttpTime mPolicyRetryAt;
int mPolicyRetryLimit;
}; // end class HttpOpRequest
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index 76c1e22431..54c9c6bb1b 100755
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -140,6 +140,7 @@ void HttpPolicy::addOp(HttpOpRequest * op)
const int policy_class(op->mReqPolicy);
op->mPolicyRetries = 0;
+ op->mPolicy503Retries = 0;
mState[policy_class].mReadyQueue.push(op);
}
@@ -155,6 +156,7 @@ void HttpPolicy::retryOp(HttpOpRequest * op)
5000000 // ... to every 5.0 S.
};
static const int delta_max(int(LL_ARRAY_SIZE(retry_deltas)) - 1);
+ static const HttpStatus error_503(503);
const HttpTime now(totalTime());
const int policy_class(op->mReqPolicy);
@@ -162,6 +164,10 @@ void HttpPolicy::retryOp(HttpOpRequest * op)
const HttpTime delta(retry_deltas[llclamp(op->mPolicyRetries, 0, delta_max)]);
op->mPolicyRetryAt = now + delta;
++op->mPolicyRetries;
+ if (error_503 == op->mStatus)
+ {
+ ++op->mPolicy503Retries;
+ }
LL_WARNS("CoreHttp") << "HTTP request " << static_cast<HttpHandle>(op)
<< " retry " << op->mPolicyRetries
<< " scheduled for +" << (delta / HttpTime(1000))
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index 1699d19f8d..4dcd862ca4 100755
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -38,6 +38,7 @@ HttpOptions::HttpOptions()
mWantHeaders(false),
mTracing(HTTP_TRACE_OFF),
mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
+ mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
mRetries(HTTP_RETRY_COUNT_DEFAULT)
{}
@@ -64,6 +65,12 @@ void HttpOptions::setTimeout(unsigned int timeout)
}
+void HttpOptions::setTransferTimeout(unsigned int timeout)
+{
+ mTransferTimeout = timeout;
+}
+
+
void HttpOptions::setRetries(unsigned int retries)
{
mRetries = retries;
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 97e46a8cd3..623d71d3e6 100755
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -86,6 +86,12 @@ public:
return mTimeout;
}
+ void setTransferTimeout(unsigned int timeout);
+ unsigned int getTransferTimeout() const
+ {
+ return mTransferTimeout;
+ }
+
void setRetries(unsigned int retries);
unsigned int getRetries() const
{
@@ -96,6 +102,7 @@ protected:
bool mWantHeaders;
int mTracing;
unsigned int mTimeout;
+ unsigned int mTransferTimeout;
unsigned int mRetries;
}; // end class HttpOptions
diff --git a/indra/llcorehttp/httpresponse.cpp b/indra/llcorehttp/httpresponse.cpp
index a552e48a1b..c974395b0a 100755
--- a/indra/llcorehttp/httpresponse.cpp
+++ b/indra/llcorehttp/httpresponse.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -39,7 +39,9 @@ HttpResponse::HttpResponse()
mReplyLength(0U),
mReplyFullLength(0U),
mBufferArray(NULL),
- mHeaders(NULL)
+ mHeaders(NULL),
+ mRetries(0U),
+ m503Retries(0U)
{}
diff --git a/indra/llcorehttp/httpresponse.h b/indra/llcorehttp/httpresponse.h
index 4a481db6ac..a7f296e03f 100755
--- a/indra/llcorehttp/httpresponse.h
+++ b/indra/llcorehttp/httpresponse.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -144,6 +144,19 @@ public:
mContentType = con_type;
}
+ /// Get and set retry attempt information on the request.
+ void getRetries(unsigned int * retries, unsigned int * retries_503) const
+ {
+ *retries = mRetries;
+ *retries_503 = m503Retries;
+ }
+
+ void setRetries(unsigned int retries, unsigned int retries_503)
+ {
+ mRetries = retries;
+ m503Retries = retries_503;
+ }
+
protected:
// Response data here
HttpStatus mStatus;
@@ -153,6 +166,8 @@ protected:
BufferArray * mBufferArray;
HttpHeaders * mHeaders;
std::string mContentType;
+ unsigned int mRetries;
+ unsigned int m503Retries;
};
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index 142344e277..b601b31d21 100755
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -37,11 +37,13 @@ LLAppCoreHttp::LLAppCoreHttp()
: mRequest(NULL),
mStopHandle(LLCORE_HTTP_HANDLE_INVALID),
mStopRequested(0.0),
- mStopped(false),
- mPolicyDefault(-1),
- mPolicyTexture(-1),
- mPolicyMesh(-1)
-{}
+ mStopped(false)
+{
+ for (int i(0); i < LL_ARRAY_SIZE(mPolicies); ++i)
+ {
+ mPolicies[i] = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+ }
+}
LLAppCoreHttp::~LLAppCoreHttp()
@@ -53,11 +55,43 @@ LLAppCoreHttp::~LLAppCoreHttp()
void LLAppCoreHttp::init()
{
+ static const struct
+ {
+ EAppPolicy mPolicy;
+ U32 mDefault;
+ U32 mMin;
+ U32 mMax;
+ U32 mDivisor;
+ std::string mKey;
+ const char * mUsage;
+ } init_data[] = // Default and dynamic values for classes
+ {
+ {
+ AP_TEXTURE, 8, 1, 12, 1,
+ "TextureFetchConcurrency",
+ "texture fetch"
+ },
+ {
+ AP_MESH, 8, 1, 32, 4,
+ "MeshMaxConcurrentRequests",
+ "mesh fetch"
+ },
+ {
+ AP_LARGE_MESH, 2, 1, 8, 1,
+ "",
+ "large mesh fetch"
+ },
+ {
+ AP_UPLOADS, 2, 1, 8, 1,
+ "",
+ "asset upload"
+ }
+ };
+
LLCore::HttpStatus status = LLCore::HttpRequest::createService();
if (! status)
{
- LL_ERRS("Init") << "Failed to initialize HTTP services. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to initialize HTTP services. Reason: " << status.toString()
<< LL_ENDL;
}
@@ -66,8 +100,7 @@ void LLAppCoreHttp::init()
gDirUtilp->getCAFile());
if (! status)
{
- LL_ERRS("Init") << "Failed to set CA File for HTTP services. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to set CA File for HTTP services. Reason: " << status.toString()
<< LL_ENDL;
}
@@ -77,8 +110,7 @@ void LLAppCoreHttp::init()
status = LLCore::HttpRequest::setPolicyGlobalOption(LLCore::HttpRequest::GP_LLPROXY, 1);
if (! status)
{
- LL_ERRS("Init") << "Failed to set HTTP proxy for HTTP services. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to set HTTP proxy for HTTP services. Reason: " << status.toString()
<< LL_ENDL;
}
@@ -96,80 +128,72 @@ void LLAppCoreHttp::init()
}
// Setup default policy and constrain if directed to
- mPolicyDefault = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+ mPolicies[AP_DEFAULT] = LLCore::HttpRequest::DEFAULT_POLICY_ID;
- // Texture policy will use default for now.
- mPolicyTexture = mPolicyDefault;
- static const std::string texture_concur("TextureFetchConcurrency");
- if (gSavedSettings.controlExists(texture_concur))
+ // Setup additional policies based on table and some special rules
+ // *TODO: Make these configurations dynamic later
+ for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
{
- U32 concur(llmin(gSavedSettings.getU32(texture_concur), U32(12)));
+ const EAppPolicy policy(init_data[i].mPolicy);
- if (concur > 0)
+ // Create a policy class but use default for texture for now.
+ // This also has the side-effect of initializing the default
+ // class to desired values.
+ if (AP_TEXTURE == policy)
{
- LLCore::HttpStatus status;
- status = LLCore::HttpRequest::setPolicyClassOption(mPolicyTexture,
- LLCore::HttpRequest::CP_CONNECTION_LIMIT,
- concur);
- if (! status)
- {
- LL_WARNS("Init") << "Unable to set texture fetch concurrency. Reason: "
- << status.toString()
- << LL_ENDL;
- }
- else
+ mPolicies[policy] = mPolicies[AP_DEFAULT];
+ }
+ else
+ {
+ mPolicies[policy] = LLCore::HttpRequest::createPolicyClass();
+ if (! mPolicies[policy])
{
- LL_INFOS("Init") << "Application settings overriding default texture fetch concurrency. New value: "
- << concur
+ // Use default policy (but don't accidentally modify default)
+ LL_WARNS("Init") << "Failed to create HTTP policy class for " << init_data[i].mUsage
+ << ". Using default policy."
<< LL_ENDL;
+ mPolicies[policy] = mPolicies[AP_DEFAULT];
+ continue;
}
}
- }
- // Create the mesh class
- mPolicyMesh = LLCore::HttpRequest::createPolicyClass();
- if (! mPolicyMesh)
- {
- LL_WARNS("Init") << "Failed to create HTTP policy class for Mesh. Using default policy."
- << LL_ENDL;
- mPolicyMesh = mPolicyDefault;
- }
- else
- {
- static const std::string mesh_concur("MeshMaxConcurrentRequests");
- if (gSavedSettings.controlExists(mesh_concur))
+ // Get target connection concurrency value
+ U32 setting(init_data[i].mDefault);
+ if (! init_data[i].mKey.empty() && gSavedSettings.controlExists(init_data[i].mKey))
{
- U32 setting(llmin(gSavedSettings.getU32(mesh_concur), 256U) / 4U);
- setting = llmax(setting, 2U);
-
- if (setting > 0)
+ U32 new_setting(gSavedSettings.getU32(init_data[i].mKey));
+ if (new_setting)
{
- LLCore::HttpStatus status;
- status = LLCore::HttpRequest::setPolicyClassOption(mPolicyMesh,
- LLCore::HttpRequest::CP_CONNECTION_LIMIT,
- setting);
- if (! status)
- {
- LL_WARNS("Init") << "Unable to set mesh fetch concurrency. Reason: "
- << status.toString()
- << LL_ENDL;
- }
- else
- {
- LL_INFOS("Init") << "Application settings overriding default mesh fetch concurrency. New value: "
- << setting
- << LL_ENDL;
- }
+ // Treat zero settings as an ask for default
+ setting = new_setting / init_data[i].mDivisor;
+ setting = llclamp(setting, init_data[i].mMin, init_data[i].mMax);
}
}
+
+ // Set it and report
+ LLCore::HttpStatus status;
+ status = LLCore::HttpRequest::setPolicyClassOption(mPolicies[policy],
+ LLCore::HttpRequest::CP_CONNECTION_LIMIT,
+ setting);
+ if (! status)
+ {
+ LL_WARNS("Init") << "Unable to set " << init_data[i].mUsage
+ << " concurrency. Reason: " << status.toString()
+ << LL_ENDL;
+ }
+ else if (setting != init_data[i].mDefault)
+ {
+ LL_INFOS("Init") << "Application settings overriding default " << init_data[i].mUsage
+ << " concurrency. New value: " << setting
+ << LL_ENDL;
+ }
}
// Kick the thread
status = LLCore::HttpRequest::startThread();
if (! status)
{
- LL_ERRS("Init") << "Failed to start HTTP servicing thread. Reason: "
- << status.toString()
+ LL_ERRS("Init") << "Failed to start HTTP servicing thread. Reason: " << status.toString()
<< LL_ENDL;
}
diff --git a/indra/newview/llappcorehttp.h b/indra/newview/llappcorehttp.h
index d90af9e5ca..532e1f5cb0 100755
--- a/indra/newview/llappcorehttp.h
+++ b/indra/newview/llappcorehttp.h
@@ -41,6 +41,19 @@
class LLAppCoreHttp : public LLCore::HttpHandler
{
public:
+ typedef LLCore::HttpRequest::policy_t policy_t;
+
+ enum EAppPolicy
+ {
+ AP_DEFAULT,
+ AP_TEXTURE,
+ AP_MESH,
+ AP_LARGE_MESH,
+ AP_UPLOADS,
+ AP_COUNT // Must be last
+ };
+
+public:
LLAppCoreHttp();
~LLAppCoreHttp();
@@ -65,22 +78,11 @@ public:
// Notification when the stop request is complete.
virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
- // Retrieve the policy class for default operations.
- int getPolicyDefault() const
- {
- return mPolicyDefault;
- }
-
- // Get the texture fetch policy class.
- int getPolicyTexture() const
- {
- return mPolicyTexture;
- }
-
- // Get the mesh fetch policy class.
- int getPolicyMesh() const
+ // Retrieve a policy class identifier for desired
+ // application function.
+ policy_t getPolicy(EAppPolicy policy) const
{
- return mPolicyMesh;
+ return mPolicies[policy];
}
private:
@@ -91,9 +93,7 @@ private:
LLCore::HttpHandle mStopHandle;
F64 mStopRequested;
bool mStopped;
- int mPolicyDefault;
- int mPolicyTexture;
- int mPolicyMesh;
+ policy_t mPolicies[AP_COUNT];
};
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 702e940983..f0ec97a34d 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -80,6 +80,10 @@ LLMeshRepository gMeshRepo;
const S32 MESH_HEADER_SIZE = 4096;
const U32 MAX_MESH_REQUESTS_PER_SECOND = 100;
+const S32 REQUEST_HIGH_WATER_MIN = 32;
+const S32 REQUEST_LOW_WATER_MIN = 16;
+const U32 LARGE_MESH_FETCH_THRESHOLD = 1U << 21; // Size at which requests goes to narrow/slow queue
+const long LARGE_MESH_XFER_TIMEOUT = 240L; // Seconds to complete xfer
// Maximum mesh version to support. Three least significant digits are reserved for the minor version,
// with major version changes indicating a format change that is not backwards compatible and should not
@@ -210,6 +214,8 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res,
S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
S32 LLMeshRepoThread::sActiveLODRequests = 0;
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
+S32 LLMeshRepoThread::sRequestLowWater = REQUEST_LOW_WATER_MIN;
+S32 LLMeshRepoThread::sRequestHighWater = REQUEST_HIGH_WATER_MIN;
class LLMeshHandlerBase : public LLCore::HttpHandler
{
@@ -548,25 +554,37 @@ public:
LLMeshRepoThread::LLMeshRepoThread()
: LLThread("mesh repo"),
- mCurlRequest(NULL),
mWaiting(false),
mHttpRequest(NULL),
mHttpOptions(NULL),
+ mHttpLargeOptions(NULL),
mHttpHeaders(NULL),
- mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID)
+ mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+ mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
+ mHttpPriority(0),
+ mHttpGetCount(0U),
+ mHttpLargeGetCount(0U)
{
mMutex = new LLMutex(NULL);
mHeaderMutex = new LLMutex(NULL);
mSignal = new LLCondition(NULL);
mHttpRequest = new LLCore::HttpRequest;
mHttpOptions = new LLCore::HttpOptions;
+ mHttpLargeOptions = new LLCore::HttpOptions;
+ mHttpLargeOptions->setTransferTimeout(LARGE_MESH_XFER_TIMEOUT);
mHttpHeaders = new LLCore::HttpHeaders;
mHttpHeaders->mHeaders.push_back("Accept: application/vnd.ll.mesh");
- mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyMesh();
+ mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_MESH);
+ mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_LARGE_MESH);
}
+
LLMeshRepoThread::~LLMeshRepoThread()
{
+ LL_INFOS("Mesh") << "Small GETs issued: "
+ << mHttpGetCount << ", Large GETs issued: "
+ << mHttpLargeGetCount << LL_ENDL;
+
for (http_request_set::iterator iter(mHttpRequestSet.begin());
iter != mHttpRequestSet.end();
++iter)
@@ -584,6 +602,11 @@ LLMeshRepoThread::~LLMeshRepoThread()
mHttpOptions->release();
mHttpOptions = NULL;
}
+ if (mHttpLargeOptions)
+ {
+ mHttpLargeOptions->release();
+ mHttpLargeOptions = NULL;
+ }
delete mHttpRequest;
mHttpRequest = NULL;
delete mMutex;
@@ -596,7 +619,6 @@ LLMeshRepoThread::~LLMeshRepoThread()
void LLMeshRepoThread::run()
{
- mCurlRequest = new LLCurlRequest();
LLCDResult res = LLConvexDecomposition::initThread();
if (res != LLCD_OK)
{
@@ -627,7 +649,7 @@ void LLMeshRepoThread::run()
// NOTE: throttling intentionally favors LOD requests over header requests
- while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < sMaxConcurrentRequests)
+ while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND)
{
if (mMutex)
{
@@ -646,7 +668,7 @@ void LLMeshRepoThread::run()
}
}
- while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < sMaxConcurrentRequests)
+ while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND)
{
if (mMutex)
{
@@ -701,8 +723,6 @@ void LLMeshRepoThread::run()
}
mPhysicsShapeRequests = incomplete;
}
-
- mCurlRequest->process();
}
}
@@ -716,9 +736,6 @@ void LLMeshRepoThread::run()
{
llwarns << "convex decomposition unable to be quit" << llendl;
}
-
- delete mCurlRequest;
- mCurlRequest = NULL;
}
void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
@@ -800,6 +817,42 @@ std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
return http_url;
}
+// May only be called by repo thread
+LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
+ size_t offset,
+ size_t len,
+ LLCore::HttpHandler * handler)
+{
+ LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
+
+ if (len < LARGE_MESH_FETCH_THRESHOLD)
+ {
+ handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,
+ mHttpPriority,
+ url,
+ offset,
+ len,
+ mHttpOptions,
+ mHttpHeaders,
+ handler);
+ ++mHttpGetCount;
+ }
+ else
+ {
+ handle = mHttpRequest->requestGetByteRange(mHttpLargePolicyClass,
+ mHttpPriority,
+ url,
+ offset,
+ len,
+ mHttpLargeOptions,
+ mHttpHeaders,
+ handler);
+ ++mHttpLargeGetCount;
+ }
+ return handle;
+}
+
+
bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
{ //protected by mMutex
@@ -863,14 +916,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
{
LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size);
// LL_WARNS("Mesh") << "MESH: Issuing Skin Info Request" << LL_ENDL;
- LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,
- 0, // *TODO: Get better priority value
- http_url,
- offset,
- size,
- mHttpOptions,
- mHttpHeaders,
- handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
// *TODO: Better error message
@@ -959,14 +1005,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
{
LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size);
// LL_WARNS("Mesh") << "MESH: Issuing Decomp Request" << LL_ENDL;
- LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,
- 0, // *TODO: Get better priority value
- http_url,
- offset,
- size,
- mHttpOptions,
- mHttpHeaders,
- handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
// *TODO: Better error message
@@ -1054,14 +1093,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
{
LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size);
// LL_WARNS("Mesh") << "MESH: Issuing Physics Shape Request" << LL_ENDL;
- LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,
- 0, // *TODO: Get better priority value
- http_url,
- offset,
- size,
- mHttpOptions,
- mHttpHeaders,
- handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
// *TODO: Better error message
@@ -1154,14 +1186,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c
LLMeshHeaderHandler * handler = new LLMeshHeaderHandler(mesh_params);
// LL_WARNS("Mesh") << "MESH: Issuing Request" << LL_ENDL;
- LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,
- 0, // *TODO: Get better priority value
- http_url,
- 0,
- MESH_HEADER_SIZE,
- mHttpOptions,
- mHttpHeaders,
- handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, 0, MESH_HEADER_SIZE, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
// *TODO: Better error message
@@ -1241,14 +1266,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
{
LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size);
// LL_WARNS("Mesh") << "MESH: Issuing LOD Request" << LL_ENDL;
- LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,
- 0, // *TODO: Get better priority value
- http_url,
- offset,
- size,
- mHttpOptions,
- mHttpHeaders,
- handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
// *TODO: Better error message
@@ -2537,9 +2555,14 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
void LLMeshRepository::notifyLoadedMeshes()
{ //called from main thread
-
- LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests");
-
+ // *FIXME: Scaling down the setting by a factor of 4 for now to reflect
+ // target goal. May want to rename the setting before release.
+ LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests") / 4;
+ LLMeshRepoThread::sRequestHighWater = llmax(50 * S32(LLMeshRepoThread::sMaxConcurrentRequests),
+ REQUEST_HIGH_WATER_MIN);
+ LLMeshRepoThread::sRequestLowWater = llmax(LLMeshRepoThread::sRequestLowWater / 2,
+ REQUEST_LOW_WATER_MIN);
+
//clean up completed upload threads
for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); )
{
@@ -2617,7 +2640,7 @@ void LLMeshRepository::notifyLoadedMeshes()
//call completed callbacks on finished decompositions
mDecompThread->notifyCompleted();
- if (!mThread->mWaiting)
+ if (!mThread->mWaiting && mPendingRequests.empty())
{ //curl thread is churning, wait for it to go idle
return;
}
@@ -2644,47 +2667,55 @@ void LLMeshRepository::notifyLoadedMeshes()
mUploadErrorQ.pop();
}
- S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests);
-
- if (push_count > 0)
+ S32 active_count = LLMeshRepoThread::sActiveHeaderRequests + LLMeshRepoThread::sActiveLODRequests;
+ if (active_count < LLMeshRepoThread::sRequestLowWater)
{
- //calculate "score" for pending requests
-
- //create score map
- std::map<LLUUID, F32> score_map;
+ S32 push_count = LLMeshRepoThread::sRequestHighWater - active_count;
- for (U32 i = 0; i < 4; ++i)
+ if (mPendingRequests.size() > push_count)
{
- for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter)
+ // More requests than the high-water limit allows so
+ // sort and forward the most important.
+
+ //calculate "score" for pending requests
+
+ //create score map
+ std::map<LLUUID, F32> score_map;
+
+ for (U32 i = 0; i < 4; ++i)
{
- F32 max_score = 0.f;
- for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
+ for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter)
{
- LLViewerObject* object = gObjectList.findObject(*obj_iter);
-
- if (object)
+ F32 max_score = 0.f;
+ for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ LLViewerObject* object = gObjectList.findObject(*obj_iter);
+
+ if (object)
{
- F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f);
- max_score = llmax(max_score, cur_score);
+ LLDrawable* drawable = object->mDrawable;
+ if (drawable)
+ {
+ F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f);
+ max_score = llmax(max_score, cur_score);
+ }
}
}
- }
- score_map[iter->first.getSculptID()] = max_score;
+ score_map[iter->first.getSculptID()] = max_score;
+ }
}
- }
- //set "score" for pending requests
- for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
- {
- iter->mScore = score_map[iter->mMeshParams.getSculptID()];
- }
+ //set "score" for pending requests
+ for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
+ {
+ iter->mScore = score_map[iter->mMeshParams.getSculptID()];
+ }
- //sort by "score"
- std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
+ //sort by "score"
+ std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count,
+ mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
+ }
while (!mPendingRequests.empty() && push_count > 0)
{
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 62f81ce9e2..0dca29e7d4 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -224,13 +224,14 @@ public:
static S32 sActiveHeaderRequests;
static S32 sActiveLODRequests;
static U32 sMaxConcurrentRequests;
+ static S32 sRequestLowWater;
+ static S32 sRequestHighWater;
- LLCurlRequest* mCurlRequest;
LLMutex* mMutex;
LLMutex* mHeaderMutex;
LLCondition* mSignal;
- bool mWaiting;
+ volatile bool mWaiting;
//map of known mesh headers
typedef std::map<LLUUID, LLSD> mesh_header_map;
@@ -324,8 +325,11 @@ public:
// llcorehttp library interface objects.
LLCore::HttpRequest * mHttpRequest;
LLCore::HttpOptions * mHttpOptions;
+ LLCore::HttpOptions * mHttpLargeOptions;
LLCore::HttpHeaders * mHttpHeaders;
LLCore::HttpRequest::policy_t mHttpPolicyClass;
+ LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
+ LLCore::HttpRequest::priority_t mHttpPriority;
typedef std::set<LLCore::HttpHandler *> http_request_set;
http_request_set mHttpRequestSet; // Outstanding HTTP requests
@@ -373,6 +377,19 @@ public:
static void incActiveHeaderRequests();
static void decActiveHeaderRequests();
+private:
+ // Issue a GET request to a URL with 'Range' header using
+ // the correct policy class and other attributes. If an invalid
+ // handle is returned, the request failed and caller must retry
+ // or dispose of handler.
+ //
+ // Threads: Repo thread only
+ LLCore::HttpHandle getByteRange(const std::string & url, size_t offset, size_t len,
+ LLCore::HttpHandler * handler);
+
+private:
+ U32 mHttpGetCount;
+ U32 mHttpLargeGetCount;
};
class LLMeshUploadThread : public LLThread
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index be5fde9e2b..d934ef9dc4 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -2410,7 +2410,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c");
mHttpMetricsHeaders = new LLCore::HttpHeaders;
mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml");
- mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault();
+ mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_TEXTURE);
}
LLTextureFetch::~LLTextureFetch()