After seeing sdague do his happy dance over trunk working "the best he has ever seen". I'm not sure I should be doing this commit, but oh well.

So anyway, it moves the Asset downloading (packet sending) to a module (AssetDownloadModule). 
So now at last, AssetCache should be just dealing with fetching assets from the asset server and caching them.
0.6.0-stable
MW 2008-02-27 21:11:01 +00:00
parent 34073607a2
commit e978d00914
5 changed files with 367 additions and 89 deletions

View File

@ -69,12 +69,12 @@ namespace OpenSim.Framework.Communications.Cache
///
/// Assets requests which are waiting for asset server data. This includes texture requests
/// </summary>
private Dictionary<LLUUID, AssetRequest> RequestedAssets;
// private Dictionary<LLUUID, AssetRequest> RequestedAssets;
/// <summary>
/// Asset requests with data which are ready to be sent back to requesters. This includes textures.
/// </summary>
private List<AssetRequest> AssetRequests;
// private List<AssetRequest> AssetRequests;
/// <summary>
@ -84,7 +84,7 @@ namespace OpenSim.Framework.Communications.Cache
private readonly IAssetServer m_assetServer;
private readonly Thread m_assetCacheThread;
// private readonly Thread m_assetCacheThread;
/// <summary>
/// Report statistical data.
@ -94,8 +94,8 @@ namespace OpenSim.Framework.Communications.Cache
m_log.InfoFormat("Assets:{0} Textures:{1} AssetRequests:{2} RequestedAssets:{3} RequestLists:{4}",
Assets.Count,
Textures.Count,
AssetRequests.Count,
RequestedAssets.Count,
// AssetRequests.Count,
// RequestedAssets.Count,
RequestLists.Count);
int temporaryImages = 0;
@ -150,9 +150,9 @@ namespace OpenSim.Framework.Communications.Cache
{
Assets = new Dictionary<LLUUID, AssetInfo>();
Textures = new Dictionary<LLUUID, TextureImage>();
AssetRequests = new List<AssetRequest>();
// AssetRequests = new List<AssetRequest>();
RequestedAssets = new Dictionary<LLUUID, AssetRequest>();
// RequestedAssets = new Dictionary<LLUUID, AssetRequest>();
RequestLists = new Dictionary<LLUUID, AssetRequestsList>();
}
@ -168,18 +168,18 @@ namespace OpenSim.Framework.Communications.Cache
m_assetServer = assetServer;
m_assetServer.SetReceiver(this);
m_assetCacheThread = new Thread(new ThreadStart(RunAssetManager));
m_assetCacheThread.Name = "AssetCacheThread";
m_assetCacheThread.IsBackground = true;
m_assetCacheThread.Start();
OpenSim.Framework.ThreadTracker.Add(m_assetCacheThread);
// m_assetCacheThread = new Thread(new ThreadStart(RunAssetManager));
// m_assetCacheThread.Name = "AssetCacheThread";
// m_assetCacheThread.IsBackground = true;
// m_assetCacheThread.Start();
// OpenSim.Framework.ThreadTracker.Add(m_assetCacheThread);
}
/// <summary>
/// Process the asset queue which holds data which is packeted up and sent
/// directly back to the client.
/// </summary>
public void RunAssetManager()
/* public void RunAssetManager()
{
while (true)
{
@ -193,7 +193,7 @@ namespace OpenSim.Framework.Communications.Cache
m_log.Error("[ASSET CACHE]: " + e.ToString());
}
}
}
}*/
/// <summary>
/// Only get an asset if we already have it in the cache.
@ -449,7 +449,7 @@ namespace OpenSim.Framework.Communications.Cache
StatsManager.SimExtraStats.AddAsset(assetInf);
}
if (RequestedAssets.ContainsKey(assetInf.FullID))
/* if (RequestedAssets.ContainsKey(assetInf.FullID))
{
#if DEBUG
//m_log.DebugFormat("[ASSET CACHE]: Moving {0} from RequestedAssets to AssetRequests", asset.FullID);
@ -461,7 +461,7 @@ namespace OpenSim.Framework.Communications.Cache
RequestedAssets.Remove(assetInf.FullID);
AssetRequests.Add(req);
}
}*/
}
}
@ -541,6 +541,7 @@ namespace OpenSim.Framework.Communications.Cache
}
/*
/// <summary>
/// Calculate the number of packets required to send the asset to the client.
/// </summary>
@ -734,7 +735,7 @@ namespace OpenSim.Framework.Communications.Cache
{
}
}
*/
public class AssetInfo : AssetBase
{

View File

@ -390,6 +390,8 @@ namespace OpenSim.Framework
public delegate void RemoveInventoryFolder(
IClientAPI remoteClient, LLUUID folderID);
public delegate void RequestAsset(IClientAPI remoteClient, TransferRequestPacket transferRequest);
public delegate void RezScript(IClientAPI remoteClient, LLUUID itemID, uint localID);
public delegate void UpdateTaskInventory(IClientAPI remoteClient, LLUUID itemID, LLUUID folderID, uint localID);
@ -503,6 +505,7 @@ namespace OpenSim.Framework
event RezScript OnRezScript;
event UpdateTaskInventory OnUpdateTaskInventory;
event RemoveTaskInventory OnRemoveTaskItem;
event RequestAsset OnRequestAsset;
event UUIDNameRequest OnNameFromUUIDRequest;

View File

@ -51,10 +51,10 @@ namespace OpenSim.Region.ClientStack
/// </summary>
public class ClientView : IClientAPI
{
// ~ClientView()
// {
// System.Console.WriteLine("[CLIENTVIEW]: Destructor called");
// }
// ~ClientView()
// {
// System.Console.WriteLine("[CLIENTVIEW]: Destructor called");
// }
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@ -119,7 +119,7 @@ namespace OpenSim.Region.ClientStack
protected LLVector3 m_startpos;
protected EndPoint m_userEndPoint;
/* Instantiated Designated Event Delegates */
/* Instantiated Designated Event Delegates */
//- used so we don't create new objects for each incoming packet and then toss it out later */
private RequestAvatarProperties handler001 = null; //OnRequestAvatarProperties;
@ -214,7 +214,8 @@ namespace OpenSim.Region.ClientStack
private UpdateVector handler089 = null; //OnUpdatePrimGroupPosition;
private UpdatePrimRotation handler090 = null; //OnUpdatePrimGroupRotation;
private UpdatePrimGroupRotation handler091 = null; //OnUpdatePrimGroupMouseRotation;
private PacketStats handler093 = null; // OnPacketStats;
private PacketStats handler093 = null; // OnPacketStats;#
private RequestAsset handler094 = null; // OnRequestAsset;
/* Properties */
@ -363,7 +364,7 @@ namespace OpenSim.Region.ClientStack
// We can't reach into other scenes and close the connection
// We need to do this over grid communications
//m_scene.CloseAllAgents(CircuitCode);
// If we're not shutting down the circuit, then this is the last time we'll go here.
// If we are shutting down the circuit, the UDP Server will come back here with
// ShutDownCircuit = false
@ -502,7 +503,7 @@ namespace OpenSim.Region.ClientStack
protected virtual void ClientLoop()
{
m_log.Info("[CLIENT]: Entered loop");
while( true )
while (true)
{
QueItem nextPacket = m_packetQueue.Dequeue();
if (nextPacket.Incoming)
@ -690,6 +691,7 @@ namespace OpenSim.Region.ClientStack
public event RezScript OnRezScript;
public event UpdateTaskInventory OnUpdateTaskInventory;
public event RemoveTaskInventory OnRemoveTaskItem;
public event RequestAsset OnRequestAsset;
public event UUIDNameRequest OnNameFromUUIDRequest;
@ -1410,7 +1412,7 @@ namespace OpenSim.Region.ClientStack
OutPacket(replyPacket, ThrottleOutPacketType.Task);
}
public void SendAgentDataUpdate(LLUUID agentid, LLUUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname,string grouptitle)
public void SendAgentDataUpdate(LLUUID agentid, LLUUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
{
AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
@ -1420,7 +1422,7 @@ namespace OpenSim.Region.ClientStack
sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
sendAgentDataUpdate.AgentData.GroupTitle = Helpers.StringToField(grouptitle);
sendAgentDataUpdate.AgentData.LastName = Helpers.StringToField(lastname);
OutPacket(sendAgentDataUpdate,ThrottleOutPacketType.Task);
OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
}
/// <summary>
@ -2329,10 +2331,10 @@ namespace OpenSim.Region.ClientStack
{
LLUUID partId = part.UUID;
UpdatePrimRotation handler090 = OnUpdatePrimGroupRotation;
UpdatePrimGroupRotation handler091 = OnUpdatePrimGroupMouseRotation;
@ -2344,7 +2346,7 @@ namespace OpenSim.Region.ClientStack
handler086 = OnUpdatePrimSinglePosition;
if (handler086 != null)
{
// System.Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
handler086(localId, pos1, this);
}
@ -2355,18 +2357,18 @@ namespace OpenSim.Region.ClientStack
handler087 = OnUpdatePrimSingleRotation;
if (handler087 != null)
{
//System.Console.WriteLine("new tab rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
handler087(localId, rot1, this);
}
break;
case 3:
LLQuaternion rot2 = new LLQuaternion(block.Data, 12, true);
handler087 = OnUpdatePrimSingleRotation;
if (handler087 != null)
{
//System.Console.WriteLine("new mouse rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
handler087(localId, rot2, this);
}
@ -2378,7 +2380,7 @@ namespace OpenSim.Region.ClientStack
handler088 = OnUpdatePrimScale;
if (handler088 != null)
{
// Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
handler088(localId, scale1, this);
}
@ -2390,18 +2392,18 @@ namespace OpenSim.Region.ClientStack
if (handler089 != null)
{
handler089(localId, pos2, this);
}
break;
case 10:
LLQuaternion rot3 = new LLQuaternion(block.Data, 0, true);
handler090 = OnUpdatePrimGroupRotation;
if (handler090 != null)
{
// Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
handler090(localId, rot3, this);
}
@ -2429,7 +2431,7 @@ namespace OpenSim.Region.ClientStack
handler088 = OnUpdatePrimScale;
if (handler088 != null)
{
//Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
handler088(localId, scale2, this);
@ -2449,10 +2451,10 @@ namespace OpenSim.Region.ClientStack
handler088 = OnUpdatePrimScale;
if (handler088 != null)
{
// Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z );
handler088(localId, scale5, this);
handler086 = OnUpdatePrimSinglePosition;
if (handler086 != null)
{
@ -2762,7 +2764,7 @@ namespace OpenSim.Region.ClientStack
if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
{
//m_log.Debug("[NETWORK]: Resending " + packet.Type.ToString() + " packet, " +
//(now - packet.TickCount) + "ms have passed");
//(now - packet.TickCount) + "ms have passed");
packet.Header.Resent = true;
OutPacket(packet, ThrottleOutPacketType.Resend);
@ -2863,13 +2865,13 @@ namespace OpenSim.Region.ClientStack
case PacketType.AvatarPropertiesRequest:
AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
handler001 = OnRequestAvatarProperties;
if (handler001 != null)
{
handler001(this, avatarProperties.AgentData.AvatarID);
}
break;
case PacketType.ChatFromViewer:
@ -2900,7 +2902,7 @@ namespace OpenSim.Region.ClientStack
handler002(this, args);
}
break;
case PacketType.ScriptDialogReply:
@ -2921,7 +2923,7 @@ namespace OpenSim.Region.ClientStack
if (handler003 != null)
handler003(this, args);
}
break;
case PacketType.ImprovedInstantMessage:
ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack;
@ -2940,7 +2942,7 @@ namespace OpenSim.Region.ClientStack
msgpack.MessageBlock.BinaryBucket);
}
break;
case PacketType.AcceptFriendship:
@ -2963,7 +2965,7 @@ namespace OpenSim.Region.ClientStack
handler005(this, agentID, transactionID, callingCardFolders);
}
break;
@ -2977,7 +2979,7 @@ namespace OpenSim.Region.ClientStack
{
handler006(this, listOwnerAgentID, exFriendID);
}
break;
case PacketType.RezObject:
@ -2995,7 +2997,7 @@ namespace OpenSim.Region.ClientStack
//rezPacket.RezData.RezSelected;
//rezPacket.RezData.FromTaskID;
//m_log.Info("[REZData]: " + rezPacket.ToString());
handler007(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd,
rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID,
rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection,
@ -3004,7 +3006,7 @@ namespace OpenSim.Region.ClientStack
rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem,
rezPacket.RezData.FromTaskID);
}
break;
case PacketType.DeRezObject:
handler008 = OnDeRezObject;
@ -3012,7 +3014,7 @@ namespace OpenSim.Region.ClientStack
{
handler008(Pack, this);
}
break;
case PacketType.ModifyLand:
ModifyLandPacket modify = (ModifyLandPacket)Pack;
@ -3021,7 +3023,7 @@ namespace OpenSim.Region.ClientStack
{
if (OnModifyTerrain != null)
{
for (int i = 0; i < modify.ParcelData.Length; i++)
{
handler009 = OnModifyTerrain;
@ -3036,7 +3038,7 @@ namespace OpenSim.Region.ClientStack
}
}
}
break;
case PacketType.RegionHandshakeReply:
@ -3045,7 +3047,7 @@ namespace OpenSim.Region.ClientStack
{
handler010(this);
}
break;
case PacketType.AgentWearablesRequest:
handler011 = OnRequestWearables;
@ -3054,7 +3056,7 @@ namespace OpenSim.Region.ClientStack
{
handler011();
}
handler012 = OnRequestAvatarsData;
@ -3063,7 +3065,7 @@ namespace OpenSim.Region.ClientStack
handler012(this);
}
break;
case PacketType.AgentSetAppearance:
AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
@ -3073,7 +3075,7 @@ namespace OpenSim.Region.ClientStack
{
handler013(appear.ObjectData.TextureEntry, appear.VisualParam);
}
break;
case PacketType.AgentIsNowWearing:
if (OnAvatarNowWearing != null)
@ -3094,7 +3096,7 @@ namespace OpenSim.Region.ClientStack
handler014(this, wearingArgs);
}
}
break;
case PacketType.RezSingleAttachmentFromInv:
@ -3102,28 +3104,28 @@ namespace OpenSim.Region.ClientStack
handler015 = OnRezSingleAttachmentFromInv;
if (handler015 != null)
{
RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket) Pack;
handler015(this, rez.ObjectData.ItemID,
RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
handler015(this, rez.ObjectData.ItemID,
rez.ObjectData.AttachmentPt, rez.ObjectData.ItemFlags, rez.ObjectData.NextOwnerMask);
}
break;
break;
case PacketType.ObjectAttach:
if (OnObjectAttach != null)
{
ObjectAttachPacket att = (ObjectAttachPacket)Pack;
handler016 = OnObjectAttach;
if (handler016 != null)
{
{
handler016(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation);
}
}
break;
break;
case PacketType.SetAlwaysRun:
SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack;
@ -3131,7 +3133,7 @@ namespace OpenSim.Region.ClientStack
if (handler017 != null)
handler017(this, run.AgentData.AlwaysRun);
break;
case PacketType.CompleteAgentMovement:
@ -3243,7 +3245,7 @@ namespace OpenSim.Region.ClientStack
case PacketType.SetStartLocationRequest:
SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId)
{
handler027 = OnSetStartLocationRequest;
@ -3494,7 +3496,7 @@ namespace OpenSim.Region.ClientStack
byte set = permChanges.Set;
handler043 = OnObjectPermissions;
if (handler043 != null)
OnObjectPermissions(this, AgentID, SessionID, field, localID, mask, set);
}
@ -3539,7 +3541,7 @@ namespace OpenSim.Region.ClientStack
case PacketType.RequestImage:
RequestImagePacket imageRequest = (RequestImagePacket)Pack;
//Console.WriteLine("image request: " + Pack.ToString());
handler045 = null;
for (int i = 0; i < imageRequest.RequestImage.Length; i++)
@ -3551,9 +3553,9 @@ namespace OpenSim.Region.ClientStack
args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel;
args.PacketNumber = imageRequest.RequestImage[i].Packet;
args.Priority = imageRequest.RequestImage[i].DownloadPriority;
handler045 = OnRequestTexture;
if (handler045 != null)
OnRequestTexture(this, args);
}
@ -3562,7 +3564,12 @@ namespace OpenSim.Region.ClientStack
case PacketType.TransferRequest:
//Console.WriteLine("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
TransferRequestPacket transfer = (TransferRequestPacket)Pack;
m_assetCache.AddAssetRequest(this, transfer);
// m_assetCache.AddAssetRequest(this, transfer);
handler094 = OnRequestAsset;
if (handler094 != null)
{
handler094(this, transfer);
}
break;
case PacketType.AssetUploadRequest:
AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
@ -3606,7 +3613,7 @@ namespace OpenSim.Region.ClientStack
handler049 = OnConfirmXfer;
if (handler049 != null)
{
handler049(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
handler049(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
}
break;
case PacketType.CreateInventoryFolder:
@ -3615,7 +3622,7 @@ namespace OpenSim.Region.ClientStack
handler050 = OnCreateNewInventoryFolder;
if (handler050 != null)
{
handler050(this, invFolder.FolderData.FolderID,
(ushort)invFolder.FolderData.Type,
Util.FieldToString(invFolder.FolderData.Name),
@ -3709,7 +3716,7 @@ namespace OpenSim.Region.ClientStack
}
break;
case PacketType.PurgeInventoryDescendents:
PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack;
handler056 = OnPurgeInventoryDescendents;
@ -4130,7 +4137,7 @@ namespace OpenSim.Region.ClientStack
}
break;
case PacketType.EstateCovenantRequest:
EstateCovenantRequestPacket.AgentDataBlock epack =
((EstateCovenantRequestPacket)Pack).AgentData;
@ -4246,9 +4253,9 @@ namespace OpenSim.Region.ClientStack
m_log.Warn("[CLIENT]: unhandled MuteListRequest packet");
break;
//case PacketType.AgentDataUpdateRequest:
// TODO: handle this packet
//m_log.Warn("[CLIENT]: unhandled AgentDataUpdateRequest packet");
//break;
// TODO: handle this packet
//m_log.Warn("[CLIENT]: unhandled AgentDataUpdateRequest packet");
//break;
case PacketType.ParcelDwellRequest:
// TODO: handle this packet
@ -4275,9 +4282,9 @@ namespace OpenSim.Region.ClientStack
m_log.Warn("[CLIENT]: unhandled SoundTrigger packet");
break;
//case PacketType.UserInfoRequest:
// TODO: handle this packet
//m_log.Warn("[CLIENT]: unhandled UserInfoRequest packet");
//break;
// TODO: handle this packet
//m_log.Warn("[CLIENT]: unhandled UserInfoRequest packet");
//break;
case PacketType.InventoryDescendents:
// TODO: handle this packet
m_log.Warn("[CLIENT]: unhandled InventoryDescent packet");

View File

@ -26,25 +26,57 @@
*
*/
using System;
using System.Collections.Generic;
using System.Threading;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes;
using libsecondlife;
using libsecondlife.Packets;
namespace OpenSim.Region.Environment.Modules
{
public class AssetDownloadModule : IRegionModule
{
private Scene m_scene;
private Dictionary<LLUUID, Scene> RegisteredScenes = new Dictionary<LLUUID, Scene>();
///
/// Assets requests (for each user) which are waiting for asset server data. This includes texture requests
/// </summary>
private Dictionary<LLUUID, Dictionary<LLUUID,AssetRequest>> RequestedAssets;
/// <summary>
/// Asset requests with data which are ready to be sent back to requesters. This includes textures.
/// </summary>
private List<AssetRequest> AssetRequests;
private Thread m_thread;
public AssetDownloadModule()
{
RequestedAssets = new Dictionary<LLUUID, Dictionary<LLUUID, AssetRequest>>();
AssetRequests = new List<AssetRequest>();
}
public void Initialise(Scene scene, IConfigSource config)
{
m_scene = scene;
m_scene.EventManager.OnNewClient += NewClient;
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
{
RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
scene.EventManager.OnNewClient += NewClient;
}
if (m_scene == null)
{
m_scene = scene;
m_thread = new Thread(new ThreadStart(RunAssetQueue));
m_thread.Name = "AssetDownloadQueueThread";
m_thread.IsBackground = true;
m_thread.Start();
OpenSim.Framework.ThreadTracker.Add(m_thread);
}
}
public void PostInitialise()
@ -67,6 +99,240 @@ namespace OpenSim.Region.Environment.Modules
public void NewClient(IClientAPI client)
{
client.OnRequestAsset += AddAssetRequest;
}
/// <summary>
/// Make an asset request the result of which will be packeted up and sent directly back to the client.
/// </summary>
/// <param name="userInfo"></param>
/// <param name="transferRequest"></param>
public void AddAssetRequest(IClientAPI userInfo, TransferRequestPacket transferRequest)
{
LLUUID requestID = null;
byte source = 2;
if (transferRequest.TransferInfo.SourceType == 2)
{
//direct asset request
requestID = new LLUUID(transferRequest.TransferInfo.Params, 0);
}
else if (transferRequest.TransferInfo.SourceType == 3)
{
//inventory asset request
requestID = new LLUUID(transferRequest.TransferInfo.Params, 80);
source = 3;
//Console.WriteLine("asset request " + requestID);
}
//not found asset
// so request from asset server
Dictionary<LLUUID, AssetRequest> userRequests = null;
if (RequestedAssets.TryGetValue(userInfo.AgentId, out userRequests))
{
if (!userRequests.ContainsKey(requestID))
{
AssetRequest request = new AssetRequest();
request.RequestUser = userInfo;
request.RequestAssetID = requestID;
request.TransferRequestID = transferRequest.TransferInfo.TransferID;
request.AssetRequestSource = source;
request.Params = transferRequest.TransferInfo.Params;
userRequests[requestID] = request;
m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
}
}
else
{
userRequests = new Dictionary<LLUUID, AssetRequest>();
AssetRequest request = new AssetRequest();
request.RequestUser = userInfo;
request.RequestAssetID = requestID;
request.TransferRequestID = transferRequest.TransferInfo.TransferID;
request.AssetRequestSource = source;
request.Params = transferRequest.TransferInfo.Params;
userRequests.Add(requestID, request);
RequestedAssets[userInfo.AgentId] = userRequests;
m_scene.AssetCache.GetAsset(requestID, AssetCallback, false);
}
return;
}
public void AssetCallback(LLUUID assetID, AssetBase asset)
{
if (asset != null)
{
foreach (Dictionary<LLUUID, AssetRequest> userRequests in RequestedAssets.Values)
{
if (userRequests.ContainsKey(assetID))
{
AssetRequest req = userRequests[assetID];
if (req != null)
{
req.AssetInf = asset;
req.NumPackets = CalculateNumPackets(asset.Data);
userRequests.Remove(assetID);
AssetRequests.Add(req);
}
}
}
}
}
private void RunAssetQueue()
{
while (true)
{
try
{
ProcessAssetQueue();
Thread.Sleep(500);
}
catch (Exception e)
{
// m_log.Error("[ASSET CACHE]: " + e.ToString());
}
}
}
/// <summary>
/// Process the asset queue which sends packets directly back to the client.
/// </summary>
private void ProcessAssetQueue()
{
//should move the asset downloading to a module, like has been done with texture downloading
if (AssetRequests.Count == 0)
{
//no requests waiting
return;
}
// if less than 5, do all of them
int num = Math.Min(5, AssetRequests.Count);
AssetRequest req;
for (int i = 0; i < num; i++)
{
req = (AssetRequest)AssetRequests[i];
//Console.WriteLine("sending asset " + req.RequestAssetID);
TransferInfoPacket Transfer = new TransferInfoPacket();
Transfer.TransferInfo.ChannelType = 2;
Transfer.TransferInfo.Status = 0;
Transfer.TransferInfo.TargetType = 0;
if (req.AssetRequestSource == 2)
{
Transfer.TransferInfo.Params = new byte[20];
Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
int assType = (int)req.AssetInf.Type;
Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
}
else if (req.AssetRequestSource == 3)
{
Transfer.TransferInfo.Params = req.Params;
// Transfer.TransferInfo.Params = new byte[100];
//Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
//Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
}
Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
Transfer.TransferInfo.TransferID = req.TransferRequestID;
req.RequestUser.OutPacket(Transfer, ThrottleOutPacketType.Asset);
if (req.NumPackets == 1)
{
TransferPacketPacket TransferPacket = new TransferPacketPacket();
TransferPacket.TransferData.Packet = 0;
TransferPacket.TransferData.ChannelType = 2;
TransferPacket.TransferData.TransferID = req.TransferRequestID;
TransferPacket.TransferData.Data = req.AssetInf.Data;
TransferPacket.TransferData.Status = 1;
req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
}
else
{
int processedLength = 0;
// libsecondlife hardcodes 1500 as the maximum data chunk size
int maxChunkSize = 1250;
int packetNumber = 0;
while (processedLength < req.AssetInf.Data.Length)
{
TransferPacketPacket TransferPacket = new TransferPacketPacket();
TransferPacket.TransferData.Packet = packetNumber;
TransferPacket.TransferData.ChannelType = 2;
TransferPacket.TransferData.TransferID = req.TransferRequestID;
int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
byte[] chunk = new byte[chunkSize];
Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
TransferPacket.TransferData.Data = chunk;
// 0 indicates more packets to come, 1 indicates last packet
if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
{
TransferPacket.TransferData.Status = 0;
}
else
{
TransferPacket.TransferData.Status = 1;
}
req.RequestUser.OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
processedLength += chunkSize;
packetNumber++;
}
}
}
//remove requests that have been completed
for (int i = 0; i < num; i++)
{
AssetRequests.RemoveAt(0);
}
}
/// <summary>
/// Calculate the number of packets required to send the asset to the client.
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private int CalculateNumPackets(byte[] data)
{
const uint m_maxPacketSize = 600;
int numPackets = 1;
if (data.LongLength > m_maxPacketSize)
{
// over max number of bytes so split up file
long restData = data.LongLength - m_maxPacketSize;
int restPackets = (int)((restData + m_maxPacketSize - 1) / m_maxPacketSize);
numPackets += restPackets;
}
return numPackets;
}
public class AssetRequest
{
public IClientAPI RequestUser;
public LLUUID RequestAssetID;
public AssetBase AssetInf;
public AssetBase ImageInfo;
public LLUUID TransferRequestID;
public long DataPointer = 0;
public int NumPackets = 0;
public int PacketCounter = 0;
public bool IsTextureRequest;
public byte AssetRequestSource = 2;
public byte[] Params = null;
//public bool AssetInCache;
//public int TimeRequested;
public int DiscardLevel = -1;
public AssetRequest()
{
}
}
}
}

View File

@ -131,6 +131,7 @@ namespace SimpleApp
public event RezScript OnRezScript;
public event UpdateTaskInventory OnUpdateTaskInventory;
public event RemoveTaskInventory OnRemoveTaskItem;
public event RequestAsset OnRequestAsset;
public event UUIDNameRequest OnNameFromUUIDRequest;