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

Generated on Thu Jul 1 06:08:19 2010 for Second Life Viewer by  doxygen 1.4.7