Exemplo n.º 1
0
// virtual
void LLViewerAssetStorage::_queueDataRequest(
	const LLUUID& uuid,
	LLAssetType::EType atype,
	LLGetAssetCallback callback,
	void *user_data,
	BOOL duplicate,
	BOOL is_priority)
{
	if (mUpstreamHost.isOk())
	{
		// stash the callback info so we can find it after we get the response message
		LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype);
		req->mDownCallback = callback;
		req->mUserData = user_data;
		req->mIsPriority = is_priority;
		if (!duplicate)
		{
			// Only collect metrics for non-duplicate requests.  Others 
			// are piggy-backing and will artificially lower averages.
			req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp();
		}
		
		mPendingDownloads.push_back(req);
	
		if (!duplicate)
		{
			// send request message to our upstream data provider
			// Create a new asset transfer.
			LLTransferSourceParamsAsset spa;
			spa.setAsset(uuid, atype);

			// Set our destination file, and the completion callback.
			LLTransferTargetParamsVFile tpvf;
			tpvf.setAsset(uuid, atype);
			tpvf.setCallback(downloadCompleteCallback, req);

			LL_DEBUGS("AssetStorage") << "Starting transfer for " << uuid << llendl;
			LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
			ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));

			LLViewerAssetStatsFF::record_enqueue_main(atype, false, false);
		}
	}
	else
	{
		// uh-oh, we shouldn't have gotten here
		llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
		if (callback)
		{
			callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
		}
	}
}
Exemplo n.º 2
0
//
// *NOTE:  Logic here is replicated in LLViewerAssetStorage::_queueDataRequest.
// Changes here may need to be replicated in the viewer's derived class.
//
void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType atype,
									   LLGetAssetCallback callback,
									   void *user_data, BOOL duplicate,
									   BOOL is_priority)
{
	if (mUpstreamHost.isOk())
	{
		// stash the callback info so we can find it after we get the response message
		LLAssetRequest *req = new LLAssetRequest(uuid, atype);
		req->mDownCallback = callback;
		req->mUserData = user_data;
		req->mIsPriority = is_priority;
	
		mPendingDownloads.push_back(req);
	
		if (!duplicate)
		{
			// send request message to our upstream data provider
			// Create a new asset transfer.
			LLTransferSourceParamsAsset spa;
			spa.setAsset(uuid, atype);

			// Set our destination file, and the completion callback.
			LLTransferTargetParamsVFile tpvf;
			tpvf.setAsset(uuid, atype);
			tpvf.setCallback(downloadCompleteCallback, req);

			//LL_INFOS() << "Starting transfer for " << uuid << LL_ENDL;
			LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
			ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
		}
	}
	else
	{
		// uh-oh, we shouldn't have gotten here
		LL_WARNS() << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL;
		if (callback)
		{
			add(sFailedDownloadCount, 1);
			callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
		}
	}
}
Exemplo n.º 3
0
//static
void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
{
	//llinfos << "LLTransferManager::processTransferPacket" << llendl;

	LLUUID transfer_id;
	LLTransferChannelType channel_type;
	msgp->getUUID("TransferInfo", "TransferID", transfer_id);
	msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);

	// See if it's a target that we're trying to abort
	// Find the transfer associated with this packet.
	LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
	if (ttcp)
	{
		LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
		if (ttp)
		{
			ttp->abortTransfer();
			ttcp->deleteTransfer(ttp);
			return;
		}
	}

	// Hmm, not a target.  Maybe it's a source.
	LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
	if (tscp)
	{
		LLTransferSource *tsp = tscp->findTransferSource(transfer_id);
		if (tsp)
		{
			tsp->abortTransfer();
			tscp->deleteTransfer(tsp);
			return;
		}
	}

	llwarns << "Couldn't find transfer " << transfer_id << " to abort!" << llendl;
}
Exemplo n.º 4
0
void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
									 const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id,
									 const LLUUID &asset_id, LLAssetType::EType atype,
									 LLGetAssetCallback callback, void *user_data, BOOL is_priority)
{
	lldebugs << "LLAssetStorage::getInvItemAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << llendl;

	//
	// Probably will get rid of this early out?
	//
	//if (asset_id.isNull())
	//{
	//	// Special case early out for NULL uuid
	//	if (callback)
	//	{
	//		callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE);
	//	}
	//	return;
	//}

	bool exists = false; 
	U32 size = 0;

	if(asset_id.notNull())
	{
		exists = mVFS->getExists(asset_id, atype);
		LLVFile file(mVFS, asset_id, atype);
		size = exists ? file.getSize() : 0;
		if(exists && size < 1)
		{
			llwarns << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << llendl;
			file.remove();
		}

	}

	if (size < 1)
	{
		// See whether we should talk to the object's originating sim,
		// or the upstream provider.
		LLHost source_host;
		if (object_sim.isOk())
		{
			source_host = object_sim;
		}
		else
		{
			source_host = mUpstreamHost;
		}
		if (source_host.isOk())
		{
			// stash the callback info so we can find it after we get the response message
			LLInvItemRequest *req = new LLInvItemRequest(asset_id, atype);
			req->mDownCallback = callback;
			req->mUserData = user_data;
			req->mIsPriority = is_priority;

			// send request message to our upstream data provider
			// Create a new asset transfer.
			LLTransferSourceParamsInvItem spi;
			spi.setAgentSession(agent_id, session_id);
			spi.setInvItem(owner_id, task_id, item_id);
			spi.setAsset(asset_id, atype);

			// Set our destination file, and the completion callback.
			LLTransferTargetParamsVFile tpvf;
			tpvf.setAsset(asset_id, atype);
			tpvf.setCallback(downloadInvItemCompleteCallback, req);

			llinfos << "Starting transfer for inventory asset "
				<< item_id << " owned by " << owner_id << "," << task_id
				<< llendl;
			LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
			ttcp->requestTransfer(spi, tpvf, 100.f + (is_priority ? 1.f : 0.f));
		}
		else
		{
			// uh-oh, we shouldn't have gotten here
			llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl;
			if (callback)
			{
				callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
			}
		}
	}
	else
	{
		// we've already got the file
		// theoretically, partial files w/o a pending request shouldn't happen
		// unless there's a weird error
		if (callback)
		{
			callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
		}
	}
}
void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
									const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
									 LLGetAssetCallback callback, void *user_data, BOOL is_priority)
{
	LL_DEBUGS() << "LLAssetStorage::getEstateAsset() - " << asset_id << "," << LLAssetType::lookup(atype) << ", estatetype " << etype << LL_ENDL;

	//
	// Probably will get rid of this early out?
	//
	if (asset_id.isNull())
	{
		// Special case early out for NULL uuid
		if (callback)
		{
			callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID);
		}
		return;
	}

	// Try static VFS first.
	if (findInStaticVFSAndInvokeCallback(asset_id,atype,callback,user_data))
	{
		return;
	}
	
	BOOL exists = mVFS->getExists(asset_id, atype);
	LLVFile file(mVFS, asset_id, atype);
	U32 size = exists ? file.getSize() : 0;

	if (size > 0)
	{
		// we've already got the file
		// theoretically, partial files w/o a pending request shouldn't happen
		// unless there's a weird error
		if (callback)
		{
			callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LL_EXSTAT_VFS_CACHED);
		}
	}
	else
	{
		if (exists)
		{
			LL_WARNS() << "Asset vfile " << asset_id << ":" << atype << " found with bad size " << file.getSize() << ", removing" << LL_ENDL;
			file.remove();
		}

		// See whether we should talk to the object's originating sim, or the upstream provider.
		LLHost source_host;
		if (object_sim.isOk())
		{
			source_host = object_sim;
		}
		else
		{
			source_host = mUpstreamHost;
		}
		if (source_host.isOk())
		{
			// stash the callback info so we can find it after we get the response message
			LLEstateAssetRequest *req = new LLEstateAssetRequest(asset_id, atype, etype);
			req->mDownCallback = callback;
			req->mUserData = user_data;
			req->mIsPriority = is_priority;

			// send request message to our upstream data provider
			// Create a new asset transfer.
			LLTransferSourceParamsEstate spe;
			spe.setAgentSession(agent_id, session_id);
			spe.setEstateAssetType(etype);

			// Set our destination file, and the completion callback.
			LLTransferTargetParamsVFile tpvf;
			tpvf.setAsset(asset_id, atype);
			tpvf.setCallback(downloadEstateAssetCompleteCallback, req);

			LL_DEBUGS("AssetStorage") << "Starting transfer for " << asset_id << LL_ENDL;
			LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(source_host, LLTCT_ASSET);
			ttcp->requestTransfer(spe, tpvf, 100.f + (is_priority ? 1.f : 0.f));
		}
		else
		{
			// uh-oh, we shouldn't have gotten here
			LL_WARNS() << "Attempt to move asset data request upstream w/o valid upstream provider" << LL_ENDL;
			if (callback)
			{
				callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM);
			}
		}
	}
}
Exemplo n.º 6
0
//static
void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
{
	//llinfos << "LLTransferManager::processTransferPacket" << llendl;

	LLUUID transfer_id;
	LLTransferChannelType channel_type;
	S32 packet_id;
	LLTSCode status;
	S32 size;
	msgp->getUUID("TransferData", "TransferID", transfer_id);
	msgp->getS32("TransferData", "ChannelType", (S32 &)channel_type);
	msgp->getS32("TransferData", "Packet", packet_id);
	msgp->getS32("TransferData", "Status", (S32 &)status);

	// Find the transfer associated with this packet.
	//llinfos << transfer_id << ":" << channel_type << llendl;
	LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
	if (!ttcp)
	{
		llwarns << "Target channel not found" << llendl;
		return;
	}

	LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
	if (!ttp)
	{
		llwarns << "Didn't find matching transfer for " << transfer_id
			<< " processing packet " << packet_id
			<< " from " << msgp->getSender() << llendl;
		return;
	}

	size = msgp->getSize("TransferData", "Data");

	S32 msg_bytes = 0;
	if (msgp->getReceiveCompressedSize())
	{
		msg_bytes = msgp->getReceiveCompressedSize();
	}
	else
	{
		msg_bytes = msgp->getReceiveSize();
	}
	gTransferManager.addTransferBitsIn(ttcp->mChannelType, msg_bytes*8);

	if ((size < 0) || (size > MAX_PACKET_DATA_SIZE))
	{
		llwarns << "Invalid transfer packet size " << size << llendl;
		return;
	}

	U8 tmp_data[MAX_PACKET_DATA_SIZE];
	if (size > 0)
	{
		// Only pull the data out if the size is > 0
		msgp->getBinaryData("TransferData", "Data", tmp_data, size);
	}

	if ((!ttp->gotInfo()) || (ttp->getNextPacketID() != packet_id))
	{
		// Put this on a list of packets to be delivered later.
		if(!ttp->addDelayedPacket(packet_id, status, tmp_data, size))
		{
			// Whoops - failed to add a delayed packet for some reason.
			llwarns << "Too many delayed packets processing transfer "
				<< transfer_id << " from " << msgp->getSender() << llendl;
			ttp->abortTransfer();
			ttcp->deleteTransfer(ttp);
			return;
		}
#if 0
		// Spammy!
		const S32 LL_TRANSFER_WARN_GAP = 10;
		if(!ttp->gotInfo())
		{
			llwarns << "Got data packet before information in transfer "
				<< transfer_id << " from " << msgp->getSender()
				<< ", got " << packet_id << llendl;
		}
		else if((packet_id - ttp->getNextPacketID()) > LL_TRANSFER_WARN_GAP)
		{
			llwarns << "Out of order packet in transfer " << transfer_id
				<< " from " << msgp->getSender() << ", got " << packet_id
				<< " expecting " << ttp->getNextPacketID() << llendl;
		}
#endif
		return;
	}

	// Loop through this until we're done with all delayed packets
	
	//
	// NOTE: THERE IS A CUT AND PASTE OF THIS CODE IN THE TRANSFERINFO HANDLER
	// SO WE CAN PLAY BACK DELAYED PACKETS THERE!!!!!!!!!!!!!!!!!!!!!!!!!
	//
	BOOL done = FALSE;
	while (!done)
	{
		LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
		if (ret_code == LLTS_OK)
		{
			ttp->setLastPacketID(packet_id);
		}

		if (status != LLTS_OK)
		{
			if (status != LLTS_DONE)
			{
				llwarns << "LLTransferManager::processTransferPacket Error in transfer!" << llendl;
			}
			else
			{
// 				llinfos << "LLTransferManager::processTransferPacket done for " << transfer_id << llendl;
			}
			// This transfer is done, either via error or not.
			ttp->completionCallback(status);
			ttcp->deleteTransfer(ttp);
			return;
		}

		// See if we've got any delayed packets
		packet_id = ttp->getNextPacketID();
		if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
		{
			// Perhaps this stuff should be inside a method in LLTransferPacket?
			// I'm too lazy to do it now, though.
// 			llinfos << "Playing back delayed packet " << packet_id << llendl;
			LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];

			// This is somewhat inefficient, but avoids us having to duplicate
			// code between the off-the-wire and delayed paths.
			packet_id = packetp->mPacketID;
			size = packetp->mSize;
			if (size)
			{
				if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
				{
					memcpy(tmp_data, packetp->mDatap, size);	/*Flawfinder: ignore*/
				}
			}
			status = packetp->mStatus;
			ttp->mDelayedPacketMap.erase(packet_id);
			delete packetp;
		}
		else
		{
			// No matching delayed packet, abort it.
			done = TRUE;
		}
	}
}
Exemplo n.º 7
0
//static
void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
{
	//llinfos << "LLTransferManager::processTransferInfo" << llendl;

	LLUUID transfer_id;
	LLTransferTargetType target_type;
	LLTransferChannelType channel_type;
	LLTSCode status;
	S32 size;

	msgp->getUUID("TransferInfo", "TransferID", transfer_id);
	msgp->getS32("TransferInfo", "TargetType", (S32 &)target_type);
	msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
	msgp->getS32("TransferInfo", "Status", (S32 &)status);
	msgp->getS32("TransferInfo", "Size", size);

	//llinfos << transfer_id << ":" << target_type<< ":" << channel_type << llendl;
	LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
	if (!ttcp)
	{
		llwarns << "Target channel not found" << llendl;
		// Should send a message to abort the transfer.
		return;
	}

	LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
	if (!ttp)
	{
		llwarns << "TransferInfo for unknown transfer!  Not able to handle this yet!" << llendl;
		// This could happen if we're doing a push transfer, although to avoid confusion,
		// maybe it should be a different message.
		return;
	}

	if (status != LLTS_OK)
	{
		llwarns << transfer_id << ": Non-ok status, cleaning up" << llendl;
		ttp->completionCallback(status);
		// Clean up the transfer.
		ttcp->deleteTransfer(ttp);
		return;
	}

	// unpack the params
	S32 params_size = msgp->getSize("TransferInfo", "Params");
	if(params_size > MAX_PARAMS_SIZE)
	{
		llwarns << "LLTransferManager::processTransferInfo params too big."
			<< llendl;
		return;
	}
	else if(params_size > 0)
	{
		U8 tmp[MAX_PARAMS_SIZE];
		msgp->getBinaryData("TransferInfo", "Params", tmp, params_size);
		LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
		if (!ttp->unpackParams(dpb))
		{
			// This should only happen if the data is corrupt or
			// incorrectly packed.
			llwarns << "LLTransferManager::processTransferRequest: bad params."
				<< llendl;
			ttp->abortTransfer();
			ttcp->deleteTransfer(ttp);
			return;
		}
	}

	llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
	ttp->setSize(size);
	ttp->setGotInfo(TRUE);

	// OK, at this point we to handle any delayed transfer packets (which could happen
	// if this packet was lost)

	// This is a lame cut and paste of code down below.  If we change the logic down there,
	// we HAVE to change the logic up here.

	while (1)
	{
		S32 packet_id = 0;
		U8 tmp_data[MAX_PACKET_DATA_SIZE];
		// See if we've got any delayed packets
		packet_id = ttp->getNextPacketID();
		if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
		{
			// Perhaps this stuff should be inside a method in LLTransferPacket?
			// I'm too lazy to do it now, though.
// 			llinfos << "Playing back delayed packet " << packet_id << llendl;
			LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];

			// This is somewhat inefficient, but avoids us having to duplicate
			// code between the off-the-wire and delayed paths.
			packet_id = packetp->mPacketID;
			size = packetp->mSize;
			if (size)
			{
				if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
				{
					memcpy(tmp_data, packetp->mDatap, size);	/*Flawfinder: ignore*/
				}
			}
			status = packetp->mStatus;
			ttp->mDelayedPacketMap.erase(packet_id);
			delete packetp;
		}
		else
		{
			// No matching delayed packet, we're done.
			break;
		}

		LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
		if (ret_code == LLTS_OK)
		{
			ttp->setLastPacketID(packet_id);
		}

		if (status != LLTS_OK)
		{
			if (status != LLTS_DONE)
			{
				llwarns << "LLTransferManager::processTransferInfo Error in playback!" << llendl;
			}
			else
			{
				llinfos << "LLTransferManager::processTransferInfo replay FINISHED for " << transfer_id << llendl;
			}
			// This transfer is done, either via error or not.
			ttp->completionCallback(status);
			ttcp->deleteTransfer(ttp);
			return;
		}
	}
}