From 65862aaceadc69218895e07b5d547266b12916a9 Mon Sep 17 00:00:00 2001
From: Justin Clarke Casey
Date: Mon, 25 Feb 2008 23:26:35 +0000
Subject: * Start sending "ImageNotFound" packet back to the client if we can't
find an image * This might stop some client's constant requests for unfound
textures, which is a candidate for the memory leak * If a texture is not
found then the "Image not found" texture will now be displayed clientside *
If it works, this should resolve mantis 676 * Non texture image requests do
not receive this packet yet * This will require a prebuild
---
.../Environment/Interfaces/ITextureSender.cs | 61 ++++++++++++++++++
.../Environment/Modules/TextureDownloadModule.cs | 22 ++++---
.../Environment/Modules/TextureNotFoundSender.cs | 75 ++++++++++++++++++++++
.../Region/Environment/Modules/TextureSender.cs | 33 +++++++---
.../Modules/UserTextureDownloadService.cs | 35 ++++++----
5 files changed, 195 insertions(+), 31 deletions(-)
create mode 100644 OpenSim/Region/Environment/Interfaces/ITextureSender.cs
create mode 100644 OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs
(limited to 'OpenSim/Region/Environment')
diff --git a/OpenSim/Region/Environment/Interfaces/ITextureSender.cs b/OpenSim/Region/Environment/Interfaces/ITextureSender.cs
new file mode 100644
index 0000000..6ea08d0
--- /dev/null
+++ b/OpenSim/Region/Environment/Interfaces/ITextureSender.cs
@@ -0,0 +1,61 @@
+/*
+* Copyright (c) Contributors, http://opensimulator.org/
+* See CONTRIBUTORS.TXT for a full list of copyright holders.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of the OpenSim Project nor the
+* names of its contributors may be used to endorse or promote products
+* derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*/
+
+using System;
+
+namespace OpenSim.Region.Environment.Interfaces
+{
+ ///
+ /// Interface for an object which can send texture information to a client
+ ///
+ public interface ITextureSender
+ {
+ ///
+ /// Are we in the process of sending the texture?
+ ///
+ bool Sending { get; set; }
+
+ ///
+ /// Has the texture send been cancelled?
+ ///
+ bool Cancel { get; set; }
+
+ ///
+ /// Update the non data properties of a texture request
+ ///
+ ///
+ ///
+ void UpdateRequest(int discardLevel, uint packetNumber);
+
+ ///
+ /// Send a texture packet to the client.
+ ///
+ /// True if the last packet has been sent, false otherwise.
+ bool SendTexturePacket();
+ }
+}
diff --git a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
index c773f9e..2b2ac42 100644
--- a/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
+++ b/OpenSim/Region/Environment/Modules/TextureDownloadModule.cs
@@ -52,7 +52,8 @@ namespace OpenSim.Region.Environment.Modules
///
/// There is one queue for all textures waiting to be sent, regardless of the requesting user.
///
- private readonly BlockingQueue m_queueSenders = new BlockingQueue();
+ private readonly BlockingQueue m_queueSenders
+ = new BlockingQueue();
///
/// Each user has their own texture download service.
@@ -135,17 +136,19 @@ namespace OpenSim.Region.Environment.Modules
///
///
/// Always returns true, since a service is created if one does not already exist
- private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService)
+ private bool TryGetUserTextureService(
+ IClientAPI client, out UserTextureDownloadService textureService)
{
lock (m_userTextureServices)
{
- if (m_userTextureServices.TryGetValue(userID, out textureService))
+ if (m_userTextureServices.TryGetValue(client.AgentId, out textureService))
{
return true;
}
- textureService = new UserTextureDownloadService(m_scene, m_queueSenders);
- m_userTextureServices.Add(userID, textureService);
+ textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders);
+ m_userTextureServices.Add(client.AgentId, textureService);
+
return true;
}
}
@@ -159,9 +162,10 @@ namespace OpenSim.Region.Environment.Modules
{
IClientAPI client = (IClientAPI) sender;
UserTextureDownloadService textureService;
- if (TryGetUserTextureService(client.AgentId, out textureService))
+
+ if (TryGetUserTextureService(client, out textureService))
{
- textureService.HandleTextureRequest(client, e);
+ textureService.HandleTextureRequest(e);
}
}
@@ -170,7 +174,7 @@ namespace OpenSim.Region.Environment.Modules
///
public void ProcessTextureSenders()
{
- TextureSender sender = null;
+ ITextureSender sender = null;
while (true)
{
@@ -206,7 +210,7 @@ namespace OpenSim.Region.Environment.Modules
/// Called when the texture has finished sending.
///
///
- private void TextureSent(TextureSender sender)
+ private void TextureSent(ITextureSender sender)
{
sender.Sending = false;
//m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID);
diff --git a/OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs b/OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs
new file mode 100644
index 0000000..f85e900
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/TextureNotFoundSender.cs
@@ -0,0 +1,75 @@
+/*
+ * Created by SharpDevelop.
+ * User: caseyj
+ * Date: 25/02/2008
+ * Time: 21:30
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+
+using System;
+
+using libsecondlife;
+using libsecondlife.Packets;
+
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+
+namespace OpenSim.Region.Environment.Modules
+{
+ ///
+ /// Sends a 'texture not found' packet back to the client
+ ///
+ public class TextureNotFoundSender : ITextureSender
+ {
+ //private static readonly log4net.ILog m_log
+ // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+
+ private LLUUID m_textureId;
+ private IClientAPI m_client;
+
+ // See ITextureSender
+ public bool Sending
+ {
+ get { return false; }
+ set { m_sending = value; }
+ }
+
+ private bool m_sending = false;
+
+ // See ITextureSender
+ public bool Cancel
+ {
+ get { return false; }
+ set { m_cancel = value; }
+ }
+
+ private bool m_cancel = false;
+
+ public TextureNotFoundSender(IClientAPI client, LLUUID textureID)
+ {
+ m_client = client;
+ m_textureId = textureID;
+ }
+
+ // See ITextureSender
+ public void UpdateRequest(int discardLevel, uint packetNumber)
+ {
+ // Not need to implement since priority changes don't affect this operation
+ }
+
+ // See ITextureSender
+ public bool SendTexturePacket()
+ {
+ //m_log.InfoFormat(
+ // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found",
+ // m_textureId);
+
+ ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket();
+ notFound.ImageID.ID = m_textureId;
+ m_client.OutPacket(notFound, ThrottleOutPacketType.Unknown);
+
+ return true;
+ }
+ }
+}
diff --git a/OpenSim/Region/Environment/Modules/TextureSender.cs b/OpenSim/Region/Environment/Modules/TextureSender.cs
index 056b8e1..3d097c8 100644
--- a/OpenSim/Region/Environment/Modules/TextureSender.cs
+++ b/OpenSim/Region/Environment/Modules/TextureSender.cs
@@ -31,6 +31,7 @@ using libsecondlife;
using libsecondlife.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Console;
+using OpenSim.Region.Environment.Interfaces;
namespace OpenSim.Region.Environment.Modules
{
@@ -38,7 +39,7 @@ namespace OpenSim.Region.Environment.Modules
/// 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.
///
- public class TextureSender
+ public class TextureSender : ITextureSender
{
private static readonly log4net.ILog m_log
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@@ -67,9 +68,25 @@ namespace OpenSim.Region.Environment.Modules
///
private int PacketCounter = 0;
- public bool Cancel = false;
+ // See ITextureSender
+ public bool Cancel
+ {
+ get { return false; }
+ set { m_cancel = value; }
+ }
+
+ private bool m_cancel = false;
+
+ // See ITextureSender
+ public bool Sending
+ {
+ get { return false; }
+ set { m_sending = value; }
+ }
+
+ private bool m_sending = false;
+
public bool ImageLoaded = false;
- public bool Sending = false;
private IClientAPI RequestUser;
@@ -97,6 +114,7 @@ namespace OpenSim.Region.Environment.Modules
ImageLoaded = true;
}
+ // See ITextureSender
public void UpdateRequest(int discardLevel, uint packetNumber)
{
RequestedDiscardLevel = discardLevel;
@@ -104,12 +122,11 @@ namespace OpenSim.Region.Environment.Modules
PacketCounter = (int) StartPacketNumber;
}
- ///
- /// Send a texture packet to the client.
- ///
- /// True if the last packet has been sent, false otherwise.
+ // See ITextureSender
public bool SendTexturePacket()
{
+ //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID);
+
SendPacket();
counter++;
if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) ||
@@ -170,7 +187,7 @@ namespace OpenSim.Region.Environment.Modules
}
catch (ArgumentOutOfRangeException)
{
- m_log.Error("[TEXTURE]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
+ m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" +
m_asset.FullID.ToString() );
return;
}
diff --git a/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs
index 8987a19..77829f0 100644
--- a/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs
+++ b/OpenSim/Region/Environment/Modules/UserTextureDownloadService.cs
@@ -28,9 +28,13 @@
using System;
using System.Collections.Generic;
+
using libsecondlife;
+using libsecondlife.Packets;
+
using OpenSim.Framework;
using OpenSim.Framework.Console;
+using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes;
namespace OpenSim.Region.Environment.Modules
@@ -54,12 +58,16 @@ namespace OpenSim.Region.Environment.Modules
/// Texture Senders are placed in this queue once they have received their texture from the asset
/// cache. Another module actually invokes the send.
///
- private readonly BlockingQueue m_sharedSendersQueue;
+ private readonly BlockingQueue m_sharedSendersQueue;
private readonly Scene m_scene;
+
+ private readonly IClientAPI m_client;
- public UserTextureDownloadService(Scene scene, BlockingQueue sharedQueue)
+ public UserTextureDownloadService(
+ IClientAPI client, Scene scene, BlockingQueue sharedQueue)
{
+ m_client = client;
m_scene = scene;
m_sharedSendersQueue = sharedQueue;
}
@@ -68,9 +76,8 @@ namespace OpenSim.Region.Environment.Modules
/// Handle a texture request. This involves creating a texture sender and placing it on the
/// previously passed in shared queue.
///
- ///
///
- public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e)
+ public void HandleTextureRequest(TextureRequestArgs e)
{
TextureSender textureSender;
@@ -91,7 +98,7 @@ namespace OpenSim.Region.Environment.Modules
m_scene.AddPendingDownloads(1);
TextureSender requestHandler =
- new TextureSender(client, e.DiscardLevel, e.PacketNumber);
+ new TextureSender(m_client, e.DiscardLevel, e.PacketNumber);
m_textureSenders.Add(e.RequestedAssetID, requestHandler);
m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true);
@@ -118,6 +125,8 @@ namespace OpenSim.Region.Environment.Modules
///
public void TextureCallback(LLUUID textureID, AssetBase texture)
{
+ //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false));
+
lock (m_textureSenders)
{
TextureSender textureSender;
@@ -129,13 +138,12 @@ namespace OpenSim.Region.Environment.Modules
// Needs investigation.
if (texture == null || texture.Data == null)
{
- // Right now, leaving it up to lower level asset server code to post the fact that
- // this texture could not be found
-
- // TODO Send packet back to the client telling it not to expect the texture
-
- //m_log.DebugFormat("[USER TEXTURE DOWNLOAD]: Removing download stat for {0}", textureID);
- m_scene.AddPendingDownloads(-1);
+ m_log.DebugFormat(
+ "[USER TEXTURE DOWNLOAD SERVICE]: Queueing TextureNotFoundSender for {0}",
+ textureID);
+
+ ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID);
+ EnqueueTextureSender(textureNotFoundSender);
}
else
{
@@ -163,11 +171,10 @@ namespace OpenSim.Region.Environment.Modules
/// Place a ready texture sender on the processing queue.
///
///
- private void EnqueueTextureSender(TextureSender textureSender)
+ private void EnqueueTextureSender(ITextureSender textureSender)
{
textureSender.Cancel = false;
textureSender.Sending = true;
- textureSender.counter = 0;
if (!m_sharedSendersQueue.Contains(textureSender))
{
--
cgit v1.1