* Add documentation
* The reason why pending downloads tick ever upwards is because missing assets are never signalled to the TextureSender * Rectifying this is not straightfoward, but this will constitute the next patch. * This does not explain the memory leak.ThreadPoolClientBranch
parent
9a8c19d67b
commit
48e085c774
|
@ -49,8 +49,14 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private List<Scene> m_scenes = new List<Scene>();
|
private List<Scene> m_scenes = new List<Scene>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// There is one queue for all textures waiting to be sent, regardless of the requesting user.
|
||||||
|
/// </summary>
|
||||||
private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>();
|
private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each user has their own texture download queue.
|
||||||
|
/// </summary>
|
||||||
private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
|
private readonly Dictionary<LLUUID, UserTextureDownloadService> m_userTextureServices =
|
||||||
new Dictionary<LLUUID, UserTextureDownloadService>();
|
new Dictionary<LLUUID, UserTextureDownloadService>();
|
||||||
|
|
||||||
|
@ -80,6 +86,10 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cleanup the texture service related objects for the removed presence.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="agentId"> </param>
|
||||||
private void EventManager_OnRemovePresence(LLUUID agentId)
|
private void EventManager_OnRemovePresence(LLUUID agentId)
|
||||||
{
|
{
|
||||||
UserTextureDownloadService textureService;
|
UserTextureDownloadService textureService;
|
||||||
|
@ -118,6 +128,12 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
client.OnRequestTexture += TextureRequest;
|
client.OnRequestTexture += TextureRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Does this user have a registered texture download service?
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userID"></param>
|
||||||
|
/// <param name="textureService"></param>
|
||||||
|
/// <returns>Always returns true, since a service is created if one does not already exist</returns>
|
||||||
private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService)
|
private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService)
|
||||||
{
|
{
|
||||||
lock (m_userTextureServices)
|
lock (m_userTextureServices)
|
||||||
|
@ -133,6 +149,11 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start the process of requesting a given texture.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"> </param>
|
||||||
|
/// <param name="e"></param>
|
||||||
public void TextureRequest(Object sender, TextureRequestArgs e)
|
public void TextureRequest(Object sender, TextureRequestArgs e)
|
||||||
{
|
{
|
||||||
IClientAPI client = (IClientAPI) sender;
|
IClientAPI client = (IClientAPI) sender;
|
||||||
|
@ -142,9 +163,11 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
textureService.HandleTextureRequest(client, e);
|
textureService.HandleTextureRequest(client, e);
|
||||||
m_scene.AddPendingDownloads(1);
|
m_scene.AddPendingDownloads(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Entry point for the thread dedicated to processing the texture queue.
|
||||||
|
/// </summary>
|
||||||
public void ProcessTextureSenders()
|
public void ProcessTextureSenders()
|
||||||
{
|
{
|
||||||
TextureSender sender = null;
|
TextureSender sender = null;
|
||||||
|
@ -179,11 +202,14 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the texture has finished sending.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
private void TextureSent(TextureSender sender)
|
private void TextureSent(TextureSender sender)
|
||||||
{
|
{
|
||||||
sender.Sending = false;
|
sender.Sending = false;
|
||||||
m_scene.AddPendingDownloads(-1);
|
m_scene.AddPendingDownloads(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,36 +34,59 @@ using OpenSim.Framework.Console;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A TextureSender handles the process of receiving a texture requested by the client from the
|
||||||
|
/// AssetCache, and then sending that texture back to the client.
|
||||||
|
/// </summary>
|
||||||
public class TextureSender
|
public class TextureSender
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog m_log
|
private static readonly log4net.ILog m_log
|
||||||
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Records the number of times texture send has been called.
|
||||||
|
/// </summary>
|
||||||
public int counter = 0;
|
public int counter = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds the texture asset to send.
|
||||||
|
/// </summary>
|
||||||
private AssetBase m_asset;
|
private AssetBase m_asset;
|
||||||
public long DataPointer = 0;
|
|
||||||
public int NumPackets = 0;
|
/// <summary>
|
||||||
public int PacketCounter = 0;
|
/// This is actually the number of extra packets required to send the texture data! We always assume
|
||||||
|
/// at least one is required.
|
||||||
|
/// </summary>
|
||||||
|
private int NumPackets = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds the packet number to send next. In this case, each packet is 1000 bytes long and starts
|
||||||
|
/// at the 600th byte (0th indexed).
|
||||||
|
/// </summary>
|
||||||
|
private int PacketCounter = 0;
|
||||||
|
|
||||||
public bool Cancel = false;
|
public bool Cancel = false;
|
||||||
public bool ImageLoaded = false;
|
public bool ImageLoaded = false;
|
||||||
|
|
||||||
public bool Sending = false;
|
public bool Sending = false;
|
||||||
|
|
||||||
public IClientAPI RequestUser;
|
private IClientAPI RequestUser;
|
||||||
public LLUUID RequestedAssetID;
|
|
||||||
public int RequestedDiscardLevel = -1;
|
|
||||||
public uint StartPacketNumber = 0;
|
|
||||||
|
|
||||||
// private int m_sentDiscardLevel = -1;
|
private int RequestedDiscardLevel = -1;
|
||||||
|
private uint StartPacketNumber = 0;
|
||||||
|
|
||||||
public TextureSender(IClientAPI client, LLUUID textureID, int discardLevel, uint packetNumber)
|
public TextureSender(IClientAPI client, int discardLevel, uint packetNumber)
|
||||||
{
|
{
|
||||||
RequestUser = client;
|
RequestUser = client;
|
||||||
RequestedAssetID = textureID;
|
|
||||||
RequestedDiscardLevel = discardLevel;
|
RequestedDiscardLevel = discardLevel;
|
||||||
StartPacketNumber = packetNumber;
|
StartPacketNumber = packetNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load up the texture data to send.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">
|
||||||
|
/// A <see cref="AssetBase"/>
|
||||||
|
/// </param>
|
||||||
public void TextureReceived(AssetBase asset)
|
public void TextureReceived(AssetBase asset)
|
||||||
{
|
{
|
||||||
m_asset = asset;
|
m_asset = asset;
|
||||||
|
@ -79,6 +102,10 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
PacketCounter = (int) StartPacketNumber;
|
PacketCounter = (int) StartPacketNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a texture packet to the client.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the last packet has been sent, false otherwise.</returns>
|
||||||
public bool SendTexturePacket()
|
public bool SendTexturePacket()
|
||||||
{
|
{
|
||||||
SendPacket();
|
SendPacket();
|
||||||
|
@ -91,6 +118,9 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a texture packet to the client.
|
||||||
|
/// </summary>
|
||||||
private void SendPacket()
|
private void SendPacket()
|
||||||
{
|
{
|
||||||
if (PacketCounter <= NumPackets)
|
if (PacketCounter <= NumPackets)
|
||||||
|
@ -148,6 +178,12 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the number of packets that will be required to send the texture loaded into this sender
|
||||||
|
/// This is actually the number of 1000 byte packets not including an initial 600 byte packet...
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length"></param>
|
||||||
|
/// <returns></returns>
|
||||||
private int CalculateNumPackets(int length)
|
private int CalculateNumPackets(int length)
|
||||||
{
|
{
|
||||||
int numPackets = 0;
|
int numPackets = 0;
|
||||||
|
|
|
@ -35,13 +35,27 @@ using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
namespace OpenSim.Region.Environment.Modules
|
namespace OpenSim.Region.Environment.Modules
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This module sets up texture senders in response to client texture requests, and places them on a
|
||||||
|
/// processing queue once those senders have the appropriate data (i.e. a texture retrieved from the
|
||||||
|
/// asset cache).
|
||||||
|
/// </summary>
|
||||||
public class UserTextureDownloadService
|
public class UserTextureDownloadService
|
||||||
{
|
{
|
||||||
private static readonly log4net.ILog m_log
|
private static readonly log4net.ILog m_log
|
||||||
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Holds texture senders before they have received the appropriate texture from the asset cache.
|
||||||
|
/// </summary>
|
||||||
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
private readonly Dictionary<LLUUID, TextureSender> m_textureSenders = new Dictionary<LLUUID, TextureSender>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture Senders are placed in this queue once they have received their texture from the asset
|
||||||
|
/// cache. Another module actually invokes the send.
|
||||||
|
/// </summary>
|
||||||
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
private readonly BlockingQueue<TextureSender> m_sharedSendersQueue;
|
||||||
|
|
||||||
private readonly Scene m_scene;
|
private readonly Scene m_scene;
|
||||||
|
|
||||||
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
|
public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue)
|
||||||
|
@ -50,6 +64,12 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
m_sharedSendersQueue = sharedQueue;
|
m_sharedSendersQueue = sharedQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle a texture request. This involves creating a texture sender and placing it on the
|
||||||
|
/// previously passed in shared queue.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"> </param>
|
||||||
|
/// <param name="e"></param>
|
||||||
public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
|
public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
|
||||||
{
|
{
|
||||||
TextureSender textureSender;
|
TextureSender textureSender;
|
||||||
|
@ -72,8 +92,9 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextureSender requestHandler =
|
TextureSender requestHandler =
|
||||||
new TextureSender(client, e.RequestedAssetID, e.DiscardLevel, e.PacketNumber);
|
new TextureSender(client, e.DiscardLevel, e.PacketNumber);
|
||||||
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
|
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
|
||||||
|
|
||||||
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
|
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +111,12 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The callback for the asset cache when a texture has been retrieved. This method queues the
|
||||||
|
/// texture sender for processing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textureID"></param>
|
||||||
|
/// <param name="asset"></param>
|
||||||
public void TextureCallback(LLUUID textureID, AssetBase asset)
|
public void TextureCallback(LLUUID textureID, AssetBase asset)
|
||||||
{
|
{
|
||||||
lock (m_textureSenders)
|
lock (m_textureSenders)
|
||||||
|
@ -115,6 +142,10 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Place a ready texture sender on the processing queue.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textureSender"></param>
|
||||||
private void EnqueueTextureSender(TextureSender textureSender)
|
private void EnqueueTextureSender(TextureSender textureSender)
|
||||||
{
|
{
|
||||||
textureSender.Cancel = false;
|
textureSender.Cancel = false;
|
||||||
|
@ -127,6 +158,9 @@ namespace OpenSim.Region.Environment.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close this module.
|
||||||
|
/// </summary>
|
||||||
internal void Close()
|
internal void Close()
|
||||||
{
|
{
|
||||||
lock (m_textureSenders)
|
lock (m_textureSenders)
|
||||||
|
|
Loading…
Reference in New Issue