diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/app_settings/settings.xml | 12 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.cpp | 143 | ||||
-rw-r--r-- | indra/newview/llmeshrepository.h | 13 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 10 | ||||
-rw-r--r-- | indra/newview/lltexturefetch.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llviewerassetstats.cpp | 394 | ||||
-rw-r--r-- | indra/newview/llviewerassetstats.h | 59 | ||||
-rw-r--r-- | indra/newview/llviewerassetstorage.cpp | 728 | ||||
-rw-r--r-- | indra/newview/llviewerassetstorage.h | 29 | ||||
-rw-r--r-- | indra/newview/llviewercontrol.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llviewerregion.cpp | 14 | ||||
-rw-r--r-- | indra/newview/llviewerregion.h | 4 | ||||
-rw-r--r-- | indra/newview/tests/llviewerassetstats_test.cpp | 26 |
13 files changed, 739 insertions, 705 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 717deba8c7..9b26053fb5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -15808,6 +15808,18 @@ <integer>0</integer> </map> + <key>ViewerAssetHttpTypes</key> + <map> + <key>Comment</key> + <string>Use the ViewerAsset cap and HTTP pipeline for fetching assets of the listed type names. "none" and "all" are recognized as a special values.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>all</string> + </map> + <key>SimulateFBOFailure</key> <map> <key>Comment</key> diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 1a533dace7..a0dced3cfd 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -808,10 +808,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 +826,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 +1100,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 +1110,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 +1127,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 +1143,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 +1154,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 +1251,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 +1343,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 +1434,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 +1527,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 +1537,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 +1613,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 +3259,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3 LLMeshRepository::LLMeshRepository() : mMeshMutex(NULL), mMeshThreadCount(0), - mThread(NULL), - mGetMeshVersion(2) + mThread(NULL) { } @@ -3476,35 +3442,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 +3562,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/llstartup.cpp b/indra/newview/llstartup.cpp index b762b2ae1c..0ef337b6c4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -312,6 +312,16 @@ void set_flags_and_update_appearance() // true when all initialization done. bool idle_startup() { + // FIXME asset-http - this configuration stuff is temporary + // construction; once it is always on for certain types + // we can remove the setting. + static bool va_types_initialized = false; + if (!va_types_initialized) + { + va_types_initialized = true; + LLAssetType::setFetchWithVACapConfigString(gSavedSettings.getString("ViewerAssetHttpTypes")); + } + const F32 PRECACHING_DELAY = gSavedSettings.getF32("PrecachingDelay"); static LLTimer timeout; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 07b3dc1aa4..7c0d02c9ca 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1351,7 +1351,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) @@ -4580,7 +4580,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/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index 54ac29723f..a9e0ba7b5d 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) { @@ -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)], F64Microseconds(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..41f407b8d9 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -33,9 +33,14 @@ #include "message.h" #include "llagent.h" +#include "llviewerregion.h" + #include "lltransfersourceasset.h" #include "lltransfertargetvfile.h" #include "llviewerassetstats.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "llsdutil.h" ///---------------------------------------------------------------------------- /// LLViewerAssetRequest @@ -51,38 +56,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 +98,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() << "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); + } + } } 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 +342,204 @@ 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) +{ + if (LLAssetType::lookupFetchWithVACap(atype)) + { + queueRequestHttp(uuid, atype, callback, user_data, duplicate, is_priority); + } + else + { + queueRequestUDP(uuid, atype, callback, user_data, duplicate, is_priority); + } +} + +void LLViewerAssetStorage::queueRequestUDP( + const LLUUID& uuid, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data, + BOOL duplicate, + BOOL is_priority) +{ + LL_DEBUGS("ViewerAsset") << "Request asset via UDP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL; + + if (mUpstreamHost.isOk()) + { + // stash the callback info so we can find it after we get the response message + bool with_http = false; + 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); + + 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)); + + bool with_http = false; + bool is_temp = false; + LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp); + } + } + 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); + } + } +} + +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; + std::string cap_url = gAgent.getRegion()->getCapability("ViewerAsset"); + if (cap_url.empty()) + { + LL_WARNS() << "No ViewerAsset cap found, fetch fails" << LL_ENDL; + // TODO asset-http: handle waiting for caps? Other failure mechanism? + return; + } + else + { + LL_DEBUGS("ViewerAsset") << "Will fetch via ViewerAsset cap " << cap_url << 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::assetRequestCoro( + LLViewerAssetRequest *req, + const LLUUID& uuid, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data) { - 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); - } - } + std::string url = getAssetURL(uuid,atype); + LL_DEBUGS("ViewerAsset") << "request url: " << url << LL_ENDL; + + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + 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); + + S32 result_code = LL_ERR_NOERR; + LLExtStat ext_status = LL_EXSTAT_NONE; + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + if (!status) + { + // TODO asset-http: handle failures + LL_DEBUGS("ViewerAsset") << "request failed, status " << status.toTerseString() << ", now what?" << 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's 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() << "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() << "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() << "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 LLUUID& uuid, LLAssetType::EType atype) +{ + std::string cap_url = gAgent.getRegion()->getViewerAssetUrl(); + 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..3ca8112601 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,29 @@ protected: void *user_data, BOOL duplicate, BOOL is_priority); + + void queueRequestUDP(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 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 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 LLUUID& uuid, LLAssetType::EType atype); + }; #endif diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 7c1921b143..c0a87adca5 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -127,6 +127,13 @@ static bool handleDebugAvatarJointsChanged(const LLSD& newvalue) return true; } +static bool handleViewerAssetHttpTypesChanged(const LLSD& newvalue) +{ + std::string new_string = newvalue.asString(); + LLAssetType::setFetchWithVACapConfigString(new_string); + return true; +} + static bool handleSetShaderChanged(const LLSD& newvalue) { // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache @@ -750,6 +757,7 @@ void settings_setup_listeners() gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged)); gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged)); gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); + gSavedSettings.getControl("ViewerAssetHttpTypes")->getCommitSignal()->connect(boost::bind(&handleViewerAssetHttpTypesChanged, _2)); } #if TEST_CACHED_CONTROL 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 ®ion); /// 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/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 |