diff options
author | AndreyL ProductEngine <alihatskiy@productengine.com> | 2017-06-20 23:16:03 +0300 |
---|---|---|
committer | AndreyL ProductEngine <alihatskiy@productengine.com> | 2017-06-20 23:16:03 +0300 |
commit | 270cd8ff15d01ff9e2f390ae442e9f5de2b5adec (patch) | |
tree | dcd736ad4cd7db0e299e2542d3c8ad58b43d906e /indra/llmessage | |
parent | 21f22ced4ddf10afcbe0fae299a24b3ceb01d1de (diff) | |
parent | f1e52656e9e328d66aa5050bc9e59948a0217283 (diff) |
Merged in lindenlab/viewer-release
Diffstat (limited to 'indra/llmessage')
-rw-r--r-- | indra/llmessage/llassetstorage.cpp | 2381 | ||||
-rw-r--r-- | indra/llmessage/llassetstorage.h | 112 |
2 files changed, 1164 insertions, 1329 deletions
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(×tamp); - 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(×tamp); + 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, |