summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags1
-rwxr-xr-xdoc/contributions.txt1
-rw-r--r--indra/llcommon/llassettype.h2
-rw-r--r--indra/llcommon/llerror.cpp2
-rw-r--r--indra/llmessage/llassetstorage.cpp2381
-rw-r--r--indra/llmessage/llassetstorage.h112
-rw-r--r--indra/newview/app_settings/settings.xml20
-rw-r--r--indra/newview/llappviewer.cpp21
-rw-r--r--indra/newview/llmeshrepository.cpp147
-rw-r--r--indra/newview/llmeshrepository.h13
-rw-r--r--indra/newview/lltexturefetch.cpp95
-rw-r--r--indra/newview/lltexturefetch.h2
-rw-r--r--indra/newview/llviewerassetstats.cpp398
-rw-r--r--indra/newview/llviewerassetstats.h59
-rw-r--r--indra/newview/llviewerassetstorage.cpp758
-rw-r--r--indra/newview/llviewerassetstorage.h34
-rw-r--r--indra/newview/llviewerdisplay.cpp7
-rw-r--r--indra/newview/llviewerregion.cpp14
-rw-r--r--indra/newview/llviewerregion.h4
-rw-r--r--indra/newview/llvoavatar.cpp3
-rw-r--r--indra/newview/tests/llviewerassetstats_test.cpp26
-rw-r--r--indra/test/test.cpp2
-rw-r--r--scripts/metrics/viewer_asset_logs.py102
23 files changed, 2100 insertions, 2104 deletions
diff --git a/.hgtags b/.hgtags
index 3f2adaf5dd..90a21a647f 100755
--- a/.hgtags
+++ b/.hgtags
@@ -527,3 +527,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
diff --git a/doc/contributions.txt b/doc/contributions.txt
index eb012ee318..79ff7161f6 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1302,6 +1302,7 @@ Sovereign Engineer
MAINT-6218
MAINT-6913
STORM-2143
+ MAINT-7343
SpacedOut Frye
VWR-34
VWR-45
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 3a4b5dad18..b849be9f16 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -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:
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 2ddb3edbdd..cfca42809a 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -572,7 +572,7 @@ namespace LLError
mFunctionString += std::string(mFunction) + ":";
for (size_t i = 0; i < mTagCount; i++)
{
- mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : ",");
+ mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? " " : ",");
}
}
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index bcf4e52b8f..596d57c7b7 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -60,64 +60,60 @@ static LLTrace::CountStatHandle<> sFailedDownloadCount("faileddownloads", "Numbe
const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-000000000010"));
-const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
-
-LLTempAssetStorage::~LLTempAssetStorage()
-{
-}
+const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
///----------------------------------------------------------------------------
/// LLAssetInfo
///----------------------------------------------------------------------------
LLAssetInfo::LLAssetInfo( void )
-: mDescription(),
- mName(),
- mUuid(),
- mCreatorID(),
- mType( LLAssetType::AT_NONE )
+ : mDescription(),
+ mName(),
+ mUuid(),
+ mCreatorID(),
+ mType( LLAssetType::AT_NONE )
{ }
LLAssetInfo::LLAssetInfo( const LLUUID& object_id, const LLUUID& creator_id,
- LLAssetType::EType type, const char* name,
- const char* desc )
-: mUuid( object_id ),
- mCreatorID( creator_id ),
- mType( type )
+ LLAssetType::EType type, const char* name,
+ const char* desc )
+ : mUuid( object_id ),
+ mCreatorID( creator_id ),
+ mType( type )
{
- setName( name );
- setDescription( desc );
+ setName( name );
+ setDescription( desc );
}
LLAssetInfo::LLAssetInfo( const LLNameValue& nv )
{
- setFromNameValue( nv );
+ setFromNameValue( nv );
}
// make sure the name is short enough, and strip all pipes since they
// are reserved characters in our inventory tracking system.
void LLAssetInfo::setName( const std::string& name )
{
- if( !name.empty() )
- {
- mName.assign( name, 0, llmin((U32)name.size(), (U32)DB_INV_ITEM_NAME_STR_LEN) );
- mName.erase( std::remove(mName.begin(), mName.end(), '|'),
- mName.end() );
- }
+ if( !name.empty() )
+ {
+ mName.assign( name, 0, llmin((U32)name.size(), (U32)DB_INV_ITEM_NAME_STR_LEN) );
+ mName.erase( std::remove(mName.begin(), mName.end(), '|'),
+ mName.end() );
+ }
}
// make sure the name is short enough, and strip all pipes since they
// are reserved characters in our inventory tracking system.
void LLAssetInfo::setDescription( const std::string& desc )
{
- if( !desc.empty() )
- {
- mDescription.assign( desc, 0, llmin((U32)desc.size(),
- (U32)DB_INV_ITEM_DESC_STR_LEN) );
- mDescription.erase( std::remove(mDescription.begin(),
- mDescription.end(), '|'),
- mDescription.end() );
- }
+ if( !desc.empty() )
+ {
+ mDescription.assign( desc, 0, llmin((U32)desc.size(),
+ (U32)DB_INV_ITEM_DESC_STR_LEN) );
+ mDescription.erase( std::remove(mDescription.begin(),
+ mDescription.end(), '|'),
+ mDescription.end() );
+ }
}
// Assets (aka potential inventory items) can be applied to an
@@ -130,31 +126,31 @@ void LLAssetInfo::setDescription( const std::string& desc )
// value=<creatorid>|<name>|<description>|
void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
{
- std::string str;
- std::string buf;
- std::string::size_type pos1;
- std::string::size_type pos2;
-
- // convert the name to useful information
- str.assign( nv.mName );
- pos1 = str.find('|');
- buf.assign( str, 0, pos1++ );
- mType = LLAssetType::lookup( buf );
- buf.assign( str, pos1, std::string::npos );
- mUuid.set( buf );
-
- // convert the value to useful information
- str.assign( nv.getAsset() );
- pos1 = str.find('|');
- buf.assign( str, 0, pos1++ );
- mCreatorID.set( buf );
- pos2 = str.find( '|', pos1 );
- buf.assign( str, pos1, (pos2++) - pos1 );
- setName( buf );
- buf.assign( str, pos2, std::string::npos );
- setDescription( buf );
- LL_DEBUGS("AssetStorage") << "uuid: " << mUuid << LL_ENDL;
- LL_DEBUGS("AssetStorage") << "creator: " << mCreatorID << LL_ENDL;
+ std::string str;
+ std::string buf;
+ std::string::size_type pos1;
+ std::string::size_type pos2;
+
+ // convert the name to useful information
+ str.assign( nv.mName );
+ pos1 = str.find('|');
+ buf.assign( str, 0, pos1++ );
+ mType = LLAssetType::lookup( buf );
+ buf.assign( str, pos1, std::string::npos );
+ mUuid.set( buf );
+
+ // convert the value to useful information
+ str.assign( nv.getAsset() );
+ pos1 = str.find('|');
+ buf.assign( str, 0, pos1++ );
+ mCreatorID.set( buf );
+ pos2 = str.find( '|', pos1 );
+ buf.assign( str, pos1, (pos2++) - pos1 );
+ setName( buf );
+ buf.assign( str, pos2, std::string::npos );
+ setDescription( buf );
+ LL_DEBUGS("AssetStorage") << "uuid: " << mUuid << LL_ENDL;
+ LL_DEBUGS("AssetStorage") << "creator: " << mCreatorID << LL_ENDL;
}
///----------------------------------------------------------------------------
@@ -162,15 +158,15 @@ void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
///----------------------------------------------------------------------------
LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType type)
-: mUUID(uuid),
-mType(type),
-mDownCallback(NULL),
-mUserData(NULL),
-mHost(),
-mIsTemp(FALSE),
-mIsPriority(FALSE),
-mDataSentInFirstPacket(FALSE),
-mDataIsInVFS(FALSE)
+ : mUUID(uuid),
+ mType(type),
+ mDownCallback(NULL),
+ mUserData(NULL),
+ mHost(),
+ mIsTemp(FALSE),
+ mIsPriority(FALSE),
+ mDataSentInFirstPacket(FALSE),
+ mDataIsInVFS(FALSE)
{
// Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
// running a message system loop.
@@ -194,12 +190,13 @@ LLBaseDownloadRequest* LLBaseDownloadRequest::getCopy()
///----------------------------------------------------------------------------
LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
-: LLBaseDownloadRequest(uuid, type),
- mUpCallback( NULL ),
- mInfoCallback( NULL ),
- mIsLocal(FALSE),
- mIsUserWaiting(FALSE),
- mTimeout(LL_ASSET_STORAGE_TIMEOUT)
+ : LLBaseDownloadRequest(uuid, type),
+ mUpCallback( NULL ),
+ mInfoCallback( NULL ),
+ mIsLocal(FALSE),
+ mIsUserWaiting(FALSE),
+ mTimeout(LL_ASSET_STORAGE_TIMEOUT),
+ mBytesFetched(0)
{
}
@@ -211,31 +208,31 @@ LLAssetRequest::~LLAssetRequest()
// virtual
LLSD LLAssetRequest::getTerseDetails() const
{
- LLSD sd;
- sd["asset_id"] = getUUID();
- sd["type_long"] = LLAssetType::lookupHumanReadable(getType());
- sd["type"] = LLAssetType::lookup(getType());
- sd["time"] = mTime.value();
- time_t timestamp = (time_t) mTime.value();
- std::ostringstream time_string;
- time_string << ctime(&timestamp);
- sd["time_string"] = time_string.str();
- return sd;
+ LLSD sd;
+ sd["asset_id"] = getUUID();
+ sd["type_long"] = LLAssetType::lookupHumanReadable(getType());
+ sd["type"] = LLAssetType::lookup(getType());
+ sd["time"] = mTime.value();
+ time_t timestamp = (time_t) mTime.value();
+ std::ostringstream time_string;
+ time_string << ctime(&timestamp);
+ sd["time_string"] = time_string.str();
+ return sd;
}
// virtual
LLSD LLAssetRequest::getFullDetails() const
{
- LLSD sd = getTerseDetails();
- sd["host"] = mHost.getIPandPort();
- sd["requesting_agent"] = mRequestingAgentID;
- sd["is_temp"] = mIsTemp;
- sd["is_local"] = mIsLocal;
- sd["is_priority"] = mIsPriority;
- sd["data_send_in_first_packet"] = mDataSentInFirstPacket;
- sd["data_is_in_vfs"] = mDataIsInVFS;
-
- return sd;
+ LLSD sd = getTerseDetails();
+ sd["host"] = mHost.getIPandPort();
+ sd["requesting_agent"] = mRequestingAgentID;
+ sd["is_temp"] = mIsTemp;
+ sd["is_local"] = mIsLocal;
+ sd["is_priority"] = mIsPriority;
+ sd["data_send_in_first_packet"] = mDataSentInFirstPacket;
+ sd["data_is_in_vfs"] = mDataIsInVFS;
+
+ return sd;
}
LLBaseDownloadRequest* LLAssetRequest::getCopy()
@@ -248,7 +245,7 @@ LLBaseDownloadRequest* LLAssetRequest::getCopy()
///----------------------------------------------------------------------------
LLInvItemRequest::LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType type)
-: LLBaseDownloadRequest(uuid, type)
+ : LLBaseDownloadRequest(uuid, type)
{
}
@@ -267,9 +264,9 @@ LLBaseDownloadRequest* LLInvItemRequest::getCopy()
///----------------------------------------------------------------------------
LLEstateAssetRequest::LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType atype,
- EstateAssetType etype)
-: LLBaseDownloadRequest(uuid, atype),
- mEstateAssetType(etype)
+ EstateAssetType etype)
+ : LLBaseDownloadRequest(uuid, atype),
+ mEstateAssetType(etype)
{
}
@@ -299,152 +296,150 @@ LLBaseDownloadRequest* LLEstateAssetRequest::getCopy()
LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, LLVFS *static_vfs, const LLHost &upstream_host)
{
- _init(msg, xfer, vfs, static_vfs, upstream_host);
+ _init(msg, xfer, vfs, static_vfs, upstream_host);
}
-
LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
- LLVFS *vfs, LLVFS *static_vfs)
+ LLVFS *vfs, LLVFS *static_vfs)
{
- _init(msg, xfer, vfs, static_vfs, LLHost());
+ _init(msg, xfer, vfs, static_vfs, LLHost());
}
-
void LLAssetStorage::_init(LLMessageSystem *msg,
- LLXferManager *xfer,
- LLVFS *vfs,
- LLVFS *static_vfs,
- const LLHost &upstream_host)
+ LLXferManager *xfer,
+ LLVFS *vfs,
+ LLVFS *static_vfs,
+ const LLHost &upstream_host)
{
- mShutDown = FALSE;
- mMessageSys = msg;
- mXferManager = xfer;
- mVFS = vfs;
- mStaticVFS = static_vfs;
-
- setUpstream(upstream_host);
- msg->setHandlerFuncFast(_PREHASH_AssetUploadComplete, processUploadComplete, (void **)this);
+ mShutDown = FALSE;
+ mMessageSys = msg;
+ mXferManager = xfer;
+ mVFS = vfs;
+ mStaticVFS = static_vfs;
+
+ setUpstream(upstream_host);
+ msg->setHandlerFuncFast(_PREHASH_AssetUploadComplete, processUploadComplete, (void **)this);
}
LLAssetStorage::~LLAssetStorage()
{
- mShutDown = TRUE;
-
- _cleanupRequests(TRUE, LL_ERR_CIRCUIT_GONE);
-
- if (gMessageSystem)
- {
- // Warning! This won't work if there's more than one asset storage.
- // unregister our callbacks with the message system
- gMessageSystem->setHandlerFuncFast(_PREHASH_AssetUploadComplete, NULL, NULL);
- }
-
- // Clear the toxic asset map
- mToxicAssetMap.clear();
+ mShutDown = TRUE;
+
+ _cleanupRequests(TRUE, LL_ERR_CIRCUIT_GONE);
+
+ if (gMessageSystem)
+ {
+ // Warning! This won't work if there's more than one asset storage.
+ // unregister our callbacks with the message system
+ gMessageSystem->setHandlerFuncFast(_PREHASH_AssetUploadComplete, NULL, NULL);
+ }
+
+ // Clear the toxic asset map
+ mToxicAssetMap.clear();
}
void LLAssetStorage::setUpstream(const LLHost &upstream_host)
{
- LL_DEBUGS("AppInit") << "AssetStorage: Setting upstream provider to " << upstream_host << LL_ENDL;
-
- mUpstreamHost = upstream_host;
+ LL_DEBUGS("AppInit") << "AssetStorage: Setting upstream provider to " << upstream_host << LL_ENDL;
+
+ mUpstreamHost = upstream_host;
}
void LLAssetStorage::checkForTimeouts()
{
- _cleanupRequests(FALSE, LL_ERR_TCP_TIMEOUT);
+ _cleanupRequests(FALSE, LL_ERR_TCP_TIMEOUT);
}
void LLAssetStorage::_cleanupRequests(BOOL all, S32 error)
{
- F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
-
- request_list_t timed_out;
- S32 rt;
- for (rt = 0; rt < RT_COUNT; rt++)
- {
- request_list_t* requests = getRequestList((ERequestType)rt);
- for (request_list_t::iterator iter = requests->begin();
- iter != requests->end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* tmp = *curiter;
- // if all is true, we want to clean up everything
- // otherwise just check for timed out requests
- // EXCEPT for upload timeouts
- if (all
- || ((RT_DOWNLOAD == rt)
- && LL_ASSET_STORAGE_TIMEOUT < (mt_secs - tmp->mTime)))
- {
- LL_WARNS() << "Asset " << getRequestName((ERequestType)rt) << " request "
- << (all ? "aborted" : "timed out") << " for "
- << tmp->getUUID() << "."
- << LLAssetType::lookup(tmp->getType()) << LL_ENDL;
-
- timed_out.push_front(tmp);
- iter = requests->erase(curiter);
- }
- }
- }
-
- LLAssetInfo info;
- for (request_list_t::iterator iter = timed_out.begin();
- iter != timed_out.end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* tmp = *curiter;
- if (tmp->mUpCallback)
- {
- tmp->mUpCallback(tmp->getUUID(), tmp->mUserData, error, LL_EXSTAT_NONE);
- }
- if (tmp->mDownCallback)
- {
- tmp->mDownCallback(mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, error, LL_EXSTAT_NONE);
- }
- if (tmp->mInfoCallback)
- {
- tmp->mInfoCallback(&info, tmp->mUserData, error);
- }
- delete tmp;
- }
+ F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
+
+ request_list_t timed_out;
+ S32 rt;
+ for (rt = 0; rt < RT_COUNT; rt++)
+ {
+ request_list_t* requests = getRequestList((ERequestType)rt);
+ for (request_list_t::iterator iter = requests->begin();
+ iter != requests->end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* tmp = *curiter;
+ // if all is true, we want to clean up everything
+ // otherwise just check for timed out requests
+ // EXCEPT for upload timeouts
+ if (all
+ || ((RT_DOWNLOAD == rt)
+ && LL_ASSET_STORAGE_TIMEOUT < (mt_secs - tmp->mTime)))
+ {
+ LL_WARNS("AssetStorage") << "Asset " << getRequestName((ERequestType)rt) << " request "
+ << (all ? "aborted" : "timed out") << " for "
+ << tmp->getUUID() << "."
+ << LLAssetType::lookup(tmp->getType()) << LL_ENDL;
+
+ timed_out.push_front(tmp);
+ iter = requests->erase(curiter);
+ }
+ }
+ }
+
+ LLAssetInfo info;
+ for (request_list_t::iterator iter = timed_out.begin();
+ iter != timed_out.end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* tmp = *curiter;
+ if (tmp->mUpCallback)
+ {
+ tmp->mUpCallback(tmp->getUUID(), tmp->mUserData, error, LL_EXSTAT_NONE);
+ }
+ if (tmp->mDownCallback)
+ {
+ tmp->mDownCallback(mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, error, LL_EXSTAT_NONE);
+ }
+ if (tmp->mInfoCallback)
+ {
+ tmp->mInfoCallback(&info, tmp->mUserData, error);
+ }
+ delete tmp;
+ }
}
BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type)
{
- return mStaticVFS->getExists(uuid, type) || mVFS->getExists(uuid, type);
+ return mStaticVFS->getExists(uuid, type) || mVFS->getExists(uuid, type);
}
bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
- LLGetAssetCallback callback, void *user_data)
-{
- if (user_data)
- {
- // The *user_data should not be passed without a callback to clean it up.
- llassert(callback != NULL);
- }
-
- BOOL exists = mStaticVFS->getExists(uuid, type);
- if (exists)
- {
- LLVFile file(mStaticVFS, uuid, type);
- U32 size = file.getSize();
- if (size > 0)
- {
- // we've already got the file
- if (callback)
- {
- callback(mStaticVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
- }
- return true;
- }
- else
- {
- LL_WARNS() << "Asset vfile " << uuid << ":" << type
- << " found in static cache with bad size " << file.getSize() << ", ignoring" << LL_ENDL;
- }
- }
- return false;
+ LLGetAssetCallback callback, void *user_data)
+{
+ if (user_data)
+ {
+ // The *user_data should not be passed without a callback to clean it up.
+ llassert(callback != NULL);
+ }
+
+ BOOL exists = mStaticVFS->getExists(uuid, type);
+ if (exists)
+ {
+ LLVFile file(mStaticVFS, uuid, type);
+ U32 size = file.getSize();
+ if (size > 0)
+ {
+ // we've already got the file
+ if (callback)
+ {
+ callback(mStaticVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
+ }
+ return true;
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type
+ << " found in static cache with bad size " << file.getSize() << ", ignoring" << LL_ENDL;
+ }
+ }
+ return false;
}
///////////////////////////////////////////////////////////////////////////
@@ -452,526 +447,506 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse
///////////////////////////////////////////////////////////////////////////
// IW - uuid is passed by value to avoid side effects, please don't re-add &
-void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LLGetAssetCallback callback, void *user_data, BOOL is_priority)
-{
- LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << LL_ENDL;
-
- LL_DEBUGS("AssetStorage") << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << LL_ENDL;
-
- if (user_data)
- {
- // The *user_data should not be passed without a callback to clean it up.
- llassert(callback != NULL);
- }
-
- if (mShutDown)
- {
- LL_DEBUGS("AssetStorage") << "ASSET_TRACE cancelled " << uuid << " type " << LLAssetType::lookup(type) << " shutting down" << LL_ENDL;
-
- if (callback)
- {
- add(sFailedDownloadCount, 1);
- callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_NONE);
- }
- return;
- }
-
- if (uuid.isNull())
- {
- // Special case early out for NULL uuid and for shutting down
- if (callback)
- {
- add(sFailedDownloadCount, 1);
- callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
- }
- return;
- }
-
- // Try static VFS first.
- if (findInStaticVFSAndInvokeCallback(uuid,type,callback,user_data))
- {
- LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in static VFS" << LL_ENDL;
- return;
- }
-
- BOOL exists = mVFS->getExists(uuid, type);
- LLVFile file(mVFS, uuid, type);
- U32 size = exists ? file.getSize() : 0;
-
- if (size > 0)
- {
- // we've already got the file
- // theoretically, partial files w/o a pending request shouldn't happen
- // unless there's a weird error
- if (callback)
- {
- callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
- }
-
- LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in VFS" << LL_ENDL;
- }
- else
- {
- if (exists)
- {
- LL_WARNS() << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
- file.remove();
- }
-
- BOOL duplicate = FALSE;
-
- // check to see if there's a pending download of this uuid already
- for (request_list_t::iterator iter = mPendingDownloads.begin();
- iter != mPendingDownloads.end(); ++iter )
- {
- LLAssetRequest *tmp = *iter;
- if ((type == tmp->getType()) && (uuid == tmp->getUUID()))
- {
- if (callback == tmp->mDownCallback && user_data == tmp->mUserData)
- {
- // this is a duplicate from the same subsystem - throw it away
- LL_WARNS() << "Discarding duplicate request for asset " << uuid
- << "." << LLAssetType::lookup(type) << LL_ENDL;
- return;
- }
-
- // this is a duplicate request
- // queue the request, but don't actually ask for it again
- duplicate = TRUE;
- }
- }
- if (duplicate)
- {
- LL_DEBUGS("AssetStorage") << "Adding additional non-duplicate request for asset " << uuid
- << "." << LLAssetType::lookup(type) << LL_ENDL;
- }
-
- // This can be overridden by subclasses
- _queueDataRequest(uuid, type, callback, user_data, duplicate, is_priority);
- }
-
+void LLAssetStorage::getAssetData(const LLUUID uuid,
+ LLAssetType::EType type,
+ LLGetAssetCallback callback,
+ void *user_data,
+ BOOL is_priority)
+{
+ LL_DEBUGS("AssetStorage") << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << LL_ENDL;
+
+ LL_DEBUGS("AssetStorage") << "ASSET_TRACE requesting " << uuid << " type " << LLAssetType::lookup(type) << LL_ENDL;
+
+ if (user_data)
+ {
+ // The *user_data should not be passed without a callback to clean it up.
+ llassert(callback != NULL);
+ }
+
+ if (mShutDown)
+ {
+ LL_DEBUGS("AssetStorage") << "ASSET_TRACE cancelled " << uuid << " type " << LLAssetType::lookup(type) << " shutting down" << LL_ENDL;
+
+ if (callback)
+ {
+ add(sFailedDownloadCount, 1);
+ callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_NONE);
+ }
+ return;
+ }
+
+ if (uuid.isNull())
+ {
+ // Special case early out for NULL uuid and for shutting down
+ if (callback)
+ {
+ add(sFailedDownloadCount, 1);
+ callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
+ }
+ return;
+ }
+
+ // Try static VFS first.
+ if (findInStaticVFSAndInvokeCallback(uuid,type,callback,user_data))
+ {
+ LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in static VFS" << LL_ENDL;
+ return;
+ }
+
+ BOOL exists = mVFS->getExists(uuid, type);
+ LLVFile file(mVFS, uuid, type);
+ U32 size = exists ? file.getSize() : 0;
+
+ if (size > 0)
+ {
+ // we've already got the file
+ // theoretically, partial files w/o a pending request shouldn't happen
+ // unless there's a weird error
+ if (callback)
+ {
+ callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
+ }
+
+ LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in VFS" << LL_ENDL;
+ }
+ else
+ {
+ if (exists)
+ {
+ LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
+ file.remove();
+ }
+
+ BOOL duplicate = FALSE;
+
+ // check to see if there's a pending download of this uuid already
+ for (request_list_t::iterator iter = mPendingDownloads.begin();
+ iter != mPendingDownloads.end(); ++iter )
+ {
+ LLAssetRequest *tmp = *iter;
+ if ((type == tmp->getType()) && (uuid == tmp->getUUID()))
+ {
+ if (callback == tmp->mDownCallback && user_data == tmp->mUserData)
+ {
+ // this is a duplicate from the same subsystem - throw it away
+ LL_WARNS("AssetStorage") << "Discarding duplicate request for asset " << uuid
+ << "." << LLAssetType::lookup(type) << LL_ENDL;
+ return;
+ }
+
+ // this is a duplicate request
+ // queue the request, but don't actually ask for it again
+ duplicate = TRUE;
+ }
+ }
+ if (duplicate)
+ {
+ LL_DEBUGS("AssetStorage") << "Adding additional non-duplicate request for asset " << uuid
+ << "." << LLAssetType::lookup(type) << LL_ENDL;
+ }
+
+ _queueDataRequest(uuid, type, callback, user_data, duplicate, is_priority);
+ }
}
-//
-// *NOTE: Logic here is replicated in LLViewerAssetStorage::_queueDataRequest.
-// Changes here may need to be replicated in the viewer's derived class.
-//
-void LLAssetStorage::_queueDataRequest(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
- LLAssetRequest *req = new LLAssetRequest(uuid, atype);
- req->mDownCallback = callback;
- req->mUserData = user_data;
- req->mIsPriority = is_priority;
-
- 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_INFOS() << "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));
- }
- }
- 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)
- {
- add(sFailedDownloadCount, 1);
- callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
- }
- }
+// static
+void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type,
+ const LLUUID& callback_id, LLAssetType::EType callback_type,
+ S32 result_code, LLExtStat ext_status)
+{
+ // find and callback ALL pending requests for this UUID
+ // SJB: We process the callbacks in reverse order, I do not know if this is important,
+ // but I didn't want to mess with it.
+ request_list_t requests;
+ for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
+ iter != gAssetStorage->mPendingDownloads.end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* tmp = *curiter;
+ if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type))
+ {
+ requests.push_front(tmp);
+ iter = gAssetStorage->mPendingDownloads.erase(curiter);
+ }
+ }
+ for (request_list_t::iterator iter = requests.begin();
+ iter != requests.end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* tmp = *curiter;
+ if (tmp->mDownCallback)
+ {
+ if (result_code!= LL_ERR_NOERR)
+ {
+ add(sFailedDownloadCount, 1);
+ }
+ tmp->mDownCallback(gAssetStorage->mVFS, callback_id, callback_type, tmp->mUserData, result_code, ext_status);
+ }
+ delete tmp;
+ }
}
-
void LLAssetStorage::downloadCompleteCallback(
- S32 result,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data, LLExtStat ext_status)
-{
- LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << file_id << " downloadCompleteCallback" << LL_ENDL;
-
- LL_DEBUGS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback() for " << file_id
- << "," << LLAssetType::lookup(file_type) << LL_ENDL;
- LLAssetRequest* req = (LLAssetRequest*)user_data;
- if(!req)
- {
- LL_WARNS() << "LLAssetStorage::downloadCompleteCallback called without"
- "a valid request." << LL_ENDL;
- return;
- }
- if (!gAssetStorage)
- {
- LL_WARNS() << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL;
- return;
- }
-
- LLUUID callback_id;
- LLAssetType::EType callback_type;
-
- // Inefficient since we're doing a find through a list that may have thousands of elements.
- // This is due for refactoring; we will probably change mPendingDownloads into a set.
- request_list_t::iterator download_iter = std::find(gAssetStorage->mPendingDownloads.begin(),
- gAssetStorage->mPendingDownloads.end(),
- req);
-
- if (download_iter != gAssetStorage->mPendingDownloads.end())
- {
- callback_id = file_id;
- callback_type = file_type;
- }
- else
- {
- // either has already been deleted by _cleanupRequests or it's a transfer.
- callback_id = req->getUUID();
- callback_type = req->getType();
- }
-
- if (LL_ERR_NOERR == result)
- {
- // we might have gotten a zero-size file
- LLVFile vfile(gAssetStorage->mVFS, callback_id, callback_type);
- if (vfile.getSize() <= 0)
- {
- LL_WARNS() << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL;
-
- result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
- vfile.remove();
- }
- }
-
- // find and callback ALL pending requests for this UUID
- // SJB: We process the callbacks in reverse order, I do not know if this is important,
- // but I didn't want to mess with it.
- request_list_t requests;
- for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
- iter != gAssetStorage->mPendingDownloads.end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* tmp = *curiter;
- if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type))
- {
- requests.push_front(tmp);
- iter = gAssetStorage->mPendingDownloads.erase(curiter);
- }
- }
- for (request_list_t::iterator iter = requests.begin();
- iter != requests.end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* tmp = *curiter;
- if (tmp->mDownCallback)
- {
- if (result != LL_ERR_NOERR)
- {
- add(sFailedDownloadCount, 1);
- }
- tmp->mDownCallback(gAssetStorage->mVFS, callback_id, callback_type, tmp->mUserData, result, ext_status);
- }
- delete tmp;
- }
-}
-
-void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
- const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
- LLGetAssetCallback callback, void *user_data, BOOL is_priority)
-{
- LL_DEBUGS() << "LLAssetStorage::getEstateAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << ", estatetype " << etype << LL_ENDL;
-
- //
- // Probably will get rid of this early out?
- //
- if (asset_id.isNull())
- {
- // Special case early out for NULL uuid
- if (callback)
- {
- add(sFailedDownloadCount, 1);
- callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
- }
- return;
- }
-
- // Try static VFS first.
- if (findInStaticVFSAndInvokeCallback(asset_id,atype,callback,user_data))
- {
- return;
- }
-
- BOOL exists = mVFS->getExists(asset_id, atype);
- LLVFile file(mVFS, asset_id, atype);
- U32 size = exists ? file.getSize() : 0;
-
- if (size > 0)
- {
- // we've already got the file
- // theoretically, partial files w/o a pending request shouldn't happen
- // unless there's a weird error
- if (callback)
- {
- callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
- }
- }
- else
- {
- if (exists)
- {
- LL_WARNS() << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
- file.remove();
- }
-
- // See whether we should talk to the object's originating sim, or the upstream provider.
- LLHost source_host;
- if (object_sim.isOk())
- {
- source_host = object_sim;
- }
- else
- {
- source_host = mUpstreamHost;
- }
- if (source_host.isOk())
- {
- // stash the callback info so we can find it after we get the response message
- LLEstateAssetRequest req(asset_id, atype, etype);
- req.mDownCallback = callback;
- req.mUserData = user_data;
- req.mIsPriority = is_priority;
-
- // send request message to our upstream data provider
- // Create a new asset transfer.
- LLTransferSourceParamsEstate spe;
- spe.setAgentSession(agent_id, session_id);
- spe.setEstateAssetType(etype);
-
- // Set our destination file, and the completion callback.
- LLTransferTargetParamsVFile tpvf;
- tpvf.setAsset(asset_id, atype);
- tpvf.setCallback(downloadEstateAssetCompleteCallback, req);
-
- LL_DEBUGS("AssetStorage") << "Starting transfer for " << asset_id << LL_ENDL;
- LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
- ttcp->requestTransfer(spe, tpvf, 100.f + (is_priority ? 1.f : 0.f));
- }
- 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)
- {
- add(sFailedDownloadCount, 1);
- callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
- }
- }
- }
+ S32 result,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data,
+ LLExtStat ext_status)
+{
+ LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << file_id << " downloadCompleteCallback" << LL_ENDL;
+
+ LL_DEBUGS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback() for " << file_id
+ << "," << LLAssetType::lookup(file_type) << LL_ENDL;
+ LLAssetRequest* req = (LLAssetRequest*)user_data;
+ if(!req)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback called without"
+ "a valid request." << LL_ENDL;
+ return;
+ }
+ if (!gAssetStorage)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL;
+ return;
+ }
+
+ LLUUID callback_id;
+ LLAssetType::EType callback_type;
+
+ // Inefficient since we're doing a find through a list that may have thousands of elements.
+ // This is due for refactoring; we will probably change mPendingDownloads into a set.
+ request_list_t::iterator download_iter = std::find(gAssetStorage->mPendingDownloads.begin(),
+ gAssetStorage->mPendingDownloads.end(),
+ req);
+
+ if (download_iter != gAssetStorage->mPendingDownloads.end())
+ {
+ callback_id = file_id;
+ callback_type = file_type;
+ }
+ else
+ {
+ // either has already been deleted by _cleanupRequests or it's a transfer.
+ callback_id = req->getUUID();
+ callback_type = req->getType();
+ }
+
+ if (LL_ERR_NOERR == result)
+ {
+ // we might have gotten a zero-size file
+ LLVFile vfile(gAssetStorage->mVFS, callback_id, callback_type);
+ if (vfile.getSize() <= 0)
+ {
+ LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL;
+
+ result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
+ vfile.remove();
+ }
+ else
+ {
+#if 1
+ for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
+ iter != gAssetStorage->mPendingDownloads.end(); ++iter )
+ {
+ LLAssetRequest* dlreq = *iter;
+ if ((dlreq->getUUID() == file_id) && (dlreq->getType()== file_type))
+ {
+ dlreq->mBytesFetched = vfile.getSize();
+ }
+ }
+#endif
+ }
+ }
+
+ removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, ext_status, result);
+}
+
+void LLAssetStorage::getEstateAsset(
+ const LLHost &object_sim,
+ const LLUUID &agent_id,
+ const LLUUID &session_id,
+ const LLUUID &asset_id,
+ LLAssetType::EType atype,
+ EstateAssetType etype,
+ LLGetAssetCallback callback,
+ void *user_data,
+ BOOL is_priority)
+{
+ LL_DEBUGS() << "LLAssetStorage::getEstateAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << ", estatetype " << etype << LL_ENDL;
+
+ //
+ // Probably will get rid of this early out?
+ //
+ if (asset_id.isNull())
+ {
+ // Special case early out for NULL uuid
+ if (callback)
+ {
+ add(sFailedDownloadCount, 1);
+ callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
+ }
+ return;
+ }
+
+ // Try static VFS first.
+ if (findInStaticVFSAndInvokeCallback(asset_id,atype,callback,user_data))
+ {
+ return;
+ }
+
+ BOOL exists = mVFS->getExists(asset_id, atype);
+ LLVFile file(mVFS, asset_id, atype);
+ U32 size = exists ? file.getSize() : 0;
+
+ if (size > 0)
+ {
+ // we've already got the file
+ // theoretically, partial files w/o a pending request shouldn't happen
+ // unless there's a weird error
+ if (callback)
+ {
+ callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
+ }
+ }
+ else
+ {
+ if (exists)
+ {
+ LL_WARNS("AssetStorage") << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
+ file.remove();
+ }
+
+ // See whether we should talk to the object's originating sim, or the upstream provider.
+ LLHost source_host;
+ if (object_sim.isOk())
+ {
+ source_host = object_sim;
+ }
+ else
+ {
+ source_host = mUpstreamHost;
+ }
+ if (source_host.isOk())
+ {
+ // stash the callback info so we can find it after we get the response message
+ LLEstateAssetRequest req(asset_id, atype, etype);
+ req.mDownCallback = callback;
+ req.mUserData = user_data;
+ req.mIsPriority = is_priority;
+
+ // send request message to our upstream data provider
+ // Create a new asset transfer.
+ LLTransferSourceParamsEstate spe;
+ spe.setAgentSession(agent_id, session_id);
+ spe.setEstateAssetType(etype);
+
+ // Set our destination file, and the completion callback.
+ LLTransferTargetParamsVFile tpvf;
+ tpvf.setAsset(asset_id, atype);
+ tpvf.setCallback(downloadEstateAssetCompleteCallback, req);
+
+ LL_DEBUGS("AssetStorage") << "Starting transfer for " << asset_id << LL_ENDL;
+ LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
+ ttcp->requestTransfer(spe, tpvf, 100.f + (is_priority ? 1.f : 0.f));
+ }
+ else
+ {
+ // uh-oh, we shouldn't have gotten here
+ LL_WARNS("AssetStorage") << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL;
+ if (callback)
+ {
+ add(sFailedDownloadCount, 1);
+ callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
+ }
+ }
+ }
}
void LLAssetStorage::downloadEstateAssetCompleteCallback(
- S32 result,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data,
- LLExtStat ext_status)
-{
- LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data;
- if(!req)
- {
- LL_WARNS() << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
- " without a valid request." << LL_ENDL;
- return;
- }
- if (!gAssetStorage)
- {
- LL_WARNS() << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
- " without any asset system, aborting!" << LL_ENDL;
- return;
- }
-
- req->setUUID(file_id);
- req->setType(file_type);
- if (LL_ERR_NOERR == result)
- {
- // we might have gotten a zero-size file
- LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType());
- if (vfile.getSize() <= 0)
- {
- LL_WARNS() << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL;
-
- result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
- vfile.remove();
- }
- }
-
- if (result != LL_ERR_NOERR)
- {
- add(sFailedDownloadCount, 1);
- }
- req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status);
-}
-
-void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
- const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id,
- const LLUUID &asset_id, LLAssetType::EType atype,
- LLGetAssetCallback callback, void *user_data, BOOL is_priority)
-{
- LL_DEBUGS() << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << LL_ENDL;
-
- //
- // Probably will get rid of this early out?
- //
- //if (asset_id.isNull())
- //{
- // // Special case early out for NULL uuid
- // if (callback)
- // {
- // callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE);
- // }
- // return;
- //}
-
- bool exists = false;
- U32 size = 0;
-
- if(asset_id.notNull())
- {
- // Try static VFS first.
- if (findInStaticVFSAndInvokeCallback( asset_id, atype, callback, user_data))
- {
- return;
- }
-
- exists = mVFS->getExists(asset_id, atype);
- LLVFile file(mVFS, asset_id, atype);
- size = exists ? file.getSize() : 0;
- if(exists && size < 1)
- {
- LL_WARNS() << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
- file.remove();
- }
-
- }
-
- if (size > 0)
- {
- // we've already got the file
- // theoretically, partial files w/o a pending request shouldn't happen
- // unless there's a weird error
- if (callback)
- {
- callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
- }
- }
- else
- {
- // See whether we should talk to the object's originating sim,
- // or the upstream provider.
- LLHost source_host;
- if (object_sim.isOk())
- {
- source_host = object_sim;
- }
- else
- {
- source_host = mUpstreamHost;
- }
- if (source_host.isOk())
- {
- // stash the callback info so we can find it after we get the response message
- LLInvItemRequest req(asset_id, atype);
- req.mDownCallback = callback;
- req.mUserData = user_data;
- req.mIsPriority = is_priority;
-
- // send request message to our upstream data provider
- // Create a new asset transfer.
- LLTransferSourceParamsInvItem spi;
- spi.setAgentSession(agent_id, session_id);
- spi.setInvItem(owner_id, task_id, item_id);
- spi.setAsset(asset_id, atype);
-
- // Set our destination file, and the completion callback.
- LLTransferTargetParamsVFile tpvf;
- tpvf.setAsset(asset_id, atype);
- tpvf.setCallback(downloadInvItemCompleteCallback, req);
-
- LL_DEBUGS("AssetStorage") << "Starting transfer for inventory asset "
- << item_id << " owned by " << owner_id << "," << task_id
- << LL_ENDL;
- LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
- ttcp->requestTransfer(spi, tpvf, 100.f + (is_priority ? 1.f : 0.f));
- }
- 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)
- {
- add(sFailedDownloadCount, 1);
- callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
- }
- }
- }
+ S32 result,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data,
+ LLExtStat ext_status)
+{
+ LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data;
+ if(!req)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
+ " without a valid request." << LL_ENDL;
+ return;
+ }
+ if (!gAssetStorage)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
+ " without any asset system, aborting!" << LL_ENDL;
+ return;
+ }
+
+ req->setUUID(file_id);
+ req->setType(file_type);
+ if (LL_ERR_NOERR == result)
+ {
+ // we might have gotten a zero-size file
+ LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType());
+ if (vfile.getSize() <= 0)
+ {
+ LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL;
+
+ result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
+ vfile.remove();
+ }
+ }
+
+ if (result != LL_ERR_NOERR)
+ {
+ add(sFailedDownloadCount, 1);
+ }
+ req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status);
+}
+
+void LLAssetStorage::getInvItemAsset(
+ const LLHost &object_sim,
+ const LLUUID &agent_id,
+ const LLUUID &session_id,
+ const LLUUID &owner_id,
+ const LLUUID &task_id,
+ const LLUUID &item_id,
+ const LLUUID &asset_id,
+ LLAssetType::EType atype,
+ LLGetAssetCallback callback,
+ void *user_data,
+ BOOL is_priority)
+{
+ LL_DEBUGS() << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << LL_ENDL;
+
+ bool exists = false;
+ U32 size = 0;
+
+ if(asset_id.notNull())
+ {
+ // Try static VFS first.
+ if (findInStaticVFSAndInvokeCallback( asset_id, atype, callback, user_data))
+ {
+ return;
+ }
+
+ exists = mVFS->getExists(asset_id, atype);
+ LLVFile file(mVFS, asset_id, atype);
+ size = exists ? file.getSize() : 0;
+ if(exists && size < 1)
+ {
+ LL_WARNS("AssetStorage") << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
+ file.remove();
+ }
+
+ }
+
+ if (size > 0)
+ {
+ // we've already got the file
+ // theoretically, partial files w/o a pending request shouldn't happen
+ // unless there's a weird error
+ if (callback)
+ {
+ callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
+ }
+ }
+ else
+ {
+ // See whether we should talk to the object's originating sim,
+ // or the upstream provider.
+ LLHost source_host;
+ if (object_sim.isOk())
+ {
+ source_host = object_sim;
+ }
+ else
+ {
+ source_host = mUpstreamHost;
+ }
+ if (source_host.isOk())
+ {
+ // stash the callback info so we can find it after we get the response message
+ LLInvItemRequest req(asset_id, atype);
+ req.mDownCallback = callback;
+ req.mUserData = user_data;
+ req.mIsPriority = is_priority;
+
+ // send request message to our upstream data provider
+ // Create a new asset transfer.
+ LLTransferSourceParamsInvItem spi;
+ spi.setAgentSession(agent_id, session_id);
+ spi.setInvItem(owner_id, task_id, item_id);
+ spi.setAsset(asset_id, atype);
+
+ LL_DEBUGS("ViewerAsset") << "requesting inv item id " << item_id << " asset_id " << asset_id << " type " << LLAssetType::lookup(atype) << LL_ENDL;
+
+ // Set our destination file, and the completion callback.
+ LLTransferTargetParamsVFile tpvf;
+ tpvf.setAsset(asset_id, atype);
+ tpvf.setCallback(downloadInvItemCompleteCallback, req);
+
+ LL_DEBUGS("AssetStorage") << "Starting transfer for inventory asset "
+ << item_id << " owned by " << owner_id << "," << task_id
+ << LL_ENDL;
+ LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
+ ttcp->requestTransfer(spi, tpvf, 100.f + (is_priority ? 1.f : 0.f));
+ }
+ else
+ {
+ // uh-oh, we shouldn't have gotten here
+ LL_WARNS("AssetStorage") << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL;
+ if (callback)
+ {
+ add(sFailedDownloadCount, 1);
+ callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
+ }
+ }
+ }
}
void LLAssetStorage::downloadInvItemCompleteCallback(
- S32 result,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data,
- LLExtStat ext_status)
-{
- LLInvItemRequest *req = (LLInvItemRequest*)user_data;
- if(!req)
- {
- LL_WARNS() << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
- " without a valid request." << LL_ENDL;
- return;
- }
- if (!gAssetStorage)
- {
- LL_WARNS() << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL;
- return;
- }
-
- req->setUUID(file_id);
- req->setType(file_type);
- if (LL_ERR_NOERR == result)
- {
- // we might have gotten a zero-size file
- LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
- if (vfile.getSize() <= 0)
- {
- LL_WARNS() << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL;
-
- result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
- vfile.remove();
- }
- }
-
- if (result != LL_ERR_NOERR)
- {
- add(sFailedDownloadCount, 1);
- }
- req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status);
+ S32 result,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data,
+ LLExtStat ext_status)
+{
+ LLInvItemRequest *req = (LLInvItemRequest*)user_data;
+ if(!req)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
+ " without a valid request." << LL_ENDL;
+ return;
+ }
+ if (!gAssetStorage)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << LL_ENDL;
+ return;
+ }
+
+ req->setUUID(file_id);
+ req->setType(file_type);
+ if (LL_ERR_NOERR == result)
+ {
+ // we might have gotten a zero-size file
+ LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
+ if (vfile.getSize() <= 0)
+ {
+ LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL;
+
+ result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
+ vfile.remove();
+ }
+ }
+
+ if (result != LL_ERR_NOERR)
+ {
+ add(sFailedDownloadCount, 1);
+ }
+ req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -979,654 +954,558 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// static
-void LLAssetStorage::uploadCompleteCallback(const LLUUID& uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
-{
- if (!gAssetStorage)
- {
- LL_WARNS() << "LLAssetStorage::uploadCompleteCallback has no gAssetStorage!" << LL_ENDL;
- return;
- }
- LLAssetRequest *req = (LLAssetRequest *)user_data;
- BOOL success = TRUE;
-
- if (result)
- {
- LL_WARNS() << "LLAssetStorage::uploadCompleteCallback " << result << ":" << getErrorString(result) << " trying to upload file to upstream provider" << LL_ENDL;
- success = FALSE;
- }
-
- // we're done grabbing the file, tell the client
- gAssetStorage->mMessageSys->newMessageFast(_PREHASH_AssetUploadComplete);
- gAssetStorage->mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
- gAssetStorage->mMessageSys->addUUIDFast(_PREHASH_UUID, uuid);
- gAssetStorage->mMessageSys->addS8Fast(_PREHASH_Type, req->getType());
- gAssetStorage->mMessageSys->addBOOLFast(_PREHASH_Success, success);
- gAssetStorage->mMessageSys->sendReliable(req->mHost);
-
- delete req;
+void LLAssetStorage::uploadCompleteCallback(
+ const LLUUID& uuid,
+ void *user_data,
+ S32 result,
+ LLExtStat ext_status) // StoreAssetData callback (fixed)
+{
+ if (!gAssetStorage)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::uploadCompleteCallback has no gAssetStorage!" << LL_ENDL;
+ return;
+ }
+ LLAssetRequest *req = (LLAssetRequest *)user_data;
+ BOOL success = TRUE;
+
+ if (result)
+ {
+ LL_WARNS("AssetStorage") << "LLAssetStorage::uploadCompleteCallback " << result << ":" << getErrorString(result) << " trying to upload file to upstream provider" << LL_ENDL;
+ success = FALSE;
+ }
+
+ // we're done grabbing the file, tell the client
+ gAssetStorage->mMessageSys->newMessageFast(_PREHASH_AssetUploadComplete);
+ gAssetStorage->mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
+ gAssetStorage->mMessageSys->addUUIDFast(_PREHASH_UUID, uuid);
+ gAssetStorage->mMessageSys->addS8Fast(_PREHASH_Type, req->getType());
+ gAssetStorage->mMessageSys->addBOOLFast(_PREHASH_Success, success);
+ gAssetStorage->mMessageSys->sendReliable(req->mHost);
+
+ delete req;
}
void LLAssetStorage::processUploadComplete(LLMessageSystem *msg, void **user_data)
{
- LLAssetStorage *this_ptr = (LLAssetStorage *)user_data;
- LLUUID uuid;
- S8 asset_type_s8;
- LLAssetType::EType asset_type;
- BOOL success = FALSE;
-
- msg->getUUIDFast(_PREHASH_AssetBlock, _PREHASH_UUID, uuid);
- msg->getS8Fast(_PREHASH_AssetBlock, _PREHASH_Type, asset_type_s8);
- msg->getBOOLFast(_PREHASH_AssetBlock, _PREHASH_Success, success);
-
- asset_type = (LLAssetType::EType)asset_type_s8;
- this_ptr->_callUploadCallbacks(uuid, asset_type, success, LL_EXSTAT_NONE);
+ LLAssetStorage *this_ptr = (LLAssetStorage *)user_data;
+ LLUUID uuid;
+ S8 asset_type_s8;
+ LLAssetType::EType asset_type;
+ BOOL success = FALSE;
+
+ msg->getUUIDFast(_PREHASH_AssetBlock, _PREHASH_UUID, uuid);
+ msg->getS8Fast(_PREHASH_AssetBlock, _PREHASH_Type, asset_type_s8);
+ msg->getBOOLFast(_PREHASH_AssetBlock, _PREHASH_Success, success);
+
+ asset_type = (LLAssetType::EType)asset_type_s8;
+ this_ptr->_callUploadCallbacks(uuid, asset_type, success, LL_EXSTAT_NONE);
}
void LLAssetStorage::_callUploadCallbacks(const LLUUID &uuid, LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status )
{
- // SJB: We process the callbacks in reverse order, I do not know if this is important,
- // but I didn't want to mess with it.
- request_list_t requests;
- for (request_list_t::iterator iter = mPendingUploads.begin();
- iter != mPendingUploads.end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* req = *curiter;
- if ((req->getUUID() == uuid) && (req->getType() == asset_type))
- {
- requests.push_front(req);
- iter = mPendingUploads.erase(curiter);
- }
- }
- for (request_list_t::iterator iter = mPendingLocalUploads.begin();
- iter != mPendingLocalUploads.end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* req = *curiter;
- if ((req->getUUID() == uuid) && (req->getType() == asset_type))
- {
- requests.push_front(req);
- iter = mPendingLocalUploads.erase(curiter);
- }
- }
- for (request_list_t::iterator iter = requests.begin();
- iter != requests.end(); )
- {
- request_list_t::iterator curiter = iter++;
- LLAssetRequest* req = *curiter;
- if (req->mUpCallback)
- {
- req->mUpCallback(uuid, req->mUserData, (success ? LL_ERR_NOERR : LL_ERR_ASSET_REQUEST_FAILED ), ext_status );
- }
- delete req;
- }
+ // SJB: We process the callbacks in reverse order, I do not know if this is important,
+ // but I didn't want to mess with it.
+ request_list_t requests;
+ for (request_list_t::iterator iter = mPendingUploads.begin();
+ iter != mPendingUploads.end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* req = *curiter;
+ if ((req->getUUID() == uuid) && (req->getType() == asset_type))
+ {
+ requests.push_front(req);
+ iter = mPendingUploads.erase(curiter);
+ }
+ }
+ for (request_list_t::iterator iter = mPendingLocalUploads.begin();
+ iter != mPendingLocalUploads.end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* req = *curiter;
+ if ((req->getUUID() == uuid) && (req->getType() == asset_type))
+ {
+ requests.push_front(req);
+ iter = mPendingLocalUploads.erase(curiter);
+ }
+ }
+ for (request_list_t::iterator iter = requests.begin();
+ iter != requests.end(); )
+ {
+ request_list_t::iterator curiter = iter++;
+ LLAssetRequest* req = *curiter;
+ if (req->mUpCallback)
+ {
+ req->mUpCallback(uuid, req->mUserData, (success ? LL_ERR_NOERR : LL_ERR_ASSET_REQUEST_FAILED ), ext_status );
+ }
+ delete req;
+ }
}
LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::ERequestType rt)
{
- switch (rt)
- {
- case RT_DOWNLOAD:
- return &mPendingDownloads;
- case RT_UPLOAD:
- return &mPendingUploads;
- case RT_LOCALUPLOAD:
- return &mPendingLocalUploads;
- default:
- LL_WARNS() << "Unable to find request list for request type '" << rt << "'" << LL_ENDL;
- return NULL;
- }
+ switch (rt)
+ {
+ case RT_DOWNLOAD:
+ return &mPendingDownloads;
+ case RT_UPLOAD:
+ return &mPendingUploads;
+ case RT_LOCALUPLOAD:
+ return &mPendingLocalUploads;
+ default:
+ LL_WARNS("AssetStorage") << "Unable to find request list for request type '" << rt << "'" << LL_ENDL;
+ return NULL;
+ }
}
const LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::ERequestType rt) const
{
- switch (rt)
- {
- case RT_DOWNLOAD:
- return &mPendingDownloads;
- case RT_UPLOAD:
- return &mPendingUploads;
- case RT_LOCALUPLOAD:
- return &mPendingLocalUploads;
- default:
- LL_WARNS() << "Unable to find request list for request type '" << rt << "'" << LL_ENDL;
- return NULL;
- }
+ switch (rt)
+ {
+ case RT_DOWNLOAD:
+ return &mPendingDownloads;
+ case RT_UPLOAD:
+ return &mPendingUploads;
+ case RT_LOCALUPLOAD:
+ return &mPendingLocalUploads;
+ default:
+ LL_WARNS("AssetStorage") << "Unable to find request list for request type '" << rt << "'" << LL_ENDL;
+ return NULL;
+ }
}
// static
std::string LLAssetStorage::getRequestName(LLAssetStorage::ERequestType rt)
{
- switch (rt)
- {
- case RT_DOWNLOAD:
- return "download";
- case RT_UPLOAD:
- return "upload";
- case RT_LOCALUPLOAD:
- return "localupload";
- default:
- LL_WARNS() << "Unable to find request name for request type '" << rt << "'" << LL_ENDL;
- return "";
- }
+ switch (rt)
+ {
+ case RT_DOWNLOAD:
+ return "download";
+ case RT_UPLOAD:
+ return "upload";
+ case RT_LOCALUPLOAD:
+ return "localupload";
+ default:
+ LL_WARNS("AssetStorage") << "Unable to find request name for request type '" << rt << "'" << LL_ENDL;
+ return "";
+ }
}
S32 LLAssetStorage::getNumPending(LLAssetStorage::ERequestType rt) const
{
- const request_list_t* requests = getRequestList(rt);
- S32 num_pending = -1;
- if (requests)
- {
- num_pending = requests->size();
- }
- return num_pending;
+ const request_list_t* requests = getRequestList(rt);
+ S32 num_pending = -1;
+ if (requests)
+ {
+ num_pending = requests->size();
+ }
+ return num_pending;
}
S32 LLAssetStorage::getNumPendingDownloads() const
{
- return getNumPending(RT_DOWNLOAD);
+ return getNumPending(RT_DOWNLOAD);
}
S32 LLAssetStorage::getNumPendingUploads() const
{
- return getNumPending(RT_UPLOAD);
+ return getNumPending(RT_UPLOAD);
}
S32 LLAssetStorage::getNumPendingLocalUploads()
{
- return getNumPending(RT_LOCALUPLOAD);
+ return getNumPending(RT_LOCALUPLOAD);
}
-// virtual
LLSD LLAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt,
- LLAssetType::EType asset_type,
- const std::string& detail_prefix) const
+ LLAssetType::EType asset_type,
+ const std::string& detail_prefix) const
{
- const request_list_t* requests = getRequestList(rt);
- LLSD sd;
- sd["requests"] = getPendingDetailsImpl(requests, asset_type, detail_prefix);
- return sd;
+ const request_list_t* requests = getRequestList(rt);
+ LLSD sd;
+ sd["requests"] = getPendingDetailsImpl(requests, asset_type, detail_prefix);
+ return sd;
}
-// virtual
LLSD LLAssetStorage::getPendingDetailsImpl(const LLAssetStorage::request_list_t* requests,
- LLAssetType::EType asset_type,
- const std::string& detail_prefix) const
-{
- LLSD details;
- if (requests)
- {
- request_list_t::const_iterator it = requests->begin();
- request_list_t::const_iterator end = requests->end();
- for ( ; it != end; ++it)
- {
- LLAssetRequest* req = *it;
- if ( (LLAssetType::AT_NONE == asset_type)
- || (req->getType() == asset_type) )
- {
- LLSD row = req->getTerseDetails();
-
- std::ostringstream detail;
- detail << detail_prefix << "/" << LLAssetType::lookup(req->getType())
- << "/" << req->getUUID();
- row["detail"] = LLURI(detail.str());
-
- details.append(row);
- }
- }
- }
- return details;
+ LLAssetType::EType asset_type,
+ const std::string& detail_prefix) const
+{
+ LLSD details;
+ if (requests)
+ {
+ request_list_t::const_iterator it = requests->begin();
+ request_list_t::const_iterator end = requests->end();
+ for ( ; it != end; ++it)
+ {
+ LLAssetRequest* req = *it;
+ if ( (LLAssetType::AT_NONE == asset_type)
+ || (req->getType() == asset_type) )
+ {
+ LLSD row = req->getTerseDetails();
+
+ std::ostringstream detail;
+ detail << detail_prefix << "/" << LLAssetType::lookup(req->getType())
+ << "/" << req->getUUID();
+ row["detail"] = LLURI(detail.str());
+
+ details.append(row);
+ }
+ }
+ }
+ return details;
}
// static
const LLAssetRequest* LLAssetStorage::findRequest(const LLAssetStorage::request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id)
-{
- if (requests)
- {
- // Search the requests list for the asset.
- request_list_t::const_iterator iter = requests->begin();
- request_list_t::const_iterator end = requests->end();
- for (; iter != end; ++iter)
- {
- const LLAssetRequest* req = *iter;
- if (asset_type == req->getType() &&
- asset_id == req->getUUID() )
- {
- return req;
- }
- }
- }
- return NULL;
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id)
+{
+ if (requests)
+ {
+ // Search the requests list for the asset.
+ request_list_t::const_iterator iter = requests->begin();
+ request_list_t::const_iterator end = requests->end();
+ for (; iter != end; ++iter)
+ {
+ const LLAssetRequest* req = *iter;
+ if (asset_type == req->getType() &&
+ asset_id == req->getUUID() )
+ {
+ return req;
+ }
+ }
+ }
+ return NULL;
}
// static
LLAssetRequest* LLAssetStorage::findRequest(LLAssetStorage::request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id)
-{
- if (requests)
- {
- // Search the requests list for the asset.
- request_list_t::iterator iter = requests->begin();
- request_list_t::iterator end = requests->end();
- for (; iter != end; ++iter)
- {
- LLAssetRequest* req = *iter;
- if (asset_type == req->getType() &&
- asset_id == req->getUUID() )
- {
- return req;
- }
- }
- }
- return NULL;
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id)
+{
+ if (requests)
+ {
+ // Search the requests list for the asset.
+ request_list_t::iterator iter = requests->begin();
+ request_list_t::iterator end = requests->end();
+ for (; iter != end; ++iter)
+ {
+ LLAssetRequest* req = *iter;
+ if (asset_type == req->getType() &&
+ asset_id == req->getUUID() )
+ {
+ return req;
+ }
+ }
+ }
+ return NULL;
}
-// virtual
LLSD LLAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id) const
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id) const
{
- const request_list_t* requests = getRequestList(rt);
- return getPendingRequestImpl(requests, asset_type, asset_id);
+ const request_list_t* requests = getRequestList(rt);
+ return getPendingRequestImpl(requests, asset_type, asset_id);
}
-// virtual
LLSD LLAssetStorage::getPendingRequestImpl(const LLAssetStorage::request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id) const
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id) const
{
- LLSD sd;
- const LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
- if (req)
- {
- sd = req->getFullDetails();
- }
- return sd;
+ LLSD sd;
+ const LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
+ if (req)
+ {
+ sd = req->getFullDetails();
+ }
+ return sd;
}
-// virtual
bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id)
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id)
{
- request_list_t* requests = getRequestList(rt);
- if (deletePendingRequestImpl(requests, asset_type, asset_id))
- {
- LL_DEBUGS("AssetStorage") << "Asset " << getRequestName(rt) << " request for "
- << asset_id << "." << LLAssetType::lookup(asset_type)
- << " removed from pending queue." << LL_ENDL;
- return true;
- }
- return false;
+ request_list_t* requests = getRequestList(rt);
+ if (deletePendingRequestImpl(requests, asset_type, asset_id))
+ {
+ LL_DEBUGS("AssetStorage") << "Asset " << getRequestName(rt) << " request for "
+ << asset_id << "." << LLAssetType::lookup(asset_type)
+ << " removed from pending queue." << LL_ENDL;
+ return true;
+ }
+ return false;
}
-// virtual
bool LLAssetStorage::deletePendingRequestImpl(LLAssetStorage::request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id)
-{
- LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
- if (req)
- {
- // Remove the request from this list.
- requests->remove(req);
- S32 error = LL_ERR_TCP_TIMEOUT;
- // Run callbacks.
- if (req->mUpCallback)
- {
- req->mUpCallback(req->getUUID(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
- }
- if (req->mDownCallback)
- {
- add(sFailedDownloadCount, 1);
- req->mDownCallback(mVFS, req->getUUID(), req->getType(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
- }
- if (req->mInfoCallback)
- {
- LLAssetInfo info;
- req->mInfoCallback(&info, req->mUserData, error);
- }
- delete req;
- return true;
- }
-
- return false;
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id)
+{
+ LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
+ if (req)
+ {
+ // Remove the request from this list.
+ requests->remove(req);
+ S32 error = LL_ERR_TCP_TIMEOUT;
+ // Run callbacks.
+ if (req->mUpCallback)
+ {
+ req->mUpCallback(req->getUUID(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
+ }
+ if (req->mDownCallback)
+ {
+ add(sFailedDownloadCount, 1);
+ req->mDownCallback(mVFS, req->getUUID(), req->getType(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
+ }
+ if (req->mInfoCallback)
+ {
+ LLAssetInfo info;
+ req->mInfoCallback(&info, req->mUserData, error);
+ }
+ delete req;
+ return true;
+ }
+
+ return false;
}
// static
const char* LLAssetStorage::getErrorString(S32 status)
{
- switch( status )
- {
- case LL_ERR_NOERR:
- return "No error";
+ switch( status )
+ {
+ case LL_ERR_NOERR:
+ return "No error";
- case LL_ERR_ASSET_REQUEST_FAILED:
- return "Asset request: failed";
+ case LL_ERR_ASSET_REQUEST_FAILED:
+ return "Asset request: failed";
- case LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE:
- return "Asset request: non-existent file";
+ case LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE:
+ return "Asset request: non-existent file";
- case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
- return "Asset request: asset not found in database";
+ case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
+ return "Asset request: asset not found in database";
- case LL_ERR_EOF:
- return "End of file";
+ case LL_ERR_EOF:
+ return "End of file";
- case LL_ERR_CANNOT_OPEN_FILE:
- return "Cannot open file";
+ case LL_ERR_CANNOT_OPEN_FILE:
+ return "Cannot open file";
- case LL_ERR_FILE_NOT_FOUND:
- return "File not found";
+ case LL_ERR_FILE_NOT_FOUND:
+ return "File not found";
- case LL_ERR_TCP_TIMEOUT:
- return "File transfer timeout";
+ case LL_ERR_TCP_TIMEOUT:
+ return "File transfer timeout";
- case LL_ERR_CIRCUIT_GONE:
- return "Circuit gone";
+ case LL_ERR_CIRCUIT_GONE:
+ return "Circuit gone";
- case LL_ERR_PRICE_MISMATCH:
- return "Viewer and server do not agree on price";
+ case LL_ERR_PRICE_MISMATCH:
+ return "Viewer and server do not agree on price";
- default:
- return "Unknown status";
- }
+ default:
+ return "Unknown status";
+ }
}
-
-
-void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, BOOL is_priority)
+void LLAssetStorage::getAssetData(const LLUUID uuid,
+ LLAssetType::EType type,
+ void (*callback)(const char*,
+ const LLUUID&,
+ void *,
+ S32,
+ LLExtStat),
+ void *user_data,
+ BOOL is_priority)
{
- // check for duplicates here, since we're about to fool the normal duplicate checker
- for (request_list_t::iterator iter = mPendingDownloads.begin();
- iter != mPendingDownloads.end(); )
- {
- LLAssetRequest* tmp = *iter++;
- if (type == tmp->getType() &&
- uuid == tmp->getUUID() &&
- legacyGetDataCallback == tmp->mDownCallback &&
- callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
- user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
- {
- // this is a duplicate from the same subsystem - throw it away
- LL_DEBUGS("AssetStorage") << "Discarding duplicate request for UUID " << uuid << LL_ENDL;
- return;
- }
- }
-
-
- LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
-
- legacy->mDownCallback = callback;
- legacy->mUserData = user_data;
-
- getAssetData(uuid, type, legacyGetDataCallback, (void **)legacy,
- is_priority);
-}
+ // check for duplicates here, since we're about to fool the normal duplicate checker
+ for (request_list_t::iterator iter = mPendingDownloads.begin();
+ iter != mPendingDownloads.end(); )
+ {
+ LLAssetRequest* tmp = *iter++;
+ if (type == tmp->getType() &&
+ uuid == tmp->getUUID() &&
+ legacyGetDataCallback == tmp->mDownCallback &&
+ callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
+ user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
+ {
+ // this is a duplicate from the same subsystem - throw it away
+ LL_DEBUGS("AssetStorage") << "Discarding duplicate request for UUID " << uuid << LL_ENDL;
+ return;
+ }
+ }
+
+
+ LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
-// static
-void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 status, LLExtStat ext_status)
-{
- LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
- std::string filename;
-
- // Check if the asset is marked toxic, and don't load bad stuff
- BOOL toxic = gAssetStorage->isAssetToxic( uuid );
-
- if ( !status
- && !toxic )
- {
- LLVFile file(vfs, uuid, type);
-
- std::string uuid_str;
-
- uuid.toString(uuid_str);
- filename = llformat("%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type));
-
- LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */
- if (fp)
- {
- const S32 buf_size = 65536;
- U8 copy_buf[buf_size];
- while (file.read(copy_buf, buf_size)) /* Flawfinder: ignore */
- {
- if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1)
- {
- // return a bad file error if we can't write the whole thing
- status = LL_ERR_CANNOT_OPEN_FILE;
- }
- }
-
- fclose(fp);
- }
- else
- {
- status = LL_ERR_CANNOT_OPEN_FILE;
- }
- }
-
- if (status != LL_ERR_NOERR)
- {
- add(sFailedDownloadCount, 1);
- }
- legacy->mDownCallback(filename.c_str(), uuid, legacy->mUserData, status, ext_status);
- delete legacy;
-}
-
-// this is overridden on the viewer and the sim, so it doesn't really do anything
-// virtual
-void LLAssetStorage::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)
-{
- LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
- // LLAssetStorage metric: Virtual base call
- reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 1" );
-}
-
-// virtual
-// this does nothing, viewer and sim both override this.
-void LLAssetStorage::storeAssetData(
- const LLUUID& asset_id,
- LLAssetType::EType asset_type,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file ,
- bool is_priority,
- bool store_local,
- const LLUUID& requesting_agent_id,
- bool user_waiting,
- F64Seconds timeout)
-{
- LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
- // LLAssetStorage metric: Virtual base call
- reportMetric( asset_id, asset_type, LLStringUtil::null, requesting_agent_id, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 2" );
-}
+ legacy->mDownCallback = callback;
+ legacy->mUserData = user_data;
-// virtual
-// this does nothing, viewer and sim both override this.
-void LLAssetStorage::storeAssetData(
- const std::string& filename,
- const LLUUID& asset_id,
- LLAssetType::EType asset_type,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file,
- bool is_priority,
- bool user_waiting,
- F64Seconds timeout)
-{
- LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
- // LLAssetStorage metric: Virtual base call
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 3" );
+ getAssetData(uuid, type, legacyGetDataCallback, (void **)legacy,
+ is_priority);
}
-// virtual
-// this does nothing, viewer and sim both override this.
-void LLAssetStorage::storeAssetData(
- const std::string& filename,
- const LLTransactionID &transactoin_id,
- LLAssetType::EType asset_type,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file,
- bool is_priority,
- bool user_waiting,
- F64Seconds timeout)
-{
- LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
- // LLAssetStorage metric: Virtual base call
- reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 4" );
+// static
+void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs,
+ const LLUUID &uuid,
+ LLAssetType::EType type,
+ void *user_data,
+ S32 status,
+ LLExtStat ext_status)
+{
+ LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
+ std::string filename;
+
+ // Check if the asset is marked toxic, and don't load bad stuff
+ BOOL toxic = gAssetStorage->isAssetToxic( uuid );
+
+ if ( !status
+ && !toxic )
+ {
+ LLVFile file(vfs, uuid, type);
+
+ std::string uuid_str;
+
+ uuid.toString(uuid_str);
+ filename = llformat("%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type));
+
+ LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */
+ if (fp)
+ {
+ const S32 buf_size = 65536;
+ U8 copy_buf[buf_size];
+ while (file.read(copy_buf, buf_size)) /* Flawfinder: ignore */
+ {
+ if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1)
+ {
+ // return a bad file error if we can't write the whole thing
+ status = LL_ERR_CANNOT_OPEN_FILE;
+ }
+ }
+
+ fclose(fp);
+ }
+ else
+ {
+ status = LL_ERR_CANNOT_OPEN_FILE;
+ }
+ }
+
+ if (status != LL_ERR_NOERR)
+ {
+ add(sFailedDownloadCount, 1);
+ }
+ legacy->mDownCallback(filename.c_str(), uuid, legacy->mUserData, status, ext_status);
+ delete legacy;
}
// static
void LLAssetStorage::legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status)
{
- LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
- if (legacy && legacy->mUpCallback)
- {
- legacy->mUpCallback(uuid, legacy->mUserData, status, ext_status);
- }
- delete legacy;
+ LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
+ if (legacy && legacy->mUpCallback)
+ {
+ legacy->mUpCallback(uuid, legacy->mUserData, status, ext_status);
+ }
+ delete legacy;
}
-// virtual
-void LLAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name)
-{ }
-
-// virtual
-BOOL LLAssetStorage::hasTempAssetData(const LLUUID& texture_id) const
-{ return FALSE; }
-
-// virtual
-std::string LLAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const
-{ return std::string(); }
-
-// virtual
-LLUUID LLAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const
-{ return LLUUID::null; }
-
-// virtual
-void LLAssetStorage::removeTempAssetData(const LLUUID& asset_id)
-{ }
-
-// virtual
-void LLAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id)
-{ }
-
-// virtual
-void LLAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const
-{ }
-
-// virtual
-void LLAssetStorage::clearTempAssetData()
-{ }
-
// static
void LLAssetStorage::reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const std::string& in_filename,
- const LLUUID& agent_id, S32 asset_size, EMetricResult result,
- const char *file, const S32 line, const std::string& in_message )
-{
- if( !metric_recipient )
- {
- LL_DEBUGS("AssetStorage") << "Couldn't store LLAssetStoreage::reportMetric - no metrics_recipient" << LL_ENDL;
- return;
- }
-
- std::string filename(in_filename);
- if (filename.empty())
- filename = ll_safe_string(file);
-
- // Create revised message - new_message = "in_message :: file:line"
- std::stringstream new_message;
- new_message << in_message << " :: " << filename << ":" << line;
-
- // Change always_report to true if debugging... do not check it in this way
- static bool always_report = false;
- const char *metric_name = "LLAssetStorage::Metrics";
-
- bool success = result == MR_OKAY;
-
- if( (!success) || always_report )
- {
- LLSD stats;
- stats["asset_id"] = asset_id;
- stats["asset_type"] = asset_type;
- stats["filename"] = filename;
- stats["agent_id"] = agent_id;
- stats["asset_size"] = (S32)asset_size;
- stats["result"] = (S32)result;
-
- metric_recipient->recordEventDetails( metric_name, new_message.str(), success, stats);
- }
- else
- {
- metric_recipient->recordEvent(metric_name, new_message.str(), success);
- }
+ const LLUUID& agent_id, S32 asset_size, EMetricResult result,
+ const char *file, const S32 line, const std::string& in_message )
+{
+ if( !metric_recipient )
+ {
+ LL_DEBUGS("AssetStorage") << "Couldn't store LLAssetStoreage::reportMetric - no metrics_recipient" << LL_ENDL;
+ return;
+ }
+
+ std::string filename(in_filename);
+ if (filename.empty())
+ filename = ll_safe_string(file);
+
+ // Create revised message - new_message = "in_message :: file:line"
+ std::stringstream new_message;
+ new_message << in_message << " :: " << filename << ":" << line;
+
+ // Change always_report to true if debugging... do not check it in this way
+ static bool always_report = false;
+ const char *metric_name = "LLAssetStorage::Metrics";
+
+ bool success = result == MR_OKAY;
+
+ if( (!success) || always_report )
+ {
+ LLSD stats;
+ stats["asset_id"] = asset_id;
+ stats["asset_type"] = asset_type;
+ stats["filename"] = filename;
+ stats["agent_id"] = agent_id;
+ stats["asset_size"] = (S32)asset_size;
+ stats["result"] = (S32)result;
+
+ metric_recipient->recordEventDetails( metric_name, new_message.str(), success, stats);
+ }
+ else
+ {
+ metric_recipient->recordEvent(metric_name, new_message.str(), success);
+ }
}
// Check if an asset is in the toxic map. If it is, the entry is updated
-BOOL LLAssetStorage::isAssetToxic( const LLUUID& uuid )
+BOOL LLAssetStorage::isAssetToxic( const LLUUID& uuid )
{
- BOOL is_toxic = FALSE;
-
- if ( !uuid.isNull() )
- {
- toxic_asset_map_t::iterator iter = mToxicAssetMap.find( uuid );
- if ( iter != mToxicAssetMap.end() )
- { // Found toxic asset
- (*iter).second = LLFrameTimer::getTotalTime() + TOXIC_ASSET_LIFETIME;
- is_toxic = TRUE;
- }
- }
- return is_toxic;
+ BOOL is_toxic = FALSE;
+
+ if ( !uuid.isNull() )
+ {
+ toxic_asset_map_t::iterator iter = mToxicAssetMap.find( uuid );
+ if ( iter != mToxicAssetMap.end() )
+ { // Found toxic asset
+ (*iter).second = LLFrameTimer::getTotalTime() + TOXIC_ASSET_LIFETIME;
+ is_toxic = TRUE;
+ }
+ }
+ return is_toxic;
}
// Clean the toxic asset list, remove old entries
-void LLAssetStorage::flushOldToxicAssets( BOOL force_it )
-{
- // Scan and look for old entries
- U64 now = LLFrameTimer::getTotalTime();
- toxic_asset_map_t::iterator iter = mToxicAssetMap.begin();
- while ( iter != mToxicAssetMap.end() )
- {
- if ( force_it
- || (*iter).second < now )
- { // Too old - remove it
- mToxicAssetMap.erase( iter++ );
- }
- else
- {
- iter++;
- }
- }
+void LLAssetStorage::flushOldToxicAssets( BOOL force_it )
+{
+ // Scan and look for old entries
+ U64 now = LLFrameTimer::getTotalTime();
+ toxic_asset_map_t::iterator iter = mToxicAssetMap.begin();
+ while ( iter != mToxicAssetMap.end() )
+ {
+ if ( force_it
+ || (*iter).second < now )
+ { // Too old - remove it
+ mToxicAssetMap.erase( iter++ );
+ }
+ else
+ {
+ iter++;
+ }
+ }
}
// Add an item to the toxic asset map
-void LLAssetStorage::markAssetToxic( const LLUUID& uuid )
-{
- if ( !uuid.isNull() )
- {
- // Set the value to the current time. Creates a new entry if needed
- mToxicAssetMap[ uuid ] = LLFrameTimer::getTotalTime() + TOXIC_ASSET_LIFETIME;
- }
+void LLAssetStorage::markAssetToxic( const LLUUID& uuid )
+{
+ if ( !uuid.isNull() )
+ {
+ // Set the value to the current time. Creates a new entry if needed
+ mToxicAssetMap[ uuid ] = LLFrameTimer::getTotalTime() + TOXIC_ASSET_LIFETIME;
+ }
}
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 0f23754096..33b88473b9 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -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);
-
- /*
- * 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);
+ F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) = 0;
- 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,23 +351,10 @@ 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
*/
virtual void storeAssetData(
@@ -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,
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index de31425c27..fbc984692d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14694,6 +14694,17 @@
<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>
@@ -14767,6 +14778,15 @@
<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
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index a26ee2204b..da247c7bf6 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -839,12 +839,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;
@@ -5927,23 +5921,14 @@ void LLAppViewer::metricsSend(bool enable_reporting)
{
std::string caps_url = regionp->getCapability("ViewerMetrics");
- if (gSavedSettings.getBOOL("QAModeMetrics"))
- {
- dump_sequential_xml("metric_asset_stats",gViewerAssetStats->asLLSD(true));
- }
-
- // Make a copy of the main stats to send into another thread.
- // Receiving thread takes ownership.
- LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStats));
- main_stats->stop();
-
+ LLSD sd = gViewerAssetStats->asLLSD(true);
+
// Send a report request into 'thread1' to get the rest of the data
// and provide some additional parameters while here.
LLAppViewer::sTextureFetch->commandSendMetrics(caps_url,
gAgentSessionID,
gAgentID,
- main_stats);
- main_stats = 0; // Ownership transferred
+ sd);
}
else
{
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index f7e0e32256..c4d1917567 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -343,10 +343,6 @@ LLMeshRepository gMeshRepo;
const S32 MESH_HEADER_SIZE = 4096; // Important: assumption is that headers fit in this space
-const S32 REQUEST_HIGH_WATER_MIN = 32; // Limits for GetMesh regions
-const S32 REQUEST_HIGH_WATER_MAX = 150; // Should remain under 2X throttle
-const S32 REQUEST_LOW_WATER_MIN = 16;
-const S32 REQUEST_LOW_WATER_MAX = 75;
const S32 REQUEST2_HIGH_WATER_MIN = 32; // Limits for GetMesh2 regions
const S32 REQUEST2_HIGH_WATER_MAX = 100;
@@ -808,10 +804,8 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpLargeOptions(),
mHttpHeaders(),
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpPriority(0),
- mGetMeshVersion(2)
+ mHttpPriority(0)
{
LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
@@ -828,7 +822,6 @@ LLMeshRepoThread::LLMeshRepoThread()
mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders);
mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_VND_LL_MESH);
mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH2);
- mHttpLegacyPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_MESH1);
mHttpLargePolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_LARGE_MESH);
}
@@ -1103,13 +1096,9 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
}
// Mutex: must be holding mMutex when called
-void LLMeshRepoThread::setGetMeshCaps(const std::string & get_mesh1,
- const std::string & get_mesh2,
- int pref_version)
+void LLMeshRepoThread::setGetMeshCap(const std::string & mesh_cap)
{
- mGetMeshCapability = get_mesh1;
- mGetMesh2Capability = get_mesh2;
- mGetMeshVersion = pref_version;
+ mGetMeshCapability = mesh_cap;
}
@@ -1117,29 +1106,14 @@ void LLMeshRepoThread::setGetMeshCaps(const std::string & get_mesh1,
// over a GetMesh cap.
//
// Mutex: acquires mMutex
-void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * version)
+void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url)
{
std::string res_url;
- int res_version(2);
if (gAgent.getRegion())
{
LLMutexLock lock(mMutex);
-
- // Get a consistent pair of (cap string, version). The
- // locking could be eliminated here without loss of safety
- // by using a set of staging values in setGetMeshCaps().
-
- if (! mGetMesh2Capability.empty() && mGetMeshVersion > 1)
- {
- res_url = mGetMesh2Capability;
- res_version = 2;
- }
- else
- {
- res_url = mGetMeshCapability;
- res_version = 1;
- }
+ res_url = mGetMeshCapability;
}
if (! res_url.empty())
@@ -1149,19 +1123,15 @@ void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * ver
}
else
{
- LL_WARNS_ONCE(LOG_MESH) << "Current region does not have GetMesh capability! Cannot load "
+ LL_WARNS_ONCE(LOG_MESH) << "Current region does not have ViewerAsset capability! Cannot load "
<< mesh_id << ".mesh" << LL_ENDL;
}
*url = res_url;
- *version = res_version;
}
// Issue an HTTP GET request with byte range using the right
-// policy class. Large requests go to the large request class.
-// If the current region supports GetMesh2, we prefer that for
-// smaller requests otherwise we try to use the traditional
-// GetMesh capability and connection concurrency.
+// policy class.
//
// @return Valid handle or LLCORE_HTTP_HANDLE_INVALID.
// If the latter, actual status is found in
@@ -1169,7 +1139,7 @@ void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * ver
// next call to this method.
//
// Thread: repo
-LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int cap_version,
+LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,
size_t offset, size_t len,
const LLCore::HttpHandler::ptr_t &handler)
{
@@ -1180,16 +1150,14 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int c
if (len < LARGE_MESH_FETCH_THRESHOLD)
{
- handle = mHttpRequest->requestGetByteRange((2 == cap_version
- ? mHttpPolicyClass
- : mHttpLegacyPolicyClass),
- mHttpPriority,
- url,
- (disable_range_req ? size_t(0) : offset),
- (disable_range_req ? size_t(0) : len),
- mHttpOptions,
- mHttpHeaders,
- handler);
+ handle = mHttpRequest->requestGetByteRange( mHttpPolicyClass,
+ mHttpPriority,
+ url,
+ (disable_range_req ? size_t(0) : offset),
+ (disable_range_req ? size_t(0) : len),
+ mHttpOptions,
+ mHttpHeaders,
+ handler);
if (LLCORE_HTTP_HANDLE_INVALID != handle)
{
++LLMeshRepository::sHTTPRequestCount;
@@ -1279,14 +1247,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshSkinInfoHandler(mesh_id, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for skin info on mesh " << mID
@@ -1372,14 +1339,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshDecompositionHandler(mesh_id, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for decomposition mesh " << mID
@@ -1464,14 +1430,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshPhysicsShapeHandler(mesh_id, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for physics shape on mesh " << mID
@@ -1558,9 +1523,8 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
//either cache entry doesn't exist or is corrupt, request header from simulator
bool retval = true;
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_params.getSculptID(), &http_url, &cap_version);
+ constructUrl(mesh_params.getSculptID(), &http_url);
if (!http_url.empty())
{
@@ -1569,7 +1533,7 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
//NOTE -- this will break of headers ever exceed 4KB
LLMeshHandlerBase::ptr_t handler(new LLMeshHeaderHandler(mesh_params, 0, MESH_HEADER_SIZE));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, 0, MESH_HEADER_SIZE, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, 0, MESH_HEADER_SIZE, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for mesh header " << mID
@@ -1645,14 +1609,13 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
}
//reading from VFS failed for whatever reason, fetch from sim
- int cap_version(2);
std::string http_url;
- constructUrl(mesh_id, &http_url, &cap_version);
+ constructUrl(mesh_id, &http_url);
if (!http_url.empty())
{
LLMeshHandlerBase::ptr_t handler(new LLMeshLODHandler(mesh_params, lod, offset, size));
- LLCore::HttpHandle handle = getByteRange(http_url, cap_version, offset, size, handler);
+ LLCore::HttpHandle handle = getByteRange(http_url, offset, size, handler);
if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
LL_WARNS(LOG_MESH) << "HTTP GET request failed for LOD on mesh " << mID
@@ -3292,8 +3255,7 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * /* body */, S3
LLMeshRepository::LLMeshRepository()
: mMeshMutex(NULL),
mMeshThreadCount(0),
- mThread(NULL),
- mGetMeshVersion(2)
+ mThread(NULL)
{
}
@@ -3476,35 +3438,21 @@ void LLMeshRepository::notifyLoadedMeshes()
{ //called from main thread
LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
- if (1 == mGetMeshVersion)
- {
- // Legacy GetMesh operation with high connection concurrency
- LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests");
- LLMeshRepoThread::sRequestHighWater = llclamp(2 * S32(LLMeshRepoThread::sMaxConcurrentRequests),
- REQUEST_HIGH_WATER_MIN,
- REQUEST_HIGH_WATER_MAX);
- LLMeshRepoThread::sRequestLowWater = llclamp(LLMeshRepoThread::sRequestHighWater / 2,
- REQUEST_LOW_WATER_MIN,
- REQUEST_LOW_WATER_MAX);
- }
- else
- {
- // GetMesh2 operation with keepalives, etc. With pipelining,
- // we'll increase this. See llappcorehttp and llcorehttp for
- // discussion on connection strategies.
- LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
- S32 scale(app_core_http.isPipelined(LLAppCoreHttp::AP_MESH2)
- ? (2 * LLAppCoreHttp::PIPELINING_DEPTH)
- : 5);
-
- LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("Mesh2MaxConcurrentRequests");
- LLMeshRepoThread::sRequestHighWater = llclamp(scale * S32(LLMeshRepoThread::sMaxConcurrentRequests),
- REQUEST2_HIGH_WATER_MIN,
- REQUEST2_HIGH_WATER_MAX);
- LLMeshRepoThread::sRequestLowWater = llclamp(LLMeshRepoThread::sRequestHighWater / 2,
- REQUEST2_LOW_WATER_MIN,
- REQUEST2_LOW_WATER_MAX);
- }
+ // GetMesh2 operation with keepalives, etc. With pipelining,
+ // we'll increase this. See llappcorehttp and llcorehttp for
+ // discussion on connection strategies.
+ LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+ S32 scale(app_core_http.isPipelined(LLAppCoreHttp::AP_MESH2)
+ ? (2 * LLAppCoreHttp::PIPELINING_DEPTH)
+ : 5);
+
+ LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("Mesh2MaxConcurrentRequests");
+ LLMeshRepoThread::sRequestHighWater = llclamp(scale * S32(LLMeshRepoThread::sMaxConcurrentRequests),
+ REQUEST2_HIGH_WATER_MIN,
+ REQUEST2_HIGH_WATER_MAX);
+ LLMeshRepoThread::sRequestLowWater = llclamp(LLMeshRepoThread::sRequestHighWater / 2,
+ REQUEST2_LOW_WATER_MIN,
+ REQUEST2_LOW_WATER_MAX);
//clean up completed upload threads
for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); )
@@ -3610,15 +3558,10 @@ void LLMeshRepository::notifyLoadedMeshes()
if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
{
region_name = gAgent.getRegion()->getName();
- const bool use_v1(gSavedSettings.getBOOL("MeshUseGetMesh1"));
- const std::string mesh1(gAgent.getRegion()->getCapability("GetMesh"));
- const std::string mesh2(gAgent.getRegion()->getCapability("GetMesh2"));
- mGetMeshVersion = (mesh2.empty() || use_v1) ? 1 : 2;
- mThread->setGetMeshCaps(mesh1, mesh2, mGetMeshVersion);
+ const std::string mesh_cap(gAgent.getRegion()->getViewerAssetUrl());
+ mThread->setGetMeshCap(mesh_cap);
LL_DEBUGS(LOG_MESH) << "Retrieving caps for region '" << region_name
- << "', GetMesh2: " << mesh2
- << ", GetMesh: " << mesh1
- << ", using version: " << mGetMeshVersion
+ << "', ViewerAsset cap: " << mesh_cap
<< LL_ENDL;
}
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 30f042845a..23af837f6f 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -279,7 +279,6 @@ public:
LLCore::HttpOptions::ptr_t mHttpLargeOptions;
LLCore::HttpHeaders::ptr_t mHttpHeaders;
LLCore::HttpRequest::policy_t mHttpPolicyClass;
- LLCore::HttpRequest::policy_t mHttpLegacyPolicyClass;
LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
LLCore::HttpRequest::priority_t mHttpPriority;
@@ -287,8 +286,6 @@ public:
http_request_set mHttpRequestSet; // Outstanding HTTP requests
std::string mGetMeshCapability;
- std::string mGetMesh2Capability;
- int mGetMeshVersion;
LLMeshRepoThread();
~LLMeshRepoThread();
@@ -335,12 +332,10 @@ public:
// mesh fetch URLs.
//
// Mutex: must be holding mMutex when called
- void setGetMeshCaps(const std::string & get_mesh1,
- const std::string & get_mesh2,
- int pref_version);
+ void setGetMeshCap(const std::string & get_mesh);
// Mutex: acquires mMutex
- void constructUrl(LLUUID mesh_id, std::string * url, int * version);
+ void constructUrl(LLUUID mesh_id, std::string * url);
private:
// Issue a GET request to a URL with 'Range' header using
@@ -349,7 +344,7 @@ private:
// or dispose of handler.
//
// Threads: Repo thread only
- LLCore::HttpHandle getByteRange(const std::string & url, int cap_version,
+ LLCore::HttpHandle getByteRange(const std::string & url,
size_t offset, size_t len,
const LLCore::HttpHandler::ptr_t &handler);
};
@@ -585,8 +580,6 @@ public:
void uploadError(LLSD& args);
void updateInventory(inventory_data data);
-
- int mGetMeshVersion; // Shadows value in LLMeshRepoThread
};
extern LLMeshRepository gMeshRepo;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 07b3dc1aa4..b78d0b51d5 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -30,8 +30,6 @@
#include <map>
#include <algorithm>
-#include "llstl.h"
-
#include "lltexturefetch.h"
#include "lldir.h"
@@ -485,7 +483,7 @@ private:
void recordTextureStart(bool is_http);
// Threads: Ttf
- void recordTextureDone(bool is_http);
+ void recordTextureDone(bool is_http, F64 byte_count);
void lockWorkMutex() { mWorkMutex.lock(); }
void unlockWorkMutex() { mWorkMutex.unlock(); }
@@ -824,7 +822,7 @@ public:
TFReqSendMetrics(const std::string & caps_url,
const LLUUID & session_id,
const LLUUID & agent_id,
- LLViewerAssetStats * main_stats);
+ LLSD& stats_sd);
TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined
virtual ~TFReqSendMetrics();
@@ -835,7 +833,7 @@ public:
const std::string mCapsURL;
const LLUUID mSessionID;
const LLUUID mAgentID;
- LLViewerAssetStats * mMainStats;
+ LLSD mStatsSD;
private:
LLCore::HttpHandler::ptr_t mHandler;
@@ -1351,7 +1349,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (region)
{
- std::string http_url = region->getHttpUrl() ;
+ std::string http_url = region->getViewerAssetUrl();
if (!http_url.empty())
{
if (mFTType != FTT_DEFAULT)
@@ -1426,6 +1424,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())
@@ -1443,7 +1455,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
setState(DECODE_IMAGE);
mWriteToCacheState = SHOULD_WRITE;
- recordTextureDone(false);
+
+ recordTextureDone(false, byte_count);
}
else
{
@@ -2093,7 +2106,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe
mFetcher->removeFromHTTPQueue(mID, data_size);
- recordTextureDone(true);
+ recordTextureDone(true, data_size);
} // -Mw
@@ -2222,6 +2235,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;
}
@@ -2493,14 +2507,15 @@ void LLTextureFetchWorker::recordTextureStart(bool is_http)
// Threads: Ttf
-void LLTextureFetchWorker::recordTextureDone(bool is_http)
+void LLTextureFetchWorker::recordTextureDone(bool is_http, F64 byte_count)
{
if (mMetricsStartTime.value())
{
LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_TEXTURE,
- is_http,
- LLImageBase::TYPE_AVATAR_BAKE == mType,
- LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime);
+ is_http,
+ LLImageBase::TYPE_AVATAR_BAKE == mType,
+ LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime,
+ byte_count);
mMetricsStartTime = (U32Seconds)0;
}
LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE,
@@ -3863,9 +3878,9 @@ void LLTextureFetch::commandSetRegion(U64 region_handle)
void LLTextureFetch::commandSendMetrics(const std::string & caps_url,
const LLUUID & session_id,
const LLUUID & agent_id,
- LLViewerAssetStats * main_stats)
+ LLSD& stats_sd)
{
- TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, main_stats);
+ TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, stats_sd);
cmdEnqueue(req);
}
@@ -3974,22 +3989,20 @@ TFReqSetRegion::doWork(LLTextureFetch *)
}
TFReqSendMetrics::TFReqSendMetrics(const std::string & caps_url,
- const LLUUID & session_id,
- const LLUUID & agent_id,
- LLViewerAssetStats * main_stats):
+ const LLUUID & session_id,
+ const LLUUID & agent_id,
+ LLSD& stats_sd):
LLTextureFetch::TFRequest(),
mCapsURL(caps_url),
mSessionID(session_id),
mAgentID(agent_id),
- mMainStats(main_stats),
+ mStatsSD(stats_sd),
mHandler(new AssetReportHandler)
{}
TFReqSendMetrics::~TFReqSendMetrics()
{
- delete mMainStats;
- mMainStats = 0;
}
@@ -4010,26 +4023,19 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
static volatile bool reporting_started(false);
static volatile S32 report_sequence(0);
- // We've taken over ownership of the stats copy at this
- // point. Get a working reference to it for merging here
- // but leave it in 'this'. Destructor will rid us of it.
- LLViewerAssetStats & main_stats = *mMainStats;
-
- LLViewerAssetStats::AssetStats stats;
- main_stats.getStats(stats, true);
- //LLSD merged_llsd = main_stats.asLLSD();
+ // In mStatsSD, we have a copy we own of the LLSD representation
+ // of the asset stats. Add some additional fields and ship it off.
+ static const S32 metrics_data_version = 2;
+
bool initial_report = !reporting_started;
- stats.session_id = mSessionID;
- stats.agent_id = mAgentID;
- stats.message = "ViewerAssetMetrics";
- stats.sequence = static_cast<bool>(report_sequence);
- stats.initial = initial_report;
- stats.break_ = static_cast<bool>(LLTextureFetch::svMetricsDataBreak);
-
- LLSD sd;
- LLParamSDParser parser;
- parser.writeSD(sd, stats);
+ mStatsSD["session_id"] = mSessionID;
+ mStatsSD["agent_id"] = mAgentID;
+ mStatsSD["message"] = "ViewerAssetMetrics";
+ mStatsSD["sequence"] = report_sequence;
+ mStatsSD["initial"] = initial_report;
+ mStatsSD["version"] = metrics_data_version;
+ mStatsSD["break"] = static_cast<bool>(LLTextureFetch::svMetricsDataBreak);
// Update sequence number
if (S32_MAX == ++report_sequence)
@@ -4040,8 +4046,13 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
// Limit the size of the stats report if necessary.
- sd["truncated"] = truncate_viewer_metrics(10, sd);
+ mStatsSD["truncated"] = truncate_viewer_metrics(10, mStatsSD);
+ if (gSavedSettings.getBOOL("QAModeMetrics"))
+ {
+ dump_sequential_xml("metric_asset_stats",mStatsSD);
+ }
+
if (! mCapsURL.empty())
{
// Don't care about handle, this is a fire-and-forget operation.
@@ -4049,7 +4060,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
fetcher->getMetricsPolicyClass(),
report_priority,
mCapsURL,
- sd,
+ mStatsSD,
LLCore::HttpOptions::ptr_t(),
fetcher->getMetricsHeaders(),
mHandler);
@@ -4063,7 +4074,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
// In QA mode, Metrics submode, log the result for ease of testing
if (fetcher->isQAMode())
{
- LL_INFOS(LOG_TXT) << ll_pretty_print_sd(sd) << LL_ENDL;
+ LL_INFOS(LOG_TXT) << "ViewerAssetMetrics as submitted\n" << ll_pretty_print_sd(mStatsSD) << LL_ENDL;
}
return true;
@@ -4580,7 +4591,7 @@ void LLTextureFetchDebugger::debugHTTP()
return;
}
- mHTTPUrl = region->getHttpUrl();
+ mHTTPUrl = region->getViewerAssetUrl();
if (mHTTPUrl.empty())
{
LL_INFOS(LOG_TXT) << "Fetch Debugger : Current region URL undefined. Cannot fetch textures through HTTP." << LL_ENDL;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 072e6a3307..cfa312ccd9 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -160,7 +160,7 @@ public:
void commandSendMetrics(const std::string & caps_url,
const LLUUID & session_id,
const LLUUID & agent_id,
- LLViewerAssetStats * main_stats);
+ LLSD& stats_sd);
// Threads: T*
void commandDataBreak();
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index 54ac29723f..14e05fd440 100644
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -80,6 +80,47 @@
*
*/
+namespace LLTrace
+{
+// This little bit of shimmery is to allow the creation of
+// default-constructed stat and event handles so we can make arrays of
+// the things.
+
+// The only sensible way to use this function is to immediately make a
+// copy of the contents, since it always returns the same pointer.
+const char *makeNewAutoName()
+{
+ static char name[64];
+ static S32 auto_namer_number = 0;
+ snprintf(name,64,"auto_name_%d",auto_namer_number);
+ auto_namer_number++;
+ return name;
+}
+
+template <typename T = F64>
+class DCCountStatHandle:
+ public CountStatHandle<T>
+{
+public:
+ DCCountStatHandle(const char *name = makeNewAutoName(), const char *description=NULL):
+ CountStatHandle<T>(name,description)
+ {
+ }
+};
+
+template <typename T = F64>
+class DCEventStatHandle:
+ public EventStatHandle<T>
+{
+public:
+ DCEventStatHandle(const char *name = makeNewAutoName(), const char *description=NULL):
+ EventStatHandle<T>(name,description)
+ {
+ }
+};
+
+}
+
namespace LLViewerAssetStatsFF
{
static EViewerAssetCategories asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp)
@@ -90,176 +131,45 @@ namespace LLViewerAssetStatsFF
// - wearables (clothing, bodyparts) which directly affect
// user experiences when they log in
// - sounds
- // - gestures
+ // - gestures, including animations
// - everything else.
//
- llassert_always(50 == LLViewerAssetType::AT_COUNT);
- // Multiple asset definitions are floating around so this requires some
- // maintenance and attention.
- static const EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] =
- {
- EVACTextureTempHTTPGet, // (0) AT_TEXTURE
- EVACSoundUDPGet, // AT_SOUND
- EVACOtherGet, // AT_CALLINGCARD
- EVACOtherGet, // AT_LANDMARK
- EVACOtherGet, // AT_SCRIPT
- EVACWearableUDPGet, // AT_CLOTHING
- EVACOtherGet, // AT_OBJECT
- EVACOtherGet, // AT_NOTECARD
- EVACOtherGet, // AT_CATEGORY
- EVACOtherGet, // AT_ROOT_CATEGORY
- EVACOtherGet, // (10) AT_LSL_TEXT
- EVACOtherGet, // AT_LSL_BYTECODE
- EVACOtherGet, // AT_TEXTURE_TGA
- EVACWearableUDPGet, // AT_BODYPART
- EVACOtherGet, // AT_TRASH
- EVACOtherGet, // AT_SNAPSHOT_CATEGORY
- EVACOtherGet, // AT_LOST_AND_FOUND
- EVACSoundUDPGet, // AT_SOUND_WAV
- EVACOtherGet, // AT_IMAGE_TGA
- EVACOtherGet, // AT_IMAGE_JPEG
- EVACGestureUDPGet, // (20) AT_ANIMATION
- EVACGestureUDPGet, // AT_GESTURE
- EVACOtherGet, // AT_SIMSTATE
- EVACOtherGet, // AT_FAVORITE
- EVACOtherGet, // AT_LINK
- EVACOtherGet, // AT_LINK_FOLDER
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, // (30)
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, // (40)
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, //
- EVACOtherGet, // AT_MESH
- // (50)
- };
-
- if (at < 0 || at >= LLViewerAssetType::AT_COUNT)
- {
- return EVACOtherGet;
- }
- EViewerAssetCategories ret(asset_to_bin_map[at]);
- if (EVACTextureTempHTTPGet == ret)
- {
- // Indexed with [is_temp][with_http]
- static const EViewerAssetCategories texture_bin_map[2][2] =
- {
- {
- EVACTextureNonTempUDPGet,
- EVACTextureNonTempHTTPGet,
- },
- {
- EVACTextureTempUDPGet,
- EVACTextureTempHTTPGet,
- }
- };
-
- ret = texture_bin_map[is_temp][with_http];
- }
+ EViewerAssetCategories ret;
+ switch (at)
+ {
+ case LLAssetType::AT_TEXTURE:
+ if (is_temp)
+ ret = with_http ? EVACTextureTempHTTPGet : EVACTextureTempUDPGet;
+ else
+ ret = with_http ? EVACTextureNonTempHTTPGet : EVACTextureNonTempUDPGet;
+ break;
+ case LLAssetType::AT_SOUND:
+ case LLAssetType::AT_SOUND_WAV:
+ ret = with_http ? EVACSoundHTTPGet : EVACSoundUDPGet;
+ break;
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ ret = with_http ? EVACWearableHTTPGet : EVACWearableUDPGet;
+ break;
+ case LLAssetType::AT_ANIMATION:
+ case LLAssetType::AT_GESTURE:
+ ret = with_http ? EVACGestureHTTPGet : EVACGestureUDPGet;
+ break;
+ case LLAssetType::AT_LANDMARK:
+ ret = with_http ? EVACLandmarkHTTPGet : EVACLandmarkUDPGet;
+ break;
+ default:
+ ret = with_http ? EVACOtherHTTPGet : EVACOtherUDPGet;
+ break;
+ }
return ret;
}
- static LLTrace::CountStatHandle<> sEnqueueAssetRequestsTempTextureHTTP ("enqueuedassetrequeststemptexturehttp",
- "Number of temporary texture asset http requests enqueued"),
- sEnqueueAssetRequestsTempTextureUDP ("enqueuedassetrequeststemptextureudp",
- "Number of temporary texture asset udp requests enqueued"),
- sEnqueueAssetRequestsNonTempTextureHTTP("enqueuedassetrequestsnontemptexturehttp",
- "Number of texture asset http requests enqueued"),
- sEnqueueAssetRequestsNonTempTextureUDP ("enqueuedassetrequestsnontemptextureudp",
- "Number of texture asset udp requests enqueued"),
- sEnqueuedAssetRequestsWearableUdp ("enqueuedassetrequestswearableudp",
- "Number of wearable asset requests enqueued"),
- sEnqueuedAssetRequestsSoundUdp ("enqueuedassetrequestssoundudp",
- "Number of sound asset requests enqueued"),
- sEnqueuedAssetRequestsGestureUdp ("enqueuedassetrequestsgestureudp",
- "Number of gesture asset requests enqueued"),
- sEnqueuedAssetRequestsOther ("enqueuedassetrequestsother",
- "Number of other asset requests enqueued");
-
- static LLTrace::CountStatHandle<>* sEnqueued[EVACCount] = {
- &sEnqueueAssetRequestsTempTextureHTTP,
- &sEnqueueAssetRequestsTempTextureUDP,
- &sEnqueueAssetRequestsNonTempTextureHTTP,
- &sEnqueueAssetRequestsNonTempTextureUDP,
- &sEnqueuedAssetRequestsWearableUdp,
- &sEnqueuedAssetRequestsSoundUdp,
- &sEnqueuedAssetRequestsGestureUdp,
- &sEnqueuedAssetRequestsOther
- };
-
- static LLTrace::CountStatHandle<> sDequeueAssetRequestsTempTextureHTTP ("dequeuedassetrequeststemptexturehttp",
- "Number of temporary texture asset http requests dequeued"),
- sDequeueAssetRequestsTempTextureUDP ("dequeuedassetrequeststemptextureudp",
- "Number of temporary texture asset udp requests dequeued"),
- sDequeueAssetRequestsNonTempTextureHTTP("dequeuedassetrequestsnontemptexturehttp",
- "Number of texture asset http requests dequeued"),
- sDequeueAssetRequestsNonTempTextureUDP ("dequeuedassetrequestsnontemptextureudp",
- "Number of texture asset udp requests dequeued"),
- sDequeuedAssetRequestsWearableUdp ("dequeuedassetrequestswearableudp",
- "Number of wearable asset requests dequeued"),
- sDequeuedAssetRequestsSoundUdp ("dequeuedassetrequestssoundudp",
- "Number of sound asset requests dequeued"),
- sDequeuedAssetRequestsGestureUdp ("dequeuedassetrequestsgestureudp",
- "Number of gesture asset requests dequeued"),
- sDequeuedAssetRequestsOther ("dequeuedassetrequestsother",
- "Number of other asset requests dequeued");
-
- static LLTrace::CountStatHandle<>* sDequeued[EVACCount] = {
- &sDequeueAssetRequestsTempTextureHTTP,
- &sDequeueAssetRequestsTempTextureUDP,
- &sDequeueAssetRequestsNonTempTextureHTTP,
- &sDequeueAssetRequestsNonTempTextureUDP,
- &sDequeuedAssetRequestsWearableUdp,
- &sDequeuedAssetRequestsSoundUdp,
- &sDequeuedAssetRequestsGestureUdp,
- &sDequeuedAssetRequestsOther
- };
-
- static LLTrace::EventStatHandle<F64Seconds > sResponseAssetRequestsTempTextureHTTP ("assetresponsetimestemptexturehttp",
- "Time spent responding to temporary texture asset http requests"),
- sResponseAssetRequestsTempTextureUDP ("assetresponsetimestemptextureudp",
- "Time spent responding to temporary texture asset udp requests"),
- sResponseAssetRequestsNonTempTextureHTTP("assetresponsetimesnontemptexturehttp",
- "Time spent responding to texture asset http requests"),
- sResponseAssetRequestsNonTempTextureUDP ("assetresponsetimesnontemptextureudp",
- "Time spent responding to texture asset udp requests"),
- sResponsedAssetRequestsWearableUdp ("assetresponsetimeswearableudp",
- "Time spent responding to wearable asset requests"),
- sResponsedAssetRequestsSoundUdp ("assetresponsetimessoundudp",
- "Time spent responding to sound asset requests"),
- sResponsedAssetRequestsGestureUdp ("assetresponsetimesgestureudp",
- "Time spent responding to gesture asset requests"),
- sResponsedAssetRequestsOther ("assetresponsetimesother",
- "Time spent responding to other asset requests");
-
- static LLTrace::EventStatHandle<F64Seconds >* sResponse[EVACCount] = {
- &sResponseAssetRequestsTempTextureHTTP,
- &sResponseAssetRequestsTempTextureUDP,
- &sResponseAssetRequestsNonTempTextureHTTP,
- &sResponseAssetRequestsNonTempTextureUDP,
- &sResponsedAssetRequestsWearableUdp,
- &sResponsedAssetRequestsSoundUdp,
- &sResponsedAssetRequestsGestureUdp,
- &sResponsedAssetRequestsOther
- };
+ static LLTrace::DCCountStatHandle<> sEnqueued[EVACCount];
+ static LLTrace::DCCountStatHandle<> sDequeued[EVACCount];
+ static LLTrace::DCEventStatHandle<> sBytesFetched[EVACCount];
+ static LLTrace::DCEventStatHandle<F64Seconds > sResponse[EVACCount];
}
// ------------------------------------------------------
@@ -353,6 +263,26 @@ void LLViewerAssetStats::setRegion(region_handle_t region_handle)
mRegionHandle = region_handle;
}
+template <typename T>
+void LLViewerAssetStats::getStat(LLTrace::Recording& rec, T& req, LLViewerAssetStatsFF::EViewerAssetCategories cat, bool compact_output)
+{
+ using namespace LLViewerAssetStatsFF;
+
+ if (!compact_output
+ || rec.getSampleCount(sEnqueued[cat])
+ || rec.getSampleCount(sDequeued[cat])
+ || rec.getSampleCount(sResponse[cat]))
+ {
+ req .enqueued(rec.getSampleCount(sEnqueued[cat]))
+ .dequeued(rec.getSampleCount(sDequeued[cat]))
+ .resp_count(rec.getSampleCount(sResponse[cat]))
+ .resp_min(rec.getMin(sResponse[cat]).value())
+ .resp_max(rec.getMax(sResponse[cat]).value())
+ .resp_mean(rec.getMean(sResponse[cat]).value())
+ .resp_mean_bytes(rec.getMean(sBytesFetched[cat]));
+ }
+}
+
void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
{
using namespace LLViewerAssetStatsFF;
@@ -365,108 +295,22 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
{
RegionStats& r = stats.regions.add();
LLTrace::Recording& rec = it->second;
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureTempHTTPGet])
- || rec.getSum(*sDequeued[EVACTextureTempHTTPGet])
- || rec.getSum(*sResponse[EVACTextureTempHTTPGet]).value())
- {
- r.get_texture_temp_http .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureTempHTTPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureTempHTTPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureTempHTTPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureTempHTTPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureTempHTTPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureTempHTTPGet]).value());
- }
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureTempUDPGet])
- || rec.getSum(*sDequeued[EVACTextureTempUDPGet])
- || rec.getSum(*sResponse[EVACTextureTempUDPGet]).value())
- {
- r.get_texture_temp_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureTempUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureTempUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureTempUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureTempUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureTempUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureTempUDPGet]).value());
- }
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureNonTempHTTPGet])
- || rec.getSum(*sDequeued[EVACTextureNonTempHTTPGet])
- || rec.getSum(*sResponse[EVACTextureNonTempHTTPGet]).value())
- {
- r.get_texture_non_temp_http .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureNonTempHTTPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureNonTempHTTPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureNonTempHTTPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureNonTempHTTPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureNonTempHTTPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureNonTempHTTPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACTextureNonTempUDPGet])
- || rec.getSum(*sDequeued[EVACTextureNonTempUDPGet])
- || rec.getSum(*sResponse[EVACTextureNonTempUDPGet]).value())
- {
- r.get_texture_non_temp_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureNonTempUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACTextureNonTempUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACTextureNonTempUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACTextureNonTempUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACTextureNonTempUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACTextureNonTempUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACWearableUDPGet])
- || rec.getSum(*sDequeued[EVACWearableUDPGet])
- || rec.getSum(*sResponse[EVACWearableUDPGet]).value())
- {
- r.get_wearable_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACWearableUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACWearableUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACWearableUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACWearableUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACWearableUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACWearableUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACSoundUDPGet])
- || rec.getSum(*sDequeued[EVACSoundUDPGet])
- || rec.getSum(*sResponse[EVACSoundUDPGet]).value())
- {
- r.get_sound_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACSoundUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACSoundUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACSoundUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACSoundUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACSoundUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACSoundUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACGestureUDPGet])
- || rec.getSum(*sDequeued[EVACGestureUDPGet])
- || rec.getSum(*sResponse[EVACGestureUDPGet]).value())
- {
- r.get_gesture_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACGestureUDPGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACGestureUDPGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACGestureUDPGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACGestureUDPGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACGestureUDPGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACGestureUDPGet]).value());
- }
-
- if (!compact_output
- || rec.getSum(*sEnqueued[EVACOtherGet])
- || rec.getSum(*sDequeued[EVACOtherGet])
- || rec.getSum(*sResponse[EVACOtherGet]).value())
- {
- r.get_other .enqueued((S32)rec.getSum(*sEnqueued[EVACOtherGet]))
- .dequeued((S32)rec.getSum(*sDequeued[EVACOtherGet]))
- .resp_count((S32)rec.getSum(*sResponse[EVACOtherGet]).value())
- .resp_min(rec.getMin(*sResponse[EVACOtherGet]).value())
- .resp_max(rec.getMax(*sResponse[EVACOtherGet]).value())
- .resp_mean(rec.getMean(*sResponse[EVACOtherGet]).value());
- }
+ getStat(rec, r.get_texture_temp_http, EVACTextureTempHTTPGet, compact_output);
+ getStat(rec, r.get_texture_temp_udp, EVACTextureTempUDPGet, compact_output);
+ getStat(rec, r.get_texture_non_temp_http, EVACTextureNonTempHTTPGet, compact_output);
+ getStat(rec, r.get_texture_non_temp_udp, EVACTextureNonTempUDPGet, compact_output);
+ getStat(rec, r.get_wearable_http, EVACWearableHTTPGet, compact_output);
+ getStat(rec, r.get_wearable_udp, EVACWearableUDPGet, compact_output);
+ getStat(rec, r.get_sound_http, EVACSoundHTTPGet, compact_output);
+ getStat(rec, r.get_sound_udp, EVACSoundUDPGet, compact_output);
+ getStat(rec, r.get_gesture_http, EVACGestureHTTPGet, compact_output);
+ getStat(rec, r.get_gesture_udp, EVACGestureUDPGet, compact_output);
+ getStat(rec, r.get_landmark_http, EVACLandmarkHTTPGet, compact_output);
+ getStat(rec, r.get_landmark_udp, EVACLandmarkUDPGet, compact_output);
+ getStat(rec, r.get_other_http, EVACOtherHTTPGet, compact_output);
+ getStat(rec, r.get_other_udp, EVACOtherUDPGet, compact_output);
+
S32 fps = (S32)rec.getLastValue(LLStatViewer::FPS_SAMPLE);
if (!compact_output || fps != 0)
{
@@ -479,10 +323,10 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
grid_from_region_handle(it->first, &grid_x, &grid_y);
r .grid_x(grid_x)
.grid_y(grid_y)
- .duration(F64Microseconds(rec.getDuration()).value());
+ .duration(F64Seconds(rec.getDuration()).value());
}
- stats.duration(mCurRecording ? F64Microseconds(mCurRecording->getDuration()).value() : 0.0);
+ stats.duration(mCurRecording ? F64Seconds(mCurRecording->getDuration()).value() : 0.0);
}
LLSD LLViewerAssetStats::asLLSD(bool compact_output)
@@ -518,21 +362,22 @@ void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- add(*sEnqueued[int(eac)], 1);
+ add(sEnqueued[int(eac)], 1);
}
void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- add(*sDequeued[int(eac)], 1);
+ add(sDequeued[int(eac)], 1);
}
-void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
+void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration, F64 bytes)
{
const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
- record(*sResponse[int(eac)], F64Microseconds(duration));
+ record(sResponse[int(eac)], F64Seconds(duration));
+ record(sBytesFetched[int(eac)], bytes);
}
void init()
@@ -561,7 +406,8 @@ LLViewerAssetStats::AssetRequestType::AssetRequestType()
resp_count("resp_count"),
resp_min("resp_min"),
resp_max("resp_max"),
- resp_mean("resp_mean")
+ resp_mean("resp_mean"),
+ resp_mean_bytes("resp_mean_bytes")
{}
LLViewerAssetStats::FPSStats::FPSStats()
@@ -576,10 +422,16 @@ LLViewerAssetStats::RegionStats::RegionStats()
get_texture_temp_udp("get_texture_temp_udp"),
get_texture_non_temp_http("get_texture_non_temp_http"),
get_texture_non_temp_udp("get_texture_non_temp_udp"),
+ get_wearable_http("get_wearable_http"),
get_wearable_udp("get_wearable_udp"),
+ get_sound_http("get_sound_http"),
get_sound_udp("get_sound_udp"),
+ get_gesture_http("get_gesture_http"),
get_gesture_udp("get_gesture_udp"),
- get_other("get_other"),
+ get_landmark_http("get_landmark_http"),
+ get_landmark_udp("get_landmark_udp"),
+ get_other_http("get_other_http"),
+ get_other_udp("get_other_udp"),
fps("fps"),
grid_x("grid_x"),
grid_y("grid_y"),
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 9d425c82fc..718c284224 100644
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -39,6 +39,29 @@
#include "lltrace.h"
#include "llinitparam.h"
+namespace LLViewerAssetStatsFF
+{
+ enum EViewerAssetCategories
+ {
+ EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP
+ EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP
+ EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP
+ EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP
+ EVACWearableHTTPGet, //< Wearable GETs HTTP
+ EVACWearableUDPGet, //< Wearable GETs UDP
+ EVACSoundHTTPGet, //< Sound GETs HTTP
+ EVACSoundUDPGet, //< Sound GETs UDP
+ EVACGestureHTTPGet, //< Gesture GETs HTTP
+ EVACGestureUDPGet, //< Gesture GETs UDP
+ EVACLandmarkHTTPGet, //< Landmark GETs HTTP
+ EVACLandmarkUDPGet, //< Landmark GETs UDP
+ EVACOtherHTTPGet, //< Other GETs HTTP
+ EVACOtherUDPGet, //< Other GETs UDP
+
+ EVACCount // Must be last
+ };
+}
+
/**
* @class LLViewerAssetStats
* @brief Records performance aspects of asset access operations.
@@ -74,6 +97,7 @@
* LLViewerAssetStatsFF is provided for conditional test-and-call
* operations.
*/
+
class LLViewerAssetStats : public LLStopWatchControlsMixin<LLViewerAssetStats>
{
public:
@@ -98,13 +122,14 @@ public:
resp_count;
Mandatory<F64> resp_min,
resp_max,
- resp_mean;
+ resp_mean,
+ resp_mean_bytes;
AssetRequestType();
};
struct FPSStats : public LLInitParam::Block<FPSStats>
- {
+ {
Mandatory<S32> count;
Mandatory<F64> min,
max,
@@ -113,15 +138,21 @@ public:
};
struct RegionStats : public LLInitParam::Block<RegionStats>
- {
+ {
Optional<AssetRequestType> get_texture_temp_http,
get_texture_temp_udp,
get_texture_non_temp_http,
get_texture_non_temp_udp,
+ get_wearable_http,
get_wearable_udp,
+ get_sound_http,
get_sound_udp,
+ get_gesture_http,
get_gesture_udp,
- get_other;
+ get_landmark_http,
+ get_landmark_udp,
+ get_other_http,
+ get_other_udp;
Optional<FPSStats> fps;
Optional<S32> grid_x,
grid_y;
@@ -165,6 +196,11 @@ public:
// Retrieve current metrics for all visited regions (NULL region UUID/handle excluded)
// Uses AssetStats structure seen above
void getStats(AssetStats& stats, bool compact_output);
+
+ // Retrieve a single asset request type (taken from a single region)
+ template <typename T>
+ void getStat(LLTrace::Recording& rec, T& req, LLViewerAssetStatsFF::EViewerAssetCategories cat, bool compact_output);
+
LLSD asLLSD(bool compact_output);
protected:
@@ -205,19 +241,6 @@ extern LLViewerAssetStats * gViewerAssetStats;
namespace LLViewerAssetStatsFF
{
- enum EViewerAssetCategories
- {
- EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP
- EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP
- EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP
- EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP
- EVACWearableUDPGet, //< Wearable GETs
- EVACSoundUDPGet, //< Sound GETs
- EVACGestureUDPGet, //< Gesture GETs
- EVACOtherGet, //< Other GETs
-
- EVACCount // Must be last
- };
/**
* @brief Allocation and deallocation of globals.
@@ -250,7 +273,7 @@ void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp,
- LLViewerAssetStats::duration_t duration);
+ LLViewerAssetStats::duration_t duration, F64 bytes=0);
void record_avatar_stats();
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 2db9c7e67c..e0b64403ef 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -33,9 +33,17 @@
#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"
///----------------------------------------------------------------------------
/// LLViewerAssetRequest
@@ -51,267 +59,283 @@
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;
-
- LLVFile vfile(mVFS, asset_id, asset_type, LLVFile::READ);
- S32 asset_size = vfile.getSize();
-
- LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type);
- req->mUpCallback = callback;
- req->mUserData = user_data;
-
- if (asset_size < 1)
- {
- // This can happen if there's a bug in our code or if the VFS has been corrupted.
- LL_WARNS() << "LLViewerAssetStorage::storeAssetData() Data _should_ already be in the VFS, but it's not! " << asset_id << LL_ENDL;
- // LLAssetStorage metric: Zero size VFS
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
-
- delete req;
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_VFS_CORRUPT);
- }
- return;
- }
- else
- {
- // LLAssetStorage metric: Successful Request
- S32 size = mVFS->getSize(asset_id, asset_type);
- const char *message = "Added to upload queue";
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message );
-
- if(is_priority)
- {
- mPendingUploads.push_front(req);
- }
- else
- {
- mPendingUploads.push_back(req);
- }
- }
-
- // Read the data from the VFS if it'll fit in this packet.
- if (asset_size + 100 < MTUBYTES)
- {
- BOOL res = vfile.read(buffer, asset_size); /* Flawfinder: ignore */
- S32 bytes_read = res ? vfile.getLastBytesRead() : 0;
-
- if( bytes_read == asset_size )
- {
- req->mDataSentInFirstPacket = TRUE;
- //LL_INFOS() << "LLViewerAssetStorage::createAsset sending data in first packet" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "Probable corruption in VFS file, aborting store asset data" << LL_ENDL;
-
- // LLAssetStorage metric: VFS corrupt - bogus size
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, asset_size, MR_VFS_CORRUPTION, __FILE__, __LINE__, "VFS corruption" );
-
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_VFS_CORRUPT);
- }
- return;
- }
- }
- else
- {
- // Too big, do an xfer
- buffer[0] = 0;
- asset_size = 0;
- }
- mMessageSys->newMessageFast(_PREHASH_AssetUploadRequest);
- mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
- mMessageSys->addUUIDFast(_PREHASH_TransactionID, tid);
- mMessageSys->addS8Fast(_PREHASH_Type, (S8)asset_type);
- mMessageSys->addBOOLFast(_PREHASH_Tempfile, temp_file);
- mMessageSys->addBOOLFast(_PREHASH_StoreLocal, store_local);
- mMessageSys->addBinaryDataFast( _PREHASH_AssetData, buffer, asset_size );
- mMessageSys->sendReliable(mUpstreamHost);
- }
- else
- {
- LL_WARNS() << "AssetStorage: attempt to upload non-existent vfile " << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
- // LLAssetStorage metric: Zero size VFS
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE);
- }
- }
- }
- else
- {
- LL_WARNS() << "Attempt to move asset store request upstream w/o valid upstream provider" << LL_ENDL;
- // LLAssetStorage metric: Upstream provider dead
- reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_NO_UPSTREAM, __FILE__, __LINE__, "No upstream provider" );
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
- }
- }
+ LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+ LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy) " << tid << ":" << LLAssetType::lookup(asset_type)
+ << " ASSET_ID: " << asset_id << LL_ENDL;
+
+ if (mUpstreamHost.isOk())
+ {
+ if (mVFS->getExists(asset_id, asset_type))
+ {
+ // Pack data into this packet if we can fit it.
+ U8 buffer[MTUBYTES];
+ buffer[0] = 0;
+
+ LLVFile vfile(mVFS, asset_id, asset_type, LLVFile::READ);
+ S32 asset_size = vfile.getSize();
+
+ LLAssetRequest *req = new LLAssetRequest(asset_id, asset_type);
+ req->mUpCallback = callback;
+ req->mUserData = user_data;
+
+ if (asset_size < 1)
+ {
+ // This can happen if there's a bug in our code or if the VFS has been corrupted.
+ LL_WARNS("AssetStorage") << "LLViewerAssetStorage::storeAssetData() Data _should_ already be in the VFS, but it's not! " << asset_id << LL_ENDL;
+ // LLAssetStorage metric: Zero size VFS
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
+
+ delete req;
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_VFS_CORRUPT);
+ }
+ return;
+ }
+ else
+ {
+ // LLAssetStorage metric: Successful Request
+ S32 size = mVFS->getSize(asset_id, asset_type);
+ const char *message = "Added to upload queue";
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message );
+
+ if(is_priority)
+ {
+ mPendingUploads.push_front(req);
+ }
+ else
+ {
+ mPendingUploads.push_back(req);
+ }
+ }
+
+ // Read the data from the VFS if it'll fit in this packet.
+ if (asset_size + 100 < MTUBYTES)
+ {
+ BOOL res = vfile.read(buffer, asset_size); /* Flawfinder: ignore */
+ S32 bytes_read = res ? vfile.getLastBytesRead() : 0;
+
+ if( bytes_read == asset_size )
+ {
+ req->mDataSentInFirstPacket = TRUE;
+ //LL_INFOS() << "LLViewerAssetStorage::createAsset sending data in first packet" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "Probable corruption in VFS file, aborting store asset data" << LL_ENDL;
+
+ // LLAssetStorage metric: VFS corrupt - bogus size
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, asset_size, MR_VFS_CORRUPTION, __FILE__, __LINE__, "VFS corruption" );
+
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_VFS_CORRUPT);
+ }
+ return;
+ }
+ }
+ else
+ {
+ // Too big, do an xfer
+ buffer[0] = 0;
+ asset_size = 0;
+ }
+ mMessageSys->newMessageFast(_PREHASH_AssetUploadRequest);
+ mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
+ mMessageSys->addUUIDFast(_PREHASH_TransactionID, tid);
+ mMessageSys->addS8Fast(_PREHASH_Type, (S8)asset_type);
+ mMessageSys->addBOOLFast(_PREHASH_Tempfile, temp_file);
+ mMessageSys->addBOOLFast(_PREHASH_StoreLocal, store_local);
+ mMessageSys->addBinaryDataFast( _PREHASH_AssetData, buffer, asset_size );
+ mMessageSys->sendReliable(mUpstreamHost);
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "AssetStorage: attempt to upload non-existent vfile " << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
+ // LLAssetStorage metric: Zero size VFS
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" );
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE);
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("AssetStorage") << "Attempt to move asset store request upstream w/o valid upstream provider" << LL_ENDL;
+ // LLAssetStorage metric: Upstream provider dead
+ reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_NO_UPSTREAM, __FILE__, __LINE__, "No upstream provider" );
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
+ }
+ }
}
void LLViewerAssetStorage::storeAssetData(
- const std::string& filename,
- const LLTransactionID& tid,
- LLAssetType::EType asset_type,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file,
- bool is_priority,
- bool user_waiting,
- F64Seconds timeout)
+ const std::string& filename,
+ const LLTransactionID& tid,
+ LLAssetType::EType asset_type,
+ LLStoreAssetCallback callback,
+ void* user_data,
+ bool temp_file,
+ bool is_priority,
+ bool user_waiting,
+ F64Seconds timeout)
{
- if(filename.empty())
- {
- // LLAssetStorage metric: no filename
- reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_VFS_CORRUPTION, __FILE__, __LINE__, "Filename missing" );
- LL_ERRS() << "No filename specified" << LL_ENDL;
- return;
- }
-
- LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
- LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
-
- LL_DEBUGS("AssetStorage") << "ASSET_ID: " << asset_id << LL_ENDL;
-
- S32 size = 0;
- LLFILE* fp = LLFile::fopen(filename, "rb");
- if (fp)
- {
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- }
- if( size )
- {
- LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
-
- legacy->mUpCallback = callback;
- legacy->mUserData = user_data;
-
- LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
-
- file.setMaxSize(size);
-
- const S32 buf_size = 65536;
- U8 copy_buf[buf_size];
- while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
- {
- file.write(copy_buf, size);
- }
- fclose(fp);
-
- // if this upload fails, the caller needs to setup a new tempfile for us
- if (temp_file)
- {
- LLFile::remove(filename);
- }
-
- // LLAssetStorage metric: Success not needed; handled in the overloaded method here:
-
- LLViewerAssetStorage::storeAssetData(
- tid,
- asset_type,
- legacyStoreDataCallback,
- (void**)legacy,
- temp_file,
- is_priority);
- }
- else // size == 0 (but previous block changes size)
- {
- if( fp )
- {
- // LLAssetStorage metric: Zero size
- reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" );
- }
- else
- {
- // LLAssetStorage metric: Missing File
- reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" );
- }
- if (callback)
- {
- callback(asset_id, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE);
- }
- }
+ if(filename.empty())
+ {
+ // LLAssetStorage metric: no filename
+ reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_VFS_CORRUPTION, __FILE__, __LINE__, "Filename missing" );
+ LL_ERRS() << "No filename specified" << LL_ENDL;
+ return;
+ }
+
+ LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+ LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << LL_ENDL;
+
+ LL_DEBUGS("AssetStorage") << "ASSET_ID: " << asset_id << LL_ENDL;
+
+ S32 size = 0;
+ LLFILE* fp = LLFile::fopen(filename, "rb");
+ if (fp)
+ {
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ }
+ if( size )
+ {
+ LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
+
+ legacy->mUpCallback = callback;
+ legacy->mUserData = user_data;
+
+ LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE);
+
+ file.setMaxSize(size);
+
+ const S32 buf_size = 65536;
+ U8 copy_buf[buf_size];
+ while ((size = (S32)fread(copy_buf, 1, buf_size, fp)))
+ {
+ file.write(copy_buf, size);
+ }
+ fclose(fp);
+
+ // if this upload fails, the caller needs to setup a new tempfile for us
+ if (temp_file)
+ {
+ LLFile::remove(filename);
+ }
+
+ // LLAssetStorage metric: Success not needed; handled in the overloaded method here:
+
+ LLViewerAssetStorage::storeAssetData(
+ tid,
+ asset_type,
+ legacyStoreDataCallback,
+ (void**)legacy,
+ temp_file,
+ is_priority);
+ }
+ else // size == 0 (but previous block changes size)
+ {
+ if( fp )
+ {
+ // LLAssetStorage metric: Zero size
+ reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" );
+ }
+ else
+ {
+ // LLAssetStorage metric: Missing File
+ reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" );
+ }
+ if (callback)
+ {
+ callback(asset_id, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE);
+ }
+ }
}
@@ -334,56 +358,218 @@ 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)
+{
+ 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)
{
- 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);
- }
- }
+ LL_DEBUGS("ViewerAsset") << "Request asset via HTTP " << uuid << " type " << LLAssetType::lookup(atype) << LL_ENDL;
+
+ bool with_http = true;
+ LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype, with_http);
+ req->mDownCallback = callback;
+ req->mUserData = user_data;
+ req->mIsPriority = is_priority;
+ if (!duplicate)
+ {
+ // Only collect metrics for non-duplicate requests. Others
+ // are piggy-backing and will artificially lower averages.
+ req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
+ }
+ mPendingDownloads.push_back(req);
+
+ // This is the same as the current UDP logic - don't re-request a duplicate.
+ if (!duplicate)
+ {
+ bool with_http = true;
+ bool is_temp = false;
+ LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
+
+ 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())
+ {
+ LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_NONE;
+ removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status);
+ return;
+ }
+ std::string url = getAssetURL(mViewerAssetUrl, uuid,atype);
+ LL_DEBUGS("ViewerAsset") << "request url: " << url << LL_ENDL;
+
+ LLCore::HttpRequest::policy_t httpPolicy(LLAppCoreHttp::AP_TEXTURE);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("assetRequestCoro", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+ LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts);
+
+ 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 was used in the UDP
+ // case.
+ LLUUID temp_id;
+ temp_id.generate();
+ LLVFile vf(gAssetStorage->mVFS, temp_id, atype, LLVFile::WRITE);
+ vf.setMaxSize(size);
+ req->mBytesFetched = size;
+ if (!vf.write(raw.data(),size))
+ {
+ // TODO asset-http: handle error
+ LL_WARNS("ViewerAsset") << "Failure in vf.write()" << LL_ENDL;
+ result_code = LL_ERR_ASSET_REQUEST_FAILED;
+ ext_status = LL_EXSTAT_VFS_CORRUPT;
+ }
+ 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;
+}
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index 6baec647e6..50131682e7 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -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
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 960a36a251..e53db403e1 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -106,6 +106,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();
@@ -226,6 +227,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");
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 899ab3a371..eb37613c95 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -521,7 +521,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mColoName("unknown"),
mProductSKU("unknown"),
mProductName("unknown"),
- mHttpUrl(""),
+ mViewerAssetUrl(""),
mCacheLoaded(FALSE),
mCacheDirty(FALSE),
mReleaseNotesRequested(FALSE),
@@ -2843,12 +2843,9 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("IsExperienceAdmin");
capabilityNames.append("IsExperienceContributor");
capabilityNames.append("RegionExperiences");
- capabilityNames.append("GetMesh");
- capabilityNames.append("GetMesh2");
capabilityNames.append("GetMetadata");
capabilityNames.append("GetObjectCost");
capabilityNames.append("GetObjectPhysicsData");
- capabilityNames.append("GetTexture");
capabilityNames.append("GroupAPIv1");
capabilityNames.append("GroupMemberData");
capabilityNames.append("GroupProposalBallot");
@@ -2895,6 +2892,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("UpdateScriptAgent");
capabilityNames.append("UpdateScriptTask");
capabilityNames.append("UploadBakedTexture");
+ capabilityNames.append("ViewerAsset");
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
@@ -2961,9 +2959,9 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
else
{
mImpl->mCapabilities[name] = url;
- if(name == "GetTexture")
+ if(name == "ViewerAsset")
{
- mHttpUrl = url ;
+ mViewerAssetUrl = url;
}
}
}
@@ -2974,9 +2972,9 @@ void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::stri
if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) )
{
mImpl->mSecondCapabilitiesTracker[name] = url;
- if(name == "GetTexture")
+ if(name == "ViewerAsset")
{
- mHttpUrl = url ;
+ mViewerAssetUrl = url;
}
}
}
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index a7bb546d2c..61ce5b454d 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -354,7 +354,7 @@ public:
friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion &region);
/// implements LLCapabilityProvider
virtual std::string getDescription() const;
- std::string getHttpUrl() const { return mHttpUrl ;}
+ std::string getViewerAssetUrl() const { return mViewerAssetUrl; }
U32 getNumOfVisibleGroups() const;
U32 getNumOfActiveCachedObjects() const;
@@ -506,7 +506,7 @@ private:
std::string mColoName;
std::string mProductSKU;
std::string mProductName;
- std::string mHttpUrl ;
+ std::string mViewerAssetUrl ;
// Maps local ids to cache entries.
// Regions can have order 10,000 objects, so assume
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 3968266c27..80c6805ead 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -9387,6 +9387,3 @@ BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type,
// non-self avatars don't have wearables
return FALSE;
}
-
-
-
diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp
index a08e32cb49..e2e7f09c3b 100644
--- a/indra/newview/tests/llviewerassetstats_test.cpp
+++ b/indra/newview/tests/llviewerassetstats_test.cpp
@@ -71,25 +71,33 @@ static const char * all_keys[] =
{
"duration",
"fps",
- "get_other",
+ "get_other_http",
+ "get_other_udp",
"get_texture_temp_http",
"get_texture_temp_udp",
"get_texture_non_temp_http",
"get_texture_non_temp_udp",
+ "get_wearable_http",
"get_wearable_udp",
+ "get_sound_http",
"get_sound_udp",
+ "get_gesture_http",
"get_gesture_udp"
};
static const char * resp_keys[] =
{
- "get_other",
+ "get_other_http",
+ "get_other_udp",
"get_texture_temp_http",
"get_texture_temp_udp",
"get_texture_non_temp_http",
"get_texture_non_temp_udp",
+ "get_wearable_http",
"get_wearable_udp",
+ "get_sound_http",
"get_sound_udp",
+ "get_gesture_http",
"get_gesture_udp"
};
@@ -540,11 +548,17 @@ namespace tut
ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger()));
ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger()));
- ensure("sd[get_wearable_udp][enqueued] is 4", (4 == sd["get_wearable_udp"]["enqueued"].asInteger()));
- ensure("sd[get_wearable_udp][dequeued] is 4", (4 == sd["get_wearable_udp"]["dequeued"].asInteger()));
+ ensure("sd[get_wearable_http][enqueued] is 2", (2 == sd["get_wearable_http"]["enqueued"].asInteger()));
+ ensure("sd[get_wearable_http][dequeued] is 2", (2 == sd["get_wearable_http"]["dequeued"].asInteger()));
- ensure("sd[get_other][enqueued] is 4", (4 == sd["get_other"]["enqueued"].asInteger()));
- ensure("sd[get_other][dequeued] is 0", (0 == sd["get_other"]["dequeued"].asInteger()));
+ ensure("sd[get_wearable_udp][enqueued] is 2", (2 == sd["get_wearable_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_wearable_udp][dequeued] is 2", (2 == sd["get_wearable_udp"]["dequeued"].asInteger()));
+
+ ensure("sd[get_other_http][enqueued] is 2", (2 == sd["get_other_http"]["enqueued"].asInteger()));
+ ensure("sd[get_other_http][dequeued] is 0", (0 == sd["get_other_http"]["dequeued"].asInteger()));
+
+ ensure("sd[get_other_udp][enqueued] is 2", (2 == sd["get_other_udp"]["enqueued"].asInteger()));
+ ensure("sd[get_other_udp][dequeued] is 0", (0 == sd["get_other_udp"]["dequeued"].asInteger()));
// Reset and check zeros...
// Reset leaves current region in place
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index e42374d56b..630af2b73b 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -34,6 +34,7 @@
*
*/
+
#include "linden_common.h"
#include "llerrorcontrol.h"
#include "lltut.h"
@@ -684,4 +685,5 @@ int main(int argc, char **argv)
return retval;
//delete mycallback;
+
}
diff --git a/scripts/metrics/viewer_asset_logs.py b/scripts/metrics/viewer_asset_logs.py
new file mode 100644
index 0000000000..e48286f696
--- /dev/null
+++ b/scripts/metrics/viewer_asset_logs.py
@@ -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"]
+