llassetstorage.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 // system library includes
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 
00038 #include "llassetstorage.h"
00039 
00040 // linden library includes
00041 #include "llmath.h"
00042 #include "llstring.h"
00043 #include "lldir.h"
00044 #include "llsd.h"
00045 
00046 // this library includes
00047 #include "message.h"
00048 #include "llxfermanager.h"
00049 #include "llvfile.h"
00050 #include "llvfs.h"
00051 #include "lldbstrings.h"
00052 
00053 #include "lltransfersourceasset.h"
00054 #include "lltransfertargetvfile.h" // For debugging
00055 
00056 #include "llmetrics.h"
00057 
00058 LLAssetStorage *gAssetStorage = NULL;
00059 LLMetrics *LLAssetStorage::metric_recipient = NULL;
00060 
00061 const LLUUID CATEGORIZE_LOST_AND_FOUND_ID("00000000-0000-0000-0000-000000000010");
00062 
00066 
00067 LLAssetInfo::LLAssetInfo( void )
00068 :       mDescription(),
00069         mName(),
00070         mUuid(),
00071         mCreatorID(),
00072         mType( LLAssetType::AT_NONE )
00073 { }
00074 
00075 LLAssetInfo::LLAssetInfo( const LLUUID& object_id, const LLUUID& creator_id,
00076                                                   LLAssetType::EType type, const char* name,
00077                                                   const char* desc )
00078 :       mUuid( object_id ), 
00079         mCreatorID( creator_id ), 
00080         mType( type )
00081 {
00082         setName( name );
00083         setDescription( desc );
00084 }
00085 
00086 LLAssetInfo::LLAssetInfo( const LLNameValue& nv )
00087 {
00088         setFromNameValue( nv );
00089 }
00090 
00091 // make sure the name is short enough, and strip all pipes since they
00092 // are reserved characters in our inventory tracking system.
00093 void LLAssetInfo::setName( const std::string& name )
00094 {
00095         if( !name.empty() )
00096         {
00097                 mName.assign( name, 0, llmin((U32)name.size(), (U32)DB_INV_ITEM_NAME_STR_LEN) );
00098                 mName.erase( std::remove(mName.begin(), mName.end(), '|'),
00099                                          mName.end() );
00100         }
00101 }
00102 
00103 // make sure the name is short enough, and strip all pipes since they
00104 // are reserved characters in our inventory tracking system.
00105 void LLAssetInfo::setDescription( const std::string& desc )
00106 {
00107         if( !desc.empty() )
00108         {
00109                 mDescription.assign( desc, 0, llmin((U32)desc.size(),
00110                                                                                  (U32)DB_INV_ITEM_DESC_STR_LEN) );
00111                 mDescription.erase( std::remove(mDescription.begin(),
00112                                                                                 mDescription.end(), '|'),
00113                                                         mDescription.end() );
00114         }
00115 }
00116 
00117 // Assets (aka potential inventory items) can be applied to an
00118 // object in the world. We'll store that as a string name value
00119 // pair where the name encodes part of asset info, and the value
00120 // the rest.  LLAssetInfo objects will be responsible for parsing
00121 // the meaning out froman LLNameValue object. See the inventory
00122 // design docs for details. Briefly:
00123 //   name=<inv_type>|<uuid>
00124 //   value=<creatorid>|<name>|<description>|
00125 void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
00126 {
00127         std::string str;
00128         std::string buf;
00129         std::string::size_type pos1;
00130         std::string::size_type pos2;
00131 
00132         // convert the name to useful information
00133         str.assign( nv.mName );
00134         pos1 = str.find('|');
00135         buf.assign( str, 0, pos1++ );
00136         mType = LLAssetType::lookup( buf.c_str() );
00137         buf.assign( str, pos1, std::string::npos );
00138         mUuid.set( buf.c_str() );
00139 
00140         // convert the value to useful information
00141         str.assign( nv.getAsset() );
00142         pos1 = str.find('|');
00143         buf.assign( str, 0, pos1++ );
00144         mCreatorID.set( buf.c_str() );
00145         pos2 = str.find( '|', pos1 );
00146         buf.assign( str, pos1, (pos2++) - pos1 );
00147         setName( buf.c_str() );
00148         buf.assign( str, pos2, std::string::npos );
00149         setDescription( buf.c_str() );
00150         llinfos << "uuid: " << mUuid << llendl;
00151         llinfos << "creator: " << mCreatorID << llendl;
00152 }
00153 
00157 
00158 LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
00159 :       mUUID(uuid),
00160         mType(type),
00161         mDownCallback( NULL ),
00162         mUpCallback( NULL ),
00163         mInfoCallback( NULL ),
00164         mUserData( NULL ),
00165         mHost(),
00166         mIsTemp( FALSE ),
00167         mIsLocal(FALSE),
00168         mIsUserWaiting(FALSE),
00169         mTimeout(LL_ASSET_STORAGE_TIMEOUT),
00170         mIsPriority(FALSE),
00171         mDataSentInFirstPacket(FALSE),
00172         mDataIsInVFS( FALSE )
00173 {
00174         // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
00175         //  running a message system loop.
00176         mTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
00177 }
00178 
00179 // virtual
00180 LLAssetRequest::~LLAssetRequest()
00181 {
00182 }
00183 
00184 // virtual
00185 LLSD LLAssetRequest::getTerseDetails() const
00186 {
00187         LLSD sd;
00188         sd["asset_id"] = getUUID();
00189         sd["type_long"] = LLAssetType::lookupHumanReadable(getType());
00190         sd["type"] = LLAssetType::lookup(getType());
00191         sd["time"] = mTime;
00192         time_t timestamp = (time_t) mTime;
00193         std::ostringstream time_string;
00194         time_string << ctime(&timestamp);
00195         sd["time_string"] = time_string.str();
00196         return sd;
00197 }
00198 
00199 // virtual
00200 LLSD LLAssetRequest::getFullDetails() const
00201 {
00202         LLSD sd = getTerseDetails();
00203         sd["host"] = mHost.getIPandPort();
00204         sd["requesting_agent"] = mRequestingAgentID;
00205         sd["is_temp"] = mIsTemp;
00206         sd["is_local"] = mIsLocal;
00207         sd["is_priority"] = mIsPriority;
00208         sd["data_send_in_first_packet"] = mDataSentInFirstPacket;
00209         sd["data_is_in_vfs"] = mDataIsInVFS;
00210 
00211         return sd;
00212 }
00213 
00217 
00218 LLInvItemRequest::LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType type)
00219 :       mUUID(uuid),
00220         mType(type),
00221         mDownCallback( NULL ),
00222         mUserData( NULL ),
00223         mHost(),
00224         mIsTemp( FALSE ),
00225         mIsPriority(FALSE),
00226         mDataSentInFirstPacket(FALSE),
00227         mDataIsInVFS( FALSE )
00228 {
00229         // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
00230         //  running a message system loop.
00231         mTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
00232 }
00233 
00234 LLInvItemRequest::~LLInvItemRequest()
00235 {
00236 }
00237 
00241 
00242 LLEstateAssetRequest::LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType atype,
00243                                                                                    EstateAssetType etype)
00244 :       mUUID(uuid),
00245         mAType(atype),
00246         mEstateAssetType(etype),
00247         mDownCallback( NULL ),
00248         mUserData( NULL ),
00249         mHost(),
00250         mIsTemp( FALSE ),
00251         mIsPriority(FALSE),
00252         mDataSentInFirstPacket(FALSE),
00253         mDataIsInVFS( FALSE )
00254 {
00255         // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
00256         //  running a message system loop.
00257         mTime = LLMessageSystem::getMessageTimeSeconds(TRUE);
00258 }
00259 
00260 LLEstateAssetRequest::~LLEstateAssetRequest()
00261 {
00262 }
00263 
00264 
00268 
00269 // since many of these functions are called by the messaging and xfer systems,
00270 // they are declared as static and are passed a "this" handle
00271 // it's a C/C++ mish-mash!
00272 
00273 // TODO: permissions on modifications - maybe don't allow at all?
00274 // TODO: verify that failures get propogated down
00275 // TODO: rework tempfile handling?
00276 
00277 
00278 LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, const LLHost &upstream_host)
00279 {
00280         _init(msg, xfer, vfs, upstream_host);
00281 }
00282 
00283 
00284 LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer,
00285                                                            LLVFS *vfs)
00286 {
00287         _init(msg, xfer, vfs, LLHost::invalid);
00288 }
00289 
00290 
00291 void LLAssetStorage::_init(LLMessageSystem *msg,
00292                                                    LLXferManager *xfer,
00293                                                    LLVFS *vfs,
00294                                                    const LLHost &upstream_host)
00295 {
00296         mShutDown = FALSE;
00297         mMessageSys = msg;
00298         mXferManager = xfer;
00299         mVFS = vfs;
00300 
00301         setUpstream(upstream_host);
00302         msg->setHandlerFuncFast(_PREHASH_AssetUploadComplete, processUploadComplete, (void **)this);
00303 }
00304 
00305 LLAssetStorage::~LLAssetStorage()
00306 {
00307         mShutDown = TRUE;
00308         
00309         _cleanupRequests(TRUE, LL_ERR_CIRCUIT_GONE);
00310 
00311         if (gMessageSystem)
00312         {
00313                 // Warning!  This won't work if there's more than one asset storage.
00314                 // unregister our callbacks with the message system
00315                 gMessageSystem->setHandlerFuncFast(_PREHASH_AssetUploadComplete, NULL, NULL);
00316         }
00317 }
00318 
00319 void LLAssetStorage::setUpstream(const LLHost &upstream_host)
00320 {
00321         LL_DEBUGS("AppInit") << "AssetStorage: Setting upstream provider to " << upstream_host << LL_ENDL;
00322         
00323         mUpstreamHost = upstream_host;
00324 }
00325 
00326 void LLAssetStorage::checkForTimeouts()
00327 {
00328         _cleanupRequests(FALSE, LL_ERR_TCP_TIMEOUT);
00329 }
00330 
00331 void LLAssetStorage::_cleanupRequests(BOOL all, S32 error)
00332 {
00333         F64 mt_secs = LLMessageSystem::getMessageTimeSeconds();
00334 
00335         request_list_t timed_out;
00336         S32 rt;
00337         for (rt = 0; rt < RT_COUNT; rt++)
00338         {
00339                 request_list_t* requests = getRequestList((ERequestType)rt);
00340                 for (request_list_t::iterator iter = requests->begin();
00341                          iter != requests->end(); )
00342                 {
00343                         request_list_t::iterator curiter = iter++;
00344                         LLAssetRequest* tmp = *curiter;
00345                         // if all is true, we want to clean up everything
00346                         // otherwise just check for timed out requests
00347                         // EXCEPT for upload timeouts
00348                         if (all 
00349                                 || ((RT_DOWNLOAD == rt)
00350                                         && LL_ASSET_STORAGE_TIMEOUT < (mt_secs - tmp->mTime)))
00351                         {
00352                                 llwarns << "Asset " << getRequestName((ERequestType)rt) << " request "
00353                                                 << (all ? "aborted" : "timed out") << " for "
00354                                                 << tmp->getUUID() << "."
00355                                                 << LLAssetType::lookup(tmp->getType()) << llendl;
00356 
00357                                 timed_out.push_front(tmp);
00358                                 iter = requests->erase(curiter);
00359                         }
00360                 }
00361         }
00362 
00363         LLAssetInfo     info;
00364         for (request_list_t::iterator iter = timed_out.begin();
00365                  iter != timed_out.end();  )
00366         {
00367                 request_list_t::iterator curiter = iter++;
00368                 LLAssetRequest* tmp = *curiter;
00369                 if (tmp->mUpCallback)
00370                 {
00371                         tmp->mUpCallback(tmp->getUUID(), tmp->mUserData, error, LL_EXSTAT_NONE);
00372                 }
00373                 if (tmp->mDownCallback)
00374                 {
00375                         tmp->mDownCallback(mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, error, LL_EXSTAT_NONE);
00376                 }
00377                 if (tmp->mInfoCallback)
00378                 {
00379                         tmp->mInfoCallback(&info, tmp->mUserData, error);
00380                 }
00381                 delete tmp;
00382         }
00383 
00384 }
00385 
00386 BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type)
00387 {
00388         return mVFS->getExists(uuid, type);
00389 }
00390 
00392 // GET routines
00394 
00395 // IW - uuid is passed by value to avoid side effects, please don't re-add &    
00396 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)
00397 {
00398         lldebugs << "LLAssetStorage::getAssetData() - " << uuid << "," << LLAssetType::lookup(type) << llendl;
00399 
00400         if (mShutDown)
00401         {
00402                 return; // don't get the asset or do any callbacks, we are shutting down
00403         }
00404                 
00405         if (uuid.isNull())
00406         {
00407                 // Special case early out for NULL uuid
00408                 if (callback)
00409                 {
00410                         callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
00411                 }
00412                 return;
00413         }
00414 
00415         BOOL exists = mVFS->getExists(uuid, type);
00416         LLVFile file(mVFS, uuid, type);
00417         U32 size = exists ? file.getSize() : 0;
00418         
00419         if (size < 1)
00420         {
00421                 if (exists)
00422                 {
00423                         llwarns << "Asset vfile " << uuid << ":" << type << " found with bad size " << file.getSize() << ", removing" << llendl;
00424                         file.remove();
00425                 }
00426                 
00427                 BOOL duplicate = FALSE;
00428                 
00429                 // check to see if there's a pending download of this uuid already
00430                 for (request_list_t::iterator iter = mPendingDownloads.begin();
00431                          iter != mPendingDownloads.end(); ++iter )
00432                 {
00433                         LLAssetRequest  *tmp = *iter;
00434                         if ((type == tmp->getType()) && (uuid == tmp->getUUID()))
00435                         {
00436                                 if (callback == tmp->mDownCallback && user_data == tmp->mUserData)
00437                                 {
00438                                         // this is a duplicate from the same subsystem - throw it away
00439                                         llwarns << "Discarding duplicate request for asset " << uuid
00440                                                         << "." << LLAssetType::lookup(type) << llendl;
00441                                         return;
00442                                 }
00443                                 
00444                                 // this is a duplicate request
00445                                 // queue the request, but don't actually ask for it again
00446                                 duplicate = TRUE;
00447                         }
00448                 }
00449                 if (duplicate)
00450                 {
00451                         llinfos << "Adding additional non-duplicate request for asset " << uuid 
00452                                         << "." << LLAssetType::lookup(type) << llendl;
00453                 }
00454                 
00455                 // This can be overridden by subclasses
00456                 _queueDataRequest(uuid, type, callback, user_data, duplicate, is_priority);     
00457         }
00458         else
00459         {
00460                 // we've already got the file
00461                 // theoretically, partial files w/o a pending request shouldn't happen
00462                 // unless there's a weird error
00463                 if (callback)
00464                 {
00465                         callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
00466                 }
00467         }
00468 }
00469 
00470 void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType atype,
00471                                                                            LLGetAssetCallback callback,
00472                                                                            void *user_data, BOOL duplicate,
00473                                                                            BOOL is_priority)
00474 {
00475         if (mUpstreamHost.isOk())
00476         {
00477                 // stash the callback info so we can find it after we get the response message
00478                 LLAssetRequest *req = new LLAssetRequest(uuid, atype);
00479                 req->mDownCallback = callback;
00480                 req->mUserData = user_data;
00481                 req->mIsPriority = is_priority;
00482         
00483                 mPendingDownloads.push_back(req);
00484         
00485                 if (!duplicate)
00486                 {
00487                         // send request message to our upstream data provider
00488                         // Create a new asset transfer.
00489                         LLTransferSourceParamsAsset spa;
00490                         spa.setAsset(uuid, atype);
00491 
00492                         // Set our destination file, and the completion callback.
00493                         LLTransferTargetParamsVFile tpvf;
00494                         tpvf.setAsset(uuid, atype);
00495                         tpvf.setCallback(downloadCompleteCallback, req);
00496 
00497                         llinfos << "Starting transfer for " << uuid << llendl;
00498                         LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
00499                         ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
00500                 }
00501         }
00502         else
00503         {
00504                 // uh-oh, we shouldn't have gotten here
00505                 llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
00506                 if (callback)
00507                 {
00508                         callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
00509                 }
00510         }
00511 }
00512 
00513 
00514 void LLAssetStorage::downloadCompleteCallback(
00515         S32 result,
00516         const LLUUID& file_id,
00517         LLAssetType::EType file_type,
00518         void* user_data, LLExtStat ext_status)
00519 {
00520         lldebugs << "LLAssetStorage::downloadCompleteCallback() for " << file_id
00521                  << "," << LLAssetType::lookup(file_type) << llendl;
00522         LLAssetRequest* req = (LLAssetRequest*)user_data;
00523         if(!req)
00524         {
00525                 llwarns << "LLAssetStorage::downloadCompleteCallback called without"
00526                         "a valid request." << llendl;
00527                 return;
00528         }
00529         if (!gAssetStorage)
00530         {
00531                 llwarns << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << llendl;
00532                 return;
00533         }
00534 
00535         req->setUUID(file_id);
00536         req->setType(file_type);
00537         if (LL_ERR_NOERR == result)
00538         {
00539                 // we might have gotten a zero-size file
00540                 LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
00541                 if (vfile.getSize() <= 0)
00542                 {
00543                         llwarns << "downloadCompleteCallback has non-existent or zero-size asset " << req->getUUID() << llendl;
00544                         
00545                         result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
00546                         vfile.remove();
00547                 }
00548         }
00549         
00550         // find and callback ALL pending requests for this UUID
00551         // SJB: We process the callbacks in reverse order, I do not know if this is important,
00552         //      but I didn't want to mess with it.
00553         request_list_t requests;
00554         for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
00555                  iter != gAssetStorage->mPendingDownloads.end();  )
00556         {
00557                 request_list_t::iterator curiter = iter++;
00558                 LLAssetRequest* tmp = *curiter;
00559                 if ((tmp->getUUID() == req->getUUID()) && (tmp->getType()== req->getType()))
00560                 {
00561                         requests.push_front(tmp);
00562                         iter = gAssetStorage->mPendingDownloads.erase(curiter);
00563                 }
00564         }
00565         for (request_list_t::iterator iter = requests.begin();
00566                  iter != requests.end();  )
00567         {
00568                 request_list_t::iterator curiter = iter++;
00569                 LLAssetRequest* tmp = *curiter;
00570                 if (tmp->mDownCallback)
00571                 {
00572                         tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status);
00573                 }
00574                 delete tmp;
00575         }
00576 }
00577 
00578 void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
00579                                                                         const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
00580                                                                          LLGetAssetCallback callback, void *user_data, BOOL is_priority)
00581 {
00582         lldebugs << "LLAssetStorage::getEstateAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << ", estatetype " << etype << llendl;
00583 
00584         //
00585         // Probably will get rid of this early out?
00586         //
00587         if (asset_id.isNull())
00588         {
00589                 // Special case early out for NULL uuid
00590                 if (callback)
00591                 {
00592                         callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
00593                 }
00594                 return;
00595         }
00596 
00597         BOOL exists = mVFS->getExists(asset_id, atype);
00598         LLVFile file(mVFS, asset_id, atype);
00599         U32 size = exists ? file.getSize() : 0;
00600 
00601         if (size < 1)
00602         {
00603                 if (exists)
00604                 {
00605                         llwarns << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << llendl;
00606                         file.remove();
00607                 }
00608 
00609                 // See whether we should talk to the object's originating sim, or the upstream provider.
00610                 LLHost source_host;
00611                 if (object_sim.isOk())
00612                 {
00613                         source_host = object_sim;
00614                 }
00615                 else
00616                 {
00617                         source_host = mUpstreamHost;
00618                 }
00619                 if (source_host.isOk())
00620                 {
00621                         // stash the callback info so we can find it after we get the response message
00622                         LLEstateAssetRequest *req = new LLEstateAssetRequest(asset_id, atype, etype);
00623                         req->mDownCallback = callback;
00624                         req->mUserData = user_data;
00625                         req->mIsPriority = is_priority;
00626 
00627                         // send request message to our upstream data provider
00628                         // Create a new asset transfer.
00629                         LLTransferSourceParamsEstate spe;
00630                         spe.setAgentSession(agent_id, session_id);
00631                         spe.setEstateAssetType(etype);
00632 
00633                         // Set our destination file, and the completion callback.
00634                         LLTransferTargetParamsVFile tpvf;
00635                         tpvf.setAsset(asset_id, atype);
00636                         tpvf.setCallback(downloadEstateAssetCompleteCallback, req);
00637 
00638                         llinfos << "Starting transfer for " << asset_id << llendl;
00639                         LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
00640                         ttcp->requestTransfer(spe, tpvf, 100.f + (is_priority ? 1.f : 0.f));
00641                 }
00642                 else
00643                 {
00644                         // uh-oh, we shouldn't have gotten here
00645                         llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
00646                         if (callback)
00647                         {
00648                                 callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
00649                         }
00650                 }
00651         }
00652         else
00653         {
00654                 // we've already got the file
00655                 // theoretically, partial files w/o a pending request shouldn't happen
00656                 // unless there's a weird error
00657                 if (callback)
00658                 {
00659                         callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
00660                 }
00661         }
00662 }
00663 
00664 void LLAssetStorage::downloadEstateAssetCompleteCallback(
00665         S32 result,
00666         const LLUUID& file_id,
00667         LLAssetType::EType file_type,
00668         void* user_data,
00669         LLExtStat ext_status)
00670 {
00671         LLEstateAssetRequest *req = (LLEstateAssetRequest*)user_data;
00672         if(!req)
00673         {
00674                 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
00675                         " without a valid request." << llendl;
00676                 return;
00677         }
00678         if (!gAssetStorage)
00679         {
00680                 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
00681                         " without any asset system, aborting!" << llendl;
00682                 return;
00683         }
00684 
00685         req->setUUID(file_id);
00686         req->setType(file_type);
00687         if (LL_ERR_NOERR == result)
00688         {
00689                 // we might have gotten a zero-size file
00690                 LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType());
00691                 if (vfile.getSize() <= 0)
00692                 {
00693                         llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
00694 
00695                         result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
00696                         vfile.remove();
00697                 }
00698         }
00699 
00700         req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status);
00701 }
00702 
00703 void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
00704                                                                          const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id,
00705                                                                          const LLUUID &asset_id, LLAssetType::EType atype,
00706                                                                          LLGetAssetCallback callback, void *user_data, BOOL is_priority)
00707 {
00708         lldebugs << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << llendl;
00709 
00710         //
00711         // Probably will get rid of this early out?
00712         //
00713         //if (asset_id.isNull())
00714         //{
00715         //      // Special case early out for NULL uuid
00716         //      if (callback)
00717         //      {
00718         //              callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE);
00719         //      }
00720         //      return;
00721         //}
00722 
00723         bool exists = false; 
00724         U32 size = 0;
00725 
00726         if(asset_id.notNull())
00727         {
00728                 exists = mVFS->getExists(asset_id, atype);
00729                 LLVFile file(mVFS, asset_id, atype);
00730                 size = exists ? file.getSize() : 0;
00731                 if(exists && size < 1)
00732                 {
00733                         llwarns << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << llendl;
00734                         file.remove();
00735                 }
00736 
00737         }
00738 
00739         if (size < 1)
00740         {
00741                 // See whether we should talk to the object's originating sim,
00742                 // or the upstream provider.
00743                 LLHost source_host;
00744                 if (object_sim.isOk())
00745                 {
00746                         source_host = object_sim;
00747                 }
00748                 else
00749                 {
00750                         source_host = mUpstreamHost;
00751                 }
00752                 if (source_host.isOk())
00753                 {
00754                         // stash the callback info so we can find it after we get the response message
00755                         LLInvItemRequest *req = new LLInvItemRequest(asset_id, atype);
00756                         req->mDownCallback = callback;
00757                         req->mUserData = user_data;
00758                         req->mIsPriority = is_priority;
00759 
00760                         // send request message to our upstream data provider
00761                         // Create a new asset transfer.
00762                         LLTransferSourceParamsInvItem spi;
00763                         spi.setAgentSession(agent_id, session_id);
00764                         spi.setInvItem(owner_id, task_id, item_id);
00765                         spi.setAsset(asset_id, atype);
00766 
00767                         // Set our destination file, and the completion callback.
00768                         LLTransferTargetParamsVFile tpvf;
00769                         tpvf.setAsset(asset_id, atype);
00770                         tpvf.setCallback(downloadInvItemCompleteCallback, req);
00771 
00772                         llinfos << "Starting transfer for inventory asset "
00773                                 << item_id << " owned by " << owner_id << "," << task_id
00774                                 << llendl;
00775                         LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
00776                         ttcp->requestTransfer(spi, tpvf, 100.f + (is_priority ? 1.f : 0.f));
00777                 }
00778                 else
00779                 {
00780                         // uh-oh, we shouldn't have gotten here
00781                         llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
00782                         if (callback)
00783                         {
00784                                 callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
00785                         }
00786                 }
00787         }
00788         else
00789         {
00790                 // we've already got the file
00791                 // theoretically, partial files w/o a pending request shouldn't happen
00792                 // unless there's a weird error
00793                 if (callback)
00794                 {
00795                         callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
00796                 }
00797         }
00798 }
00799 
00800 
00801 void LLAssetStorage::downloadInvItemCompleteCallback(
00802         S32 result,
00803         const LLUUID& file_id,
00804         LLAssetType::EType file_type,
00805         void* user_data,
00806         LLExtStat ext_status)
00807 {
00808         LLInvItemRequest *req = (LLInvItemRequest*)user_data;
00809         if(!req)
00810         {
00811                 llwarns << "LLAssetStorage::downloadEstateAssetCompleteCallback called"
00812                         " without a valid request." << llendl;
00813                 return;
00814         }
00815         if (!gAssetStorage)
00816         {
00817                 llwarns << "LLAssetStorage::downloadCompleteCallback called without any asset system, aborting!" << llendl;
00818                 return;
00819         }
00820 
00821         req->setUUID(file_id);
00822         req->setType(file_type);
00823         if (LL_ERR_NOERR == result)
00824         {
00825                 // we might have gotten a zero-size file
00826                 LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType());
00827                 if (vfile.getSize() <= 0)
00828                 {
00829                         llwarns << "downloadCompleteCallback has non-existent or zero-size asset!" << llendl;
00830 
00831                         result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
00832                         vfile.remove();
00833                 }
00834         }
00835 
00836         req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status);
00837 }
00838 
00840 // Store routines
00842 
00843 // static
00844 void LLAssetStorage::uploadCompleteCallback(const LLUUID& uuid, void *user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
00845 {
00846         if (!gAssetStorage)
00847         {
00848                 llwarns << "LLAssetStorage::uploadCompleteCallback has no gAssetStorage!" << llendl;
00849                 return;
00850         }
00851         LLAssetRequest  *req     = (LLAssetRequest *)user_data;
00852         BOOL                    success  = TRUE;
00853 
00854         if (result)
00855         {
00856                 llwarns << "LLAssetStorage::uploadCompleteCallback " << result << ":" << getErrorString(result) << " trying to upload file to upstream provider" << llendl;
00857                 success = FALSE;
00858         }
00859 
00860         // we're done grabbing the file, tell the client
00861         gAssetStorage->mMessageSys->newMessageFast(_PREHASH_AssetUploadComplete);
00862         gAssetStorage->mMessageSys->nextBlockFast(_PREHASH_AssetBlock);
00863         gAssetStorage->mMessageSys->addUUIDFast(_PREHASH_UUID, uuid);
00864         gAssetStorage->mMessageSys->addS8Fast(_PREHASH_Type, req->getType());
00865         gAssetStorage->mMessageSys->addBOOLFast(_PREHASH_Success, success);
00866         gAssetStorage->mMessageSys->sendReliable(req->mHost);
00867 
00868         delete req;
00869 }
00870 
00871 void LLAssetStorage::processUploadComplete(LLMessageSystem *msg, void **user_data)
00872 {
00873         LLAssetStorage  *this_ptr = (LLAssetStorage *)user_data;
00874         LLUUID                  uuid;
00875         S8                              asset_type_s8;
00876         LLAssetType::EType asset_type;
00877         BOOL                    success = FALSE;
00878 
00879         msg->getUUIDFast(_PREHASH_AssetBlock, _PREHASH_UUID, uuid);
00880         msg->getS8Fast(_PREHASH_AssetBlock, _PREHASH_Type, asset_type_s8);
00881         msg->getBOOLFast(_PREHASH_AssetBlock, _PREHASH_Success, success);
00882 
00883         asset_type = (LLAssetType::EType)asset_type_s8;
00884         this_ptr->_callUploadCallbacks(uuid, asset_type, success, LL_EXSTAT_NONE);
00885 }
00886 
00887 void LLAssetStorage::_callUploadCallbacks(const LLUUID &uuid, LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status )
00888 {
00889         // SJB: We process the callbacks in reverse order, I do not know if this is important,
00890         //      but I didn't want to mess with it.
00891         request_list_t requests;
00892         for (request_list_t::iterator iter = mPendingUploads.begin();
00893                  iter != mPendingUploads.end();  )
00894         {
00895                 request_list_t::iterator curiter = iter++;
00896                 LLAssetRequest* req = *curiter;
00897                 if ((req->getUUID() == uuid) && (req->getType() == asset_type))
00898                 {
00899                         requests.push_front(req);
00900                         iter = mPendingUploads.erase(curiter);
00901                 }
00902         }
00903         for (request_list_t::iterator iter = mPendingLocalUploads.begin();
00904                  iter != mPendingLocalUploads.end();  )
00905         {
00906                 request_list_t::iterator curiter = iter++;
00907                 LLAssetRequest* req = *curiter;
00908                 if ((req->getUUID() == uuid) && (req->getType() == asset_type))
00909                 {
00910                         requests.push_front(req);
00911                         iter = mPendingLocalUploads.erase(curiter);
00912                 }
00913         }
00914         for (request_list_t::iterator iter = requests.begin();
00915                  iter != requests.end();  )
00916         {
00917                 request_list_t::iterator curiter = iter++;
00918                 LLAssetRequest* req = *curiter;
00919                 if (req->mUpCallback)
00920                 {
00921                         req->mUpCallback(uuid, req->mUserData, (success ?  LL_ERR_NOERR :  LL_ERR_ASSET_REQUEST_FAILED ), ext_status );
00922                 }
00923                 delete req;
00924         }
00925 }
00926 
00927 LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::ERequestType rt)
00928 {
00929         switch (rt)
00930         {
00931         case RT_DOWNLOAD:
00932                 return &mPendingDownloads;
00933         case RT_UPLOAD:
00934                 return &mPendingUploads;
00935         case RT_LOCALUPLOAD:
00936                 return &mPendingLocalUploads;
00937         default:
00938                 llwarns << "Unable to find request list for request type '" << rt << "'" << llendl;
00939                 return NULL;
00940         }
00941 }
00942 
00943 const LLAssetStorage::request_list_t* LLAssetStorage::getRequestList(LLAssetStorage::ERequestType rt) const
00944 {
00945         switch (rt)
00946         {
00947         case RT_DOWNLOAD:
00948                 return &mPendingDownloads;
00949         case RT_UPLOAD:
00950                 return &mPendingUploads;
00951         case RT_LOCALUPLOAD:
00952                 return &mPendingLocalUploads;
00953         default:
00954                 llwarns << "Unable to find request list for request type '" << rt << "'" << llendl;
00955                 return NULL;
00956         }
00957 }
00958 
00959 // static
00960 std::string LLAssetStorage::getRequestName(LLAssetStorage::ERequestType rt)
00961 {
00962         switch (rt)
00963         {
00964         case RT_DOWNLOAD:
00965                 return "download";
00966         case RT_UPLOAD:
00967                 return "upload";
00968         case RT_LOCALUPLOAD:
00969                 return "localupload";
00970         default:
00971                 llwarns << "Unable to find request name for request type '" << rt << "'" << llendl;
00972                 return "";
00973         }
00974 }
00975 
00976 S32 LLAssetStorage::getNumPending(LLAssetStorage::ERequestType rt) const
00977 {
00978         const request_list_t* requests = getRequestList(rt);
00979         S32 num_pending = -1;
00980         if (requests)
00981         {
00982                 num_pending = requests->size();
00983         }
00984         return num_pending;
00985 }
00986 
00987 S32 LLAssetStorage::getNumPendingDownloads() const
00988 {
00989         return getNumPending(RT_DOWNLOAD);
00990 }
00991 
00992 S32 LLAssetStorage::getNumPendingUploads() const
00993 {
00994         return getNumPending(RT_UPLOAD);
00995 }
00996 
00997 S32 LLAssetStorage::getNumPendingLocalUploads()
00998 {
00999         return getNumPending(RT_LOCALUPLOAD);
01000 }
01001 
01002 // virtual
01003 LLSD LLAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt,
01004                                                                                 LLAssetType::EType asset_type,
01005                                                                                 const std::string& detail_prefix) const
01006 {
01007         const request_list_t* requests = getRequestList(rt);
01008         LLSD sd;
01009         sd["requests"] = getPendingDetails(requests, asset_type, detail_prefix);
01010         return sd;
01011 }
01012 
01013 // virtual
01014 LLSD LLAssetStorage::getPendingDetails(const LLAssetStorage::request_list_t* requests,
01015                                                                                 LLAssetType::EType asset_type,
01016                                                                                 const std::string& detail_prefix) const
01017 {
01018         LLSD details;
01019         if (requests)
01020         {
01021                 request_list_t::const_iterator it = requests->begin();
01022                 request_list_t::const_iterator end = requests->end();
01023                 for ( ; it != end; ++it)
01024                 {
01025                         LLAssetRequest* req = *it;
01026                         if (   (LLAssetType::AT_NONE == asset_type)
01027                                 || (req->getType() == asset_type) )
01028                         {
01029                                 LLSD row = req->getTerseDetails();
01030 
01031                                 std::ostringstream detail;
01032                                 detail  << detail_prefix << "/" << LLAssetType::lookup(req->getType())
01033                                                 << "/" << req->getUUID();
01034                                 row["detail"] = LLURI(detail.str());
01035 
01036                                 details.append(row);
01037                         }
01038                 }
01039         }
01040         return details;
01041 }
01042 
01043 
01044 // static
01045 const LLAssetRequest* LLAssetStorage::findRequest(const LLAssetStorage::request_list_t* requests,
01046                                                                                 LLAssetType::EType asset_type,
01047                                                                                 const LLUUID& asset_id)
01048 {
01049         if (requests) 
01050         {
01051                 // Search the requests list for the asset.
01052                 request_list_t::const_iterator iter = requests->begin();
01053                 request_list_t::const_iterator end  = requests->end();
01054                 for (; iter != end; ++iter)
01055                 {
01056                         const LLAssetRequest* req = *iter;
01057                         if (asset_type == req->getType() &&
01058                                 asset_id == req->getUUID() )
01059                         {
01060                                 return req;
01061                         }
01062                 }
01063         }
01064         return NULL;
01065 }
01066 
01067 // static
01068 LLAssetRequest* LLAssetStorage::findRequest(LLAssetStorage::request_list_t* requests,
01069                                                                                 LLAssetType::EType asset_type,
01070                                                                                 const LLUUID& asset_id)
01071 {
01072         if (requests) 
01073         {
01074                 // Search the requests list for the asset.
01075                 request_list_t::iterator iter = requests->begin();
01076                 request_list_t::iterator end  = requests->end();
01077                 for (; iter != end; ++iter)
01078                 {
01079                         LLAssetRequest* req = *iter;
01080                         if (asset_type == req->getType() &&
01081                                 asset_id == req->getUUID() )
01082                         {
01083                                 return req;
01084                         }
01085                 }
01086         }
01087         return NULL;
01088 }
01089 
01090 
01091 // virtual
01092 LLSD LLAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt,
01093                                                                                 LLAssetType::EType asset_type,
01094                                                                                 const LLUUID& asset_id) const
01095 {
01096         const request_list_t* requests = getRequestList(rt);
01097         return getPendingRequest(requests, asset_type, asset_id);
01098 }
01099 
01100 // virtual
01101 LLSD LLAssetStorage::getPendingRequest(const LLAssetStorage::request_list_t* requests,
01102                                                                                 LLAssetType::EType asset_type,
01103                                                                                 const LLUUID& asset_id) const
01104 {
01105         LLSD sd;
01106         const LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
01107         if (req)
01108         {
01109                 sd = req->getFullDetails();
01110         }
01111         return sd;
01112 }
01113 
01114 // virtual
01115 bool LLAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt,
01116                                                                                         LLAssetType::EType asset_type,
01117                                                                                         const LLUUID& asset_id)
01118 {
01119         request_list_t* requests = getRequestList(rt);
01120         if (deletePendingRequest(requests, asset_type, asset_id))
01121         {
01122                 llinfos << "Asset " << getRequestName(rt) << " request for "
01123                                 << asset_id << "." << LLAssetType::lookup(asset_type)
01124                                 << " removed from pending queue." << llendl;
01125                 return true;
01126         }
01127         return false;
01128 }
01129 
01130 // virtual
01131 bool LLAssetStorage::deletePendingRequest(LLAssetStorage::request_list_t* requests,
01132                                                                                         LLAssetType::EType asset_type,
01133                                                                                         const LLUUID& asset_id)
01134 {
01135         LLAssetRequest* req = findRequest(requests, asset_type, asset_id);
01136         if (req)
01137         {
01138                 // Remove the request from this list.
01139                 requests->remove(req);
01140                 S32 error = LL_ERR_TCP_TIMEOUT;
01141                 // Run callbacks.
01142                 if (req->mUpCallback)
01143                 {
01144                         req->mUpCallback(req->getUUID(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
01145                 }
01146                 if (req->mDownCallback)
01147                 {
01148                         req->mDownCallback(mVFS, req->getUUID(), req->getType(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED);
01149                 }
01150                 if (req->mInfoCallback)
01151                 {
01152                         LLAssetInfo info;
01153                         req->mInfoCallback(&info, req->mUserData, error);
01154                 }
01155                 delete req;
01156                 return true;
01157         }
01158         
01159         return false;
01160 }
01161 
01162 // static
01163 const char* LLAssetStorage::getErrorString(S32 status)
01164 {
01165         switch( status )
01166         {
01167         case LL_ERR_NOERR:
01168                 return "No error";
01169 
01170         case LL_ERR_ASSET_REQUEST_FAILED:
01171                 return "Asset request: failed";
01172 
01173         case LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE:
01174                 return "Asset request: non-existent file";
01175 
01176         case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
01177                 return "Asset request: asset not found in database";
01178 
01179         case LL_ERR_EOF:
01180                 return "End of file";
01181 
01182         case LL_ERR_CANNOT_OPEN_FILE:
01183                 return "Cannot open file";
01184 
01185         case LL_ERR_FILE_NOT_FOUND:
01186                 return "File not found";
01187 
01188         case LL_ERR_TCP_TIMEOUT:
01189                 return "File transfer timeout";
01190 
01191         case LL_ERR_CIRCUIT_GONE:
01192                 return "Circuit gone";
01193 
01194         default:
01195                 return "Unknown status";
01196         }
01197 }
01198 
01199 
01200 
01201 void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, BOOL is_priority)
01202 {
01203         // check for duplicates here, since we're about to fool the normal duplicate checker
01204         for (request_list_t::iterator iter = mPendingDownloads.begin();
01205                  iter != mPendingDownloads.end();  )
01206         {
01207                 LLAssetRequest* tmp = *iter++;
01208                 if (type == tmp->getType() && 
01209                         uuid == tmp->getUUID() &&
01210                         legacyGetDataCallback == tmp->mDownCallback &&
01211                         callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
01212                         user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
01213                 {
01214                         // this is a duplicate from the same subsystem - throw it away
01215                         llinfos << "Discarding duplicate request for UUID " << uuid << llendl;
01216                         return;
01217                 }
01218         }
01219         
01220         
01221         LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest;
01222 
01223         legacy->mDownCallback = callback;
01224         legacy->mUserData = user_data;
01225 
01226         getAssetData(uuid, type, legacyGetDataCallback, (void **)legacy,
01227                                  is_priority);
01228 }
01229 
01230 // static
01231 void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 status, LLExtStat ext_status)
01232 {
01233         LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
01234         char filename[LL_MAX_PATH] = "";        /* Flawfinder: ignore */ 
01235 
01236         if (! status)
01237         {
01238                 LLVFile file(vfs, uuid, type);
01239 
01240                 char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ 
01241 
01242                 uuid.toString(uuid_str);
01243                 snprintf(filename,sizeof(filename),"%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type));   /* Flawfinder: ignore */
01244 
01245                 LLFILE* fp = LLFile::fopen(filename, "wb");     /* Flawfinder: ignore */ 
01246                 if (fp)
01247                 {
01248                         const S32 buf_size = 65536;
01249                         U8 copy_buf[buf_size];
01250                         while (file.read(copy_buf, buf_size))   /* Flawfinder: ignore */
01251                         {
01252                                 if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1)
01253                                 {
01254                                         // return a bad file error if we can't write the whole thing
01255                                         status = LL_ERR_CANNOT_OPEN_FILE;
01256                                 }
01257                         }
01258 
01259                         fclose(fp);
01260                 }
01261                 else
01262                 {
01263                         status = LL_ERR_CANNOT_OPEN_FILE;
01264                 }
01265         }
01266 
01267         legacy->mDownCallback(filename, uuid, legacy->mUserData, status, ext_status);
01268         delete legacy;
01269 }
01270 
01271 // this is overridden on the viewer and the sim, so it doesn't really do anything
01272 // virtual 
01273 void LLAssetStorage::storeAssetData(
01274         const LLTransactionID& tid,
01275         LLAssetType::EType asset_type,
01276         LLStoreAssetCallback callback,
01277         void* user_data,
01278         bool temp_file,
01279         bool is_priority,
01280         bool store_local,
01281         bool user_waiting,
01282         F64 timeout)
01283 {
01284         llwarns << "storeAssetData: wrong version called" << llendl;
01285         // LLAssetStorage metric: Virtual base call
01286         reportMetric( LLUUID::null, asset_type, NULL, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 1" );
01287 }
01288 
01289 // virtual
01290 // this does nothing, viewer and sim both override this.
01291 void LLAssetStorage::storeAssetData(
01292         const LLUUID& asset_id,
01293         LLAssetType::EType asset_type,
01294         LLStoreAssetCallback callback,
01295         void* user_data,
01296         bool temp_file ,
01297         bool is_priority,
01298         bool store_local,
01299         const LLUUID& requesting_agent_id,
01300         bool user_waiting,
01301         F64 timeout)
01302 {
01303         llwarns << "storeAssetData: wrong version called" << llendl;
01304         // LLAssetStorage metric: Virtual base call
01305         reportMetric( asset_id, asset_type, NULL, requesting_agent_id, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 2" );
01306 }
01307 
01308 // virtual
01309 // this does nothing, viewer and sim both override this.
01310 void LLAssetStorage::storeAssetData(
01311         const char* filename,
01312         const LLUUID& asset_id,
01313         LLAssetType::EType asset_type,
01314         LLStoreAssetCallback callback,
01315         void* user_data,
01316         bool temp_file,
01317         bool is_priority,
01318         bool user_waiting,
01319         F64 timeout)
01320 {
01321         llwarns << "storeAssetData: wrong version called" << llendl;
01322         // LLAssetStorage metric: Virtual base call
01323         reportMetric( asset_id, asset_type, NULL, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 3" );
01324 }
01325 
01326 // virtual
01327 // this does nothing, viewer and sim both override this.
01328 void LLAssetStorage::storeAssetData(
01329         const char* filename,
01330         const LLTransactionID &transactoin_id,
01331         LLAssetType::EType asset_type,
01332         LLStoreAssetCallback callback,
01333         void* user_data,
01334         bool temp_file,
01335         bool is_priority,
01336         bool user_waiting,
01337         F64 timeout)
01338 {
01339         llwarns << "storeAssetData: wrong version called" << llendl;
01340         // LLAssetStorage metric: Virtual base call
01341         reportMetric( LLUUID::null, asset_type, NULL, LLUUID::null, 0, MR_BAD_FUNCTION, __FILE__, __LINE__, "Illegal call to base: LLAssetStorage::storeAssetData 4" );
01342 }
01343 
01344 // static
01345 void LLAssetStorage::legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status)
01346 {
01347         LLLegacyAssetRequest *legacy = (LLLegacyAssetRequest *)user_data;
01348         if (legacy && legacy->mUpCallback)
01349         {
01350                 legacy->mUpCallback(uuid, legacy->mUserData, status, ext_status);
01351         }
01352         delete legacy;
01353 }
01354 
01355 // virtual
01356 void LLAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name) 
01357 { }
01358 
01359 // virtual
01360 BOOL LLAssetStorage::hasTempAssetData(const LLUUID& texture_id) const 
01361 { return FALSE; }
01362 
01363 // virtual
01364 std::string LLAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const 
01365 { return std::string(); }
01366 
01367 // virtual
01368 LLUUID LLAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const 
01369 { return LLUUID::null; }
01370 
01371 // virtual
01372 void LLAssetStorage::removeTempAssetData(const LLUUID& asset_id) 
01373 { }
01374 
01375 // virtual
01376 void LLAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id) 
01377 { }
01378 
01379 // virtual
01380 void LLAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const 
01381 { }
01382 
01383 // virtual
01384 void LLAssetStorage::clearTempAssetData() 
01385 { }
01386 
01387 // static
01388 void LLAssetStorage::reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const char *filename,
01389                                                                    const LLUUID& agent_id, S32 asset_size, EMetricResult result,
01390                                                                    const char *file, const S32 line, const char *message )
01391 {
01392         if( !metric_recipient )
01393         {
01394                 llinfos << "Couldn't store LLAssetStoreage::reportMetric - no metrics_recipient" << llendl;
01395                 return;
01396         }
01397 
01398         filename = filename ? filename : "";
01399         file = file ? file : "";
01400 
01401         // Create revised message - message = "message :: file:line"
01402         std::string new_message; //( message );
01403         new_message = message; // << " " << file << " " << line;
01404         new_message += " :: ";
01405         new_message += filename;
01406         char line_string[16];
01407         sprintf( line_string, ":%d", line );
01408         new_message += line_string;
01409         message = new_message.c_str();
01410 
01411         // Change always_report to true if debugging... do not check it in this way
01412         static bool always_report = false;
01413         const char *metric_name = "LLAssetStorage::Metrics";
01414 
01415         bool success = result == MR_OKAY;
01416 
01417         if( (!success) || always_report )
01418         {
01419                 LLSD stats;
01420                 stats["asset_id"] = asset_id;
01421                 stats["asset_type"] = asset_type;
01422                 stats["filename"] = filename? filename : "";
01423                 stats["agent_id"] = agent_id;
01424                 stats["asset_size"] = (S32)asset_size;
01425                 stats["result"] = (S32)result;
01426 
01427                 metric_recipient->recordEventDetails( metric_name, message, success, stats);
01428         }
01429         else
01430         {
01431                 metric_recipient->recordEvent(metric_name, message, success);
01432         }
01433 }

Generated on Fri May 16 08:32:21 2008 for SecondLife by  doxygen 1.5.5