Merge Firestorm LGPL
commit
1baf1f5091
1
.hgtags
1
.hgtags
|
|
@ -563,3 +563,4 @@ cea1632c002c065985ebea15eeeb4aac90f50545 5.0.2-release
|
|||
02c24e9f4f7d8aa0de75f27817dda098582f4936 5.0.3-release
|
||||
022709ef76a331cac1ba6ef1a6da8a5e9ef63f5a 5.0.4-release
|
||||
b4d76b5590fdf8bab72c64442353753a527cbc44 5.0.5-release
|
||||
3e5035dfd8af49bd4c0009f0a76ef46a15991a45 5.0.6-release
|
||||
|
|
|
|||
|
|
@ -1311,6 +1311,7 @@ Sovereign Engineer
|
|||
MAINT-6913
|
||||
STORM-2143
|
||||
STORM-2148
|
||||
MAINT-7343
|
||||
SpacedOut Frye
|
||||
VWR-34
|
||||
VWR-45
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public:
|
|||
|
||||
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
|
||||
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
|
||||
|
||||
|
||||
static const std::string& badLookup(); // error string when a lookup fails
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -574,8 +574,10 @@ namespace LLError
|
|||
}
|
||||
#endif
|
||||
mFunctionString += std::string(mFunction) + ":";
|
||||
const std::string tag_hash("#");
|
||||
for (size_t i = 0; i < mTagCount; i++)
|
||||
{
|
||||
mTagString.append(tag_hash);
|
||||
// <FS:ND> Tags can be 0, so work around that.
|
||||
//mTagString.append(mTags[i]);
|
||||
char const *pTag = mTags[i];
|
||||
|
|
@ -585,7 +587,6 @@ namespace LLError
|
|||
// </FS:ND>
|
||||
mTagString.append((i == mTagCount - 1) ? "" : ",");
|
||||
}
|
||||
mTagString.append("#");
|
||||
}
|
||||
|
||||
#ifdef LL_LINUX
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -138,6 +138,7 @@ public:
|
|||
BOOL mIsUserWaiting; // We don't want to try forever if a user is waiting for a result.
|
||||
F64Seconds mTimeout; // Amount of time before timing out.
|
||||
LLUUID mRequestingAgentID; // Only valid for uploads from an agent
|
||||
F64 mBytesFetched;
|
||||
|
||||
virtual LLSD getTerseDetails() const;
|
||||
virtual LLSD getFullDetails() const;
|
||||
|
|
@ -186,18 +187,9 @@ typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
|
|||
// we can use bind and remove the userData parameter.
|
||||
//
|
||||
typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
|
||||
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
|
||||
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
|
||||
|
||||
class LLTempAssetStorage
|
||||
{
|
||||
public:
|
||||
virtual ~LLTempAssetStorage() =0;
|
||||
virtual void addTempAssetData(const LLUUID& asset_id,
|
||||
const LLUUID& agent_id,
|
||||
const std::string& host_name) = 0;
|
||||
};
|
||||
|
||||
class LLAssetStorage : public LLTempAssetStorage
|
||||
class LLAssetStorage
|
||||
{
|
||||
public:
|
||||
// VFS member is public because static child methods need it :(
|
||||
|
|
@ -240,12 +232,11 @@ public:
|
|||
|
||||
void setUpstream(const LLHost &upstream_host);
|
||||
|
||||
virtual BOOL hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type);
|
||||
BOOL hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type);
|
||||
|
||||
// public interface methods
|
||||
// note that your callback may get called BEFORE the function returns
|
||||
|
||||
virtual void getAssetData(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback cb, void *user_data, BOOL is_priority = FALSE);
|
||||
void getAssetData(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback cb, void *user_data, BOOL is_priority = FALSE);
|
||||
|
||||
/*
|
||||
* TransactionID version
|
||||
|
|
@ -260,25 +251,11 @@ public:
|
|||
bool is_priority = false,
|
||||
bool store_local = false,
|
||||
bool user_waiting= false,
|
||||
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) = 0;
|
||||
|
||||
/*
|
||||
* AssetID version
|
||||
* Sim needs both store_local and requesting_agent_id.
|
||||
*/
|
||||
virtual void storeAssetData(
|
||||
const LLUUID& asset_id,
|
||||
LLAssetType::EType asset_type,
|
||||
LLStoreAssetCallback callback,
|
||||
void* user_data,
|
||||
bool temp_file = false,
|
||||
bool is_priority = false,
|
||||
bool store_local = false,
|
||||
const LLUUID& requesting_agent_id = LLUUID::null,
|
||||
bool user_waiting= false,
|
||||
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
virtual void checkForTimeouts();
|
||||
virtual void logAssetStorageInfo() = 0;
|
||||
|
||||
void checkForTimeouts();
|
||||
|
||||
void getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
|
||||
const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
|
||||
|
|
@ -303,17 +280,17 @@ protected:
|
|||
bool findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
|
||||
LLGetAssetCallback callback, void *user_data);
|
||||
|
||||
virtual LLSD getPendingDetailsImpl(const request_list_t* requests,
|
||||
LLAssetType::EType asset_type,
|
||||
const std::string& detail_prefix) const;
|
||||
LLSD getPendingDetailsImpl(const request_list_t* requests,
|
||||
LLAssetType::EType asset_type,
|
||||
const std::string& detail_prefix) const;
|
||||
|
||||
virtual LLSD getPendingRequestImpl(const request_list_t* requests,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id) const;
|
||||
LLSD getPendingRequestImpl(const request_list_t* requests,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id) const;
|
||||
|
||||
virtual bool deletePendingRequestImpl(request_list_t* requests,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id);
|
||||
bool deletePendingRequestImpl(request_list_t* requests,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id);
|
||||
|
||||
public:
|
||||
static const LLAssetRequest* findRequest(const request_list_t* requests,
|
||||
|
|
@ -332,19 +309,23 @@ public:
|
|||
S32 getNumPendingLocalUploads();
|
||||
S32 getNumPending(ERequestType rt) const;
|
||||
|
||||
virtual LLSD getPendingDetails(ERequestType rt,
|
||||
LLAssetType::EType asset_type,
|
||||
const std::string& detail_prefix) const;
|
||||
LLSD getPendingDetails(ERequestType rt,
|
||||
LLAssetType::EType asset_type,
|
||||
const std::string& detail_prefix) const;
|
||||
|
||||
virtual LLSD getPendingRequest(ERequestType rt,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id) const;
|
||||
LLSD getPendingRequest(ERequestType rt,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id) const;
|
||||
|
||||
virtual bool deletePendingRequest(ERequestType rt,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id);
|
||||
bool deletePendingRequest(ERequestType rt,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLUUID& asset_id);
|
||||
|
||||
|
||||
static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type,
|
||||
const LLUUID& callback_id, LLAssetType::EType callback_type,
|
||||
S32 result_code, LLExtStat ext_status);
|
||||
|
||||
// download process callbacks
|
||||
static void downloadCompleteCallback(
|
||||
S32 result,
|
||||
|
|
@ -370,22 +351,9 @@ public:
|
|||
static const char* getErrorString( S32 status );
|
||||
|
||||
// deprecated file-based methods
|
||||
// Not overriden
|
||||
void getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, BOOL is_priority = FALSE);
|
||||
|
||||
/*
|
||||
* AssetID version.
|
||||
*/
|
||||
virtual void storeAssetData(
|
||||
const std::string& filename,
|
||||
const LLUUID& asset_id,
|
||||
LLAssetType::EType type,
|
||||
LLStoreAssetCallback callback,
|
||||
void* user_data,
|
||||
bool temp_file = false,
|
||||
bool is_priority = false,
|
||||
bool user_waiting = false,
|
||||
F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
/*
|
||||
* TransactionID version
|
||||
*/
|
||||
|
|
@ -398,23 +366,11 @@ public:
|
|||
bool temp_file = false,
|
||||
bool is_priority = false,
|
||||
bool user_waiting = false,
|
||||
F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT);
|
||||
F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT) = 0;
|
||||
|
||||
static void legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status);
|
||||
static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status);
|
||||
|
||||
// Temp assets are stored on sim nodes, they have agent ID and location data associated with them.
|
||||
// This is a no-op for non-http asset systems
|
||||
virtual void addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name);
|
||||
virtual BOOL hasTempAssetData(const LLUUID& texture_id) const;
|
||||
virtual std::string getTempAssetHostName(const LLUUID& texture_id) const;
|
||||
virtual LLUUID getTempAssetAgentID(const LLUUID& texture_id) const;
|
||||
virtual void removeTempAssetData(const LLUUID& asset_id);
|
||||
virtual void removeTempAssetDataByAgentID(const LLUUID& agent_id);
|
||||
// Pass LLUUID::null for all
|
||||
virtual void dumpTempAssetData(const LLUUID& avatar_id) const;
|
||||
virtual void clearTempAssetData();
|
||||
|
||||
// add extra methods to handle metadata
|
||||
|
||||
protected:
|
||||
|
|
@ -424,7 +380,7 @@ protected:
|
|||
virtual void _queueDataRequest(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);
|
||||
BOOL is_priority) = 0;
|
||||
|
||||
private:
|
||||
void _init(LLMessageSystem *msg,
|
||||
|
|
|
|||
|
|
@ -17901,6 +17901,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>AssetStorageLogFrequency</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Seconds between display of AssetStorage info in log (0 for never)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>60.0</real>
|
||||
</map>
|
||||
<key>LogWearableAssetSave</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -17980,6 +17991,15 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<real>1</real>
|
||||
</map>
|
||||
<key>PoolSizeAssetStorage</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Coroutine Pool size for AssetStorage requests</string>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<real>12</real>
|
||||
</map>
|
||||
|
||||
<!-- Settings below are for back compatibility only.
|
||||
They are not used in current viewer anymore. But they can't be removed to avoid
|
||||
|
|
|
|||
|
|
@ -1022,12 +1022,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;
|
||||
|
|
@ -6906,23 +6900,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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -344,10 +344,12 @@ LLMeshRepository gMeshRepo;
|
|||
|
||||
const S32 MESH_HEADER_SIZE = 4096; // Important: assumption is that headers fit in this space
|
||||
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
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;
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
const S32 REQUEST2_HIGH_WATER_MIN = 32; // Limits for GetMesh2 regions
|
||||
const S32 REQUEST2_HIGH_WATER_MAX = 100;
|
||||
|
|
@ -814,10 +816,10 @@ LLMeshRepoThread::LLMeshRepoThread()
|
|||
mHttpLargeOptions(),
|
||||
mHttpHeaders(),
|
||||
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||
mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||
mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), // <FS:Ansariel> [UDP Assets]
|
||||
mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||
mHttpPriority(0),
|
||||
mGetMeshVersion(2)
|
||||
mLegacyGetMeshVersion(0), // <FS:Ansariel> [UDP Assets]
|
||||
mHttpPriority(0)
|
||||
{
|
||||
LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
|
||||
|
||||
|
|
@ -834,7 +836,7 @@ 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);
|
||||
mHttpLegacyPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH1); // <FS:Ansariel> [UDP Assets]
|
||||
mHttpLargePolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_LARGE_MESH);
|
||||
}
|
||||
|
||||
|
|
@ -1109,13 +1111,19 @@ 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)
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//void LLMeshRepoThread::setGetMeshCap(const std::string & mesh_cap)
|
||||
void LLMeshRepoThread::setGetMeshCap(const std::string & mesh_cap, const std::string & legacy_get_mesh1,
|
||||
const std::string & legacy_get_mesh2,
|
||||
int legacy_pref_version)
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
{
|
||||
mGetMeshCapability = get_mesh1;
|
||||
mGetMesh2Capability = get_mesh2;
|
||||
mGetMeshVersion = pref_version;
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
mLegacyGetMeshCapability = legacy_get_mesh1;
|
||||
mLegacyGetMesh2Capability = legacy_get_mesh2;
|
||||
mLegacyGetMeshVersion = legacy_pref_version;
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
mGetMeshCapability = mesh_cap;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1123,29 +1131,34 @@ 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)
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url)
|
||||
void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * legacy_version)
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
{
|
||||
std::string res_url;
|
||||
int res_version(2);
|
||||
int res_version(0); // <FS:Ansariel> [UDP Assets]
|
||||
|
||||
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)
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//res_url = mGetMeshCapability;
|
||||
if (!mGetMeshCapability.empty() && mLegacyGetMeshVersion == 0)
|
||||
{
|
||||
res_url = mGetMesh2Capability;
|
||||
res_url = mGetMeshCapability;
|
||||
}
|
||||
else if (!mLegacyGetMesh2Capability.empty() && mLegacyGetMeshVersion > 1)
|
||||
{
|
||||
res_url = mLegacyGetMesh2Capability;
|
||||
res_version = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
res_url = mGetMeshCapability;
|
||||
res_url = mLegacyGetMeshCapability;
|
||||
res_version = 1;
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
}
|
||||
|
||||
if (! res_url.empty())
|
||||
|
|
@ -1155,19 +1168,19 @@ 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 "
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LL_WARNS_ONCE(LOG_MESH) << "Current region does not have ViewerAsset capability! Cannot load "
|
||||
LL_WARNS_ONCE(LOG_MESH) << "Current region does not have ViewerAsset or GetMesh capability! Cannot load "
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
<< mesh_id << ".mesh" << LL_ENDL;
|
||||
}
|
||||
|
||||
*url = res_url;
|
||||
*version = res_version;
|
||||
*legacy_version = res_version; // <FS:Ansariel> [UDP Assets]
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
@ -1175,7 +1188,10 @@ 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,
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
|
||||
LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int legacy_cap_version,
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
size_t offset, size_t len,
|
||||
const LLCore::HttpHandler::ptr_t &handler)
|
||||
{
|
||||
|
|
@ -1186,16 +1202,17 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//handle = mHttpRequest->requestGetByteRange( mHttpPolicyClass,
|
||||
handle = mHttpRequest->requestGetByteRange( ((legacy_cap_version == 0 || legacy_cap_version == 2) ? mHttpPolicyClass : mHttpLegacyPolicyClass),
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
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;
|
||||
|
|
@ -1285,14 +1302,20 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//constructUrl(mesh_id, &http_url);
|
||||
int legacy_cap_version(0);
|
||||
constructUrl(mesh_id, &http_url, &legacy_cap_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
|
||||
LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (LLCORE_HTTP_HANDLE_INVALID == handle)
|
||||
{
|
||||
LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << mID
|
||||
|
|
@ -1378,14 +1401,20 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//constructUrl(mesh_id, &http_url);
|
||||
int legacy_cap_version(0);
|
||||
constructUrl(mesh_id, &http_url, &legacy_cap_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
|
||||
LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (LLCORE_HTTP_HANDLE_INVALID == handle)
|
||||
{
|
||||
LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << mID
|
||||
|
|
@ -1470,14 +1499,20 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//constructUrl(mesh_id, &http_url);
|
||||
int legacy_cap_version(0);
|
||||
constructUrl(mesh_id, &http_url, &legacy_cap_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
|
||||
LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (LLCORE_HTTP_HANDLE_INVALID == handle)
|
||||
{
|
||||
LL_WARNS(LOG_MESH) << "HTTP GET request failed for physics shape on mesh " << mID
|
||||
|
|
@ -1564,9 +1599,12 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//constructUrl(mesh_params.getSculptID(), &http_url);
|
||||
int legacy_cap_version(0);
|
||||
constructUrl(mesh_params.getSculptID(), &http_url, &legacy_cap_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
if (!http_url.empty())
|
||||
{
|
||||
|
|
@ -1575,7 +1613,10 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle handle = getByteRange(http_url, 0, MESH_HEADER_SIZE, handler);
|
||||
LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, 0, MESH_HEADER_SIZE, handler);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (LLCORE_HTTP_HANDLE_INVALID == handle)
|
||||
{
|
||||
LL_WARNS(LOG_MESH) << "HTTP GET request failed for mesh header " << mID
|
||||
|
|
@ -1651,14 +1692,20 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//constructUrl(mesh_id, &http_url);
|
||||
int legacy_cap_version(0);
|
||||
constructUrl(mesh_id, &http_url, &legacy_cap_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
|
||||
LLCore::HttpHandle handle = getByteRange(http_url, legacy_cap_version, offset, size, handler);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (LLCORE_HTTP_HANDLE_INVALID == handle)
|
||||
{
|
||||
LL_WARNS(LOG_MESH) << "HTTP GET request failed for LOD on mesh " << mID
|
||||
|
|
@ -3304,8 +3351,8 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3
|
|||
LLMeshRepository::LLMeshRepository()
|
||||
: mMeshMutex(NULL),
|
||||
mMeshThreadCount(0),
|
||||
mThread(NULL),
|
||||
mGetMeshVersion(2)
|
||||
mLegacyGetMeshVersion(0), // <FS:Ansariel> [UDP Assets]
|
||||
mThread(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -3488,70 +3535,78 @@ void LLMeshRepository::notifyLoadedMeshes()
|
|||
{ //called from main thread
|
||||
LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
|
||||
|
||||
if (1 == mGetMeshVersion)
|
||||
{
|
||||
// Legacy GetMesh operation with high connection concurrency
|
||||
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
||||
//LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests");
|
||||
static LLCachedControl<U32> meshMaxConcurrentRequests(gSavedSettings, "MeshMaxConcurrentRequests");
|
||||
//<FS:TS> FIRE-11451: Cap concurrent requests at a sane value
|
||||
if (meshMaxConcurrentRequests() > MESH_CONCURRENT_REQUEST_LIMIT)
|
||||
{
|
||||
U32 mesh_max_concurrent_requests_default = gSavedSettings.getControl("MeshMaxConcurrentRequests")->getDefault().asInteger();
|
||||
LLSD args;
|
||||
args["VALUE"] = llformat("%d", meshMaxConcurrentRequests());
|
||||
args["MAX"] = llformat("%d", MESH_CONCURRENT_REQUEST_LIMIT);
|
||||
args["DEFAULT"] = llformat("%d", mesh_max_concurrent_requests_default);
|
||||
args["DEBUGNAME"] = "MeshMaxConccurrentRequests";
|
||||
LLNotificationsUtil::add("MeshMaxConcurrentReqTooHigh", args);
|
||||
gSavedSettings.setU32("MeshMaxConcurrentRequests", mesh_max_concurrent_requests_default);
|
||||
}
|
||||
//</FS:TS> FIRE-11451
|
||||
LLMeshRepoThread::sMaxConcurrentRequests = meshMaxConcurrentRequests();
|
||||
// </FS:Ansariel>
|
||||
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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//// 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);
|
||||
|
||||
if (mLegacyGetMeshVersion == 1)
|
||||
{
|
||||
// Legacy GetMesh operation with high connection concurrency
|
||||
static LLCachedControl<U32> meshMaxConcurrentRequests(gSavedSettings, "MeshMaxConcurrentRequests");
|
||||
if (meshMaxConcurrentRequests() > MESH_CONCURRENT_REQUEST_LIMIT)
|
||||
{
|
||||
U32 mesh_max_concurrent_requests_default = gSavedSettings.getControl("MeshMaxConcurrentRequests")->getDefault().asInteger();
|
||||
LLSD args;
|
||||
args["VALUE"] = llformat("%d", meshMaxConcurrentRequests());
|
||||
args["MAX"] = llformat("%d", MESH_CONCURRENT_REQUEST_LIMIT);
|
||||
args["DEFAULT"] = llformat("%d", mesh_max_concurrent_requests_default);
|
||||
args["DEBUGNAME"] = "MeshMaxConccurrentRequests";
|
||||
LLNotificationsUtil::add("MeshMaxConcurrentReqTooHigh", args);
|
||||
gSavedSettings.setU32("MeshMaxConcurrentRequests", mesh_max_concurrent_requests_default);
|
||||
}
|
||||
LLMeshRepoThread::sMaxConcurrentRequests = 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);
|
||||
|
||||
static LLCachedControl<U32> mesh2MaxConcurrentRequests(gSavedSettings, "Mesh2MaxConcurrentRequests");
|
||||
if (mesh2MaxConcurrentRequests() > MESH2_CONCURRENT_REQUEST_LIMIT)
|
||||
{
|
||||
U32 mesh2_max_concurrent_requests_default = gSavedSettings.getControl("Mesh2MaxConcurrentRequests")->getDefault().asInteger();
|
||||
LLSD args;
|
||||
args["VALUE"] = llformat("%d", mesh2MaxConcurrentRequests());
|
||||
args["MAX"] = llformat("%d", MESH2_CONCURRENT_REQUEST_LIMIT);
|
||||
args["DEFAULT"] = llformat("%d", mesh2_max_concurrent_requests_default);
|
||||
args["DEBUGNAME"] = "Mesh2MaxConccurrentRequests";
|
||||
LLNotificationsUtil::add("MeshMaxConcurrentReqTooHigh", args);
|
||||
gSavedSettings.setU32("Mesh2MaxConcurrentRequests", mesh2_max_concurrent_requests_default);
|
||||
}
|
||||
LLMeshRepoThread::sMaxConcurrentRequests = 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);
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
// <FS:TM> Use faster LLCachedControls for frequently visited locations
|
||||
//LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("Mesh2MaxConcurrentRequests");
|
||||
static LLCachedControl<U32> mesh2MaxConcurrentRequests(gSavedSettings, "Mesh2MaxConcurrentRequests");
|
||||
//<FS:TS> FIRE-11451: Cap concurrent requests at a sane value
|
||||
if (mesh2MaxConcurrentRequests() > MESH2_CONCURRENT_REQUEST_LIMIT)
|
||||
{
|
||||
U32 mesh2_max_concurrent_requests_default = gSavedSettings.getControl("Mesh2MaxConcurrentRequests")->getDefault().asInteger();
|
||||
LLSD args;
|
||||
args["VALUE"] = llformat("%d", mesh2MaxConcurrentRequests());
|
||||
args["MAX"] = llformat("%d", MESH2_CONCURRENT_REQUEST_LIMIT);
|
||||
args["DEFAULT"] = llformat("%d", mesh2_max_concurrent_requests_default);
|
||||
args["DEBUGNAME"] = "Mesh2MaxConccurrentRequests";
|
||||
LLNotificationsUtil::add("MeshMaxConcurrentReqTooHigh", args);
|
||||
gSavedSettings.setU32("Mesh2MaxConcurrentRequests", mesh2_max_concurrent_requests_default);
|
||||
}
|
||||
//</FS:TS> FIRE-11451
|
||||
LLMeshRepoThread::sMaxConcurrentRequests = mesh2MaxConcurrentRequests();
|
||||
// </FS:TM>
|
||||
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(); )
|
||||
{
|
||||
|
|
@ -3656,16 +3711,25 @@ void LLMeshRepository::notifyLoadedMeshes()
|
|||
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
|
||||
{
|
||||
region_name = gAgent.getRegion()->getName();
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//const std::string mesh_cap(gAgent.getRegion()->getViewerAssetUrl());
|
||||
//mThread->setGetMeshCap(mesh_cap);
|
||||
//LL_DEBUGS(LOG_MESH) << "Retrieving caps for region '" << region_name
|
||||
// << "', ViewerAsset cap: " << mesh_cap
|
||||
// << LL_ENDL;
|
||||
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());
|
||||
const std::string legacy_mesh1_cap(gAgent.getRegion()->getCapability("GetMesh"));
|
||||
const std::string legacy_mesh2_cap(gAgent.getRegion()->getCapability("GetMesh2"));
|
||||
mLegacyGetMeshVersion = ((mesh_cap.empty() && legacy_mesh2_cap.empty()) || use_v1) ? 1 : (!mesh_cap.empty() ? 0 : 2);
|
||||
mThread->setGetMeshCap(mesh_cap, legacy_mesh1_cap, legacy_mesh2_cap, mLegacyGetMeshVersion);
|
||||
LL_DEBUGS(LOG_MESH) << "Retrieving caps for region '" << region_name
|
||||
<< "', GetMesh2: " << mesh2
|
||||
<< ", GetMesh: " << mesh1
|
||||
<< ", using version: " << mGetMeshVersion
|
||||
<< "', ViewerAsset cap: " << mesh_cap
|
||||
<< ", GetMesh2 cap: " << legacy_mesh2_cap
|
||||
<< ", GetMesh cap: " << legacy_mesh1_cap
|
||||
<< ", using version: " << mLegacyGetMeshVersion
|
||||
<< LL_ENDL;
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -281,16 +281,19 @@ 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 mHttpLegacyPolicyClass; // <FS:Ansariel> [UDP Assets]
|
||||
LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
|
||||
LLCore::HttpRequest::priority_t mHttpPriority;
|
||||
|
||||
typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set;
|
||||
http_request_set mHttpRequestSet; // Outstanding HTTP requests
|
||||
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
std::string mLegacyGetMeshCapability;
|
||||
std::string mLegacyGetMesh2Capability;
|
||||
int mLegacyGetMeshVersion;
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
std::string mGetMeshCapability;
|
||||
std::string mGetMesh2Capability;
|
||||
int mGetMeshVersion;
|
||||
|
||||
LLMeshRepoThread();
|
||||
~LLMeshRepoThread();
|
||||
|
|
@ -337,12 +340,16 @@ 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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//void setGetMeshCap(const std::string & get_mesh);
|
||||
void setGetMeshCap(const std::string & get_mesh, const std::string & legacy_get_mesh1, const std::string & legacy_get_mesh2, int legacy_pref_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
// Mutex: acquires mMutex
|
||||
void constructUrl(LLUUID mesh_id, std::string * url, int * version);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//void constructUrl(LLUUID mesh_id, std::string * url);
|
||||
void constructUrl(LLUUID mesh_id, std::string * url, int * legacy_version);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
private:
|
||||
// Issue a GET request to a URL with 'Range' header using
|
||||
|
|
@ -351,7 +358,10 @@ private:
|
|||
// or dispose of handler.
|
||||
//
|
||||
// Threads: Repo thread only
|
||||
LLCore::HttpHandle getByteRange(const std::string & url, int cap_version,
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//LLCore::HttpHandle getByteRange(const std::string & url,
|
||||
LLCore::HttpHandle getByteRange(const std::string & url, int legacy_cap_version,
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
size_t offset, size_t len,
|
||||
const LLCore::HttpHandler::ptr_t &handler);
|
||||
};
|
||||
|
|
@ -591,7 +601,8 @@ public:
|
|||
void uploadError(LLSD& args);
|
||||
void updateInventory(inventory_data data);
|
||||
|
||||
int mGetMeshVersion; // Shadows value in LLMeshRepoThread
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
int mLegacyGetMeshVersion; // Shadows value in LLMeshRepoThread
|
||||
};
|
||||
|
||||
extern LLMeshRepository gMeshRepo;
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@
|
|||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include "llstl.h"
|
||||
|
||||
#include "lltexturefetch.h"
|
||||
|
||||
#include "lldir.h"
|
||||
|
|
@ -488,7 +486,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(); }
|
||||
|
|
@ -827,7 +825,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();
|
||||
|
|
@ -838,7 +836,7 @@ public:
|
|||
const std::string mCapsURL;
|
||||
const LLUUID mSessionID;
|
||||
const LLUUID mAgentID;
|
||||
LLViewerAssetStats * mMainStats;
|
||||
LLSD mStatsSD;
|
||||
|
||||
private:
|
||||
LLCore::HttpHandler::ptr_t mHandler;
|
||||
|
|
@ -1366,7 +1364,13 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||
|
||||
if (region)
|
||||
{
|
||||
std::string http_url = region->getHttpUrl() ;
|
||||
std::string http_url = region->getViewerAssetUrl();
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
if (http_url.empty())
|
||||
{
|
||||
http_url = region->getHttpUrl();
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (!http_url.empty())
|
||||
{
|
||||
if (mFTType != FTT_DEFAULT)
|
||||
|
|
@ -1441,6 +1445,20 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||
}
|
||||
if (processSimulatorPackets())
|
||||
{
|
||||
// Capture some measure of total size for metrics
|
||||
F64 byte_count = 0;
|
||||
if (mLastPacket >= mFirstPacket)
|
||||
{
|
||||
for (S32 i=mFirstPacket; i<=mLastPacket; i++)
|
||||
{
|
||||
llassert_always((i>=0) && (i<mPackets.size()));
|
||||
if (mPackets[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())
|
||||
|
|
@ -1458,7 +1476,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||
}
|
||||
setState(DECODE_IMAGE);
|
||||
mWriteToCacheState = SHOULD_WRITE;
|
||||
recordTextureDone(false);
|
||||
|
||||
recordTextureDone(false, byte_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2108,7 +2127,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
|
|||
|
||||
mFetcher->removeFromHTTPQueue(mID, data_size);
|
||||
|
||||
recordTextureDone(true);
|
||||
recordTextureDone(true, data_size);
|
||||
} // -Mw
|
||||
|
||||
|
||||
|
|
@ -2237,6 +2256,7 @@ bool LLTextureFetchWorker::processSimulatorPackets()
|
|||
S32 buffer_size = mFormattedImage->getDataSize();
|
||||
for (S32 i = mFirstPacket; i<=mLastPacket; i++)
|
||||
{
|
||||
llassert_always((i>=0) && (i<mPackets.size()));
|
||||
llassert_always(mPackets[i]);
|
||||
buffer_size += mPackets[i]->mSize;
|
||||
}
|
||||
|
|
@ -2508,14 +2528,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,
|
||||
|
|
@ -3878,9 +3899,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);
|
||||
}
|
||||
|
|
@ -3989,22 +4010,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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4025,26 +4044,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)
|
||||
|
|
@ -4055,8 +4067,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.
|
||||
|
|
@ -4064,7 +4081,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
|
|||
fetcher->getMetricsPolicyClass(),
|
||||
report_priority,
|
||||
mCapsURL,
|
||||
sd,
|
||||
mStatsSD,
|
||||
LLCore::HttpOptions::ptr_t(),
|
||||
fetcher->getMetricsHeaders(),
|
||||
mHandler);
|
||||
|
|
@ -4078,7 +4095,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;
|
||||
|
|
@ -4595,7 +4612,13 @@ void LLTextureFetchDebugger::debugHTTP()
|
|||
return;
|
||||
}
|
||||
|
||||
mHTTPUrl = region->getHttpUrl();
|
||||
mHTTPUrl = region->getViewerAssetUrl();
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
if (mHTTPUrl.empty())
|
||||
{
|
||||
mHTTPUrl = region->getHttpUrl();
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
if (mHTTPUrl.empty())
|
||||
{
|
||||
LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,19 @@
|
|||
#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 "llcoproceduremanager.h"
|
||||
#include "lleventcoro.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llworld.h"
|
||||
|
||||
#include "llviewernetwork.h" // <FS:Ansariel> [UDP Assets]
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLViewerAssetRequest
|
||||
|
|
@ -51,268 +61,284 @@
|
|||
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;
|
||||
};
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLViewerAssetStorage
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
// Unused?
|
||||
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),
|
||||
mAssetCoroCount(0),
|
||||
mCountRequests(0),
|
||||
mCountStarted(0),
|
||||
mCountCompleted(0),
|
||||
mCountSucceeded(0),
|
||||
mTotalBytesFetched(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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),
|
||||
mAssetCoroCount(0),
|
||||
mCountRequests(0),
|
||||
mCountStarted(0),
|
||||
mCountCompleted(0),
|
||||
mCountSucceeded(0),
|
||||
mTotalBytesFetched(0)
|
||||
{
|
||||
}
|
||||
|
||||
// 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;
|
||||
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();
|
||||
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;
|
||||
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)" );
|
||||
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 );
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
// 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" );
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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);
|
||||
LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
|
||||
|
||||
file.setMaxSize(size);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
// 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:
|
||||
// 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" );
|
||||
fclose(fp); // <FS:ND/> Do not leak the file handle.
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
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" );
|
||||
fclose(fp); // <FS:ND/> Do not leak the file handle.
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -335,56 +361,256 @@ 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 (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);
|
||||
}
|
||||
}
|
||||
mCountRequests++;
|
||||
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)
|
||||
{
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
//bool with_http = true;
|
||||
//bool is_temp = false;
|
||||
//LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
|
||||
LLCoprocedureManager::instance().enqueueCoprocedure("AssetStorage","LLViewerAssetStorage::assetRequestCoro",
|
||||
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerAssetStorage::capsRecvForRegion(const LLUUID& region_id, std::string pumpname)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
struct LLScopedIncrement
|
||||
{
|
||||
LLScopedIncrement(S32& counter):
|
||||
mCounter(counter)
|
||||
{
|
||||
++mCounter;
|
||||
}
|
||||
~LLScopedIncrement()
|
||||
{
|
||||
--mCounter;
|
||||
}
|
||||
S32& mCounter;
|
||||
};
|
||||
|
||||
void LLViewerAssetStorage::assetRequestCoro(
|
||||
LLViewerAssetRequest *req,
|
||||
const LLUUID uuid,
|
||||
LLAssetType::EType atype,
|
||||
LLGetAssetCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
LLScopedIncrement coro_count_boost(mAssetCoroCount);
|
||||
mCountStarted++;
|
||||
|
||||
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())
|
||||
{
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
if (!LLGridManager::instance().isInSecondLife() && mUpstreamHost.isOk())
|
||||
{
|
||||
req->mWithHTTP = false;
|
||||
|
||||
// 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("ViewerAsset") << "Starting transfer for " << uuid << LL_ENDL;
|
||||
LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
|
||||
ttcp->requestTransfer(spa, tpvf, 100.f + (req->mIsPriority ? 1.f : 0.f));
|
||||
|
||||
bool with_http = false;
|
||||
bool is_temp = false;
|
||||
LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
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);
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
return;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
bool with_http = false;
|
||||
bool is_temp = false;
|
||||
LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
|
||||
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);
|
||||
|
||||
if (LLApp::isQuitting())
|
||||
{
|
||||
// Bail out if result arrives after shutdown has been started.
|
||||
return;
|
||||
}
|
||||
|
||||
mCountCompleted++;
|
||||
|
||||
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)
|
||||
{
|
||||
mTotalBytesFetched += size;
|
||||
|
||||
// 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("ViewerAsset") << "Failure in vf.write()" << LL_ENDL;
|
||||
result_code = LL_ERR_ASSET_REQUEST_FAILED;
|
||||
ext_status = LL_EXSTAT_VFS_CORRUPT;
|
||||
}
|
||||
else 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
|
||||
{
|
||||
mCountSucceeded++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void LLViewerAssetStorage::logAssetStorageInfo()
|
||||
{
|
||||
LLMemory::logMemoryInfo(true);
|
||||
LL_INFOS("AssetStorage") << "Active coros " << mAssetCoroCount << LL_ENDL;
|
||||
LL_INFOS("AssetStorage") << "mPendingDownloads size " << mPendingDownloads.size() << LL_ENDL;
|
||||
LL_INFOS("AssetStorage") << "mCountStarted " << mCountStarted << LL_ENDL;
|
||||
LL_INFOS("AssetStorage") << "mCountCompleted " << mCountCompleted << LL_ENDL;
|
||||
LL_INFOS("AssetStorage") << "mCountSucceeded " << mCountSucceeded << LL_ENDL;
|
||||
LL_INFOS("AssetStorage") << "mTotalBytesFetched " << mTotalBytesFetched << LL_ENDL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,12 @@
|
|||
#define LLVIEWERASSETSTORAGE_H
|
||||
|
||||
#include "llassetstorage.h"
|
||||
//#include "curl/curl.h"
|
||||
#include "llcorehttputil.h"
|
||||
|
||||
class LLVFile;
|
||||
|
||||
class LLViewerAssetRequest;
|
||||
|
||||
class LLViewerAssetStorage : public LLAssetStorage
|
||||
{
|
||||
public:
|
||||
|
|
@ -41,7 +43,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 +66,6 @@ public:
|
|||
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
protected:
|
||||
using LLAssetStorage::_queueDataRequest;
|
||||
|
||||
// virtual
|
||||
void _queueDataRequest(const LLUUID& uuid,
|
||||
LLAssetType::EType type,
|
||||
|
|
@ -74,6 +73,33 @@ 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);
|
||||
|
||||
void logAssetStorageInfo();
|
||||
|
||||
std::string mViewerAssetUrl;
|
||||
S32 mAssetCoroCount;
|
||||
S32 mCountRequests;
|
||||
S32 mCountStarted;
|
||||
S32 mCountCompleted;
|
||||
S32 mCountSucceeded;
|
||||
S64 mTotalBytesFetched;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ const F32 TELEPORT_EXPIRY_PER_ATTACHMENT = 3.f;
|
|||
U32 gRecentFrameCount = 0; // number of 'recent' frames
|
||||
LLFrameTimer gRecentFPSTime;
|
||||
LLFrameTimer gRecentMemoryTime;
|
||||
LLFrameTimer gAssetStorageLogTime;
|
||||
|
||||
// Rendering stuff
|
||||
void pre_show_depth_buffer();
|
||||
|
|
@ -248,6 +249,12 @@ void display_stats()
|
|||
LLMemory::logMemoryInfo(TRUE) ;
|
||||
gRecentMemoryTime.reset();
|
||||
}
|
||||
F32 asset_storage_log_freq = gSavedSettings.getF32("AssetStorageLogFrequency");
|
||||
if (asset_storage_log_freq > 0.f && gAssetStorageLogTime.getElapsedTimeF32() >= asset_storage_log_freq)
|
||||
{
|
||||
gAssetStorageLogTime.reset();
|
||||
gAssetStorage->logAssetStorageInfo();
|
||||
}
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_PICK("Picking");
|
||||
|
|
|
|||
|
|
@ -533,7 +533,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
|
|||
mColoName("unknown"),
|
||||
mProductSKU("unknown"),
|
||||
mProductName("unknown"),
|
||||
mHttpUrl(""),
|
||||
mHttpUrl(""), // <FS:Ansariel> [UDP Assets]
|
||||
mViewerAssetUrl(""),
|
||||
mCacheLoaded(FALSE),
|
||||
mCacheDirty(FALSE),
|
||||
mReleaseNotesRequested(FALSE),
|
||||
|
|
@ -3036,12 +3037,14 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
capabilityNames.append("IsExperienceAdmin");
|
||||
capabilityNames.append("IsExperienceContributor");
|
||||
capabilityNames.append("RegionExperiences");
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
capabilityNames.append("GetMesh");
|
||||
capabilityNames.append("GetMesh2");
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
capabilityNames.append("GetMetadata");
|
||||
capabilityNames.append("GetObjectCost");
|
||||
capabilityNames.append("GetObjectPhysicsData");
|
||||
capabilityNames.append("GetTexture");
|
||||
capabilityNames.append("GetTexture"); // <FS:Ansariel> [UDP Assets]
|
||||
capabilityNames.append("GroupAPIv1");
|
||||
capabilityNames.append("GroupMemberData");
|
||||
capabilityNames.append("GroupProposalBallot");
|
||||
|
|
@ -3088,6 +3091,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");
|
||||
|
|
@ -3154,10 +3158,16 @@ 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;
|
||||
}
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
else if (name == "GetTexure")
|
||||
{
|
||||
mHttpUrl = url;
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3167,10 +3177,16 @@ 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;
|
||||
}
|
||||
// <FS:Ansariel> [UDP Assets]
|
||||
else if (name == "GetTexure")
|
||||
{
|
||||
mHttpUrl = url;
|
||||
}
|
||||
// </FS:Ansariel> [UDP Assets]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -379,7 +379,8 @@ 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 getHttpUrl() const { return mHttpUrl; } // <FS:Ansariel> [UDP Assets]
|
||||
std::string getViewerAssetUrl() const { return mViewerAssetUrl; }
|
||||
|
||||
U32 getNumOfVisibleGroups() const;
|
||||
U32 getNumOfActiveCachedObjects() const;
|
||||
|
|
@ -534,7 +535,8 @@ private:
|
|||
std::string mColoName;
|
||||
std::string mProductSKU;
|
||||
std::string mProductName;
|
||||
std::string mHttpUrl ;
|
||||
std::string mHttpUrl; // <FS:Ansariel> [UDP Assets]
|
||||
std::string mViewerAssetUrl ;
|
||||
|
||||
// Maps local ids to cache entries.
|
||||
// Regions can have order 10,000 objects, so assume
|
||||
|
|
|
|||
|
|
@ -10401,5 +10401,3 @@ void LLVOAvatar::setIsUsingServerBakes(BOOL newval)
|
|||
appearance_version_param->setWeight(newval ? 1.0 : 0.0, false);
|
||||
}
|
||||
// </FS:Ansariel> [Legacy Bake]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "lltut.h"
|
||||
|
|
@ -697,4 +698,5 @@ int main(int argc, char **argv)
|
|||
return retval;
|
||||
|
||||
//delete mycallback;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
#!runpy.sh
|
||||
|
||||
"""\
|
||||
|
||||
This module contains tools for analyzing viewer asset metrics logs produced by the viewer.
|
||||
|
||||
$LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
Second Life Viewer Source Code
|
||||
Copyright (C) 2016, Linden Research, Inc.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
version 2.1 of the License only.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from lxml import etree
|
||||
from llbase import llsd
|
||||
|
||||
def get_metrics_record(infiles):
|
||||
for filename in args.infiles:
|
||||
f = open(filename)
|
||||
# get an iterable
|
||||
context = etree.iterparse(f, events=("start", "end"))
|
||||
|
||||
# turn it into an iterator
|
||||
context = iter(context)
|
||||
|
||||
# get the root element
|
||||
event, root = context.next()
|
||||
try:
|
||||
for event, elem in context:
|
||||
if event == "end" and elem.tag == "llsd":
|
||||
xmlstr = etree.tostring(elem, encoding="utf8", method="xml")
|
||||
sd = llsd.parse_xml(xmlstr)
|
||||
yield sd
|
||||
except etree.XMLSyntaxError:
|
||||
print "Fell off end of document"
|
||||
|
||||
f.close()
|
||||
|
||||
def update_stats(stats,rec):
|
||||
for region in rec["regions"]:
|
||||
region_key = (region["grid_x"],region["grid_y"])
|
||||
#print "region",region_key
|
||||
for field, val in region.iteritems():
|
||||
if field in ["duration","grid_x","grid_y"]:
|
||||
continue
|
||||
if field == "fps":
|
||||
# handle fps record as special case
|
||||
pass
|
||||
else:
|
||||
#print "field",field
|
||||
stats.setdefault(field,{})
|
||||
type_stats = stats.get(field)
|
||||
newcount = val["resp_count"]
|
||||
#print "field",field,"add count",newcount
|
||||
type_stats["count"] = type_stats.get("count",0) + val["resp_count"]
|
||||
#print "field",field,"count",type_stats["count"]
|
||||
if (newcount>0):
|
||||
type_stats["sum"] = type_stats.get("sum",0) + val["resp_count"] * val["resp_mean"]
|
||||
type_stats["sum_bytes"] = type_stats.get("sum_bytes",0) + val["resp_count"] * val.get("resp_mean_bytes",0)
|
||||
type_stats["enqueued"] = type_stats.get("enqueued",0) + val["enqueued"]
|
||||
type_stats["dequeued"] = type_stats.get("dequeued",0) + val["dequeued"]
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
parser = argparse.ArgumentParser(description="process metric xml files for viewer asset fetching")
|
||||
parser.add_argument("--verbose", action="store_true",help="verbose flag")
|
||||
parser.add_argument("infiles", nargs="+", help="name of .xml files to process")
|
||||
args = parser.parse_args()
|
||||
|
||||
#print "process files:",args.infiles
|
||||
|
||||
stats = {}
|
||||
for rec in get_metrics_record(args.infiles):
|
||||
#print "record",rec
|
||||
|
||||
update_stats(stats,rec)
|
||||
|
||||
for key in sorted(stats.keys()):
|
||||
val = stats[key]
|
||||
if val["count"] > 0:
|
||||
print key,"count",val["count"],"mean_time",val["sum"]/val["count"],"mean_bytes",val["sum_bytes"]/val["count"],"net bytes/sec",val["sum_bytes"]/val["sum"],"enqueued",val["enqueued"],"dequeued",val["dequeued"]
|
||||
else:
|
||||
print key,"count",val["count"],"enqueued",val["enqueued"],"dequeued",val["dequeued"]
|
||||
|
||||
Loading…
Reference in New Issue