summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmeshrepository.cpp')
-rwxr-xr-xindra/newview/llmeshrepository.cpp134
1 files changed, 89 insertions, 45 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 7146c7f4f5..97d6c57a78 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -155,20 +155,26 @@
//
// So, in addition to documentation, take this as a to-do/review
// list and see if you can improve things. For porters to non-x86
-// architectures, including amd64, the weaker memory models will
-// make these platforms probabilistically more susceptible to hitting
-// race conditions. True here and in other multi-thread code such
-// as texture fetching.
+// architectures, the weaker memory models will make these platforms
+// probabilistically more susceptible to hitting race conditions.
+// True here and in other multi-thread code such as texture fetching.
+// (Strong memory models make weak programmers. Weak memory models
+// make strong programmers. Ref: arm, ppc, mips, alpha)
//
// LLMeshRepository:
//
// sBytesReceived
+// sMeshRequestCount
// sHTTPRequestCount
+// sHTTPLargeRequestCount
// sHTTPRetryCount
+// sHTTPErrorCount
// sLODPending
// sLODProcessing
// sCacheBytesRead
// sCacheBytesWritten
+// sCacheReads
+// sCacheWrites
// mLoadingMeshes none rw.main.none, rw.main.mMeshMutex [4]
// mSkinMap none rw.main.none
// mDecompositionMap none rw.main.none
@@ -246,13 +252,19 @@ const long LARGE_MESH_XFER_TIMEOUT = 600L; // Seconds to complete xfer, large
const S32 MAX_MESH_VERSION = 999;
U32 LLMeshRepository::sBytesReceived = 0;
+U32 LLMeshRepository::sMeshRequestCount = 0;
U32 LLMeshRepository::sHTTPRequestCount = 0;
+U32 LLMeshRepository::sHTTPLargeRequestCount = 0;
U32 LLMeshRepository::sHTTPRetryCount = 0;
+U32 LLMeshRepository::sHTTPErrorCount = 0;
U32 LLMeshRepository::sLODProcessing = 0;
U32 LLMeshRepository::sLODPending = 0;
U32 LLMeshRepository::sCacheBytesRead = 0;
U32 LLMeshRepository::sCacheBytesWritten = 0;
+U32 LLMeshRepository::sCacheReads = 0;
+U32 LLMeshRepository::sCacheWrites = 0;
+
LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0, true); // true -> gather cpu metrics
@@ -366,6 +378,7 @@ volatile S32 LLMeshRepoThread::sActiveLODRequests = 0;
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
S32 LLMeshRepoThread::sRequestLowWater = REQUEST_LOW_WATER_MIN;
S32 LLMeshRepoThread::sRequestHighWater = REQUEST_HIGH_WATER_MIN;
+S32 LLMeshRepoThread::sRequestWaterLevel = 0;
// Base handler class for all mesh users of llcorehttp.
// This is roughly equivalent to a Responder class in
@@ -619,9 +632,7 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriority(0),
- mHttpGetCount(0U),
- mHttpLargeGetCount(0U)
+ mHttpPriority(0)
{
mMutex = new LLMutex(NULL);
mHeaderMutex = new LLMutex(NULL);
@@ -641,8 +652,8 @@ LLMeshRepoThread::LLMeshRepoThread()
LLMeshRepoThread::~LLMeshRepoThread()
{
- LL_INFOS(LOG_MESH) << "Small GETs issued: " << mHttpGetCount
- << ", Large GETs issued: " << mHttpLargeGetCount
+ LL_INFOS(LOG_MESH) << "Small GETs issued: " << LLMeshRepository::sHTTPRequestCount
+ << ", Large GETs issued: " << LLMeshRepository::sHTTPLargeRequestCount
<< LL_ENDL;
for (http_request_set::iterator iter(mHttpRequestSet.begin());
@@ -700,7 +711,8 @@ void LLMeshRepoThread::run()
if (! LLApp::isQuitting())
{
// NOTE: order of queue processing intentionally favors LOD requests over header requests
-
+
+ sRequestWaterLevel = mHttpRequestSet.size();
while (!mLODReqQ.empty() && mHttpRequestSet.size() < sRequestHighWater)
{
if (! mMutex)
@@ -743,19 +755,26 @@ void LLMeshRepoThread::run()
// list, we scan the entire thing. This gets us through any requests
// which can be resolved in the cache. It also keeps the request
// set somewhat fresher otherwise items at the end of the set
- // order will lose. Keep to the throttle enforcement and pay
- // attention to the highwater level (enforced in each fetchXXX()
- // method).
+ // order will lose.
if (! mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
{
// *FIXME: this really does need a lock as do the following ones
std::set<LLUUID> incomplete;
for (std::set<LLUUID>::iterator iter = mSkinRequests.begin(); iter != mSkinRequests.end(); ++iter)
{
- LLUUID mesh_id = *iter;
- if (!fetchMeshSkinInfo(mesh_id))
+ if (mHttpRequestSet.size() < sRequestHighWater)
+ {
+ LLUUID mesh_id = *iter;
+ if (!fetchMeshSkinInfo(mesh_id))
+ {
+ incomplete.insert(mesh_id);
+ }
+ }
+ else
{
- incomplete.insert(mesh_id);
+ // Hit high-water mark, copy remaining to incomplete.
+ incomplete.insert(iter, mSkinRequests.end());
+ break;
}
}
mSkinRequests.swap(incomplete);
@@ -766,10 +785,19 @@ void LLMeshRepoThread::run()
std::set<LLUUID> incomplete;
for (std::set<LLUUID>::iterator iter = mDecompositionRequests.begin(); iter != mDecompositionRequests.end(); ++iter)
{
- LLUUID mesh_id = *iter;
- if (!fetchMeshDecomposition(mesh_id))
+ if (mHttpRequestSet.size() < sRequestHighWater)
{
- incomplete.insert(mesh_id);
+ LLUUID mesh_id = *iter;
+ if (!fetchMeshDecomposition(mesh_id))
+ {
+ incomplete.insert(mesh_id);
+ }
+ }
+ else
+ {
+ // Hit high-water mark, copy remaining to incomplete.
+ incomplete.insert(iter, mDecompositionRequests.end());
+ break;
}
}
mDecompositionRequests.swap(incomplete);
@@ -780,10 +808,19 @@ void LLMeshRepoThread::run()
std::set<LLUUID> incomplete;
for (std::set<LLUUID>::iterator iter = mPhysicsShapeRequests.begin(); iter != mPhysicsShapeRequests.end(); ++iter)
{
- LLUUID mesh_id = *iter;
- if (!fetchMeshPhysicsShape(mesh_id))
+ if (mHttpRequestSet.size() < sRequestHighWater)
+ {
+ LLUUID mesh_id = *iter;
+ if (!fetchMeshPhysicsShape(mesh_id))
+ {
+ incomplete.insert(mesh_id);
+ }
+ }
+ else
{
- incomplete.insert(mesh_id);
+ // Hit high-water mark, copy remaining to incomplete.
+ incomplete.insert(iter, mPhysicsShapeRequests.end());
+ break;
}
}
mPhysicsShapeRequests.swap(incomplete);
@@ -926,7 +963,10 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c
mHttpOptions,
mHttpHeaders,
handler);
- ++mHttpGetCount;
+ if (LLCORE_HTTP_HANDLE_INVALID != handle)
+ {
+ ++LLMeshRepository::sHTTPRequestCount;
+ }
}
else
{
@@ -938,7 +978,10 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c
mHttpLargeOptions,
mHttpHeaders,
handler);
- ++mHttpLargeGetCount;
+ if (LLCORE_HTTP_HANDLE_INVALID != handle)
+ {
+ ++LLMeshRepository::sHTTPLargeRequestCount;
+ }
}
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
@@ -965,7 +1008,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
return false;
}
- bool ret = true ;
+ ++LLMeshRepository::sMeshRequestCount;
+ bool ret = true;
U32 header_size = mMeshHeaderSize[mesh_id];
if (header_size > 0)
@@ -983,6 +1027,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesRead += size;
+ ++LLMeshRepository::sCacheReads;
file.seek(offset);
U8* buffer = new U8[size];
file.read(buffer, size);
@@ -1007,10 +1052,6 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- if (mHttpRequestSet.size() >= sRequestHighWater)
- {
- return false;
- }
int cap_version(gMeshRepo.mGetMeshVersion);
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
@@ -1025,12 +1066,12 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
<< LL_ENDL;
delete handler;
ret = false;
+
}
else
{
handler->mHttpHandle = handle;
mHttpRequestSet.insert(handler);
- ++LLMeshRepository::sHTTPRequestCount;
}
}
}
@@ -1059,8 +1100,9 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
return false;
}
+ ++LLMeshRepository::sMeshRequestCount;
U32 header_size = mMeshHeaderSize[mesh_id];
- bool ret = true ;
+ bool ret = true;
if (header_size > 0)
{
@@ -1077,6 +1119,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesRead += size;
+ ++LLMeshRepository::sCacheReads;
file.seek(offset);
U8* buffer = new U8[size];
@@ -1102,10 +1145,6 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- if (mHttpRequestSet.size() >= sRequestHighWater)
- {
- return false;
- }
int cap_version(gMeshRepo.mGetMeshVersion);
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
@@ -1125,7 +1164,6 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
{
handler->mHttpHandle = handle;
mHttpRequestSet.insert(handler);
- ++LLMeshRepository::sHTTPRequestCount;
}
}
}
@@ -1154,8 +1192,9 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
return false;
}
+ ++LLMeshRepository::sMeshRequestCount;
U32 header_size = mMeshHeaderSize[mesh_id];
- bool ret = true ;
+ bool ret = true;
if (header_size > 0)
{
@@ -1172,6 +1211,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesRead += size;
+ ++LLMeshRepository::sCacheReads;
file.seek(offset);
U8* buffer = new U8[size];
file.read(buffer, size);
@@ -1196,10 +1236,6 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- if (mHttpRequestSet.size() >= sRequestHighWater)
- {
- return false;
- }
int cap_version(gMeshRepo.mGetMeshVersion);
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
@@ -1219,7 +1255,6 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
{
handler->mHttpHandle = handle;
mHttpRequestSet.insert(handler);
- ++LLMeshRepository::sHTTPRequestCount;
}
}
}
@@ -1268,6 +1303,8 @@ void LLMeshRepoThread::decActiveHeaderRequests()
//return false if failed to get header
bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
{
+ ++LLMeshRepository::sMeshRequestCount;
+
{
//look for mesh in asset in vfs
LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH);
@@ -1280,6 +1317,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
U8 buffer[MESH_HEADER_SIZE];
S32 bytes = llmin(size, MESH_HEADER_SIZE);
LLMeshRepository::sCacheBytesRead += bytes;
+ ++LLMeshRepository::sCacheReads;
file.read(buffer, bytes);
if (headerReceived(mesh_params, buffer, bytes))
{
@@ -1314,7 +1352,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
{
handler->mHttpHandle = handle;
mHttpRequestSet.insert(handler);
- ++LLMeshRepository::sHTTPRequestCount;
}
}
@@ -1331,6 +1368,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
mHeaderMutex->lock();
+ ++LLMeshRepository::sMeshRequestCount;
bool retval = true;
LLUUID mesh_id = mesh_params.getSculptID();
@@ -1352,6 +1390,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesRead += size;
+ ++LLMeshRepository::sCacheReads;
file.seek(offset);
U8* buffer = new U8[size];
file.read(buffer, size);
@@ -1395,7 +1434,6 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
{
handler->mHttpHandle = handle;
mHttpRequestSet.insert(handler);
- ++LLMeshRepository::sHTTPRequestCount;
}
}
else
@@ -2364,6 +2402,7 @@ void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespo
if (! status)
{
processFailure(status);
+ ++LLMeshRepository::sHTTPErrorCount;
}
else
{
@@ -2484,6 +2523,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32
if (file.getMaxSize() >= bytes || file.setMaxSize(bytes))
{
LLMeshRepository::sCacheBytesWritten += data_size;
+ ++LLMeshRepository::sCacheWrites;
file.write(data, data_size);
@@ -2556,6 +2596,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * body, U8 * data, S32 da
file.seek(offset);
file.write(data, size);
LLMeshRepository::sCacheBytesWritten += size;
+ ++LLMeshRepository::sCacheWrites;
}
}
// *TODO: Mark mesh unavailable on error
@@ -2601,6 +2642,7 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * body, U8 * data, S
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesWritten += size;
+ ++LLMeshRepository::sCacheWrites;
file.seek(offset);
file.write(data, size);
}
@@ -2648,6 +2690,7 @@ void LLMeshDecompositionHandler::processData(LLCore::BufferArray * body, U8 * da
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesWritten += size;
+ ++LLMeshRepository::sCacheWrites;
file.seek(offset);
file.write(data, size);
}
@@ -2695,6 +2738,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * body, U8 * dat
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesWritten += size;
+ ++LLMeshRepository::sCacheWrites;
file.seek(offset);
file.write(data, size);
}
@@ -4204,7 +4248,7 @@ void LLMeshRepository::metricsUpdate()
LLSD metrics;
metrics["reason"] = "Mesh Download Quiescent";
- metrics["scope"] = "Login";
+ metrics["scope"] = metrics_teleport_start_count > 1 ? "Teleport" : "Login";
metrics["start"] = started;
metrics["stop"] = stopped;
metrics["fetches"] = LLSD::Integer(total_count);