summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindra/llcorehttp/_httpoperation.cpp6
-rwxr-xr-xindra/llcorehttp/_httpoprequest.cpp156
-rwxr-xr-xindra/llcorehttp/httpcommon.cpp3
-rwxr-xr-xindra/llcorehttp/httpcommon.h5
-rwxr-xr-xindra/llmessage/llcurl.cpp11
-rwxr-xr-xindra/newview/llmeshrepository.cpp101
-rwxr-xr-xindra/newview/llmeshrepository.h19
7 files changed, 214 insertions, 87 deletions
diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp
index 7acd728bbd..5bb0654652 100755
--- 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 stageFromRequest method may not be called."
+ LL_ERRS("CoreHttp") << "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 stageFromReady method may not be called."
+ LL_ERRS("CoreHttp") << "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 stageFromActive method may not be called."
+ LL_ERRS("CoreHttp") << "Default stageFromActive method may not be called."
<< LL_ENDL;
}
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index d72f8f6119..63c4e71258 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -90,6 +90,10 @@ char * os_strtrim(char * str);
char * os_strltrim(char * str);
void os_strlower(char * str);
+// Error testing and reporting for libcurl status codes
+void check_curl_easy_code(CURLcode code);
+void check_curl_easy_code(CURLcode code, int curl_setopt_option);
+
} // end anonymous namespace
@@ -373,6 +377,8 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
//
HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
{
+ CURLcode code;
+
// Scrub transport and result data for retried op case
mCurlActive = false;
mCurlHandle = NULL;
@@ -406,12 +412,25 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions());
mCurlHandle = curl_easy_init();
- curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
- curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
- curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
- curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
+ if (! mCurlHandle)
+ {
+ // We're in trouble. We'll continue but it won't go well.
+ LL_WARNS("CoreHttp") << "Failed to allocate libcurl easy handle. Continuing."
+ << LL_ENDL;
+ return HttpStatus(HttpStatus::LLCORE, HE_BAD_ALLOC);
+ }
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+ check_curl_easy_code(code, CURLOPT_IPRESOLVE);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
+ check_curl_easy_code(code, CURLOPT_NOSIGNAL);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
+ check_curl_easy_code(code, CURLOPT_NOPROGRESS);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
+ check_curl_easy_code(code, CURLOPT_URL);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
+ check_curl_easy_code(code, CURLOPT_PRIVATE);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
+ check_curl_easy_code(code, CURLOPT_ENCODING);
if (HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)
{
@@ -421,7 +440,8 @@ 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, 15);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
+ check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
}
else
{
@@ -429,17 +449,27 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// I don't think this is valid anymore, the Multi shared DNS
// cache is working well. For the case of naked easy handles,
// consider using a shared DNS object.
- curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
+ check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
}
- curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
- 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);
- curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
- curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
+ check_curl_easy_code(code, CURLOPT_AUTOREFERER);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
+ check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
+ check_curl_easy_code(code, CURLOPT_MAXREDIRS);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
+ check_curl_easy_code(code, CURLOPT_WRITEFUNCTION);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
+ check_curl_easy_code(code, CURLOPT_WRITEDATA);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
+ check_curl_easy_code(code, CURLOPT_READFUNCTION);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
+ check_curl_easy_code(code, CURLOPT_READDATA);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
+ check_curl_easy_code(code, CURLOPT_SSL_VERIFYPEER);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
+ check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST);
if (policy.mUseLLProxy)
{
@@ -452,37 +482,46 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
{
// *TODO: This is fine for now but get fuller socks5/
// authentication thing going later....
- curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, policy.mHttpProxy.c_str());
- curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, policy.mHttpProxy.c_str());
+ check_curl_easy_code(code, CURLOPT_PROXY);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ check_curl_easy_code(code, CURLOPT_PROXYTYPE);
}
if (policy.mCAPath.size())
{
- curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, policy.mCAPath.c_str());
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, policy.mCAPath.c_str());
+ check_curl_easy_code(code, CURLOPT_CAPATH);
}
if (policy.mCAFile.size())
{
- curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, policy.mCAFile.c_str());
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, policy.mCAFile.c_str());
+ check_curl_easy_code(code, CURLOPT_CAINFO);
}
switch (mReqMethod)
{
case HOR_GET:
- curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
+ check_curl_easy_code(code, CURLOPT_HTTPGET);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
break;
case HOR_POST:
{
- curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
+ check_curl_easy_code(code, CURLOPT_POST);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
+ check_curl_easy_code(code, CURLOPT_ENCODING);
long data_size(0);
if (mReqBody)
{
data_size = mReqBody->size();
}
- curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
- curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
+ check_curl_easy_code(code, CURLOPT_POSTFIELDS);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
+ check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
@@ -491,14 +530,17 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
case HOR_PUT:
{
- curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
+ check_curl_easy_code(code, CURLOPT_UPLOAD);
long data_size(0);
if (mReqBody)
{
data_size = mReqBody->size();
}
- curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
- curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
+ check_curl_easy_code(code, CURLOPT_INFILESIZE);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
+ check_curl_easy_code(code, CURLOPT_POSTFIELDS);
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
@@ -515,9 +557,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// Tracing
if (mTracing >= HTTP_TRACE_CURL_HEADERS)
{
- curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
- curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
- curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
+ check_curl_easy_code(code, CURLOPT_VERBOSE);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
+ check_curl_easy_code(code, CURLOPT_DEBUGDATA);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback);
+ check_curl_easy_code(code, CURLOPT_DEBUGFUNCTION);
}
// There's a CURLOPT for this now...
@@ -557,8 +602,10 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
{
xfer_timeout = timeout;
}
- curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
- curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
+ check_curl_easy_code(code, CURLOPT_TIMEOUT);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
+ check_curl_easy_code(code, CURLOPT_CONNECTTIMEOUT);
// Request headers
if (mReqHeaders)
@@ -566,12 +613,15 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// Caller's headers last to override
mCurlHeaders = append_headers_to_slist(mReqHeaders, mCurlHeaders);
}
- curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
+ check_curl_easy_code(code, CURLOPT_HTTPHEADER);
if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS | PF_USE_RETRY_AFTER))
{
- curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
- curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
+ check_curl_easy_code(code, CURLOPT_HEADERFUNCTION);
+ code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
+ check_curl_easy_code(code, CURLOPT_HEADERDATA);
}
if (status)
@@ -612,7 +662,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
{
// Warn but continue if the read position moves beyond end-of-body
// for some reason.
- LL_WARNS("HttpCore") << "Request body position beyond body size. Truncating request body."
+ LL_WARNS("CoreHttp") << "Request body position beyond body size. Truncating request body."
<< LL_ENDL;
}
return 0;
@@ -1046,6 +1096,32 @@ char * os_strltrim(char * lstr)
}
-} // end anonymous namespace
+void check_curl_easy_code(CURLcode code, int curl_setopt_option)
+{
+ if (CURLE_OK != code)
+ {
+ // Comment from old llcurl code which may no longer apply:
+ //
+ // linux appears to throw a curl error once per session for a bad initialization
+ // at a pretty random time (when enabling cookies).
+ LL_WARNS("CoreHttp") << "libcurl error detected: " << curl_easy_strerror(code)
+ << ", curl_easy_setopt option: " << curl_setopt_option
+ << LL_ENDL;
+ }
+}
-
+
+void check_curl_easy_code(CURLcode code)
+{
+ if (CURLE_OK != code)
+ {
+ // Comment from old llcurl code which may no longer apply:
+ //
+ // linux appears to throw a curl error once per session for a bad initialization
+ // at a pretty random time (when enabling cookies).
+ LL_WARNS("CoreHttp") << "libcurl error detected: " << curl_easy_strerror(code)
+ << LL_ENDL;
+ }
+}
+
+} // end anonymous namespace
diff --git a/indra/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp
index ca57a18578..0cf415223e 100755
--- a/indra/llcorehttp/httpcommon.cpp
+++ b/indra/llcorehttp/httpcommon.cpp
@@ -70,7 +70,8 @@ std::string HttpStatus::toString() const
"Invalid datatype for argument or option",
"Option has not been explicitly set",
"Option is not dynamic and must be set early",
- "Invalid HTTP status code received from server"
+ "Invalid HTTP status code received from server",
+ "Could not allocate required resource"
};
static const int llcore_errors_count(sizeof(llcore_errors) / sizeof(llcore_errors[0]));
diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h
index a04b344a9e..3a0bd68108 100755
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -246,7 +246,10 @@ enum HttpError
HE_OPT_NOT_DYNAMIC = 8,
// Invalid HTTP status code returned by server
- HE_INVALID_HTTP_STATUS = 9
+ HE_INVALID_HTTP_STATUS = 9,
+
+ // Couldn't allocate resource, typically libcurl handle
+ HE_BAD_ALLOC = 10
}; // end enum HttpError
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index f2a3e059ef..5193799ade 100755
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -6,7 +6,7 @@
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
+ * Copyright (C) 2010-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
@@ -293,9 +293,12 @@ LLCurl::Easy* LLCurl::Easy::getEasy()
return NULL;
}
- // set no DNS caching as default for all easy handles. This prevents them adopting a
- // multi handles cache if they are added to one.
- CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
+ // Enable a brief cache period for now. This was zero for the longest time
+ // which caused some routers grief and generated unneeded traffic. For the
+ // threded resolver, we're using system resolution libraries and non-zero values
+ // are preferred. The c-ares resolver is another matter and it might not
+ // track server changes as well.
+ CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
check_curl_code(result);
result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
check_curl_code(result);
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index b55ba758e1..42952909d7 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -78,8 +78,6 @@
#include "netdb.h"
#endif
-#include <queue>
-
// Purpose
//
@@ -235,8 +233,7 @@
// mUploadWaitList none rw.main.none (upload thread accessing objects)
// mInventoryQ mMeshMutex [4] rw.main.mMeshMutex, ro.main.none [5]
// mUploadErrorQ mMeshMutex rw.main.mMeshMutex, rw.any.mMeshMutex
-// mGetMeshCapability none rw.main.none [0], ro.any.none
-// mGetMesh2Capability none rw.main.none [0], ro.any.none
+// mGetMeshVersion none rw.main.none
//
// LLMeshRepoThread:
//
@@ -255,6 +252,9 @@
// mUnavailableQ mMutex rw.repo.none [0], ro.main.none [5], rw.main.mMutex
// mLoadedQ mMutex rw.repo.mMutex, ro.main.none [5], rw.main.mMutex
// mPendingLOD mMutex rw.repo.mMutex, rw.any.mMutex
+// mGetMeshCapability mMutex rw.main.mMutex, ro.repo.mMutex (was: [0])
+// mGetMesh2Capability mMutex rw.main.mMutex, ro.repo.mMutex (was: [0])
+// mGetMeshVersion mMutex rw.main.mMutex, ro.repo.mMutex
// mHttp* none rw.repo.none
//
// QA/Development Testing
@@ -304,7 +304,10 @@
// With this instrumentation enabled, a stall will appear
// under the 'Mesh Fetch' timer which will be either top-level
// or under 'Render' time.
+
+#ifndef LL_MESH_FASTTIMER_ENABLE
#define LL_MESH_FASTTIMER_ENABLE 1
+#endif
#if LL_MESH_FASTTIMER_ENABLE
static LLFastTimer::DeclareTimer FTM_MESH_FETCH("Mesh Fetch");
@@ -381,7 +384,6 @@ static S32 dump_num = 0;
std::string make_dump_name(std::string prefix, S32 num)
{
return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
-
}
void dump_llsd_to_file(const LLSD& content, std::string filename);
LLSD llsd_from_file(std::string filename);
@@ -740,7 +742,8 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriority(0)
+ mHttpPriority(0),
+ mGetMeshVersion(2)
{
mMutex = new LLMutex(NULL);
mHeaderMutex = new LLMutex(NULL);
@@ -1047,30 +1050,50 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
}
}
+// Mutex: must be holding mMutex when called
+void LLMeshRepoThread::setGetMeshCaps(const std::string & get_mesh1,
+ const std::string & get_mesh2,
+ int pref_version)
+{
+ mGetMeshCapability = get_mesh1;
+ mGetMesh2Capability = get_mesh2;
+ mGetMeshVersion = pref_version;
+}
+
+
// Constructs a Cap URL for the mesh. Prefers a GetMesh2 cap
// over a GetMesh cap.
//
-//static
-std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
+// Mutex: acquires mMutex
+void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * version)
{
- std::string http_url;
+ std::string res_url;
+ int res_version(2);
if (gAgent.getRegion())
{
- if (! gMeshRepo.mGetMesh2Capability.empty() && gMeshRepo.mGetMeshVersion > 1)
+ LLMutexLock lock(mMutex);
+
+ // Get a consistent pair of (cap string, version). The
+ // locking could be eliminated here without loss of safety
+ // by using a set of staging values in setGetMeshCaps().
+
+ if (! mGetMesh2Capability.empty() && mGetMeshVersion > 1)
{
- http_url = gMeshRepo.mGetMesh2Capability;
+ res_url = mGetMesh2Capability;
+ res_version = 2;
}
else
{
- http_url = gMeshRepo.mGetMeshCapability;
+ res_url = mGetMeshCapability;
+ res_version = 1;
}
}
- if (!http_url.empty())
+ if (! res_url.empty())
{
- http_url += "/?mesh_id=";
- http_url += mesh_id.asString().c_str();
+ res_url += "/?mesh_id=";
+ res_url += mesh_id.asString().c_str();
}
else
{
@@ -1078,7 +1101,8 @@ std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
<< mesh_id << ".mesh" << LL_ENDL;
}
- return http_url;
+ *url = res_url;
+ *version = res_version;
}
// Issue an HTTP GET request with byte range using the right
@@ -1200,8 +1224,10 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(gMeshRepo.mGetMeshVersion);
- std::string http_url = constructUrl(mesh_id);
+ int cap_version(2);
+ std::string http_url;
+ constructUrl(mesh_id, &http_url, &cap_version);
+
if (!http_url.empty())
{
LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size);
@@ -1293,8 +1319,10 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(gMeshRepo.mGetMeshVersion);
- std::string http_url = constructUrl(mesh_id);
+ int cap_version(2);
+ std::string http_url;
+ constructUrl(mesh_id, &http_url, &cap_version);
+
if (!http_url.empty())
{
LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size);
@@ -1384,8 +1412,10 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(gMeshRepo.mGetMeshVersion);
- std::string http_url = constructUrl(mesh_id);
+ int cap_version(2);
+ std::string http_url;
+ constructUrl(mesh_id, &http_url, &cap_version);
+
if (!http_url.empty())
{
LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size);
@@ -1477,8 +1507,10 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
//either cache entry doesn't exist or is corrupt, request header from simulator
bool retval = true;
- int cap_version(gMeshRepo.mGetMeshVersion);
- std::string http_url = constructUrl(mesh_params.getSculptID());
+ int cap_version(2);
+ std::string http_url;
+ constructUrl(mesh_params.getSculptID(), &http_url, &cap_version);
+
if (!http_url.empty())
{
//grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits
@@ -1563,8 +1595,10 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(gMeshRepo.mGetMeshVersion);
- std::string http_url = constructUrl(mesh_id);
+ int cap_version(2);
+ std::string http_url;
+ constructUrl(mesh_id, &http_url, &cap_version);
+
if (!http_url.empty())
{
LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size);
@@ -1812,7 +1846,6 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
return true;
}
-
LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, const std::string & upload_url, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer,
@@ -3249,15 +3282,15 @@ void LLMeshRepository::notifyLoadedMeshes()
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
{
- const bool use_v1(gSavedSettings.getBOOL("MeshUseGetMesh1"));
-
region_name = gAgent.getRegion()->getName();
- mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh");
- mGetMesh2Capability = gAgent.getRegion()->getCapability("GetMesh2");
- mGetMeshVersion = (mGetMesh2Capability.empty() || use_v1) ? 1 : 2;
+ const bool use_v1(gSavedSettings.getBOOL("MeshUseGetMesh1"));
+ const std::string mesh1(gAgent.getRegion()->getCapability("GetMesh"));
+ const std::string mesh2(gAgent.getRegion()->getCapability("GetMesh2"));
+ mGetMeshVersion = (mesh2.empty() || use_v1) ? 1 : 2;
+ mThread->setGetMeshCaps(mesh1, mesh2, mGetMeshVersion);
LL_DEBUGS(LOG_MESH) << "Retrieving caps for region '" << region_name
- << "', GetMesh2: " << mGetMesh2Capability
- << ", GetMesh: " << mGetMeshCapability
+ << "', GetMesh2: " << mesh2
+ << ", GetMesh: " << mesh1
<< ", using version: " << mGetMeshVersion
<< LL_ENDL;
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index e09f39f7a8..9d8b102110 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -333,7 +333,9 @@ public:
typedef std::set<LLCore::HttpHandler *> http_request_set;
http_request_set mHttpRequestSet; // Outstanding HTTP requests
- static std::string constructUrl(LLUUID mesh_id);
+ std::string mGetMeshCapability;
+ std::string mGetMesh2Capability;
+ int mGetMeshVersion;
LLMeshRepoThread();
~LLMeshRepoThread();
@@ -376,6 +378,17 @@ public:
static void incActiveHeaderRequests();
static void decActiveHeaderRequests();
+ // Set the caps strings and preferred version for constructing
+ // mesh fetch URLs.
+ //
+ // Mutex: must be holding mMutex when called
+ void setGetMeshCaps(const std::string & get_mesh1,
+ const std::string & get_mesh2,
+ int pref_version);
+
+ // Mutex: acquires mMutex
+ void constructUrl(LLUUID mesh_id, std::string * url, int * version);
+
private:
// Issue a GET request to a URL with 'Range' header using
// the correct policy class and other attributes. If an invalid
@@ -613,9 +626,7 @@ public:
void uploadError(LLSD& args);
void updateInventory(inventory_data data);
- std::string mGetMeshCapability;
- std::string mGetMesh2Capability;
- int mGetMeshVersion;
+ int mGetMeshVersion; // Shadows value in LLMeshRepoThread
};
extern LLMeshRepository gMeshRepo;