From d51ce47b2d7635b17f3dd429158e8f59b78b83aa Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Thu, 1 May 2008 14:31:30 +0000 Subject: Update svn properties. Minor formatting cleanup. --- .../Agent/TextureDownload/TextureDownloadModule.cs | 436 +++++++++--------- .../Agent/TextureDownload/TextureNotFoundSender.cs | 194 ++++---- .../TextureDownload/UserTextureDownloadService.cs | 496 ++++++++++----------- 3 files changed, 563 insertions(+), 563 deletions(-) (limited to 'OpenSim/Region/Environment/Modules/Agent/TextureDownload') diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs index ae2df69..474ac75 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureDownloadModule.cs @@ -1,219 +1,219 @@ -/* - * 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; -using System.Collections.Generic; -using System.Threading; -using libsecondlife; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload -{ - public class TextureDownloadModule : IRegionModule - { - //private static readonly log4net.ILog m_log - // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// There is one queue for all textures waiting to be sent, regardless of the requesting user. - /// - private readonly BlockingQueue m_queueSenders - = new BlockingQueue(); - - /// - /// Each user has their own texture download service. - /// - private readonly Dictionary m_userTextureServices = - new Dictionary(); - - private Scene m_scene; - private List m_scenes = new List(); - - private Thread m_thread; - - public TextureDownloadModule() - { - } - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - if (m_scene == null) - { - //Console.WriteLine("Creating Texture download module"); - m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); - m_thread.Name = "ProcessTextureSenderThread"; - m_thread.IsBackground = true; - m_thread.Start(); - ThreadTracker.Add(m_thread); - } - - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - m_scene = scene; - m_scene.EventManager.OnNewClient += NewClient; - m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence; - } - } - - public void PostInitialise() - { - } - - public void Close() - { - } - - public string Name - { - get { return "TextureDownloadModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - /// - /// Cleanup the texture service related objects for the removed presence. - /// - /// - private void EventManager_OnRemovePresence(LLUUID agentId) - { - UserTextureDownloadService textureService; - - lock (m_userTextureServices) - { - if (m_userTextureServices.TryGetValue(agentId, out textureService)) - { - textureService.Close(); - - m_userTextureServices.Remove(agentId); - } - } - } - - public void NewClient(IClientAPI client) - { - client.OnRequestTexture += TextureRequest; - } - - /// - /// Does this user have a registered texture download service? - /// - /// - /// - /// Always returns true, since a service is created if one does not already exist - private bool TryGetUserTextureService( - IClientAPI client, out UserTextureDownloadService textureService) - { - lock (m_userTextureServices) - { - if (m_userTextureServices.TryGetValue(client.AgentId, out textureService)) - { - return true; - } - - textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders); - m_userTextureServices.Add(client.AgentId, textureService); - - return true; - } - } - - /// - /// Start the process of requesting a given texture. - /// - /// - /// - public void TextureRequest(Object sender, TextureRequestArgs e) - { - IClientAPI client = (IClientAPI) sender; - UserTextureDownloadService textureService; - - if (TryGetUserTextureService(client, out textureService)) - { - textureService.HandleTextureRequest(e); - } - } - - /// - /// Entry point for the thread dedicated to processing the texture queue. - /// - public void ProcessTextureSenders() - { - ITextureSender sender = null; - - while (true) - { - sender = m_queueSenders.Dequeue(); - - if (sender.Cancel) - { - TextureSent(sender); - - sender.Cancel = false; - } - else - { - bool finished = sender.SendTexturePacket(); - if (finished) - { - TextureSent(sender); - } - else - { - m_queueSenders.Enqueue(sender); - } - } - - // Make sure that any sender we currently have can get garbage collected - sender = null; - - //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count()); - } - } - - /// - /// Called when the texture has finished sending. - /// - /// - private void TextureSent(ITextureSender sender) - { - sender.Sending = false; - //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID); - m_scene.AddPendingDownloads(-1); - } - } +/* + * 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; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload +{ + public class TextureDownloadModule : IRegionModule + { + //private static readonly log4net.ILog m_log + // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// There is one queue for all textures waiting to be sent, regardless of the requesting user. + /// + private readonly BlockingQueue m_queueSenders + = new BlockingQueue(); + + /// + /// Each user has their own texture download service. + /// + private readonly Dictionary m_userTextureServices = + new Dictionary(); + + private Scene m_scene; + private List m_scenes = new List(); + + private Thread m_thread; + + public TextureDownloadModule() + { + } + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + if (m_scene == null) + { + //Console.WriteLine("Creating Texture download module"); + m_thread = new Thread(new ThreadStart(ProcessTextureSenders)); + m_thread.Name = "ProcessTextureSenderThread"; + m_thread.IsBackground = true; + m_thread.Start(); + ThreadTracker.Add(m_thread); + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + m_scene = scene; + m_scene.EventManager.OnNewClient += NewClient; + m_scene.EventManager.OnRemovePresence += EventManager_OnRemovePresence; + } + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "TextureDownloadModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + /// + /// Cleanup the texture service related objects for the removed presence. + /// + /// + private void EventManager_OnRemovePresence(LLUUID agentId) + { + UserTextureDownloadService textureService; + + lock (m_userTextureServices) + { + if (m_userTextureServices.TryGetValue(agentId, out textureService)) + { + textureService.Close(); + + m_userTextureServices.Remove(agentId); + } + } + } + + public void NewClient(IClientAPI client) + { + client.OnRequestTexture += TextureRequest; + } + + /// + /// Does this user have a registered texture download service? + /// + /// + /// + /// Always returns true, since a service is created if one does not already exist + private bool TryGetUserTextureService( + IClientAPI client, out UserTextureDownloadService textureService) + { + lock (m_userTextureServices) + { + if (m_userTextureServices.TryGetValue(client.AgentId, out textureService)) + { + return true; + } + + textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders); + m_userTextureServices.Add(client.AgentId, textureService); + + return true; + } + } + + /// + /// Start the process of requesting a given texture. + /// + /// + /// + public void TextureRequest(Object sender, TextureRequestArgs e) + { + IClientAPI client = (IClientAPI) sender; + UserTextureDownloadService textureService; + + if (TryGetUserTextureService(client, out textureService)) + { + textureService.HandleTextureRequest(e); + } + } + + /// + /// Entry point for the thread dedicated to processing the texture queue. + /// + public void ProcessTextureSenders() + { + ITextureSender sender = null; + + while (true) + { + sender = m_queueSenders.Dequeue(); + + if (sender.Cancel) + { + TextureSent(sender); + + sender.Cancel = false; + } + else + { + bool finished = sender.SendTexturePacket(); + if (finished) + { + TextureSent(sender); + } + else + { + m_queueSenders.Enqueue(sender); + } + } + + // Make sure that any sender we currently have can get garbage collected + sender = null; + + //m_log.InfoFormat("[TEXTURE DOWNLOAD] Texture sender queue size: {0}", m_queueSenders.Count()); + } + } + + /// + /// Called when the texture has finished sending. + /// + /// + private void TextureSent(ITextureSender sender) + { + sender.Sending = false; + //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID); + m_scene.AddPendingDownloads(-1); + } + } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs index b181d20..70e44d4 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/TextureNotFoundSender.cs @@ -1,98 +1,98 @@ -/* - * 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 libsecondlife; -using libsecondlife.Packets; -using OpenSim.Framework; -using OpenSim.Region.Environment.Interfaces; - -namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload -{ - /// - /// 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 bool m_cancel = false; - private IClientAPI m_client; - - // See ITextureSender - - private bool m_sending = false; - private LLUUID m_textureId; - - // See ITextureSender - - public TextureNotFoundSender(IClientAPI client, LLUUID textureID) - { - m_client = client; - m_textureId = textureID; - } - - #region ITextureSender Members - - public bool Sending - { - get { return false; } - set { m_sending = value; } - } - - public bool Cancel - { - get { return false; } - set { m_cancel = value; } - } - - // 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; - - // XXX Temporarily disabling as this appears to be causing client crashes on at least - // 1.19.0(5) of the Linden Second Life client. - // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture); - - return true; - } - - #endregion - } +/* + * 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 libsecondlife; +using libsecondlife.Packets; +using OpenSim.Framework; +using OpenSim.Region.Environment.Interfaces; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload +{ + /// + /// 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 bool m_cancel = false; + private IClientAPI m_client; + + // See ITextureSender + + private bool m_sending = false; + private LLUUID m_textureId; + + // See ITextureSender + + public TextureNotFoundSender(IClientAPI client, LLUUID textureID) + { + m_client = client; + m_textureId = textureID; + } + + #region ITextureSender Members + + public bool Sending + { + get { return false; } + set { m_sending = value; } + } + + public bool Cancel + { + get { return false; } + set { m_cancel = value; } + } + + // 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; + + // XXX Temporarily disabling as this appears to be causing client crashes on at least + // 1.19.0(5) of the Linden Second Life client. + // m_client.OutPacket(notFound, ThrottleOutPacketType.Texture); + + return true; + } + + #endregion + } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs index 4f63fd0..a450cdc 100644 --- a/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs +++ b/OpenSim/Region/Environment/Modules/Agent/TextureDownload/UserTextureDownloadService.cs @@ -1,249 +1,249 @@ -/* - * 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.Collections.Generic; -using System.Reflection; -using libsecondlife; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Limit; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload -{ - /// - /// 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). - /// - public class UserTextureDownloadService - { - private static readonly ILog m_log - = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// We will allow the client to request the same texture n times before dropping further requests - /// - /// This number includes repeated requests for the same texture at different resolutions (which we don't - /// currently handle properly as far as I know). However, this situation should be handled in a more - /// sophisticated way. - /// - private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5; - - /// - /// XXX Also going to limit requests for found textures. - /// - private readonly IRequestLimitStrategy foundTextureLimitStrategy - = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); - - private readonly IClientAPI m_client; - private readonly Scene m_scene; - - /// - /// 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; - - /// - /// Holds texture senders before they have received the appropriate texture from the asset cache. - /// - private readonly Dictionary m_textureSenders = new Dictionary(); - - /// - /// We're going to limit requests for the same missing texture. - /// XXX This is really a temporary solution to deal with the situation where a client continually requests - /// the same missing textures - /// - private readonly IRequestLimitStrategy missingTextureLimitStrategy - = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); - - public UserTextureDownloadService( - IClientAPI client, Scene scene, BlockingQueue sharedQueue) - { - m_client = client; - m_scene = scene; - m_sharedSendersQueue = sharedQueue; - } - - /// - /// Handle a texture request. This involves creating a texture sender and placing it on the - /// previously passed in shared queue. - /// - /// - public void HandleTextureRequest(TextureRequestArgs e) - { - TextureSender.TextureSender textureSender; - - //TODO: should be working out the data size/ number of packets to be sent for each discard level - if ((e.DiscardLevel >= 0) || (e.Priority != 0)) - { - lock (m_textureSenders) - { - if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) - { - // If we've received new non UUID information for this request and it hasn't dispatched - // yet, then update the request accordingly. - textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); - } - else - { - if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) - { -// m_log.DebugFormat( -// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}", -// e.RequestedAssetID, m_client.AgentId); - - return; - } - else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) - { - if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID)) - { - // Commenting out this message for now as it causes too much noise with other - // debug messages. - // TODO: possibly record this as a statistic in the future - // -// m_log.DebugFormat( -// "[USER TEXTURE DOWNLOAD SERVICE]: Dropping requests for notified missing texture {0} for client {1} since we have received more than {2} requests", -// e.RequestedAssetID, m_client.AgentId, MAX_ALLOWED_TEXTURE_REQUESTS); - } - - return; - } - - m_scene.AddPendingDownloads(1); - - TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber); - m_textureSenders.Add(e.RequestedAssetID, requestHandler); - - m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); - } - } - } - else - { - lock (m_textureSenders) - { - if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) - { - textureSender.Cancel = true; - } - } - } - } - - /// - /// The callback for the asset cache when a texture has been retrieved. This method queues the - /// texture sender for processing. - /// - /// - /// - 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 textureSender; - - if (m_textureSenders.TryGetValue(textureID, out textureSender)) - { - // XXX It may be perfectly valid for a texture to have no data... but if we pass - // this on to the TextureSender it will blow up, so just discard for now. - // Needs investigation. - if (texture == null || texture.Data == null) - { - if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID)) - { - missingTextureLimitStrategy.MonitorRequests(textureID); - - m_log.DebugFormat( - "[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}", - textureID, m_client.AgentId); - } - - ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID); - EnqueueTextureSender(textureNotFoundSender); - } - else - { - if (!textureSender.ImageLoaded) - { - textureSender.TextureReceived(texture); - EnqueueTextureSender(textureSender); - - foundTextureLimitStrategy.MonitorRequests(textureID); - } - } - - //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID); - m_textureSenders.Remove(textureID); - //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count); - } - else - { - m_log.WarnFormat( - "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen", - textureID); - } - } - } - - /// - /// Place a ready texture sender on the processing queue. - /// - /// - private void EnqueueTextureSender(ITextureSender textureSender) - { - textureSender.Cancel = false; - textureSender.Sending = true; - - if (!m_sharedSendersQueue.Contains(textureSender)) - { - m_sharedSendersQueue.Enqueue(textureSender); - } - } - - /// - /// Close this module. - /// - internal void Close() - { - lock (m_textureSenders) - { - foreach (TextureSender.TextureSender textureSender in m_textureSenders.Values) - { - textureSender.Cancel = true; - } - - m_textureSenders.Clear(); - } - } - } +/* + * 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.Collections.Generic; +using System.Reflection; +using libsecondlife; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Limit; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +namespace OpenSim.Region.Environment.Modules.Agent.TextureDownload +{ + /// + /// 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). + /// + public class UserTextureDownloadService + { + private static readonly ILog m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// We will allow the client to request the same texture n times before dropping further requests + /// + /// This number includes repeated requests for the same texture at different resolutions (which we don't + /// currently handle properly as far as I know). However, this situation should be handled in a more + /// sophisticated way. + /// + private static readonly int MAX_ALLOWED_TEXTURE_REQUESTS = 5; + + /// + /// XXX Also going to limit requests for found textures. + /// + private readonly IRequestLimitStrategy foundTextureLimitStrategy + = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); + + private readonly IClientAPI m_client; + private readonly Scene m_scene; + + /// + /// 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; + + /// + /// Holds texture senders before they have received the appropriate texture from the asset cache. + /// + private readonly Dictionary m_textureSenders = new Dictionary(); + + /// + /// We're going to limit requests for the same missing texture. + /// XXX This is really a temporary solution to deal with the situation where a client continually requests + /// the same missing textures + /// + private readonly IRequestLimitStrategy missingTextureLimitStrategy + = new RepeatLimitStrategy(MAX_ALLOWED_TEXTURE_REQUESTS); + + public UserTextureDownloadService( + IClientAPI client, Scene scene, BlockingQueue sharedQueue) + { + m_client = client; + m_scene = scene; + m_sharedSendersQueue = sharedQueue; + } + + /// + /// Handle a texture request. This involves creating a texture sender and placing it on the + /// previously passed in shared queue. + /// + /// + public void HandleTextureRequest(TextureRequestArgs e) + { + TextureSender.TextureSender textureSender; + + //TODO: should be working out the data size/ number of packets to be sent for each discard level + if ((e.DiscardLevel >= 0) || (e.Priority != 0)) + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + // If we've received new non UUID information for this request and it hasn't dispatched + // yet, then update the request accordingly. + textureSender.UpdateRequest(e.DiscardLevel, e.PacketNumber); + } + else + { + if (!foundTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) + { +// m_log.DebugFormat( +// "[USER TEXTURE DOWNLOAD SERVICE]: Refusing request for {0} from client {1}", +// e.RequestedAssetID, m_client.AgentId); + + return; + } + else if (!missingTextureLimitStrategy.AllowRequest(e.RequestedAssetID)) + { + if (missingTextureLimitStrategy.IsFirstRefusal(e.RequestedAssetID)) + { + // Commenting out this message for now as it causes too much noise with other + // debug messages. + // TODO: possibly record this as a statistic in the future + // +// m_log.DebugFormat( +// "[USER TEXTURE DOWNLOAD SERVICE]: Dropping requests for notified missing texture {0} for client {1} since we have received more than {2} requests", +// e.RequestedAssetID, m_client.AgentId, MAX_ALLOWED_TEXTURE_REQUESTS); + } + + return; + } + + m_scene.AddPendingDownloads(1); + + TextureSender.TextureSender requestHandler = new TextureSender.TextureSender(m_client, e.DiscardLevel, e.PacketNumber); + m_textureSenders.Add(e.RequestedAssetID, requestHandler); + + m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); + } + } + } + else + { + lock (m_textureSenders) + { + if (m_textureSenders.TryGetValue(e.RequestedAssetID, out textureSender)) + { + textureSender.Cancel = true; + } + } + } + } + + /// + /// The callback for the asset cache when a texture has been retrieved. This method queues the + /// texture sender for processing. + /// + /// + /// + 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 textureSender; + + if (m_textureSenders.TryGetValue(textureID, out textureSender)) + { + // XXX It may be perfectly valid for a texture to have no data... but if we pass + // this on to the TextureSender it will blow up, so just discard for now. + // Needs investigation. + if (texture == null || texture.Data == null) + { + if (!missingTextureLimitStrategy.IsMonitoringRequests(textureID)) + { + missingTextureLimitStrategy.MonitorRequests(textureID); + + m_log.DebugFormat( + "[USER TEXTURE DOWNLOAD SERVICE]: Queueing first TextureNotFoundSender for {0}, client {1}", + textureID, m_client.AgentId); + } + + ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID); + EnqueueTextureSender(textureNotFoundSender); + } + else + { + if (!textureSender.ImageLoaded) + { + textureSender.TextureReceived(texture); + EnqueueTextureSender(textureSender); + + foundTextureLimitStrategy.MonitorRequests(textureID); + } + } + + //m_log.InfoFormat("[TEXTURE SENDER] Removing texture sender with uuid {0}", textureID); + m_textureSenders.Remove(textureID); + //m_log.InfoFormat("[TEXTURE SENDER] Current texture senders in dictionary: {0}", m_textureSenders.Count); + } + else + { + m_log.WarnFormat( + "Got a texture uuid {0} with no sender object to handle it, this shouldn't happen", + textureID); + } + } + } + + /// + /// Place a ready texture sender on the processing queue. + /// + /// + private void EnqueueTextureSender(ITextureSender textureSender) + { + textureSender.Cancel = false; + textureSender.Sending = true; + + if (!m_sharedSendersQueue.Contains(textureSender)) + { + m_sharedSendersQueue.Enqueue(textureSender); + } + } + + /// + /// Close this module. + /// + internal void Close() + { + lock (m_textureSenders) + { + foreach (TextureSender.TextureSender textureSender in m_textureSenders.Values) + { + textureSender.Cancel = true; + } + + m_textureSenders.Clear(); + } + } + } } \ No newline at end of file -- cgit v1.1