llassetstorage.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:42k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llassetstorage.cpp
  3.  * @brief Implementation of the base asset storage system.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. // system library includes
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include "llassetstorage.h"
  37. // linden library includes
  38. #include "llmath.h"
  39. #include "llstring.h"
  40. #include "lldir.h"
  41. #include "llsd.h"
  42. #include "llframetimer.h"
  43. // this library includes
  44. #include "message.h"
  45. #include "llxfermanager.h"
  46. #include "llvfile.h"
  47. #include "llvfs.h"
  48. #include "lldbstrings.h"
  49. #include "lltransfersourceasset.h"
  50. #include "lltransfertargetvfile.h" // For debugging
  51. #include "llmetrics.h"
  52. LLAssetStorage *gAssetStorage = NULL;
  53. LLMetrics *LLAssetStorage::metric_recipient = NULL;
  54. const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-000000000010"));
  55. const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
  56. LLTempAssetStorage::~LLTempAssetStorage()
  57. {
  58. }
  59. ///----------------------------------------------------------------------------
  60. /// LLAssetInfo
  61. ///----------------------------------------------------------------------------
  62. LLAssetInfo::LLAssetInfo( void )
  63. : mDescription(),
  64. mName(),
  65. mUuid(),
  66. mCreatorID(),
  67. mType( LLAssetType::AT_NONE )
  68. { }
  69. LLAssetInfo::LLAssetInfo( const LLUUID& object_id, const LLUUID& creator_id,
  70.   LLAssetType::EType type, const char* name,
  71.   const char* desc )
  72. : mUuid( object_id ), 
  73. mCreatorID( creator_id ), 
  74. mType( type )
  75. {
  76. setName( name );
  77. setDescription( desc );
  78. }
  79. LLAssetInfo::LLAssetInfo( const LLNameValue& nv )
  80. {
  81. setFromNameValue( nv );
  82. }
  83. // make sure the name is short enough, and strip all pipes since they
  84. // are reserved characters in our inventory tracking system.
  85. void LLAssetInfo::setName( const std::string& name )
  86. {
  87. if( !name.empty() )
  88. {
  89. mName.assign( name, 0, llmin((U32)name.size(), (U32)DB_INV_ITEM_NAME_STR_LEN) );
  90. mName.erase( std::remove(mName.begin(), mName.end(), '|'),
  91.  mName.end() );
  92. }
  93. }
  94. // make sure the name is short enough, and strip all pipes since they
  95. // are reserved characters in our inventory tracking system.
  96. void LLAssetInfo::setDescription( const std::string& desc )
  97. {
  98. if( !desc.empty() )
  99. {
  100. mDescription.assign( desc, 0, llmin((U32)desc.size(),
  101.  (U32)DB_INV_ITEM_DESC_STR_LEN) );
  102. mDescription.erase( std::remove(mDescription.begin(),
  103. mDescription.end(), '|'),
  104. mDescription.end() );
  105. }
  106. }
  107. // Assets (aka potential inventory items) can be applied to an
  108. // object in the world. We'll store that as a string name value
  109. // pair where the name encodes part of asset info, and the value
  110. // the rest.  LLAssetInfo objects will be responsible for parsing
  111. // the meaning out froman LLNameValue object. See the inventory
  112. // design docs for details. Briefly:
  113. //   name=<inv_type>|<uuid>
  114. //   value=<creatorid>|<name>|<description>|
  115. void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
  116. {
  117. std::string str;
  118. std::string buf;
  119. std::string::size_type pos1;
  120. std::string::size_type pos2;
  121. // convert the name to useful information
  122. str.assign( nv.mName );
  123. pos1 = str.find('|');
  124. buf.assign( str, 0, pos1++ );
  125. mType = LLAssetType::lookup( buf );
  126. buf.assign( str, pos1, std::string::npos );
  127. mUuid.set( buf );
  128. // convert the value to useful information
  129. str.assign( nv.getAsset() );
  130. pos1 = str.find('|');
  131. buf.assign( str, 0, pos1++ );
  132. mCreatorID.set( buf );
  133. pos2 = str.find( '|', pos1 );
  134. buf.assign( str, pos1, (pos2++) - pos1 );
  135. setName( buf );
  136. buf.assign( str, pos2, std::string::npos );
  137. setDescription( buf );
  138. llinfos << "uuid: " << mUuid << llendl;
  139. llinfos << "creator: " << mCreatorID << llendl;
  140. }
  141. ///----------------------------------------------------------------------------
  142. /// LLAssetRequest
  143. ///----------------------------------------------------------------------------
  144. LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
  145. : mUUID(uuid),
  146. mType(type),
  147. mDownCallback( NULL ),
  148. mUpCallback( NULL ),
  149. mInfoCallback( NULL ),
  150. mUserData( NULL ),
  151. mHost(),
  152. mIsTemp( FALSE ),
  153. mIsLocal(FALSE),
  154. mIsUserWaiting(FALSE),
  155. mTimeout(LL_ASSET_STORAGE_TIMEOUT),
  156. mIsPriority(FALSE),
  157. mDataSentInFirstPacket(FALSE),
  158. mDataIsInVFS( FALSE )
  159. {
  160. // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
  161. //  running a message system loop.
  162. mTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
  163. }
  164. // virtual
  165. LLAssetRequest::~LLAssetRequest()
  166. {
  167. }
  168. // virtual
  169. LLSD LLAssetRequest::getTerseDetails() const
  170. {
  171. LLSD sd;
  172. sd["asset_id"] = getUUID();
  173. sd["type_long"] = LLAssetType::lookupHumanReadable(getType());
  174. sd["type"] = LLAssetType::lookup(getType());
  175. sd["time"] = mTime;
  176. time_t timestamp = (time_t) mTime;
  177. std::ostringstream time_string;
  178. time_string << ctime(&timestamp);
  179. sd["time_string"] = time_string.str();
  180. return sd;
  181. }
  182. // virtual
  183. LLSD LLAssetRequest::getFullDetails() const
  184. {
  185. LLSD sd = getTerseDetails();
  186. sd["host"] = mHost.getIPandPort();
  187. sd["requesting_agent"] = mRequestingAgentID;
  188. sd["is_temp"] = mIsTemp;
  189. sd["is_local"] = mIsLocal;
  190. sd["is_priority"] = mIsPriority;
  191. sd["data_send_in_first_packet"] = mDataSentInFirstPacket;
  192. sd["data_is_in_vfs"] = mDataIsInVFS;
  193. return sd;
  194. }
  195. ///----------------------------------------------------------------------------
  196. /// LLInvItemRequest
  197. ///----------------------------------------------------------------------------
  198. LLInvItemRequest::LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType type)
  199. : mUUID(uuid),
  200. mType(type),
  201. mDownCallback( NULL ),
  202. mUserData( NULL ),
  203. mHost(),
  204. mIsTemp( FALSE ),
  205. mIsPriority(FALSE),
  206. mDataSentInFirstPacket(FALSE),
  207. mDataIsInVFS( FALSE )
  208. {
  209. // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
  210. //  running a message system loop.
  211. mTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
  212. }
  213. LLInvItemRequest::~LLInvItemRequest()
  214. {
  215. }
  216. ///----------------------------------------------------------------------------
  217. /// LLEstateAssetRequest
  218. ///----------------------------------------------------------------------------
  219. LLEstateAssetRequest::LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType atype,
  220.    EstateAssetType etype)
  221. : mUUID(uuid),
  222. mAType(atype),
  223. mEstateAssetType(etype),
  224. mDownCallback( NULL ),
  225. mUserData( NULL ),
  226. mHost(),
  227. mIsTemp( FALSE ),
  228. mIsPriority(FALSE),
  229. mDataSentInFirstPacket(FALSE),
  230. mDataIsInVFS( FALSE )
  231. {
  232. // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
  233. //  running a message system loop.
  234. mTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
  235. }
  236. LLEstateAssetRequest::~LLEstateAssetRequest()
  237. {
  238. }
  239. ///----------------------------------------------------------------------------
  240. /// LLAssetStorage
  241. ///----------------------------------------------------------------------------
  242. // since many of these functions are called by the messaging and xfer systems,
  243. // they are declared as static and are passed a "this" handle
  244. // it's a C/C++ mish-mash!
  245. // TODO: permissions on modifications - maybe don't allow at all?
  246. // TODO: verify that failures get propogated down
  247. // TODO: rework tempfile handling?
  248. LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, const LLHost &upstream_host)
  249. {
  250. _init(msg, xfer, vfs, upstream_host);
  251. }
  252. LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
  253.    LLVFS *vfs)
  254. {
  255. _init(msg, xfer, vfs, LLHost::invalid);
  256. }
  257. void LLAssetStorage::_init(LLMessageSystem *msg,
  258.    LLXferManager *xfer,
  259.    LLVFS *vfs,
  260.    const LLHost &upstream_host)
  261. {
  262. mShutDown = FALSE;
  263. mMessageSys = msg;
  264. mXferManager = xfer;
  265. mVFS = vfs;
  266. setUpstream(upstream_host);
  267. msg->setHandlerFuncFast(_PREHASH_AssetUploadComplete, processUploadComplete, (void **)this);
  268. }
  269. LLAssetStorage::~LLAssetStorage()
  270. {
  271. mShutDown = TRUE;
  272. _cleanupRequests(TRUE, LL_ERR_CIRCUIT_GONE);
  273. if (gMessageSystem)
  274. {
  275. // Warning!  This won't work if there's more than one asset storage.
  276. // unregister our callbacks with the message system
  277. gMessageSystem->setHandlerFuncFast(_PREHASH_AssetUploadComplete, NULL, NULL);
  278. }
  279. // Clear the toxic asset map
  280. mToxicAssetMap.clear();
  281. }
  282. void LLAssetStorage::setUpstream(const LLHost &upstream_host)
  283. {
  284. LL_DEBUGS("AppInit") << "AssetStorage: Setting upstream provider to " << upstream_host << LL_ENDL;
  285. mUpstreamHost = upstream_host;
  286. }
  287. void LLAssetStorage::checkForTimeouts()
  288. {
  289. _cleanupRequests(FALSE, LL_ERR_TCP_TIMEOUT);
  290. }
  291. void LLAssetStorage::_cleanupRequests(BOOL all, S32 error)
  292. {
  293. F64 mt_secs = LLMessageSystem::getMessageTimeSeconds();
  294. request_list_t timed_out;
  295. S32 rt;
  296. for (rt = 0; rt < RT_COUNT; rt++)
  297. {
  298. request_list_t* requests = getRequestList((ERequestType)rt);
  299. for (request_list_t::iterator iter = requests->begin();
  300.  iter != requests->end(); )
  301. {
  302. request_list_t::iterator curiter = iter++;
  303. LLAssetRequest* tmp = *curiter;
  304. // if all is true, we want to clean up everything
  305. // otherwise just check for timed out requests
  306. // EXCEPT for upload timeouts
  307. if (all 
  308. || ((RT_DOWNLOAD == rt)
  309. && LL_ASSET_STORAGE_TIMEOUT < (mt_secs - tmp->mTime)))
  310. {
  311. llwarns << "Asset " << getRequestName((ERequestType)rt) << " request "
  312. << (all ? "aborted" : "timed out") << " for "
  313. << tmp->getUUID() << "."
  314. << LLAssetType::lookup(tmp->getType()) << llendl;
  315. timed_out.push_front(tmp);
  316. iter = requests->erase(curiter);
  317. }
  318. }
  319. }
  320. LLAssetInfo info;
  321. for (request_list_t::iterator iter = timed_out.begin();
  322.  iter != timed_out.end();  )
  323. {
  324. request_list_t::iterator curiter = iter++;
  325. LLAssetRequest* tmp = *curiter;
  326. if (tmp->mUpCallback)
  327. {
  328. tmp->mUpCallback(tmp->getUUID(), tmp->mUserData, error, LL_EXSTAT_NONE);
  329. }
  330. if (tmp->mDownCallback)
  331. {
  332. tmp->mDownCallback(mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, error, LL_EXSTAT_NONE);
  333. }
  334. if (tmp->mInfoCallback)
  335. {
  336. tmp->mInfoCallback(&info, tmp->mUserData, error);
  337. }
  338. delete tmp;
  339. }
  340. }
  341. BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type)
  342. {
  343. return mVFS->getExists(uuid, type);
  344. }
  345. ///////////////////////////////////////////////////////////////////////////
  346. // GET routines
  347. ///////////////////////////////////////////////////////////////////////////
  348. // IW - uuid is passed by value to avoid side effects, please don't re-add &    
  349. void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), void *user_data, BOOL is_priority)
  350. {
  351. lldebugs << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << llendl;
  352. if (mShutDown)
  353. {
  354. return; // don't get the asset or do any callbacks, we are shutting down
  355. }
  356. if (uuid.isNull())
  357. {
  358. // Special case early out for NULL uuid
  359. if (callback)
  360. {
  361. callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
  362. }
  363. return;
  364. }
  365. BOOL exists = mVFS->getExists(uuid, type);
  366. LLVFile file(mVFS, uuid, type);
  367. U32 size = exists ? file.getSize() : 0;
  368. if (size < 1)
  369. {
  370. if (exists)
  371. {
  372. llwarns << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << llendl;
  373. file.remove();
  374. }
  375. BOOL duplicate = FALSE;
  376. // check to see if there's a pending download of this uuid already
  377. for (request_list_t::iterator iter = mPendingDownloads.begin();
  378.  iter != mPendingDownloads.end(); ++iter )
  379. {
  380. LLAssetRequest  *tmp = *iter;
  381. if ((type == tmp->getType()) && (uuid == tmp->getUUID()))
  382. {
  383. if (callback == tmp->mDownCallback && user_data == tmp->mUserData)
  384. {
  385. // this is a duplicate from the same subsystem - throw it away
  386. llwarns << "Discarding duplicate request for asset " << uuid
  387. << "." << LLAssetType::lookup(type) << llendl;
  388. return;
  389. }
  390. // this is a duplicate request
  391. // queue the request, but don't actually ask for it again
  392. duplicate = TRUE;
  393. }
  394. }
  395. if (duplicate)
  396. {
  397. llinfos << "Adding additional non-duplicate request for asset " << uuid 
  398. << "." << LLAssetType::lookup(type) << llendl;
  399. }
  400. // This can be overridden by subclasses
  401. _queueDataRequest(uuid, type, callback, user_data, duplicate, is_priority);
  402. }
  403. else
  404. {
  405. // we've already got the file
  406. // theoretically, partial files w/o a pending request shouldn't happen
  407. // unless there's a weird error
  408. if (callback)
  409. {
  410. callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
  411. }
  412. }
  413. }
  414. void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType atype,
  415.    LLGetAssetCallback callback,
  416.    void *user_data, BOOL duplicate,
  417.    BOOL is_priority)
  418. {
  419. if (mUpstreamHost.isOk())
  420. {
  421. // stash the callback info so we can find it after we get the response message
  422. LLAssetRequest *req = new LLAssetRequest(uuid, atype);
  423. req->mDownCallback = callback;
  424. req->mUserData = user_data;
  425. req->mIsPriority = is_priority;
  426. mPendingDownloads.push_back(req);
  427. if (!duplicate)
  428. {
  429. // send request message to our upstream data provider
  430. // Create a new asset transfer.
  431. LLTransferSourceParamsAsset spa;
  432. spa.setAsset(uuid, atype);
  433. // Set our destination file, and the completion callback.
  434. LLTransferTargetParamsVFile tpvf;
  435. tpvf.setAsset(uuid, atype);
  436. tpvf.setCallback(downloadCompleteCallback, req);
  437. llinfos << "Starting transfer for " << uuid << llendl;
  438. LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
  439. ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
  440. }
  441. }
  442. else
  443. {
  444. // uh-oh, we shouldn't have gotten here
  445. llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
  446. if (callback)
  447. {
  448. callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
  449. }
  450. }
  451. }
  452. void LLAssetStorage::downloadCompleteCallback(
  453. S32 result,
  454. const LLUUID& file_id,
  455. LLAssetType::EType file_type,
  456. void* user_data, LLExtStat ext_status)
  457. {
  458. lldebugs << "LLAssetStorage::downloadCompleteCallback() for " << file_id
  459.  << "," << LLAssetType::lookup(file_type) << llendl;
  460. LLAssetRequest* req = (LLAssetRequest*)user_data;
  461. if(!req)
  462. {
  463. llwarns << "LLAssetStorage::downloadCompleteCallback called without"
  464. "a valid request." << llendl;
  465. return;
  466. }
  467. if (!gAssetStorage)
  468. {
  469. llwarns << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << llendl;
  470. return;
  471. }
  472. // Inefficient since we're doing a find through a list that may have thousands of elements.
  473. // This is due for refactoring; we will probably change mPendingDownloads into a set.
  474. request_list_t::iterator download_iter = std::find(gAssetStorage->mPendingDownloads.begin(), 
  475.    gAssetStorage->mPendingDownloads.end(),
  476.    req);
  477. // If the LLAssetRequest doesn't exist in the downloads queue, then it either has already been deleted
  478. // by _cleanupRequests, or it's a transfer.
  479. if (download_iter != gAssetStorage->mPendingDownloads.end())
  480. {
  481. req->setUUID(file_id);
  482. req->setType(file_type);
  483. }
  484. if (LL_ERR_NOERR == result)
  485. {
  486. // we might have gotten a zero-size file
  487. LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
  488. if (vfile.getSize() <= 0)
  489. {
  490. llwarns << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << llendl;
  491. result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
  492. vfile.remove();
  493. }
  494. }
  495. // find and callback ALL pending requests for this UUID
  496. // SJB: We process the callbacks in reverse order, I do not know if this is important,
  497. //      but I didn't want to mess with it.
  498. request_list_t requests;
  499. for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
  500.  iter != gAssetStorage->mPendingDownloads.end();  )
  501. {
  502. request_list_t::iterator curiter = iter++;
  503. LLAssetRequest* tmp = *curiter;
  504. if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type))
  505. {
  506. requests.push_front(tmp);
  507. iter = gAssetStorage->mPendingDownloads.erase(curiter);
  508. }
  509. }
  510. for (request_list_t::iterator iter = requests.begin();
  511.  iter != requests.end();  )
  512. {
  513. request_list_t::iterator curiter = iter++;
  514. LLAssetRequest* tmp = *curiter;
  515. if (tmp->mDownCallback)
  516. {
  517. tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status);
  518. }
  519. delete tmp;
  520. }
  521. }
  522. void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
  523. const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
  524.  LLGetAssetCallback callback, void *user_data, BOOL is_priority)
  525. {
  526. lldebugs << "LLAssetStorage::getEstateAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << ", estatetype " << etype << llendl;
  527. //
  528. // Probably will get rid of this early out?
  529. //
  530. if (asset_id.isNull())
  531. {
  532. // Special case early out for NULL uuid
  533. if (callback)
  534. {
  535. callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
  536. }
  537. return;
  538. }
  539. BOOL exists = mVFS->getExists(asset_id, atype);
  540. LLVFile file(mVFS, asset_id, atype);
  541. U32 size = exists ? file.getSize() : 0;
  542. if (size < 1)
  543. {
  544. if (exists)
  545. {
  546. llwarns << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << llendl;
  547. file.remove();
  548. }
  549. // See whether we should talk to the object's originating sim, or the upstream provider.
  550. LLHost source_host;
  551. if (object_sim.isOk())
  552. {
  553. source_host = object_sim;
  554. }
  555. else
  556. {
  557. source_host = mUpstreamHost;
  558. }
  559. if (source_host.isOk())
  560. {
  561. // stash the callback info so we can find it after we get the response message
  562. LLEstateAssetRequest *req = new LLEstateAssetRequest(asset_id, atype, etype);
  563. req->mDownCallback = callback;
  564. req->mUserData = user_data;
  565. req->mIsPriority = is_priority;
  566. // send request message to our upstream data provider
  567. // Create a new asset transfer.
  568. LLTransferSourceParamsEstate spe;
  569. spe.setAgentSession(agent_id, session_id);
  570. spe.setEstateAssetType(etype);
  571. // Set our destination file, and the completion callback.
  572. LLTransferTargetParamsVFile tpvf;
  573. tpvf.setAsset(asset_id, atype);
  574. tpvf.setCallback(downloadEstateAssetCompleteCallback, req);
  575. llinfos << "Starting transfer for " << asset_id << llendl;
  576. LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
  577. ttcp->requestTransfer(spe, tpvf, 100.f + (is_priority ? 1.f : 0.f));
  578. }
  579. else
  580. {
  581. // uh-oh, we shouldn't have gotten here
  582. llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
  583. if (callback)
  584. {
  585. callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
  586. }
  587. }
  588. }
  589. else
  590. {
  591. // we've already got the file
  592. // theoretically, partial files w/o a pending request shouldn't happen
  593. // unless there's a weird error
  594. if (callback)
  595. {
  596. callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
  597. }
  598. }
  599. }
  600. void LLAssetStorage::downloadEstateAssetCompleteCallback(
  601. S32 result,
  602. const LLUUID& file_id,
  603. LLAssetType::EType file_type,
  604. void* user_data,
  605. LLExtStat ext_status)
  606. {
  607. LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data;
  608. if(!req)
  609. {
  610. llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
  611. " without a valid request." << llendl;
  612. return;
  613. }
  614. if (!gAssetStorage)
  615. {
  616. llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
  617. " without any asset system, aborting!" << llendl;
  618. return;
  619. }
  620. req->setUUID(file_id);
  621. req->setType(file_type);
  622. if (LL_ERR_NOERR == result)
  623. {
  624. // we might have gotten a zero-size file
  625. LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType());
  626. if (vfile.getSize() <= 0)
  627. {
  628. llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
  629. result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
  630. vfile.remove();
  631. }
  632. }
  633. req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status);
  634. }
  635. void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
  636.  const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id,
  637.  const LLUUID &asset_id, LLAssetType::EType atype,
  638.  LLGetAssetCallback callback, void *user_data, BOOL is_priority)
  639. {
  640. lldebugs << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << llendl;
  641. //
  642. // Probably will get rid of this early out?
  643. //
  644. //if (asset_id.isNull())
  645. //{
  646. // // Special case early out for NULL uuid
  647. // if (callback)
  648. // {
  649. // callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE);
  650. // }
  651. // return;
  652. //}
  653. bool exists = false; 
  654. U32 size = 0;
  655. if(asset_id.notNull())
  656. {
  657. exists = mVFS->getExists(asset_id, atype);
  658. LLVFile file(mVFS, asset_id, atype);
  659. size = exists ? file.getSize() : 0;
  660. if(exists && size < 1)
  661. {
  662. llwarns << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << llendl;
  663. file.remove();
  664. }
  665. }
  666. if (size < 1)
  667. {
  668. // See whether we should talk to the object's originating sim,
  669. // or the upstream provider.
  670. LLHost source_host;
  671. if (object_sim.isOk())
  672. {
  673. source_host = object_sim;
  674. }
  675. else
  676. {
  677. source_host = mUpstreamHost;
  678. }
  679. if (source_host.isOk())
  680. {
  681. // stash the callback info so we can find it after we get the response message
  682. LLInvItemRequest *req = new LLInvItemRequest(asset_id, atype);
  683. req->mDownCallback = callback;
  684. req->mUserData = user_data;
  685. req->mIsPriority = is_priority;
  686. // send request message to our upstream data provider
  687. // Create a new asset transfer.
  688. LLTransferSourceParamsInvItem spi;
  689. spi.setAgentSession(agent_id, session_id);
  690. spi.setInvItem(owner_id, task_id, item_id);
  691. spi.setAsset(asset_id, atype);
  692. // Set our destination file, and the completion callback.
  693. LLTransferTargetParamsVFile tpvf;
  694. tpvf.setAsset(asset_id, atype);
  695. tpvf.setCallback(downloadInvItemCompleteCallback, req);
  696. llinfos << "Starting transfer for inventory asset "
  697. << item_id << " owned by " << owner_id << "," << task_id
  698. << llendl;
  699. LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
  700. ttcp->requestTransfer(spi, tpvf, 100.f + (is_priority ? 1.f : 0.f));
  701. }
  702. else
  703. {
  704. // uh-oh, we shouldn't have gotten here
  705. llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
  706. if (callback)
  707. {
  708. callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
  709. }
  710. }
  711. }
  712. else
  713. {
  714. // we've already got the file
  715. // theoretically, partial files w/o a pending request shouldn't happen
  716. // unless there's a weird error
  717. if (callback)
  718. {
  719. callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
  720. }
  721. }
  722. }
  723. void LLAssetStorage::downloadInvItemCompleteCallback(
  724. S32 result,
  725. const LLUUID& file_id,
  726. LLAssetType::EType file_type,
  727. void* user_data,
  728. LLExtStat ext_status)
  729. {
  730. LLInvItemRequest *req = (LLInvItemRequest*)user_data;
  731. if(!req)
  732. {
  733. llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
  734. " without a valid request." << llendl;
  735. return;
  736. }
  737. if (!gAssetStorage)
  738. {
  739. llwarns << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << llendl;
  740. return;
  741. }
  742. req->setUUID(file_id);
  743. req->setType(file_type);
  744. if (LL_ERR_NOERR == result)
  745. {
  746. // we might have gotten a zero-size file
  747. LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
  748. if (vfile.getSize() <= 0)
  749. {
  750. llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
  751. result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
  752. vfile.remove();
  753. }
  754. }
  755. req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status);
  756. }
  757. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  758. // Store routines
  759. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  760. // static
  761. void LLAssetStorage::uploadCompleteCallback(const LLUUID& uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
  762. {
  763. if (!gAssetStorage)
  764. {
  765. llwarns << "LLAssetStorage::uploadCompleteCallback has no gAssetStorage!" << llendl;
  766. return;
  767. }
  768. LLAssetRequest *req  = (LLAssetRequest *)user_data;
  769. BOOL success  = TRUE;
  770. if (result)
  771. {
  772. llwarns << "LLAssetStorage::uploadCompleteCallback " << result << ":" << getErrorString(result) << " trying to upload file to upstream provider" << llendl;
  773. success = FALSE;
  774. }
  775. // we're done grabbing the file, tell the client
  776. gAssetStorage->mMessageSys->newMessageFast(_PREHASH_AssetUploadComplete);
  777. gAssetStorage->mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
  778. gAssetStorage->mMessageSys->addUUIDFast(_PREHASH_UUID, uuid);
  779. gAssetStorage->mMessageSys->addS8Fast(_PREHASH_Type, req->getType());
  780. gAssetStorage->mMessageSys->addBOOLFast(_PREHASH_Success, success);
  781. gAssetStorage->mMessageSys->sendReliable(req->mHost);
  782. delete req;
  783. }
  784. void LLAssetStorage::processUploadComplete(LLMessageSystem *msg, void **user_data)
  785. {
  786. LLAssetStorage *this_ptr = (LLAssetStorage *)user_data;
  787. LLUUID uuid;
  788. S8 asset_type_s8;
  789. LLAssetType::EType asset_type;
  790. BOOL success = FALSE;
  791. msg->getUUIDFast(_PREHASH_AssetBlock, _PREHASH_UUID, uuid);
  792. msg->getS8Fast(_PREHASH_AssetBlock, _PREHASH_Type, asset_type_s8);
  793. msg->getBOOLFast(_PREHASH_AssetBlock, _PREHASH_Success, success);
  794. asset_type = (LLAssetType::EType)asset_type_s8;
  795. this_ptr->_callUploadCallbacks(uuid, asset_type, success, LL_EXSTAT_NONE);
  796. }
  797. void LLAssetStorage::_callUploadCallbacks(const LLUUID &uuid, LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status )
  798. {
  799. // SJB: We process the callbacks in reverse order, I do not know if this is important,
  800. //      but I didn't want to mess with it.
  801. request_list_t requests;
  802. for (request_list_t::iterator iter = mPendingUploads.begin();
  803.  iter != mPendingUploads.end();  )
  804. {
  805. request_list_t::iterator curiter = iter++;
  806. LLAssetRequest* req = *curiter;
  807. if ((req->getUUID() == uuid) && (req->getType() == asset_type))
  808. {
  809. requests.push_front(req);
  810. iter = mPendingUploads.erase(curiter);
  811. }
  812. }
  813. for (request_list_t::iterator iter = mPendingLocalUploads.begin();
  814.  iter != mPendingLocalUploads.end();  )
  815. {
  816. request_list_t::iterator curiter = iter++;
  817. LLAssetRequest* req = *curiter;
  818. if ((req->getUUID() == uuid) && (req->getType() == asset_type))
  819. {
  820. requests.push_front(req);
  821. iter = mPendingLocalUploads.erase(curiter);
  822. }
  823. }
  824. for (request_list_t::iterator iter = requests.begin();
  825.  iter != requests.end();  )
  826. {
  827. request_list_t::iterator curiter = iter++;
  828. LLAssetRequest* req = *curiter;
  829. if (req->mUpCallback)
  830. {
  831. req->mUpCallback(uuid, req->mUserData, (success ?  LL_ERR_NOERR :  LL_ERR_ASSET_REQUEST_FAILED ), ext_status );
  832. }
  833. delete req;
  834. }
  835. }
  836. LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::ERequestType rt)
  837. {
  838. switch (rt)
  839. {
  840. case RT_DOWNLOAD:
  841. return &mPendingDownloads;
  842. case RT_UPLOAD:
  843. return &mPendingUploads;
  844. case RT_LOCALUPLOAD:
  845. return &mPendingLocalUploads;
  846. default:
  847. llwarns << "Unable to find request list for request type '" << rt << "'" << llendl;
  848. return NULL;
  849. }
  850. }
  851. const LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::ERequestType rt) const
  852. {
  853. switch (rt)
  854. {
  855. case RT_DOWNLOAD:
  856. return &mPendingDownloads;
  857. case RT_UPLOAD:
  858. return &mPendingUploads;
  859. case RT_LOCALUPLOAD:
  860. return &mPendingLocalUploads;
  861. default:
  862. llwarns << "Unable to find request list for request type '" << rt << "'" << llendl;
  863. return NULL;
  864. }
  865. }
  866. // static
  867. std::string LLAssetStorage::getRequestName(LLAssetStorage::ERequestType rt)
  868. {
  869. switch (rt)
  870. {
  871. case RT_DOWNLOAD:
  872. return "download";
  873. case RT_UPLOAD:
  874. return "upload";
  875. case RT_LOCALUPLOAD:
  876. return "localupload";
  877. default:
  878. llwarns << "Unable to find request name for request type '" << rt << "'" << llendl;
  879. return "";
  880. }
  881. }
  882. S32 LLAssetStorage::getNumPending(LLAssetStorage::ERequestType rt) const
  883. {
  884. const request_list_t* requests = getRequestList(rt);
  885. S32 num_pending = -1;
  886. if (requests)
  887. {
  888. num_pending = requests->size();
  889. }
  890. return num_pending;
  891. }
  892. S32 LLAssetStorage::getNumPendingDownloads() const
  893. {
  894. return getNumPending(RT_DOWNLOAD);
  895. }
  896. S32 LLAssetStorage::getNumPendingUploads() const
  897. {
  898. return getNumPending(RT_UPLOAD);
  899. }
  900. S32 LLAssetStorage::getNumPendingLocalUploads()
  901. {
  902. return getNumPending(RT_LOCALUPLOAD);
  903. }
  904. // virtual
  905. LLSD LLAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt,
  906. LLAssetType::EType asset_type,
  907. const std::string& detail_prefix) const
  908. {
  909. const request_list_t* requests = getRequestList(rt);
  910. LLSD sd;
  911. sd["requests"] = getPendingDetailsImpl(requests, asset_type, detail_prefix);
  912. return sd;
  913. }
  914. // virtual
  915. LLSD LLAssetStorage::getPendingDetailsImpl(const LLAssetStorage::request_list_t* requests,
  916. LLAssetType::EType asset_type,
  917. const std::string& detail_prefix) const
  918. {
  919. LLSD details;
  920. if (requests)
  921. {
  922. request_list_t::const_iterator it = requests->begin();
  923. request_list_t::const_iterator end = requests->end();
  924. for ( ; it != end; ++it)
  925. {
  926. LLAssetRequest* req = *it;
  927. if (   (LLAssetType::AT_NONE == asset_type)
  928. || (req->getType() == asset_type) )
  929. {
  930. LLSD row = req->getTerseDetails();
  931. std::ostringstream detail;
  932. detail << detail_prefix << "/" << LLAssetType::lookup(req->getType())
  933. << "/" << req->getUUID();
  934. row["detail"] = LLURI(detail.str());
  935. details.append(row);
  936. }
  937. }
  938. }
  939. return details;
  940. }
  941. // static
  942. const LLAssetRequest* LLAssetStorage::findRequest(const LLAssetStorage::request_list_t* requests,
  943. LLAssetType::EType asset_type,
  944. const LLUUID& asset_id)
  945. {
  946. if (requests) 
  947. {
  948. // Search the requests list for the asset.
  949. request_list_t::const_iterator iter = requests->begin();
  950. request_list_t::const_iterator end  = requests->end();
  951. for (; iter != end; ++iter)
  952. {
  953. const LLAssetRequest* req = *iter;
  954. if (asset_type == req->getType() &&
  955. asset_id == req->getUUID() )
  956. {
  957. return req;
  958. }
  959. }
  960. }
  961. return NULL;
  962. }
  963. // static
  964. LLAssetRequest* LLAssetStorage::findRequest(LLAssetStorage::request_list_t* requests,
  965. LLAssetType::EType asset_type,
  966. const LLUUID& asset_id)
  967. {
  968. if (requests) 
  969. {
  970. // Search the requests list for the asset.
  971. request_list_t::iterator iter = requests->begin();
  972. request_list_t::iterator end  = requests->end();
  973. for (; iter != end; ++iter)
  974. {
  975. LLAssetRequest* req = *iter;
  976. if (asset_type == req->getType() &&
  977. asset_id == req->getUUID() )
  978. {
  979. return req;
  980. }
  981. }
  982. }
  983. return NULL;
  984. }
  985. // virtual
  986. LLSD LLAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt,
  987. LLAssetType::EType asset_type,
  988. const LLUUID& asset_id) const
  989. {
  990. const request_list_t* requests = getRequestList(rt);
  991. return getPendingRequestImpl(requests, asset_type, asset_id);
  992. }
  993. // virtual
  994. LLSD LLAssetStorage::getPendingRequestImpl(const LLAssetStorage::request_list_t* requests,
  995. LLAssetType::EType asset_type,
  996. const LLUUID& asset_id) const
  997. {
  998. LLSD sd;
  999. const LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
  1000. if (req)
  1001. {
  1002. sd = req->getFullDetails();
  1003. }
  1004. return sd;
  1005. }
  1006. // virtual
  1007. bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt,
  1008. LLAssetType::EType asset_type,
  1009. const LLUUID& asset_id)
  1010. {
  1011. request_list_t* requests = getRequestList(rt);
  1012. if (deletePendingRequestImpl(requests, asset_type, asset_id))
  1013. {
  1014. llinfos << "Asset " << getRequestName(rt) << " request for "
  1015. << asset_id << "." << LLAssetType::lookup(asset_type)
  1016. << " removed from pending queue." << llendl;
  1017. return true;
  1018. }
  1019. return false;
  1020. }
  1021. // virtual
  1022. bool LLAssetStorage::deletePendingRequestImpl(LLAssetStorage::request_list_t* requests,
  1023. LLAssetType::EType asset_type,
  1024. const LLUUID& asset_id)
  1025. {
  1026. LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
  1027. if (req)
  1028. {
  1029. // Remove the request from this list.
  1030. requests->remove(req);
  1031. S32 error = LL_ERR_TCP_TIMEOUT;
  1032. // Run callbacks.
  1033. if (req->mUpCallback)
  1034. {
  1035. req->mUpCallback(req->getUUID(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
  1036. }
  1037. if (req->mDownCallback)
  1038. {
  1039. req->mDownCallback(mVFS, req->getUUID(), req->getType(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
  1040. }
  1041. if (req->mInfoCallback)
  1042. {
  1043. LLAssetInfo info;
  1044. req->mInfoCallback(&info, req->mUserData, error);
  1045. }
  1046. delete req;
  1047. return true;
  1048. }
  1049. return false;
  1050. }
  1051. // static
  1052. const char* LLAssetStorage::getErrorString(S32 status)
  1053. {
  1054. switch( status )
  1055. {
  1056. case LL_ERR_NOERR:
  1057. return "No error";
  1058. case LL_ERR_ASSET_REQUEST_FAILED:
  1059. return "Asset request: failed";
  1060. case LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE:
  1061. return "Asset request: non-existent file";
  1062. case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
  1063. return "Asset request: asset not found in database";
  1064. case LL_ERR_EOF:
  1065. return "End of file";
  1066. case LL_ERR_CANNOT_OPEN_FILE:
  1067. return "Cannot open file";
  1068. case LL_ERR_FILE_NOT_FOUND:
  1069. return "File not found";
  1070. case LL_ERR_TCP_TIMEOUT:
  1071. return "File transfer timeout";
  1072. case LL_ERR_CIRCUIT_GONE:
  1073. return "Circuit gone";
  1074. case LL_ERR_PRICE_MISMATCH:
  1075. return "Viewer and server do not agree on price";
  1076. default:
  1077. return "Unknown status";
  1078. }
  1079. }
  1080. void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, BOOL is_priority)
  1081. {
  1082. // check for duplicates here, since we're about to fool the normal duplicate checker
  1083. for (request_list_t::iterator iter = mPendingDownloads.begin();
  1084.  iter != mPendingDownloads.end();  )
  1085. {
  1086. LLAssetRequest* tmp = *iter++;
  1087. if (type == tmp->getType() && 
  1088. uuid == tmp->getUUID() &&
  1089. legacyGetDataCallback == tmp->mDownCallback &&
  1090. callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
  1091. user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
  1092. {
  1093. // this is a duplicate from the same subsystem - throw it away
  1094. llinfos << "Discarding duplicate request for UUID " << uuid << llendl;
  1095. return;
  1096. }
  1097. }
  1098. LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
  1099. legacy->mDownCallback = callback;
  1100. legacy->mUserData = user_data;
  1101. getAssetData(uuid, type, legacyGetDataCallback, (void **)legacy,
  1102.  is_priority);
  1103. }
  1104. // static
  1105. void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 status, LLExtStat ext_status)
  1106. {
  1107. LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
  1108. std::string filename;
  1109. // Check if the asset is marked toxic, and don't load bad stuff
  1110. BOOL toxic = gAssetStorage->isAssetToxic( uuid );
  1111. if ( !status
  1112. && !toxic )
  1113. {
  1114. LLVFile file(vfs, uuid, type);
  1115. std::string uuid_str;
  1116. uuid.toString(uuid_str);
  1117. filename = llformat("%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type));
  1118. LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ 
  1119. if (fp)
  1120. {
  1121. const S32 buf_size = 65536;
  1122. U8 copy_buf[buf_size];
  1123. while (file.read(copy_buf, buf_size)) /* Flawfinder: ignore */
  1124. {
  1125. if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1)
  1126. {
  1127. // return a bad file error if we can't write the whole thing
  1128. status = LL_ERR_CANNOT_OPEN_FILE;
  1129. }
  1130. }
  1131. fclose(fp);
  1132. }
  1133. else
  1134. {
  1135. status = LL_ERR_CANNOT_OPEN_FILE;
  1136. }
  1137. }
  1138. legacy->mDownCallback(filename.c_str(), uuid, legacy->mUserData, status, ext_status);
  1139. delete legacy;
  1140. }
  1141. // this is overridden on the viewer and the sim, so it doesn't really do anything
  1142. // virtual 
  1143. void LLAssetStorage::storeAssetData(
  1144. const LLTransactionID& tid,
  1145. LLAssetType::EType asset_type,
  1146. LLStoreAssetCallback callback,
  1147. void* user_data,
  1148. bool temp_file,
  1149. bool is_priority,
  1150. bool store_local,
  1151. bool user_waiting,
  1152. F64 timeout)
  1153. {
  1154. llwarns << "storeAssetData: wrong version called" << llendl;
  1155. // LLAssetStorage metric: Virtual base call
  1156. reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 1" );
  1157. }
  1158. // virtual
  1159. // this does nothing, viewer and sim both override this.
  1160. void LLAssetStorage::storeAssetData(
  1161. const LLUUID& asset_id,
  1162. LLAssetType::EType asset_type,
  1163. LLStoreAssetCallback callback,
  1164. void* user_data,
  1165. bool temp_file ,
  1166. bool is_priority,
  1167. bool store_local,
  1168. const LLUUID& requesting_agent_id,
  1169. bool user_waiting,
  1170. F64 timeout)
  1171. {
  1172. llwarns << "storeAssetData: wrong version called" << llendl;
  1173. // LLAssetStorage metric: Virtual base call
  1174. reportMetric( asset_id, asset_type, LLStringUtil::null, requesting_agent_id, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 2" );
  1175. }
  1176. // virtual
  1177. // this does nothing, viewer and sim both override this.
  1178. void LLAssetStorage::storeAssetData(
  1179. const std::string& filename,
  1180. const LLUUID& asset_id,
  1181. LLAssetType::EType asset_type,
  1182. LLStoreAssetCallback callback,
  1183. void* user_data,
  1184. bool temp_file,
  1185. bool is_priority,
  1186. bool user_waiting,
  1187. F64 timeout)
  1188. {
  1189. llwarns << "storeAssetData: wrong version called" << llendl;
  1190. // LLAssetStorage metric: Virtual base call
  1191. reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 3" );
  1192. }
  1193. // virtual
  1194. // this does nothing, viewer and sim both override this.
  1195. void LLAssetStorage::storeAssetData(
  1196. const std::string& filename,
  1197. const LLTransactionID &transactoin_id,
  1198. LLAssetType::EType asset_type,
  1199. LLStoreAssetCallback callback,
  1200. void* user_data,
  1201. bool temp_file,
  1202. bool is_priority,
  1203. bool user_waiting,
  1204. F64 timeout)
  1205. {
  1206. llwarns << "storeAssetData: wrong version called" << llendl;
  1207. // LLAssetStorage metric: Virtual base call
  1208. reportMetric( LLUUID::null, asset_type, LLStringUtil::null, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 4" );
  1209. }
  1210. // static
  1211. void LLAssetStorage::legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status)
  1212. {
  1213. LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
  1214. if (legacy && legacy->mUpCallback)
  1215. {
  1216. legacy->mUpCallback(uuid, legacy->mUserData, status, ext_status);
  1217. }
  1218. delete legacy;
  1219. }
  1220. // virtual
  1221. void LLAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name) 
  1222. { }
  1223. // virtual
  1224. BOOL LLAssetStorage::hasTempAssetData(const LLUUID& texture_id) const 
  1225. { return FALSE; }
  1226. // virtual
  1227. std::string LLAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const 
  1228. { return std::string(); }
  1229. // virtual
  1230. LLUUID LLAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const 
  1231. { return LLUUID::null; }
  1232. // virtual
  1233. void LLAssetStorage::removeTempAssetData(const LLUUID& asset_id) 
  1234. { }
  1235. // virtual
  1236. void LLAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id) 
  1237. { }
  1238. // virtual
  1239. void LLAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const 
  1240. { }
  1241. // virtual
  1242. void LLAssetStorage::clearTempAssetData() 
  1243. { }
  1244. // static
  1245. void LLAssetStorage::reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const std::string& in_filename,
  1246.    const LLUUID& agent_id, S32 asset_size, EMetricResult result,
  1247.    const char *file, const S32 line, const std::string& in_message )
  1248. {
  1249. if( !metric_recipient )
  1250. {
  1251. llinfos << "Couldn't store LLAssetStoreage::reportMetric - no metrics_recipient" << llendl;
  1252. return;
  1253. }
  1254. std::string filename(in_filename);
  1255. if (filename.empty())
  1256. filename = ll_safe_string(file);
  1257. // Create revised message - new_message = "in_message :: file:line"
  1258. std::stringstream new_message;
  1259. new_message << in_message << " :: " << filename << ":" << line;
  1260. // Change always_report to true if debugging... do not check it in this way
  1261. static bool always_report = false;
  1262. const char *metric_name = "LLAssetStorage::Metrics";
  1263. bool success = result == MR_OKAY;
  1264. if( (!success) || always_report )
  1265. {
  1266. LLSD stats;
  1267. stats["asset_id"] = asset_id;
  1268. stats["asset_type"] = asset_type;
  1269. stats["filename"] = filename;
  1270. stats["agent_id"] = agent_id;
  1271. stats["asset_size"] = (S32)asset_size;
  1272. stats["result"] = (S32)result;
  1273. metric_recipient->recordEventDetails( metric_name, new_message.str(), success, stats);
  1274. }
  1275. else
  1276. {
  1277. metric_recipient->recordEvent(metric_name, new_message.str(), success);
  1278. }
  1279. }
  1280. // Check if an asset is in the toxic map.  If it is, the entry is updated
  1281. BOOL LLAssetStorage::isAssetToxic( const LLUUID& uuid )
  1282. {
  1283. BOOL is_toxic = FALSE;
  1284. if ( !uuid.isNull() )
  1285. {
  1286. toxic_asset_map_t::iterator iter = mToxicAssetMap.find( uuid );
  1287. if ( iter != mToxicAssetMap.end() )
  1288. { // Found toxic asset
  1289. (*iter).second = LLFrameTimer::getTotalTime() + TOXIC_ASSET_LIFETIME;
  1290. is_toxic = TRUE;
  1291. }
  1292. return is_toxic;
  1293. }
  1294. // Clean the toxic asset list, remove old entries
  1295. void LLAssetStorage::flushOldToxicAssets( BOOL force_it )
  1296. {
  1297. // Scan and look for old entries
  1298. U64 now = LLFrameTimer::getTotalTime();
  1299. toxic_asset_map_t::iterator iter = mToxicAssetMap.begin();
  1300. while ( iter != mToxicAssetMap.end() )
  1301. {
  1302. if ( force_it
  1303. || (*iter).second < now )
  1304. { // Too old - remove it
  1305. mToxicAssetMap.erase( iter++ );
  1306. }
  1307. else
  1308. {
  1309. iter++;
  1310. }
  1311. }
  1312. }
  1313. // Add an item to the toxic asset map
  1314. void LLAssetStorage::markAssetToxic( const LLUUID& uuid )
  1315. {
  1316. if ( !uuid.isNull() )
  1317. {
  1318. // Set the value to the current time.  Creates a new entry if needed
  1319. mToxicAssetMap[ uuid ] = LLFrameTimer::getTotalTime() + TOXIC_ASSET_LIFETIME;
  1320. }
  1321. }