summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llappviewer.cpp21
-rw-r--r--indra/newview/llmeshrepository.cpp147
-rw-r--r--indra/newview/llmeshrepository.h13
-rw-r--r--indra/newview/lltexturefetch.cpp87
-rw-r--r--indra/newview/lltexturefetch.h2
-rw-r--r--indra/newview/llviewerassetstats.cpp398
-rw-r--r--indra/newview/llviewerassetstats.h59
-rw-r--r--indra/newview/llviewerassetstorage.cpp701
-rw-r--r--indra/newview/llviewerassetstorage.h25
-rw-r--r--indra/newview/llviewerregion.cpp14
-rw-r--r--indra/newview/llviewerregion.h4
-rw-r--r--indra/newview/llvoavatar.cpp3
-rw-r--r--indra/newview/tests/llviewerassetstats_test.cpp26
13 files changed, 727 insertions, 773 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f53ba01d37..cfdc752db4 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -844,12 +844,6 @@ bool LLAppViewer::init()
LLMachineID::init();
{
- // Viewer metrics initialization
- //static LLCachedControl<bool> metrics_submode(gSavedSettings,
- // "QAModeMetrics",
- // false,
- // "Enables QA features (logging, faster cycling) for metrics collector");
-
if (gSavedSettings.getBOOL("QAModeMetrics"))
{
app_metrics_qa_mode = true;
@@ -5919,23 +5913,14 @@ void LLAppViewer::metricsSend(bool enable_reporting)
{
std::string caps_url = regionp->getCapability("ViewerMetrics");
- if (gSavedSettings.getBOOL("QAModeMetrics"))
- {
- dump_sequential_xml("metric_asset_stats",gViewerAssetStats->asLLSD(true));
- }
-
- // Make a copy of the main stats to send into another thread.
- // Receiving thread takes ownership.
- LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStats));
- main_stats->stop();
-
+ LLSD sd = gViewerAssetStats->asLLSD(true);
+
// Send a report request into 'thread1' to get the rest of the data
// and provide some additional parameters while here.
LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
gAgentSessionID,
gAgentID,
- main_stats);
- main_stats = 0; // Ownership transferred
+ sd);
}
else
{
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 1a533dace7..a28ab499fd 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -343,10 +343,6 @@ LLMeshRepository gMeshRepo;
const S32 MESH_HEADER_SIZE = 4096; // Important: assumption is that headers fit in this space
-const S32 REQUEST_HIGH_WATER_MIN = 32; // Limits for GetMesh regions
-const S32 REQUEST_HIGH_WATER_MAX = 150; // Should remain under 2X throttle
-const S32 REQUEST_LOW_WATER_MIN = 16;
-const S32 REQUEST_LOW_WATER_MAX = 75;
const S32 REQUEST2_HIGH_WATER_MIN = 32; // Limits for GetMesh2 regions
const S32 REQUEST2_HIGH_WATER_MAX = 100;
@@ -808,10 +804,8 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpLargeOptions(),
mHttpHeaders(),
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriority(0),
- mGetMeshVersion(2)
+ mHttpPriority(0)
{
LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
@@ -828,7 +822,6 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_VND_LL_MESH);
mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH2);
- mHttpLegacyPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH1);
mHttpLargePolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_LARGE_MESH);
}
@@ -1103,13 +1096,9 @@ 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)
+void LLMeshRepoThread::setGetMeshCap(const std::string & mesh_cap)
{
- mGetMeshCapability = get_mesh1;
- mGetMesh2Capability = get_mesh2;
- mGetMeshVersion = pref_version;
+ mGetMeshCapability = mesh_cap;
}
@@ -1117,29 +1106,14 @@ void LLMeshRepoThread::setGetMeshCaps(const std::string & get_mesh1,
// over a GetMesh cap.
//
// Mutex: acquires mMutex
-void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * version)
+void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url)
{
std::string res_url;
- int res_version(2);
if (gAgent.getRegion())
{
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)
- {
- res_url = mGetMesh2Capability;
- res_version = 2;
- }
- else
- {
- res_url = mGetMeshCapability;
- res_version = 1;
- }
+ res_url = mGetMeshCapability;
}
if (! res_url.empty())
@@ -1149,19 +1123,15 @@ void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * ver
}
else
{
- LL_WARNS_ONCE(LOG_MESH) << "Current region does not have GetMesh capability! Cannot load "
+ LL_WARNS_ONCE(LOG_MESH) << "Current region does not have ViewerAsset capability! Cannot load "
<< mesh_id << ".mesh" << LL_ENDL;
}
*url = res_url;
- *version = res_version;
}
// Issue an HTTP GET request with byte range using the right
-// policy class. Large requests go to the large request class.
-// If the current region supports GetMesh2, we prefer that for
-// smaller requests otherwise we try to use the traditional
-// GetMesh capability and connection concurrency.
+// policy class.
//
// @return Valid handle or LLCORE_HTTP_HANDLE_INVALID.
// If the latter, actual status is found in
@@ -1169,7 +1139,7 @@ void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * ver
// next call to this method.
//
// Thread: repo
-LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int cap_version,
+LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
size_t offset, size_t len,
const LLCore::HttpHandler::ptr_t &handler)
{
@@ -1180,16 +1150,14 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c
if (len < LARGE_MESH_FETCH_THRESHOLD)
{
- handle = mHttpRequest->requestGetByteRange((2 == cap_version
- ? mHttpPolicyClass
- : mHttpLegacyPolicyClass),
- mHttpPriority,
- url,
- (disable_range_req ? size_t(0) : offset),
- (disable_range_req ? size_t(0) : len),
- mHttpOptions,
- mHttpHeaders,
- handler);
+ handle = mHttpRequest->requestGetByteRange( mHttpPolicyClass,
+ mHttpPriority,
+ url,
+ (disable_range_req ? size_t(0) : offset),
+ (disable_range_req ? size_t(0) : len),
+ mHttpOptions,
+ mHttpHeaders,
+ handler);
if (LLCORE_HTTP_HANDLE_INVALID != handle)
{
++LLMeshRepository::sHTTPRequestCount;
@@ -1279,14 +1247,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshSkinInfoHandler(mesh_id, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << mID
@@ -1372,14 +1339,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshDecompositionHandler(mesh_id, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << mID
@@ -1464,14 +1430,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshPhysicsShapeHandler(mesh_id, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for physics shape on mesh " << mID
@@ -1558,9 +1523,8 @@ 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(2);
std::string http_url;
- constructUrl(mesh_params.getSculptID(), &http_url, &cap_version);
+ constructUrl(mesh_params.getSculptID(), &http_url);
if (!http_url.empty())
{
@@ -1569,7 +1533,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
//NOTE -- this will break of headers ever exceed 4KB
LLMeshHandlerBase::ptr_t handler(new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, 0, MESH_HEADER_SIZE, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, 0, MESH_HEADER_SIZE, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for mesh header " << mID
@@ -1645,14 +1609,13 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshLODHandler(mesh_params, lod, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for LOD on mesh " << mID
@@ -3292,8 +3255,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3
LLMeshRepository::LLMeshRepository()
: mMeshMutex(NULL),
mMeshThreadCount(0),
- mThread(NULL),
- mGetMeshVersion(2)
+ mThread(NULL)
{
}
@@ -3476,35 +3438,21 @@ void LLMeshRepository::notifyLoadedMeshes()
{ //called from main thread
LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
- if (1 == mGetMeshVersion)
- {
- // Legacy GetMesh operation with high connection concurrency
- LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests");
- LLMeshRepoThread::sRequestHighWater = llclamp(2 * S32(LLMeshRepoThread::sMaxConcurrentRequests),
- REQUEST_HIGH_WATER_MIN,
- REQUEST_HIGH_WATER_MAX);
- LLMeshRepoThread::sRequestLowWater = llclamp(LLMeshRepoThread::sRequestHighWater / 2,
- REQUEST_LOW_WATER_MIN,
- REQUEST_LOW_WATER_MAX);
- }
- else
- {
- // GetMesh2 operation with keepalives, etc. With pipelining,
- // we'll increase this. See llappcorehttp and llcorehttp for
- // discussion on connection strategies.
- LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
- S32 scale(app_core_http.isPipelined(LLAppCoreHttp::AP_MESH2)
- ? (2 * LLAppCoreHttp::PIPELINING_DEPTH)
- : 5);
-
- LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("Mesh2MaxConcurrentRequests");
- LLMeshRepoThread::sRequestHighWater = llclamp(scale * S32(LLMeshRepoThread::sMaxConcurrentRequests),
- REQUEST2_HIGH_WATER_MIN,
- REQUEST2_HIGH_WATER_MAX);
- LLMeshRepoThread::sRequestLowWater = llclamp(LLMeshRepoThread::sRequestHighWater / 2,
- REQUEST2_LOW_WATER_MIN,
- REQUEST2_LOW_WATER_MAX);
- }
+ // GetMesh2 operation with keepalives, etc. With pipelining,
+ // we'll increase this. See llappcorehttp and llcorehttp for
+ // discussion on connection strategies.
+ LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+ S32 scale(app_core_http.isPipelined(LLAppCoreHttp::AP_MESH2)
+ ? (2 * LLAppCoreHttp::PIPELINING_DEPTH)
+ : 5);
+
+ LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("Mesh2MaxConcurrentRequests");
+ LLMeshRepoThread::sRequestHighWater = llclamp(scale * S32(LLMeshRepoThread::sMaxConcurrentRequests),
+ REQUEST2_HIGH_WATER_MIN,
+ REQUEST2_HIGH_WATER_MAX);
+ LLMeshRepoThread::sRequestLowWater = llclamp(LLMeshRepoThread::sRequestHighWater / 2,
+ REQUEST2_LOW_WATER_MIN,
+ REQUEST2_LOW_WATER_MAX);
//clean up completed upload threads
for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); )
@@ -3610,15 +3558,10 @@ void LLMeshRepository::notifyLoadedMeshes()
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
{
region_name = gAgent.getRegion()->getName();
- 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);
+ const std::string mesh_cap(gAgent.getRegion()->getViewerAssetUrl());
+ mThread->setGetMeshCap(mesh_cap);
LL_DEBUGS(LOG_MESH) << "Retrieving caps for region '" << region_name
- << "', GetMesh2: " << mesh2
- << ", GetMesh: " << mesh1
- << ", using version: " << mGetMeshVersion
+ << "', ViewerAsset cap: " << mesh_cap
<< LL_ENDL;
}
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 30f042845a..23af837f6f 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -279,7 +279,6 @@ public:
LLCore::HttpOptions::ptr_t mHttpLargeOptions;
LLCore::HttpHeaders::ptr_t mHttpHeaders;
LLCore::HttpRequest::policy_t mHttpPolicyClass;
- LLCore::HttpRequest::policy_t mHttpLegacyPolicyClass;
LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
LLCore::HttpRequest::priority_t mHttpPriority;
@@ -287,8 +286,6 @@ public:
http_request_set mHttpRequestSet; // Outstanding HTTP requests
std::string mGetMeshCapability;
- std::string mGetMesh2Capability;
- int mGetMeshVersion;
LLMeshRepoThread();
~LLMeshRepoThread();
@@ -335,12 +332,10 @@ public:
// 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);
+ void setGetMeshCap(const std::string & get_mesh);
// Mutex: acquires mMutex
- void constructUrl(LLUUID mesh_id, std::string * url, int * version);
+ void constructUrl(LLUUID mesh_id, std::string * url);
private:
// Issue a GET request to a URL with 'Range' header using
@@ -349,7 +344,7 @@ private:
// or dispose of handler.
//
// Threads: Repo thread only
- LLCore::HttpHandle getByteRange(const std::string & url, int cap_version,
+ LLCore::HttpHandle getByteRange(const std::string & url,
size_t offset, size_t len,
const LLCore::HttpHandler::ptr_t &handler);
};
@@ -585,8 +580,6 @@ public:
void uploadError(LLSD& args);
void updateInventory(inventory_data data);
-
- int mGetMeshVersion; // Shadows value in LLMeshRepoThread
};
extern LLMeshRepository gMeshRepo;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 07b3dc1aa4..09d7c2eb2d 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -30,8 +30,6 @@
#include <map>
#include <algorithm>
-#include "llstl.h"
-
#include "lltexturefetch.h"
#include "lldir.h"
@@ -485,7 +483,7 @@ private:
void recordTextureStart(bool is_http);
// Threads: Ttf
- void recordTextureDone(bool is_http);
+ void recordTextureDone(bool is_http, F64 byte_count);
void lockWorkMutex() { mWorkMutex.lock(); }
void unlockWorkMutex() { mWorkMutex.unlock(); }
@@ -824,7 +822,7 @@ public:
TFReqSendMetrics(const std::string & caps_url,
const LLUUID & session_id,
const LLUUID & agent_id,
- LLViewerAssetStats * main_stats);
+ LLSD& stats_sd);
TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined
virtual ~TFReqSendMetrics();
@@ -835,7 +833,7 @@ public:
const std::string mCapsURL;
const LLUUID mSessionID;
const LLUUID mAgentID;
- LLViewerAssetStats * mMainStats;
+ LLSD mStatsSD;
private:
LLCore::HttpHandler::ptr_t mHandler;
@@ -1351,7 +1349,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (region)
{
- std::string http_url = region->getHttpUrl() ;
+ std::string http_url = region->getViewerAssetUrl();
if (!http_url.empty())
{
if (mFTType != FTT_DEFAULT)
@@ -1426,6 +1424,13 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
if (processSimulatorPackets())
{
+ // Capture some measure of total size for metrics
+ F64 byte_count = 0;
+ for (S32 i=mFirstPacket; i<=mLastPacket; i++)
+ {
+ byte_count += mPackets[i]->mSize;
+ }
+
LL_DEBUGS(LOG_TXT) << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL;
mFetcher->removeFromNetworkQueue(this, false);
if (mFormattedImage.isNull() || !mFormattedImage->getDataSize())
@@ -1443,7 +1448,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setState(DECODE_IMAGE);
mWriteToCacheState = SHOULD_WRITE;
- recordTextureDone(false);
+
+ recordTextureDone(false, byte_count);
}
else
{
@@ -2093,7 +2099,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
mFetcher->removeFromHTTPQueue(mID, data_size);
- recordTextureDone(true);
+ recordTextureDone(true, data_size);
} // -Mw
@@ -2493,14 +2499,15 @@ void LLTextureFetchWorker::recordTextureStart(bool is_http)
// Threads: Ttf
-void LLTextureFetchWorker::recordTextureDone(bool is_http)
+void LLTextureFetchWorker::recordTextureDone(bool is_http, F64 byte_count)
{
if (mMetricsStartTime.value())
{
LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_TEXTURE,
- is_http,
- LLImageBase::TYPE_AVATAR_BAKE == mType,
- LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime);
+ is_http,
+ LLImageBase::TYPE_AVATAR_BAKE == mType,
+ LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime,
+ byte_count);
mMetricsStartTime = (U32Seconds)0;
}
LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE,
@@ -3863,9 +3870,9 @@ void LLTextureFetch::commandSetRegion(U64 region_handle)
void LLTextureFetch::commandSendMetrics(const std::string & caps_url,
const LLUUID & session_id,
const LLUUID & agent_id,
- LLViewerAssetStats * main_stats)
+ LLSD& stats_sd)
{
- TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, main_stats);
+ TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, stats_sd);
cmdEnqueue(req);
}
@@ -3974,22 +3981,20 @@ TFReqSetRegion::doWork(LLTextureFetch *)
}
TFReqSendMetrics::TFReqSendMetrics(const std::string & caps_url,
- const LLUUID & session_id,
- const LLUUID & agent_id,
- LLViewerAssetStats * main_stats):
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLSD& stats_sd):
LLTextureFetch::TFRequest(),
mCapsURL(caps_url),
mSessionID(session_id),
mAgentID(agent_id),
- mMainStats(main_stats),
+ mStatsSD(stats_sd),
mHandler(new AssetReportHandler)
{}
TFReqSendMetrics::~TFReqSendMetrics()
{
- delete mMainStats;
- mMainStats = 0;
}
@@ -4010,26 +4015,19 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
static volatile bool reporting_started(false);
static volatile S32 report_sequence(0);
- // We've taken over ownership of the stats copy at this
- // point. Get a working reference to it for merging here
- // but leave it in 'this'. Destructor will rid us of it.
- LLViewerAssetStats & main_stats = *mMainStats;
-
- LLViewerAssetStats::AssetStats stats;
- main_stats.getStats(stats, true);
- //LLSD merged_llsd = main_stats.asLLSD();
+ // In mStatsSD, we have a copy we own of the LLSD representation
+ // of the asset stats. Add some additional fields and ship it off.
+ static const S32 metrics_data_version = 2;
+
bool initial_report = !reporting_started;
- stats.session_id = mSessionID;
- stats.agent_id = mAgentID;
- stats.message = "ViewerAssetMetrics";
- stats.sequence = static_cast<bool>(report_sequence);
- stats.initial = initial_report;
- stats.break_ = static_cast<bool>(LLTextureFetch::svMetricsDataBreak);
-
- LLSD sd;
- LLParamSDParser parser;
- parser.writeSD(sd, stats);
+ mStatsSD["session_id"] = mSessionID;
+ mStatsSD["agent_id"] = mAgentID;
+ mStatsSD["message"] = "ViewerAssetMetrics";
+ mStatsSD["sequence"] = report_sequence;
+ mStatsSD["initial"] = initial_report;
+ mStatsSD["version"] = metrics_data_version;
+ mStatsSD["break"] = static_cast<bool>(LLTextureFetch::svMetricsDataBreak);
// Update sequence number
if (S32_MAX == ++report_sequence)
@@ -4040,8 +4038,13 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
// Limit the size of the stats report if necessary.
- sd["truncated"] = truncate_viewer_metrics(10, sd);
+ mStatsSD["truncated"] = truncate_viewer_metrics(10, mStatsSD);
+ if (gSavedSettings.getBOOL("QAModeMetrics"))
+ {
+ dump_sequential_xml("metric_asset_stats",mStatsSD);
+ }
+
if (! mCapsURL.empty())
{
// Don't care about handle, this is a fire-and-forget operation.
@@ -4049,7 +4052,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
fetcher->getMetricsPolicyClass(),
report_priority,
mCapsURL,
- sd,
+ mStatsSD,
LLCore::HttpOptions::ptr_t(),
fetcher->getMetricsHeaders(),
mHandler);
@@ -4063,7 +4066,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
// In QA mode, Metrics submode, log the result for ease of testing
if (fetcher->isQAMode())
{
- LL_INFOS(LOG_TXT) << ll_pretty_print_sd(sd) << LL_ENDL;
+ LL_INFOS(LOG_TXT) << "ViewerAssetMetrics as submitted\n" << ll_pretty_print_sd(mStatsSD) << LL_ENDL;
}
return true;
@@ -4580,7 +4583,7 @@ void LLTextureFetchDebugger::debugHTTP()
return;
}
- mHTTPUrl = region->getHttpUrl();
+ mHTTPUrl = region->getViewerAssetUrl();
if (mHTTPUrl.empty())
{
LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << LL_ENDL;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 072e6a3307..cfa312ccd9 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -160,7 +160,7 @@ public:
void commandSendMetrics(const std::string & caps_url,
const LLUUID & session_id,
const LLUUID & agent_id,
- LLViewerAssetStats * main_stats);
+ LLSD& stats_sd);
// Threads: T*
void commandDataBreak();
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index 54ac29723f..14e05fd440 100644
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -80,6 +80,47 @@
*
*/
+namespace LLTrace
+{
+// This little bit of shimmery is to allow the creation of
+// default-constructed stat and event handles so we can make arrays of
+// the things.
+
+// The only sensible way to use this function is to immediately make a
+// copy of the contents, since it always returns the same pointer.
+const char *makeNewAutoName()
+{
+ static char name[64];
+ static S32 auto_namer_number = 0;
+ snprintf(name,64,"auto_name_%d",auto_namer_number);
+ auto_namer_number++;
+ return name;
+}
+
+template <typename T = F64>
+class DCCountStatHandle:
+ public CountStatHandle<T>
+{
+public:
+ DCCountStatHandle(const char *name = makeNewAutoName(), const char *description=NULL):
+ CountStatHandle<T>(name,description)
+ {
+ }
+};
+
+template <typename T = F64>
+class DCEventStatHandle:
+ public EventStatHandle<T>
+{
+public:
+ DCEventStatHandle(const char *name = makeNewAutoName(), const char *description=NULL):
+ EventStatHandle<T>(name,description)
+ {
+ }
+};
+
+}
+
namespace LLViewerAssetStatsFF
{
static EViewerAssetCategories asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp)
@@ -90,176 +131,45 @@ namespace LLViewerAssetStatsFF
// - wearables (clothing, bodyparts) which directly affect
// user experiences when they log in
// - sounds
- // - gestures
+ // - gestures, including animations
// - everything else.
//
- llassert_always(50 == LLViewerAssetType::AT_COUNT);
- // Multiple asset definitions are floating around so this requires some
- // maintenance and attention.
- static const EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] =
- {
- EVACTextureTempHTTPGet, // (0) AT_TEXTURE
- EVACSoundUDPGet, // AT_SOUND
- EVACOtherGet, // AT_CALLINGCARD
- EVACOtherGet, // AT_LANDMARK
- EVACOtherGet, // AT_SCRIPT
- EVACWearableUDPGet, // AT_CLOTHING
- EVACOtherGet, // AT_OBJECT
- EVACOtherGet, // AT_NOTECARD
- EVACOtherGet, // AT_CATEGORY
- EVACOtherGet, // AT_ROOT_CATEGORY
- EVACOtherGet, // (10) AT_LSL_TEXT
- EVACOtherGet, // AT_LSL_BYTECODE
- EVACOtherGet, // AT_TEXTURE_TGA
- EVACWearableUDPGet, // AT_BODYPART
- EVACOtherGet, // AT_TRASH
- EVACOtherGet, // AT_SNAPSHOT_CATEGORY
- EVACOtherGet, // AT_LOST_AND_FOUND
- EVACSoundUDPGet, // AT_SOUND_WAV
- EVACOtherGet, // AT_IMAGE_TGA
- EVACOtherGet, // AT_IMAGE_JPEG
- EVACGestureUDPGet, // (20) AT_ANIMATION
- EVACGestureUDPGet, // AT_GESTURE
- EVACOtherGet, // AT_SIMSTATE
- EVACOtherGet, // AT_FAVORITE
- EVACOtherGet, // AT_LINK
- EVACOtherGet, // AT_LINK_FOLDER
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, // (30)
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, // (40)
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, // AT_MESH
- // (50)
- };
-
- if (at < 0 || at >= LLViewerAssetType::AT_COUNT)
- {
- return EVACOtherGet;
- }
- EViewerAssetCategories ret(asset_to_bin_map[at]);
- if (EVACTextureTempHTTPGet == ret)
- {
- // Indexed with [is_temp][with_http]
- static const EViewerAssetCategories texture_bin_map[2][2] =
- {
- {
- EVACTextureNonTempUDPGet,
- EVACTextureNonTempHTTPGet,
- },
- {
- EVACTextureTempUDPGet,
- EVACTextureTempHTTPGet,
- }
- };
-
- ret = texture_bin_map[is_temp][with_http];
- }
+ EViewerAssetCategories ret;
+ switch (at)
+ {
+ case LLAssetType::AT_TEXTURE:
+ if (is_temp)
+ ret = with_http ? EVACTextureTempHTTPGet : EVACTextureTempUDPGet;
+ else
+ ret = with_http ? EVACTextureNonTempHTTPGet : EVACTextureNonTempUDPGet;
+ break;
+ case LLAssetType::AT_SOUND:
+ case LLAssetType::AT_SOUND_WAV:
+ ret = with_http ? EVACSoundHTTPGet : EVACSoundUDPGet;
+ break;
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ ret = with_http ? EVACWearableHTTPGet : EVACWearableUDPGet;
+ break;
+ case LLAssetType::AT_ANIMATION:
+ case LLAssetType::AT_GESTURE:
+ ret = with_http ? EVACGestureHTTPGet : EVACGestureUDPGet;
+ break;
+ case LLAssetType::AT_LANDMARK:
+ ret = with_http ? EVACLandmarkHTTPGet : EVACLandmarkUDPGet;
+ break;
+ default:
+ ret = with_http ? EVACOtherHTTPGet : EVACOtherUDPGet;
+ break;
+ }
return ret;
}
- static LLTrace::CountStatHandle<> sEnqueueAssetRequestsTempTextureHTTP ("enqueuedassetrequeststemptexturehttp",
- "Number of temporary texture asset http requests enqueued"),
- sEnqueueAssetRequestsTempTextureUDP ("enqueuedassetrequeststemptextureudp",
- "Number of temporary texture asset udp requests enqueued"),
- sEnqueueAssetRequestsNonTempTextureHTTP("enqueuedassetrequestsnontemptexturehttp",
- "Number of texture asset http requests enqueued"),
- sEnqueueAssetRequestsNonTempTextureUDP ("enqueuedassetrequestsnontemptextureudp",
- "Number of texture asset udp requests enqueued"),
- sEnqueuedAssetRequestsWearableUdp ("enqueuedassetrequestswearableudp",
- "Number of wearable asset requests enqueued"),
- sEnqueuedAssetRequestsSoundUdp ("enqueuedassetrequestssoundudp",
- "Number of sound asset requests enqueued"),
- sEnqueuedAssetRequestsGestureUdp ("enqueuedassetrequestsgestureudp",
- "Number of gesture asset requests enqueued"),
- sEnqueuedAssetRequestsOther ("enqueuedassetrequestsother",
- "Number of other asset requests enqueued");
-
- static LLTrace::CountStatHandle<>* sEnqueued[EVACCount] = {
- &sEnqueueAssetRequestsTempTextureHTTP,
- &sEnqueueAssetRequestsTempTextureUDP,
- &sEnqueueAssetRequestsNonTempTextureHTTP,
- &sEnqueueAssetRequestsNonTempTextureUDP,
- &sEnqueuedAssetRequestsWearableUdp,
- &sEnqueuedAssetRequestsSoundUdp,
- &sEnqueuedAssetRequestsGestureUdp,
- &sEnqueuedAssetRequestsOther
- };
-
- static LLTrace::CountStatHandle<> sDequeueAssetRequestsTempTextureHTTP ("dequeuedassetrequeststemptexturehttp",
- "Number of temporary texture asset http requests dequeued"),
- sDequeueAssetRequestsTempTextureUDP ("dequeuedassetrequeststemptextureudp",
- "Number of temporary texture asset udp requests dequeued"),
- sDequeueAssetRequestsNonTempTextureHTTP("dequeuedassetrequestsnontemptexturehttp",
- "Number of texture asset http requests dequeued"),
- sDequeueAssetRequestsNonTempTextureUDP ("dequeuedassetrequestsnontemptextureudp",
- "Number of texture asset udp requests dequeued"),
- sDequeuedAssetRequestsWearableUdp ("dequeuedassetrequestswearableudp",
- "Number of wearable asset requests dequeued"),
- sDequeuedAssetRequestsSoundUdp ("dequeuedassetrequestssoundudp",
- "Number of sound asset requests dequeued"),
- sDequeuedAssetRequestsGestureUdp ("dequeuedassetrequestsgestureudp",
- "Number of gesture asset requests dequeued"),
- sDequeuedAssetRequestsOther ("dequeuedassetrequestsother",
- "Number of other asset requests dequeued");
-
- static LLTrace::CountStatHandle<>* sDequeued[EVACCount] = {
- &sDequeueAssetRequestsTempTextureHTTP,
- &sDequeueAssetRequestsTempTextureUDP,
- &sDequeueAssetRequestsNonTempTextureHTTP,
- &sDequeueAssetRequestsNonTempTextureUDP,
- &sDequeuedAssetRequestsWearableUdp,
- &sDequeuedAssetRequestsSoundUdp,
- &sDequeuedAssetRequestsGestureUdp,
- &sDequeuedAssetRequestsOther
- };
-
- static LLTrace::EventStatHandle<F64Seconds > sResponseAssetRequestsTempTextureHTTP ("assetresponsetimestemptexturehttp",
- "Time spent responding to temporary texture asset http requests"),
- sResponseAssetRequestsTempTextureUDP ("assetresponsetimestemptextureudp",
- "Time spent responding to temporary texture asset udp requests"),
- sResponseAssetRequestsNonTempTextureHTTP("assetresponsetimesnontemptexturehttp",
- "Time spent responding to texture asset http requests"),
- sResponseAssetRequestsNonTempTextureUDP ("assetresponsetimesnontemptextureudp",
- "Time spent responding to texture asset udp requests"),
- sResponsedAssetRequestsWearableUdp ("assetresponsetimeswearableudp",
- "Time spent responding to wearable asset requests"),
- sResponsedAssetRequestsSoundUdp ("assetresponsetimessoundudp",
- "Time spent responding to sound asset requests"),
- sResponsedAssetRequestsGestureUdp ("assetresponsetimesgestureudp",
- "Time spent responding to gesture asset requests"),
- sResponsedAssetRequestsOther ("assetresponsetimesother",
- "Time spent responding to other asset requests");
-
- static LLTrace::EventStatHandle<F64Seconds >* sResponse[EVACCount] = {
- &sResponseAssetRequestsTempTextureHTTP,
- &sResponseAssetRequestsTempTextureUDP,
- &sResponseAssetRequestsNonTempTextureHTTP,
- &sResponseAssetRequestsNonTempTextureUDP,
- &sResponsedAssetRequestsWearableUdp,
- &sResponsedAssetRequestsSoundUdp,
- &sResponsedAssetRequestsGestureUdp,
- &sResponsedAssetRequestsOther
- };
+ static LLTrace::DCCountStatHandle<> sEnqueued[EVACCount];
+ static LLTrace::DCCountStatHandle<> sDequeued[EVACCount];
+ static LLTrace::DCEventStatHandle<> sBytesFetched[EVACCount];
+ static LLTrace::DCEventStatHandle<F64Seconds > sResponse[EVACCount];
}
// ------------------------------------------------------
@@ -353,6 +263,26 @@ void LLViewerAssetStats::setRegion(region_handle_t region_handle)
mRegionHandle = region_handle;
}
+template <typename T>
+void LLViewerAssetStats::getStat(LLTrace::Recording& rec, T& req, LLViewerAssetStatsFF::EViewerAssetCategories cat, bool compact_output)
+{
+ using namespace LLViewerAssetStatsFF;
+
+ if (!compact_output
+ || rec.getSampleCount(sEnqueued[cat])
+ || rec.getSampleCount(sDequeued[cat])
+ || rec.getSampleCount(sResponse[cat]))
+ {
+ req .enqueued(rec.getSampleCount(sEnqueued[cat]))
+ .dequeued(rec.getSampleCount(sDequeued[cat]))
+ .resp_count(rec.getSampleCount(sResponse[cat]))
+ .resp_min(rec.getMin(sResponse[cat]).value())
+ .resp_max(rec.getMax(sResponse[cat]).value())
+ .resp_mean(rec.getMean(sResponse[cat]).value())
+ .resp_mean_bytes(rec.getMean(sBytesFetched[cat]));
+ }
+}
+
void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
{
using namespace LLViewerAssetStatsFF;
@@ -365,108 +295,22 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
{
RegionStats& r = stats.regions.add();
LLTrace::Recording& rec = it->second;
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureTempHTTPGet])
- || rec.getSum(*sDequeued[EVACTextureTempHTTPGet])
- || rec.getSum(*sResponse[EVACTextureTempHTTPGet]).value())
- {
- r.get_texture_temp_http .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureTempHTTPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureTempHTTPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureTempHTTPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureTempHTTPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureTempHTTPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureTempHTTPGet]).value());
- }
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureTempUDPGet])
- || rec.getSum(*sDequeued[EVACTextureTempUDPGet])
- || rec.getSum(*sResponse[EVACTextureTempUDPGet]).value())
- {
- r.get_texture_temp_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureTempUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureTempUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureTempUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureTempUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureTempUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureTempUDPGet]).value());
- }
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureNonTempHTTPGet])
- || rec.getSum(*sDequeued[EVACTextureNonTempHTTPGet])
- || rec.getSum(*sResponse[EVACTextureNonTempHTTPGet]).value())
- {
- r.get_texture_non_temp_http .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureNonTempHTTPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureNonTempHTTPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureNonTempHTTPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureNonTempHTTPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureNonTempHTTPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureNonTempHTTPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureNonTempUDPGet])
- || rec.getSum(*sDequeued[EVACTextureNonTempUDPGet])
- || rec.getSum(*sResponse[EVACTextureNonTempUDPGet]).value())
- {
- r.get_texture_non_temp_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureNonTempUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureNonTempUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureNonTempUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureNonTempUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureNonTempUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureNonTempUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACWearableUDPGet])
- || rec.getSum(*sDequeued[EVACWearableUDPGet])
- || rec.getSum(*sResponse[EVACWearableUDPGet]).value())
- {
- r.get_wearable_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACWearableUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACWearableUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACWearableUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACWearableUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACWearableUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACWearableUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACSoundUDPGet])
- || rec.getSum(*sDequeued[EVACSoundUDPGet])
- || rec.getSum(*sResponse[EVACSoundUDPGet]).value())
- {
- r.get_sound_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACSoundUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACSoundUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACSoundUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACSoundUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACSoundUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACSoundUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACGestureUDPGet])
- || rec.getSum(*sDequeued[EVACGestureUDPGet])
- || rec.getSum(*sResponse[EVACGestureUDPGet]).value())
- {
- r.get_gesture_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACGestureUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACGestureUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACGestureUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACGestureUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACGestureUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACGestureUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACOtherGet])
- || rec.getSum(*sDequeued[EVACOtherGet])
- || rec.getSum(*sResponse[EVACOtherGet]).value())
- {
- r.get_other .enqueued((S32)rec.getSum(*sEnqueued[EVACOtherGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACOtherGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACOtherGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACOtherGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACOtherGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACOtherGet]).value());
- }
+ getStat(rec, r.get_texture_temp_http, EVACTextureTempHTTPGet, compact_output);
+ getStat(rec, r.get_texture_temp_udp, EVACTextureTempUDPGet, compact_output);
+ getStat(rec, r.get_texture_non_temp_http, EVACTextureNonTempHTTPGet, compact_output);
+ getStat(rec, r.get_texture_non_temp_udp, EVACTextureNonTempUDPGet, compact_output);
+ getStat(rec, r.get_wearable_http, EVACWearableHTTPGet, compact_output);
+ getStat(rec, r.get_wearable_udp, EVACWearableUDPGet, compact_output);
+ getStat(rec, r.get_sound_http, EVACSoundHTTPGet, compact_output);
+ getStat(rec, r.get_sound_udp, EVACSoundUDPGet, compact_output);
+ getStat(rec, r.get_gesture_http, EVACGestureHTTPGet, compact_output);
+ getStat(rec, r.get_gesture_udp, EVACGestureUDPGet, compact_output);
+ getStat(rec, r.get_landmark_http, EVACLandmarkHTTPGet, compact_output);
+ getStat(rec, r.get_landmark_udp, EVACLandmarkUDPGet, compact_output);
+ getStat(rec, r.get_other_http, EVACOtherHTTPGet, compact_output);
+ getStat(rec, r.get_other_udp, EVACOtherUDPGet, compact_output);
+
S32 fps = (S32)rec.getLastValue(LLStatViewer::FPS_SAMPLE);
if (!compact_output || fps != 0)
{
@@ -479,10 +323,10 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
grid_from_region_handle(it->first, &grid_x, &grid_y);
r .grid_x(grid_x)
.grid_y(grid_y)
- .duration(F64Microseconds(rec.getDuration()).value());
+ .duration(F64Seconds(rec.getDuration()).value());
}
- stats.duration(mCurRecording ? F64Microseconds(mCurRecording->getDuration()).value() : 0.0);
+ stats.duration(mCurRecording ? F64Seconds(mCurRecording->getDuration()).value() : 0.0);
}
LLSD LLViewerAssetStats::asLLSD(bool compact_output)
@@ -518,21 +362,22 @@ void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- add(*sEnqueued[int(eac)], 1);
+ add(sEnqueued[int(eac)], 1);
}
void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- add(*sDequeued[int(eac)], 1);
+ add(sDequeued[int(eac)], 1);
}
-void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
+void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration, F64 bytes)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- record(*sResponse[int(eac)], F64Microseconds(duration));
+ record(sResponse[int(eac)], F64Seconds(duration));
+ record(sBytesFetched[int(eac)], bytes);
}
void init()
@@ -561,7 +406,8 @@ LLViewerAssetStats::AssetRequestType::AssetRequestType()
resp_count("resp_count"),
resp_min("resp_min"),
resp_max("resp_max"),
- resp_mean("resp_mean")
+ resp_mean("resp_mean"),
+ resp_mean_bytes("resp_mean_bytes")
{}
LLViewerAssetStats::FPSStats::FPSStats()
@@ -576,10 +422,16 @@ LLViewerAssetStats::RegionStats::RegionStats()
get_texture_temp_udp("get_texture_temp_udp"),
get_texture_non_temp_http("get_texture_non_temp_http"),
get_texture_non_temp_udp("get_texture_non_temp_udp"),
+ get_wearable_http("get_wearable_http"),
get_wearable_udp("get_wearable_udp"),
+ get_sound_http("get_sound_http"),
get_sound_udp("get_sound_udp"),
+ get_gesture_http("get_gesture_http"),
get_gesture_udp("get_gesture_udp"),
- get_other("get_other"),
+ get_landmark_http("get_landmark_http"),
+ get_landmark_udp("get_landmark_udp"),
+ get_other_http("get_other_http"),
+ get_other_udp("get_other_udp"),
fps("fps"),
grid_x("grid_x"),
grid_y("grid_y"),
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 9d425c82fc..718c284224 100644
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -39,6 +39,29 @@
#include "lltrace.h"
#include "llinitparam.h"
+namespace LLViewerAssetStatsFF
+{
+ enum EViewerAssetCategories
+ {
+ EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP
+ EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP
+ EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP
+ EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP
+ EVACWearableHTTPGet, //< Wearable GETs HTTP
+ EVACWearableUDPGet, //< Wearable GETs UDP
+ EVACSoundHTTPGet, //< Sound GETs HTTP
+ EVACSoundUDPGet, //< Sound GETs UDP
+ EVACGestureHTTPGet, //< Gesture GETs HTTP
+ EVACGestureUDPGet, //< Gesture GETs UDP
+ EVACLandmarkHTTPGet, //< Landmark GETs HTTP
+ EVACLandmarkUDPGet, //< Landmark GETs UDP
+ EVACOtherHTTPGet, //< Other GETs HTTP
+ EVACOtherUDPGet, //< Other GETs UDP
+
+ EVACCount // Must be last
+ };
+}
+
/**
* @class LLViewerAssetStats
* @brief Records performance aspects of asset access operations.
@@ -74,6 +97,7 @@
* LLViewerAssetStatsFF is provided for conditional test-and-call
* operations.
*/
+
class LLViewerAssetStats : public LLStopWatchControlsMixin<LLViewerAssetStats>
{
public:
@@ -98,13 +122,14 @@ public:
resp_count;
Mandatory<F64> resp_min,
resp_max,
- resp_mean;
+ resp_mean,
+ resp_mean_bytes;
AssetRequestType();
};
struct FPSStats : public LLInitParam::Block<FPSStats>
- {
+ {
Mandatory<S32> count;
Mandatory<F64> min,
max,
@@ -113,15 +138,21 @@ public:
};
struct RegionStats : public LLInitParam::Block<RegionStats>
- {
+ {
Optional<AssetRequestType> get_texture_temp_http,
get_texture_temp_udp,
get_texture_non_temp_http,
get_texture_non_temp_udp,
+ get_wearable_http,
get_wearable_udp,
+ get_sound_http,
get_sound_udp,
+ get_gesture_http,
get_gesture_udp,
- get_other;
+ get_landmark_http,
+ get_landmark_udp,
+ get_other_http,
+ get_other_udp;
Optional<FPSStats> fps;
Optional<S32> grid_x,
grid_y;
@@ -165,6 +196,11 @@ public:
// Retrieve current metrics for all visited regions (NULL region UUID/handle excluded)
// Uses AssetStats structure seen above
void getStats(AssetStats& stats, bool compact_output);
+
+ // Retrieve a single asset request type (taken from a single region)
+ template <typename T>
+ void getStat(LLTrace::Recording& rec, T& req, LLViewerAssetStatsFF::EViewerAssetCategories cat, bool compact_output);
+
LLSD asLLSD(bool compact_output);
protected:
@@ -205,19 +241,6 @@ extern LLViewerAssetStats * gViewerAssetStats;
namespace LLViewerAssetStatsFF
{
- enum EViewerAssetCategories
- {
- EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP
- EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP
- EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP
- EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP
- EVACWearableUDPGet, //< Wearable GETs
- EVACSoundUDPGet, //< Sound GETs
- EVACGestureUDPGet, //< Gesture GETs
- EVACOtherGet, //< Other GETs
-
- EVACCount // Must be last
- };
/**
* @brief Allocation and deallocation of globals.
@@ -250,7 +273,7 @@ void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp,
- LLViewerAssetStats::duration_t duration);
+ LLViewerAssetStats::duration_t duration, F64 bytes=0);
void record_avatar_stats();
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 2db9c7e67c..bb9195fe90 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -33,9 +33,16 @@
#include "message.h"
#include "llagent.h"
+#include "llappcorehttp.h"
+#include "llviewerregion.h"
+
#include "lltransfersourceasset.h"
#include "lltransfertargetvfile.h"
#include "llviewerassetstats.h"
+#include "llcoros.h"
+#include "lleventcoro.h"
+#include "llsdutil.h"
+#include "llworld.h"
///----------------------------------------------------------------------------
/// LLViewerAssetRequest
@@ -51,38 +58,41 @@
class LLViewerAssetRequest : public LLAssetRequest
{
public:
- LLViewerAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
- : LLAssetRequest(uuid, type),
- mMetricsStartTime(0)
- {
- }
-
- LLViewerAssetRequest & operator=(const LLViewerAssetRequest &); // Not defined
- // Default assignment operator valid
-
- // virtual
- ~LLViewerAssetRequest()
- {
- recordMetrics();
- }
+ LLViewerAssetRequest(const LLUUID &uuid, const LLAssetType::EType type, bool with_http)
+ : LLAssetRequest(uuid, type),
+ mMetricsStartTime(0),
+ mWithHTTP(with_http)
+ {
+ }
+
+ LLViewerAssetRequest & operator=(const LLViewerAssetRequest &); // Not defined
+ // Default assignment operator valid
+
+ // virtual
+ ~LLViewerAssetRequest()
+ {
+ recordMetrics();
+ }
protected:
- void recordMetrics()
- {
- if (mMetricsStartTime.value())
- {
- // Okay, it appears this request was used for useful things. Record
- // the expected dequeue and duration of request processing.
- LLViewerAssetStatsFF::record_dequeue(mType, false, false);
- LLViewerAssetStatsFF::record_response(mType, false, false,
- (LLViewerAssetStatsFF::get_timestamp()
- - mMetricsStartTime));
- mMetricsStartTime = (U32Seconds)0;
- }
- }
-
+ void recordMetrics()
+ {
+ if (mMetricsStartTime.value())
+ {
+ // Okay, it appears this request was used for useful things. Record
+ // the expected dequeue and duration of request processing.
+ LLViewerAssetStatsFF::record_dequeue(mType, mWithHTTP, false);
+ LLViewerAssetStatsFF::record_response(mType, mWithHTTP, false,
+ (LLViewerAssetStatsFF::get_timestamp()
+ - mMetricsStartTime),
+ mBytesFetched);
+ mMetricsStartTime = (U32Seconds)0;
+ }
+ }
+
public:
- LLViewerAssetStats::duration_t mMetricsStartTime;
+ LLViewerAssetStats::duration_t mMetricsStartTime;
+ bool mWithHTTP;
};
///----------------------------------------------------------------------------
@@ -90,228 +100,228 @@ public:
///----------------------------------------------------------------------------
LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
- LLVFS *vfs, LLVFS *static_vfs,
- const LLHost &upstream_host)
- : LLAssetStorage(msg, xfer, vfs, static_vfs, upstream_host)
+ LLVFS *vfs, LLVFS *static_vfs,
+ const LLHost &upstream_host)
+ : LLAssetStorage(msg, xfer, vfs, static_vfs, upstream_host)
{
}
LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
- LLVFS *vfs, LLVFS *static_vfs)
- : LLAssetStorage(msg, xfer, vfs, static_vfs)
+ LLVFS *vfs, LLVFS *static_vfs)
+ : LLAssetStorage(msg, xfer, vfs, static_vfs)
{
}
// virtual
void LLViewerAssetStorage::storeAssetData(
- const LLTransactionID& tid,
- LLAssetType::EType asset_type,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file,
- bool is_priority,
- bool store_local,
- bool user_waiting,
- F64Seconds timeout)
+ const LLTransactionID& tid,
+ LLAssetType::EType asset_type,
+ LLStoreAssetCallback callback,
+ void* user_data,
+ bool temp_file,
+ bool is_priority,
+ bool store_local,
+ bool user_waiting,
+ F64Seconds timeout)
{
- LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
- LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy) " << tid << ":" << LLAssetType::lookup(asset_type)
- << " ASSET_ID: " << asset_id << LL_ENDL;
-
- if (mUpstreamHost.isOk())
- {
- if (mVFS->getExists(asset_id, asset_type))
- {
- // Pack data into this packet if we can fit it.
- U8 buffer[MTUBYTES];
- buffer[0] = 0;
-
- LLVFile vfile(mVFS, asset_id, asset_type, LLVFile::READ);
- S32 asset_size = vfile.getSize();
-
- LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type);
- req->mUpCallback = callback;
- req->mUserData = user_data;
-
- if (asset_size < 1)
- {
- // This can happen if there's a bug in our code or if the VFS has been corrupted.
- LL_WARNS() << "LLViewerAssetStorage::storeAssetData() Data _should_ already be in the VFS, but it's not! " << asset_id << LL_ENDL;
- // LLAssetStorage metric: Zero size VFS
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
-
- delete req;
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_VFS_CORRUPT);
- }
- return;
- }
- else
- {
- // LLAssetStorage metric: Successful Request
- S32 size = mVFS->getSize(asset_id, asset_type);
- const char *message = "Added to upload queue";
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message );
-
- if(is_priority)
- {
- mPendingUploads.push_front(req);
- }
- else
- {
- mPendingUploads.push_back(req);
- }
- }
-
- // Read the data from the VFS if it'll fit in this packet.
- if (asset_size + 100 < MTUBYTES)
- {
- BOOL res = vfile.read(buffer, asset_size); /* Flawfinder: ignore */
- S32 bytes_read = res ? vfile.getLastBytesRead() : 0;
-
- if( bytes_read == asset_size )
- {
- req->mDataSentInFirstPacket = TRUE;
- //LL_INFOS() << "LLViewerAssetStorage::createAsset sending data in first packet" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "Probable corruption in VFS file, aborting store asset data" << LL_ENDL;
-
- // LLAssetStorage metric: VFS corrupt - bogus size
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, asset_size, MR_VFS_CORRUPTION, __FILE__, __LINE__, "VFS corruption" );
-
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_VFS_CORRUPT);
- }
- return;
- }
- }
- else
- {
- // Too big, do an xfer
- buffer[0] = 0;
- asset_size = 0;
- }
- mMessageSys->newMessageFast(_PREHASH_AssetUploadRequest);
- mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
- mMessageSys->addUUIDFast(_PREHASH_TransactionID, tid);
- mMessageSys->addS8Fast(_PREHASH_Type, (S8)asset_type);
- mMessageSys->addBOOLFast(_PREHASH_Tempfile, temp_file);
- mMessageSys->addBOOLFast(_PREHASH_StoreLocal, store_local);
- mMessageSys->addBinaryDataFast( _PREHASH_AssetData, buffer, asset_size );
- mMessageSys->sendReliable(mUpstreamHost);
- }
- else
- {
- LL_WARNS() << "AssetStorage: attempt to upload non-existent vfile " << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
- // LLAssetStorage metric: Zero size VFS
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE);
- }
- }
- }
- else
- {
- LL_WARNS() << "Attempt to move asset store request upstream w/o valid upstream provider" << LL_ENDL;
- // LLAssetStorage metric: Upstream provider dead
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_NO_UPSTREAM, __FILE__, __LINE__, "No upstream provider" );
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
- }
- }
+ LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+ LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy) " << tid << ":" << LLAssetType::lookup(asset_type)
+ << " ASSET_ID: " << asset_id << LL_ENDL;
+
+ if (mUpstreamHost.isOk())
+ {
+ if (mVFS->getExists(asset_id, asset_type))
+ {
+ // Pack data into this packet if we can fit it.
+ U8 buffer[MTUBYTES];
+ buffer[0] = 0;
+
+ LLVFile vfile(mVFS, asset_id, asset_type, LLVFile::READ);
+ S32 asset_size = vfile.getSize();
+
+ LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type);
+ req->mUpCallback = callback;
+ req->mUserData = user_data;
+
+ if (asset_size < 1)
+ {
+ // This can happen if there's a bug in our code or if the VFS has been corrupted.
+ LL_WARNS("AssetStorage") << "LLViewerAssetStorage::storeAssetData() Data _should_ already be in the VFS, but it's not! " << asset_id << LL_ENDL;
+ // LLAssetStorage metric: Zero size VFS
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
+
+ delete req;
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_VFS_CORRUPT);
+ }
+ return;
+ }
+ else
+ {
+ // LLAssetStorage metric: Successful Request
+ S32 size = mVFS->getSize(asset_id, asset_type);
+ const char *message = "Added to upload queue";
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message );
+
+ if(is_priority)
+ {
+ mPendingUploads.push_front(req);
+ }
+ else
+ {
+ mPendingUploads.push_back(req);
+ }
+ }
+
+ // Read the data from the VFS if it'll fit in this packet.
+ if (asset_size + 100 < MTUBYTES)
+ {
+ BOOL res = vfile.read(buffer, asset_size); /* Flawfinder: ignore */
+ S32 bytes_read = res ? vfile.getLastBytesRead() : 0;
+
+ if( bytes_read == asset_size )
+ {
+ req->mDataSentInFirstPacket = TRUE;
+ //LL_INFOS() << "LLViewerAssetStorage::createAsset sending data in first packet" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "Probable corruption in VFS file, aborting store asset data" << LL_ENDL;
+
+ // LLAssetStorage metric: VFS corrupt - bogus size
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, asset_size, MR_VFS_CORRUPTION, __FILE__, __LINE__, "VFS corruption" );
+
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_VFS_CORRUPT);
+ }
+ return;
+ }
+ }
+ else
+ {
+ // Too big, do an xfer
+ buffer[0] = 0;
+ asset_size = 0;
+ }
+ mMessageSys->newMessageFast(_PREHASH_AssetUploadRequest);
+ mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
+ mMessageSys->addUUIDFast(_PREHASH_TransactionID, tid);
+ mMessageSys->addS8Fast(_PREHASH_Type, (S8)asset_type);
+ mMessageSys->addBOOLFast(_PREHASH_Tempfile, temp_file);
+ mMessageSys->addBOOLFast(_PREHASH_StoreLocal, store_local);
+ mMessageSys->addBinaryDataFast( _PREHASH_AssetData, buffer, asset_size );
+ mMessageSys->sendReliable(mUpstreamHost);
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "AssetStorage: attempt to upload non-existent vfile " << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
+ // LLAssetStorage metric: Zero size VFS
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE);
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "Attempt to move asset store request upstream w/o valid upstream provider" << LL_ENDL;
+ // LLAssetStorage metric: Upstream provider dead
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_NO_UPSTREAM, __FILE__, __LINE__, "No upstream provider" );
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
+ }
+ }
}
void LLViewerAssetStorage::storeAssetData(
- const std::string& filename,
- const LLTransactionID& tid,
- LLAssetType::EType asset_type,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file,
- bool is_priority,
- bool user_waiting,
- F64Seconds timeout)
+ const std::string& filename,
+ const LLTransactionID& tid,
+ LLAssetType::EType asset_type,
+ LLStoreAssetCallback callback,
+ void* user_data,
+ bool temp_file,
+ bool is_priority,
+ bool user_waiting,
+ F64Seconds timeout)
{
- if(filename.empty())
- {
- // LLAssetStorage metric: no filename
- reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_VFS_CORRUPTION, __FILE__, __LINE__, "Filename missing" );
- LL_ERRS() << "No filename specified" << LL_ENDL;
- return;
- }
-
- LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
- LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
-
- LL_DEBUGS("AssetStorage") << "ASSET_ID: " << asset_id << LL_ENDL;
-
- S32 size = 0;
- LLFILE* fp = LLFile::fopen(filename, "rb");
- if (fp)
- {
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- }
- if( size )
- {
- LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
-
- legacy->mUpCallback = callback;
- legacy->mUserData = user_data;
-
- LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
-
- file.setMaxSize(size);
-
- const S32 buf_size = 65536;
- U8 copy_buf[buf_size];
- while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
- {
- file.write(copy_buf, size);
- }
- fclose(fp);
-
- // if this upload fails, the caller needs to setup a new tempfile for us
- if (temp_file)
- {
- LLFile::remove(filename);
- }
-
- // LLAssetStorage metric: Success not needed; handled in the overloaded method here:
-
- LLViewerAssetStorage::storeAssetData(
- tid,
- asset_type,
- legacyStoreDataCallback,
- (void**)legacy,
- temp_file,
- is_priority);
- }
- else // size == 0 (but previous block changes size)
- {
- if( fp )
- {
- // LLAssetStorage metric: Zero size
- reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" );
- }
- else
- {
- // LLAssetStorage metric: Missing File
- reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" );
- }
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE);
- }
- }
+ if(filename.empty())
+ {
+ // LLAssetStorage metric: no filename
+ reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_VFS_CORRUPTION, __FILE__, __LINE__, "Filename missing" );
+ LL_ERRS() << "No filename specified" << LL_ENDL;
+ return;
+ }
+
+ LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+ LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
+
+ LL_DEBUGS("AssetStorage") << "ASSET_ID: " << asset_id << LL_ENDL;
+
+ S32 size = 0;
+ LLFILE* fp = LLFile::fopen(filename, "rb");
+ if (fp)
+ {
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ }
+ if( size )
+ {
+ LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
+
+ legacy->mUpCallback = callback;
+ legacy->mUserData = user_data;
+
+ LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
+
+ file.setMaxSize(size);
+
+ const S32 buf_size = 65536;
+ U8 copy_buf[buf_size];
+ while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
+ {
+ file.write(copy_buf, size);
+ }
+ fclose(fp);
+
+ // if this upload fails, the caller needs to setup a new tempfile for us
+ if (temp_file)
+ {
+ LLFile::remove(filename);
+ }
+
+ // LLAssetStorage metric: Success not needed; handled in the overloaded method here:
+
+ LLViewerAssetStorage::storeAssetData(
+ tid,
+ asset_type,
+ legacyStoreDataCallback,
+ (void**)legacy,
+ temp_file,
+ is_priority);
+ }
+ else // size == 0 (but previous block changes size)
+ {
+ if( fp )
+ {
+ // LLAssetStorage metric: Zero size
+ reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" );
+ }
+ else
+ {
+ // LLAssetStorage metric: Missing File
+ reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" );
+ }
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE);
+ }
+ }
}
@@ -334,56 +344,175 @@ void LLViewerAssetStorage::storeAssetData(
// virtual
void LLViewerAssetStorage::_queueDataRequest(
- const LLUUID& uuid,
- LLAssetType::EType atype,
- LLGetAssetCallback callback,
- void *user_data,
- BOOL duplicate,
- BOOL is_priority)
+ const LLUUID& uuid,
+ LLAssetType::EType atype,
+ LLGetAssetCallback callback,
+ void *user_data,
+ BOOL duplicate,
+ BOOL is_priority)
+{
+ queueRequestHttp(uuid, atype, callback, user_data, duplicate, is_priority);
+}
+
+void LLViewerAssetStorage::queueRequestHttp(
+ const LLUUID& uuid,
+ LLAssetType::EType atype,
+ LLGetAssetCallback callback,
+ void *user_data,
+ BOOL duplicate,
+ BOOL is_priority)
+{
+ LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL;
+
+ bool with_http = true;
+ LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype, with_http);
+ req->mDownCallback = callback;
+ req->mUserData = user_data;
+ req->mIsPriority = is_priority;
+ if (!duplicate)
+ {
+ // Only collect metrics for non-duplicate requests. Others
+ // are piggy-backing and will artificially lower averages.
+ req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ }
+ mPendingDownloads.push_back(req);
+
+ // This is the same as the current UDP logic - don't re-request a duplicate.
+ if (!duplicate)
+ {
+ bool with_http = true;
+ bool is_temp = false;
+ LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
+
+ LLCoros::instance().launch("LLViewerAssetStorage::assetRequestCoro",
+ boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
+ }
+}
+
+void LLViewerAssetStorage::capsRecvForRegion(const LLUUID& region_id, std::string pumpname)
{
- if (mUpstreamHost.isOk())
- {
- // stash the callback info so we can find it after we get the response message
- LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype);
- req->mDownCallback = callback;
- req->mUserData = user_data;
- req->mIsPriority = is_priority;
- if (!duplicate)
- {
- // Only collect metrics for non-duplicate requests. Others
- // are piggy-backing and will artificially lower averages.
- req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
- }
-
- mPendingDownloads.push_back(req);
-
- if (!duplicate)
- {
- // send request message to our upstream data provider
- // Create a new asset transfer.
- LLTransferSourceParamsAsset spa;
- spa.setAsset(uuid, atype);
-
- // Set our destination file, and the completion callback.
- LLTransferTargetParamsVFile tpvf;
- tpvf.setAsset(uuid, atype);
- tpvf.setCallback(downloadCompleteCallback, *req);
-
- LL_DEBUGS("AssetStorage") << "Starting transfer for " << uuid << LL_ENDL;
- LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
- ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
-
- LLViewerAssetStatsFF::record_enqueue(atype, false, false);
- }
- }
- else
- {
- // uh-oh, we shouldn't have gotten here
- LL_WARNS() << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL;
- if (callback)
- {
- callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
- }
- }
+ LLViewerRegion *regionp = LLWorld::instance().getRegionFromID(region_id);
+ if (!regionp)
+ {
+ LL_WARNS("ViewerAsset") << "region not found for region_id " << region_id << LL_ENDL;
+ }
+ else
+ {
+ mViewerAssetUrl = regionp->getViewerAssetUrl();
+ }
+
+ LLEventPumps::instance().obtain(pumpname).post(LLSD());
}
+void LLViewerAssetStorage::assetRequestCoro(
+ LLViewerAssetRequest *req,
+ const LLUUID& uuid,
+ LLAssetType::EType atype,
+ LLGetAssetCallback callback,
+ void *user_data)
+{
+ S32 result_code = LL_ERR_NOERR;
+ LLExtStat ext_status = LL_EXSTAT_NONE;
+
+ if (!gAgent.getRegion())
+ {
+ LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_NONE;
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
+ return;
+ }
+ else if (!gAgent.getRegion()->capabilitiesReceived())
+ {
+ LL_WARNS_ONCE("ViewerAsset") << "Waiting for capabilities" << LL_ENDL;
+
+ LLEventStream capsRecv("waitForCaps", true);
+
+ gAgent.getRegion()->setCapabilitiesReceivedCallback(
+ boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName()));
+
+ llcoro::suspendUntilEventOn(capsRecv);
+ LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL;
+ LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL;
+ }
+ if (mViewerAssetUrl.empty() && gAgent.getRegion())
+ {
+ mViewerAssetUrl = gAgent.getRegion()->getViewerAssetUrl();
+ }
+ if (mViewerAssetUrl.empty())
+ {
+ LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_NONE;
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
+ return;
+ }
+ std::string url = getAssetURL(mViewerAssetUrl, uuid,atype);
+ LL_DEBUGS("ViewerAsset") << "request url: " << url << LL_ENDL;
+
+ LLCore::HttpRequest::policy_t httpPolicy(LLAppCoreHttp::AP_TEXTURE);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("assetRequestCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+ LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+ if (!status)
+ {
+ LL_DEBUGS("ViewerAsset") << "request failed, status " << status.toTerseString() << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_NONE;
+ }
+ else
+ {
+ LL_DEBUGS("ViewerAsset") << "request succeeded, url " << url << LL_ENDL;
+
+ const LLSD::Binary &raw = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary();
+
+ S32 size = raw.size();
+ if (size > 0)
+ {
+ // This create-then-rename flow is modeled on
+ // LLTransferTargetVFile, which is what was used in the UDP
+ // case.
+ LLUUID temp_id;
+ temp_id.generate();
+ LLVFile vf(gAssetStorage->mVFS, temp_id, atype, LLVFile::WRITE);
+ vf.setMaxSize(size);
+ req->mBytesFetched = size;
+ if (!vf.write(raw.data(),size))
+ {
+ // TODO asset-http: handle error
+ LL_WARNS("ViewerAsset") << "Failure in vf.write()" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_VFS_CORRUPT;
+ }
+ if (!vf.rename(uuid, atype))
+ {
+ LL_WARNS("ViewerAsset") << "rename failed" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_VFS_CORRUPT;
+ }
+ }
+ else
+ {
+ // TODO asset-http: handle invalid size case
+ LL_WARNS("ViewerAsset") << "bad size" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_NONE;
+ }
+ }
+
+ // Clean up pending downloads and trigger callbacks
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
+}
+
+std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype)
+{
+ std::string type_name = LLAssetType::lookup(atype);
+ std::string url = cap_url + "/?" + type_name + "_id=" + uuid.asString();
+ return url;
+}
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index 6baec647e6..2f3eaa15a7 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -28,10 +28,11 @@
#define LLVIEWERASSETSTORAGE_H
#include "llassetstorage.h"
-//#include "curl/curl.h"
class LLVFile;
+class LLViewerAssetRequest;
+
class LLViewerAssetStorage : public LLAssetStorage
{
public:
@@ -41,7 +42,6 @@ public:
LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
LLVFS *vfs, LLVFS *static_vfs);
- using LLAssetStorage::storeAssetData;
virtual void storeAssetData(
const LLTransactionID& tid,
LLAssetType::EType atype,
@@ -65,8 +65,6 @@ public:
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
protected:
- using LLAssetStorage::_queueDataRequest;
-
// virtual
void _queueDataRequest(const LLUUID& uuid,
LLAssetType::EType type,
@@ -74,6 +72,25 @@ protected:
void *user_data,
BOOL duplicate,
BOOL is_priority);
+
+ void queueRequestHttp(const LLUUID& uuid,
+ LLAssetType::EType type,
+ void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+ void *user_data,
+ BOOL duplicate,
+ BOOL is_priority);
+
+ void capsRecvForRegion(const LLUUID& region_id, std::string pumpname);
+
+ void assetRequestCoro(LLViewerAssetRequest *req,
+ const LLUUID& uuid,
+ LLAssetType::EType atype,
+ void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+ void *user_data);
+
+ std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype);
+
+ std::string mViewerAssetUrl;
};
#endif
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 899ab3a371..eb37613c95 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -521,7 +521,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mColoName("unknown"),
mProductSKU("unknown"),
mProductName("unknown"),
- mHttpUrl(""),
+ mViewerAssetUrl(""),
mCacheLoaded(FALSE),
mCacheDirty(FALSE),
mReleaseNotesRequested(FALSE),
@@ -2843,12 +2843,9 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("IsExperienceAdmin");
capabilityNames.append("IsExperienceContributor");
capabilityNames.append("RegionExperiences");
- capabilityNames.append("GetMesh");
- capabilityNames.append("GetMesh2");
capabilityNames.append("GetMetadata");
capabilityNames.append("GetObjectCost");
capabilityNames.append("GetObjectPhysicsData");
- capabilityNames.append("GetTexture");
capabilityNames.append("GroupAPIv1");
capabilityNames.append("GroupMemberData");
capabilityNames.append("GroupProposalBallot");
@@ -2895,6 +2892,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("UpdateScriptAgent");
capabilityNames.append("UpdateScriptTask");
capabilityNames.append("UploadBakedTexture");
+ capabilityNames.append("ViewerAsset");
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
@@ -2961,9 +2959,9 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
else
{
mImpl->mCapabilities[name] = url;
- if(name == "GetTexture")
+ if(name == "ViewerAsset")
{
- mHttpUrl = url ;
+ mViewerAssetUrl = url;
}
}
}
@@ -2974,9 +2972,9 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri
if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) )
{
mImpl->mSecondCapabilitiesTracker[name] = url;
- if(name == "GetTexture")
+ if(name == "ViewerAsset")
{
- mHttpUrl = url ;
+ mViewerAssetUrl = url;
}
}
}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a7bb546d2c..61ce5b454d 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -354,7 +354,7 @@ public:
friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region);
/// implements LLCapabilityProvider
virtual std::string getDescription() const;
- std::string getHttpUrl() const { return mHttpUrl ;}
+ std::string getViewerAssetUrl() const { return mViewerAssetUrl; }
U32 getNumOfVisibleGroups() const;
U32 getNumOfActiveCachedObjects() const;
@@ -506,7 +506,7 @@ private:
std::string mColoName;
std::string mProductSKU;
std::string mProductName;
- std::string mHttpUrl ;
+ std::string mViewerAssetUrl ;
// Maps local ids to cache entries.
// Regions can have order 10,000 objects, so assume
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f6a16f7da1..6cb0f84f0c 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -9384,6 +9384,3 @@ BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type,
// non-self avatars don't have wearables
return FALSE;
}
-
-
-
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index a08e32cb49..e2e7f09c3b 100644
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -71,25 +71,33 @@ static const char * all_keys[] =
{
"duration",
"fps",
- "get_other",
+ "get_other_http",
+ "get_other_udp",
"get_texture_temp_http",
"get_texture_temp_udp",
"get_texture_non_temp_http",
"get_texture_non_temp_udp",
+ "get_wearable_http",
"get_wearable_udp",
+ "get_sound_http",
"get_sound_udp",
+ "get_gesture_http",
"get_gesture_udp"
};
static const char * resp_keys[] =
{
- "get_other",
+ "get_other_http",
+ "get_other_udp",
"get_texture_temp_http",
"get_texture_temp_udp",
"get_texture_non_temp_http",
"get_texture_non_temp_udp",
+ "get_wearable_http",
"get_wearable_udp",
+ "get_sound_http",
"get_sound_udp",
+ "get_gesture_http",
"get_gesture_udp"
};
@@ -540,11 +548,17 @@ namespace tut
ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger()));
ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
- ensure("sd[get_wearable_udp][enqueued] is 4", (4 == sd["get_wearable_udp"]["enqueued"].asInteger()));
- ensure("sd[get_wearable_udp][dequeued] is 4", (4 == sd["get_wearable_udp"]["dequeued"].asInteger()));
+ ensure("sd[get_wearable_http][enqueued] is 2", (2 == sd["get_wearable_http"]["enqueued"].asInteger()));
+ ensure("sd[get_wearable_http][dequeued] is 2", (2 == sd["get_wearable_http"]["dequeued"].asInteger()));
- ensure("sd[get_other][enqueued] is 4", (4 == sd["get_other"]["enqueued"].asInteger()));
- ensure("sd[get_other][dequeued] is 0", (0 == sd["get_other"]["dequeued"].asInteger()));
+ ensure("sd[get_wearable_udp][enqueued] is 2", (2 == sd["get_wearable_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_wearable_udp][dequeued] is 2", (2 == sd["get_wearable_udp"]["dequeued"].asInteger()));
+
+ ensure("sd[get_other_http][enqueued] is 2", (2 == sd["get_other_http"]["enqueued"].asInteger()));
+ ensure("sd[get_other_http][dequeued] is 0", (0 == sd["get_other_http"]["dequeued"].asInteger()));
+
+ ensure("sd[get_other_udp][enqueued] is 2", (2 == sd["get_other_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_other_udp][dequeued] is 0", (0 == sd["get_other_udp"]["dequeued"].asInteger()));
// Reset and check zeros...
// Reset leaves current region in place