diff --git a/OpenSim/Framework/Communications/Cache/AssetCache.cs b/OpenSim/Framework/Communications/Cache/AssetCache.cs index e3a4eb8193..d04708dc0f 100644 --- a/OpenSim/Framework/Communications/Cache/AssetCache.cs +++ b/OpenSim/Framework/Communications/Cache/AssetCache.cs @@ -242,6 +242,10 @@ namespace OpenSim.Framework.Communications.Cache /// If the asset was not found this is still called with the asset UUID but with a null asset data reference public void GetAsset(LLUUID assetId, AssetRequestCallback callback, bool isTexture) { + #if DEBUG + //m_log.DebugFormat("[ASSET CACHE]: Requesting {0} {1}", isTexture ? "texture" : "asset", assetId); + #endif + AssetBase asset; if (TryGetCachedAsset(assetId, out asset)) @@ -249,11 +253,11 @@ namespace OpenSim.Framework.Communications.Cache callback(assetId, asset); } else - { + { #if DEBUG //m_log.DebugFormat("[ASSET CACHE]: Adding request for {0} {1}", isTexture ? "texture" : "asset", assetId); #endif - + NewAssetRequest req = new NewAssetRequest(assetId, callback); // Make sure we always have a request list to which to add the asset @@ -395,7 +399,7 @@ namespace OpenSim.Framework.Communications.Cache public void AssetReceived(AssetBase asset, bool IsTexture) { #if DEBUG - m_log.DebugFormat("[ASSET CACHE]: Received {0} [{1}]", IsTexture ? "texture" : "asset", asset.FullID); + //m_log.DebugFormat("[ASSET CACHE]: Received {0} [{1}]", IsTexture ? "texture" : "asset", asset.FullID); #endif if (asset.FullID != LLUUID.Zero) // if it is set to zero then the asset wasn't found by the server @@ -479,27 +483,7 @@ namespace OpenSim.Framework.Communications.Cache // See IAssetReceiver public void AssetNotFound(LLUUID assetID) { - //m_log.ErrorFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID); - - // The 'image not found' packet needs to happen, but RequestedTextures is not actually used (should be cleaned up) - // It might also be better to do this in the TextureDownloadModule - /* - * - AssetRequest req; - - if (RequestedTextures.TryGetValue(assetID, out req)) - { - m_log.WarnFormat("[ASSET CACHE]: sending image not found for {0}", assetID); - ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); - notFound.ImageID.ID = assetID; - req.RequestUser.OutPacket(notFound, ThrottleOutPacketType.Unknown); - RequestedTextures.Remove(assetID); - } - else - { - m_log.ErrorFormat("[ASSET CACHE]: Asset [{0}] not found, but couldn't find any users to send to ", assetID); - } - */ + m_log.WarnFormat("[ASSET CACHE]: AssetNotFound for {0}", assetID); // Notify requesters for this asset lock (RequestLists) diff --git a/OpenSim/Region/Environment/Interfaces/ITextureSender.cs b/OpenSim/Region/Environment/Interfaces/ITextureSender.cs new file mode 100644 index 0000000000..6ea08d037c --- /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 c773f9ea2e..2b2ac42ee1 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 0000000000..f85e900f73 --- /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 056b8e1dce..3d097c8210 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 8987a19643..77829f0849 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)) {