diff options
author | Justin Clarke Casey | 2008-02-25 23:26:35 +0000 |
---|---|---|
committer | Justin Clarke Casey | 2008-02-25 23:26:35 +0000 |
commit | 65862aaceadc69218895e07b5d547266b12916a9 (patch) | |
tree | 67449a6fe51b5c86cc14e75a41589cbaa2c5be5b /OpenSim/Region | |
parent | Moved AsyncCommandManager into separate classes under "plugins". (diff) | |
download | opensim-SC-65862aaceadc69218895e07b5d547266b12916a9.zip opensim-SC-65862aaceadc69218895e07b5d547266b12916a9.tar.gz opensim-SC-65862aaceadc69218895e07b5d547266b12916a9.tar.bz2 opensim-SC-65862aaceadc69218895e07b5d547266b12916a9.tar.xz |
* 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
Diffstat (limited to 'OpenSim/Region')
5 files changed, 195 insertions, 31 deletions
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 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | using System; | ||
30 | |||
31 | namespace OpenSim.Region.Environment.Interfaces | ||
32 | { | ||
33 | /// <summary> | ||
34 | /// Interface for an object which can send texture information to a client | ||
35 | /// </summary> | ||
36 | public interface ITextureSender | ||
37 | { | ||
38 | /// <summary> | ||
39 | /// Are we in the process of sending the texture? | ||
40 | /// </summary> | ||
41 | bool Sending { get; set; } | ||
42 | |||
43 | /// <summary> | ||
44 | /// Has the texture send been cancelled? | ||
45 | /// </summary> | ||
46 | bool Cancel { get; set; } | ||
47 | |||
48 | /// <summary> | ||
49 | /// Update the non data properties of a texture request | ||
50 | /// </summary> | ||
51 | /// <param name="discardLevel"></param> | ||
52 | /// <param name="packetNumber"></param> | ||
53 | void UpdateRequest(int discardLevel, uint packetNumber); | ||
54 | |||
55 | /// <summary> | ||
56 | /// Send a texture packet to the client. | ||
57 | /// </summary> | ||
58 | /// <returns>True if the last packet has been sent, false otherwise.</returns> | ||
59 | bool SendTexturePacket(); | ||
60 | } | ||
61 | } | ||
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 | |||
52 | /// <summary> | 52 | /// <summary> |
53 | /// There is one queue for all textures waiting to be sent, regardless of the requesting user. | 53 | /// There is one queue for all textures waiting to be sent, regardless of the requesting user. |
54 | /// </summary> | 54 | /// </summary> |
55 | private readonly BlockingQueue<TextureSender> m_queueSenders = new BlockingQueue<TextureSender>(); | 55 | private readonly BlockingQueue<ITextureSender> m_queueSenders |
56 | = new BlockingQueue<ITextureSender>(); | ||
56 | 57 | ||
57 | /// <summary> | 58 | /// <summary> |
58 | /// Each user has their own texture download service. | 59 | /// Each user has their own texture download service. |
@@ -135,17 +136,19 @@ namespace OpenSim.Region.Environment.Modules | |||
135 | /// <param name="userID"></param> | 136 | /// <param name="userID"></param> |
136 | /// <param name="textureService"></param> | 137 | /// <param name="textureService"></param> |
137 | /// <returns>Always returns true, since a service is created if one does not already exist</returns> | 138 | /// <returns>Always returns true, since a service is created if one does not already exist</returns> |
138 | private bool TryGetUserTextureService(LLUUID userID, out UserTextureDownloadService textureService) | 139 | private bool TryGetUserTextureService( |
140 | IClientAPI client, out UserTextureDownloadService textureService) | ||
139 | { | 141 | { |
140 | lock (m_userTextureServices) | 142 | lock (m_userTextureServices) |
141 | { | 143 | { |
142 | if (m_userTextureServices.TryGetValue(userID, out textureService)) | 144 | if (m_userTextureServices.TryGetValue(client.AgentId, out textureService)) |
143 | { | 145 | { |
144 | return true; | 146 | return true; |
145 | } | 147 | } |
146 | 148 | ||
147 | textureService = new UserTextureDownloadService(m_scene, m_queueSenders); | 149 | textureService = new UserTextureDownloadService(client, m_scene, m_queueSenders); |
148 | m_userTextureServices.Add(userID, textureService); | 150 | m_userTextureServices.Add(client.AgentId, textureService); |
151 | |||
149 | return true; | 152 | return true; |
150 | } | 153 | } |
151 | } | 154 | } |
@@ -159,9 +162,10 @@ namespace OpenSim.Region.Environment.Modules | |||
159 | { | 162 | { |
160 | IClientAPI client = (IClientAPI) sender; | 163 | IClientAPI client = (IClientAPI) sender; |
161 | UserTextureDownloadService textureService; | 164 | UserTextureDownloadService textureService; |
162 | if (TryGetUserTextureService(client.AgentId, out textureService)) | 165 | |
166 | if (TryGetUserTextureService(client, out textureService)) | ||
163 | { | 167 | { |
164 | textureService.HandleTextureRequest(client, e); | 168 | textureService.HandleTextureRequest(e); |
165 | } | 169 | } |
166 | } | 170 | } |
167 | 171 | ||
@@ -170,7 +174,7 @@ namespace OpenSim.Region.Environment.Modules | |||
170 | /// </summary> | 174 | /// </summary> |
171 | public void ProcessTextureSenders() | 175 | public void ProcessTextureSenders() |
172 | { | 176 | { |
173 | TextureSender sender = null; | 177 | ITextureSender sender = null; |
174 | 178 | ||
175 | while (true) | 179 | while (true) |
176 | { | 180 | { |
@@ -206,7 +210,7 @@ namespace OpenSim.Region.Environment.Modules | |||
206 | /// Called when the texture has finished sending. | 210 | /// Called when the texture has finished sending. |
207 | /// </summary> | 211 | /// </summary> |
208 | /// <param name="sender"></param> | 212 | /// <param name="sender"></param> |
209 | private void TextureSent(TextureSender sender) | 213 | private void TextureSent(ITextureSender sender) |
210 | { | 214 | { |
211 | sender.Sending = false; | 215 | sender.Sending = false; |
212 | //m_log.DebugFormat("[TEXTURE DOWNLOAD]: Removing download stat for {0}", sender.assetID); | 216 | //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 @@ | |||
1 | /* | ||
2 | * Created by SharpDevelop. | ||
3 | * User: caseyj | ||
4 | * Date: 25/02/2008 | ||
5 | * Time: 21:30 | ||
6 | * | ||
7 | * To change this template use Tools | Options | Coding | Edit Standard Headers. | ||
8 | */ | ||
9 | |||
10 | using System; | ||
11 | |||
12 | using libsecondlife; | ||
13 | using libsecondlife.Packets; | ||
14 | |||
15 | using OpenSim.Framework; | ||
16 | using OpenSim.Region.Environment.Interfaces; | ||
17 | |||
18 | namespace OpenSim.Region.Environment.Modules | ||
19 | { | ||
20 | /// <summary> | ||
21 | /// Sends a 'texture not found' packet back to the client | ||
22 | /// </summary> | ||
23 | public class TextureNotFoundSender : ITextureSender | ||
24 | { | ||
25 | //private static readonly log4net.ILog m_log | ||
26 | // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
27 | |||
28 | private LLUUID m_textureId; | ||
29 | private IClientAPI m_client; | ||
30 | |||
31 | // See ITextureSender | ||
32 | public bool Sending | ||
33 | { | ||
34 | get { return false; } | ||
35 | set { m_sending = value; } | ||
36 | } | ||
37 | |||
38 | private bool m_sending = false; | ||
39 | |||
40 | // See ITextureSender | ||
41 | public bool Cancel | ||
42 | { | ||
43 | get { return false; } | ||
44 | set { m_cancel = value; } | ||
45 | } | ||
46 | |||
47 | private bool m_cancel = false; | ||
48 | |||
49 | public TextureNotFoundSender(IClientAPI client, LLUUID textureID) | ||
50 | { | ||
51 | m_client = client; | ||
52 | m_textureId = textureID; | ||
53 | } | ||
54 | |||
55 | // See ITextureSender | ||
56 | public void UpdateRequest(int discardLevel, uint packetNumber) | ||
57 | { | ||
58 | // Not need to implement since priority changes don't affect this operation | ||
59 | } | ||
60 | |||
61 | // See ITextureSender | ||
62 | public bool SendTexturePacket() | ||
63 | { | ||
64 | //m_log.InfoFormat( | ||
65 | // "[TEXTURE NOT FOUND SENDER]: Informing the client that texture {0} cannot be found", | ||
66 | // m_textureId); | ||
67 | |||
68 | ImageNotInDatabasePacket notFound = new ImageNotInDatabasePacket(); | ||
69 | notFound.ImageID.ID = m_textureId; | ||
70 | m_client.OutPacket(notFound, ThrottleOutPacketType.Unknown); | ||
71 | |||
72 | return true; | ||
73 | } | ||
74 | } | ||
75 | } | ||
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; | |||
31 | using libsecondlife.Packets; | 31 | using libsecondlife.Packets; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Framework.Console; | 33 | using OpenSim.Framework.Console; |
34 | using OpenSim.Region.Environment.Interfaces; | ||
34 | 35 | ||
35 | namespace OpenSim.Region.Environment.Modules | 36 | namespace OpenSim.Region.Environment.Modules |
36 | { | 37 | { |
@@ -38,7 +39,7 @@ namespace OpenSim.Region.Environment.Modules | |||
38 | /// A TextureSender handles the process of receiving a texture requested by the client from the | 39 | /// A TextureSender handles the process of receiving a texture requested by the client from the |
39 | /// AssetCache, and then sending that texture back to the client. | 40 | /// AssetCache, and then sending that texture back to the client. |
40 | /// </summary> | 41 | /// </summary> |
41 | public class TextureSender | 42 | public class TextureSender : ITextureSender |
42 | { | 43 | { |
43 | private static readonly log4net.ILog m_log | 44 | private static readonly log4net.ILog m_log |
44 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 45 | = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
@@ -67,9 +68,25 @@ namespace OpenSim.Region.Environment.Modules | |||
67 | /// </summary> | 68 | /// </summary> |
68 | private int PacketCounter = 0; | 69 | private int PacketCounter = 0; |
69 | 70 | ||
70 | public bool Cancel = false; | 71 | // See ITextureSender |
72 | public bool Cancel | ||
73 | { | ||
74 | get { return false; } | ||
75 | set { m_cancel = value; } | ||
76 | } | ||
77 | |||
78 | private bool m_cancel = false; | ||
79 | |||
80 | // See ITextureSender | ||
81 | public bool Sending | ||
82 | { | ||
83 | get { return false; } | ||
84 | set { m_sending = value; } | ||
85 | } | ||
86 | |||
87 | private bool m_sending = false; | ||
88 | |||
71 | public bool ImageLoaded = false; | 89 | public bool ImageLoaded = false; |
72 | public bool Sending = false; | ||
73 | 90 | ||
74 | private IClientAPI RequestUser; | 91 | private IClientAPI RequestUser; |
75 | 92 | ||
@@ -97,6 +114,7 @@ namespace OpenSim.Region.Environment.Modules | |||
97 | ImageLoaded = true; | 114 | ImageLoaded = true; |
98 | } | 115 | } |
99 | 116 | ||
117 | // See ITextureSender | ||
100 | public void UpdateRequest(int discardLevel, uint packetNumber) | 118 | public void UpdateRequest(int discardLevel, uint packetNumber) |
101 | { | 119 | { |
102 | RequestedDiscardLevel = discardLevel; | 120 | RequestedDiscardLevel = discardLevel; |
@@ -104,12 +122,11 @@ namespace OpenSim.Region.Environment.Modules | |||
104 | PacketCounter = (int) StartPacketNumber; | 122 | PacketCounter = (int) StartPacketNumber; |
105 | } | 123 | } |
106 | 124 | ||
107 | /// <summary> | 125 | // See ITextureSender |
108 | /// Send a texture packet to the client. | ||
109 | /// </summary> | ||
110 | /// <returns>True if the last packet has been sent, false otherwise.</returns> | ||
111 | public bool SendTexturePacket() | 126 | public bool SendTexturePacket() |
112 | { | 127 | { |
128 | //m_log.DebugFormat("[TEXTURE SENDER]: Sending packet for {0}", m_asset.FullID); | ||
129 | |||
113 | SendPacket(); | 130 | SendPacket(); |
114 | counter++; | 131 | counter++; |
115 | if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || | 132 | if ((NumPackets == 0) || (RequestedDiscardLevel == -1) || (PacketCounter > NumPackets) || |
@@ -170,7 +187,7 @@ namespace OpenSim.Region.Environment.Modules | |||
170 | } | 187 | } |
171 | catch (ArgumentOutOfRangeException) | 188 | catch (ArgumentOutOfRangeException) |
172 | { | 189 | { |
173 | m_log.Error("[TEXTURE]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + | 190 | m_log.Error("[TEXTURE SENDER]: Unable to separate texture into multiple packets: Array bounds failure on asset:" + |
174 | m_asset.FullID.ToString() ); | 191 | m_asset.FullID.ToString() ); |
175 | return; | 192 | return; |
176 | } | 193 | } |
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 @@ | |||
28 | 28 | ||
29 | using System; | 29 | using System; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | |||
31 | using libsecondlife; | 32 | using libsecondlife; |
33 | using libsecondlife.Packets; | ||
34 | |||
32 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
33 | using OpenSim.Framework.Console; | 36 | using OpenSim.Framework.Console; |
37 | using OpenSim.Region.Environment.Interfaces; | ||
34 | using OpenSim.Region.Environment.Scenes; | 38 | using OpenSim.Region.Environment.Scenes; |
35 | 39 | ||
36 | namespace OpenSim.Region.Environment.Modules | 40 | namespace OpenSim.Region.Environment.Modules |
@@ -54,12 +58,16 @@ namespace OpenSim.Region.Environment.Modules | |||
54 | /// Texture Senders are placed in this queue once they have received their texture from the asset | 58 | /// Texture Senders are placed in this queue once they have received their texture from the asset |
55 | /// cache. Another module actually invokes the send. | 59 | /// cache. Another module actually invokes the send. |
56 | /// </summary> | 60 | /// </summary> |
57 | private readonly BlockingQueue<TextureSender> m_sharedSendersQueue; | 61 | private readonly BlockingQueue<ITextureSender> m_sharedSendersQueue; |
58 | 62 | ||
59 | private readonly Scene m_scene; | 63 | private readonly Scene m_scene; |
64 | |||
65 | private readonly IClientAPI m_client; | ||
60 | 66 | ||
61 | public UserTextureDownloadService(Scene scene, BlockingQueue<TextureSender> sharedQueue) | 67 | public UserTextureDownloadService( |
68 | IClientAPI client, Scene scene, BlockingQueue<ITextureSender> sharedQueue) | ||
62 | { | 69 | { |
70 | m_client = client; | ||
63 | m_scene = scene; | 71 | m_scene = scene; |
64 | m_sharedSendersQueue = sharedQueue; | 72 | m_sharedSendersQueue = sharedQueue; |
65 | } | 73 | } |
@@ -68,9 +76,8 @@ namespace OpenSim.Region.Environment.Modules | |||
68 | /// Handle a texture request. This involves creating a texture sender and placing it on the | 76 | /// Handle a texture request. This involves creating a texture sender and placing it on the |
69 | /// previously passed in shared queue. | 77 | /// previously passed in shared queue. |
70 | /// </summary> | 78 | /// </summary> |
71 | /// <param name="client"> </param> | ||
72 | /// <param name="e"></param> | 79 | /// <param name="e"></param> |
73 | public void HandleTextureRequest(IClientAPI client, TextureRequestArgs e) | 80 | public void HandleTextureRequest(TextureRequestArgs e) |
74 | { | 81 | { |
75 | TextureSender textureSender; | 82 | TextureSender textureSender; |
76 | 83 | ||
@@ -91,7 +98,7 @@ namespace OpenSim.Region.Environment.Modules | |||
91 | m_scene.AddPendingDownloads(1); | 98 | m_scene.AddPendingDownloads(1); |
92 | 99 | ||
93 | TextureSender requestHandler = | 100 | TextureSender requestHandler = |
94 | new TextureSender(client, e.DiscardLevel, e.PacketNumber); | 101 | new TextureSender(m_client, e.DiscardLevel, e.PacketNumber); |
95 | m_textureSenders.Add(e.RequestedAssetID, requestHandler); | 102 | m_textureSenders.Add(e.RequestedAssetID, requestHandler); |
96 | 103 | ||
97 | m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); | 104 | m_scene.AssetCache.GetAsset(e.RequestedAssetID, TextureCallback, true); |
@@ -118,6 +125,8 @@ namespace OpenSim.Region.Environment.Modules | |||
118 | /// <param name="texture"></param> | 125 | /// <param name="texture"></param> |
119 | public void TextureCallback(LLUUID textureID, AssetBase texture) | 126 | public void TextureCallback(LLUUID textureID, AssetBase texture) |
120 | { | 127 | { |
128 | //m_log.DebugFormat("[USER TEXTURE DOWNLOAD SERVICE]: Calling TextureCallback with {0}, texture == null is {1}", textureID, (texture == null ? true : false)); | ||
129 | |||
121 | lock (m_textureSenders) | 130 | lock (m_textureSenders) |
122 | { | 131 | { |
123 | TextureSender textureSender; | 132 | TextureSender textureSender; |
@@ -129,13 +138,12 @@ namespace OpenSim.Region.Environment.Modules | |||
129 | // Needs investigation. | 138 | // Needs investigation. |
130 | if (texture == null || texture.Data == null) | 139 | if (texture == null || texture.Data == null) |
131 | { | 140 | { |
132 | // Right now, leaving it up to lower level asset server code to post the fact that | 141 | m_log.DebugFormat( |
133 | // this texture could not be found | 142 | "[USER TEXTURE DOWNLOAD SERVICE]: Queueing TextureNotFoundSender for {0}", |
134 | 143 | textureID); | |
135 | // TODO Send packet back to the client telling it not to expect the texture | 144 | |
136 | 145 | ITextureSender textureNotFoundSender = new TextureNotFoundSender(m_client, textureID); | |
137 | //m_log.DebugFormat("[USER TEXTURE DOWNLOAD]: Removing download stat for {0}", textureID); | 146 | EnqueueTextureSender(textureNotFoundSender); |
138 | m_scene.AddPendingDownloads(-1); | ||
139 | } | 147 | } |
140 | else | 148 | else |
141 | { | 149 | { |
@@ -163,11 +171,10 @@ namespace OpenSim.Region.Environment.Modules | |||
163 | /// Place a ready texture sender on the processing queue. | 171 | /// Place a ready texture sender on the processing queue. |
164 | /// </summary> | 172 | /// </summary> |
165 | /// <param name="textureSender"></param> | 173 | /// <param name="textureSender"></param> |
166 | private void EnqueueTextureSender(TextureSender textureSender) | 174 | private void EnqueueTextureSender(ITextureSender textureSender) |
167 | { | 175 | { |
168 | textureSender.Cancel = false; | 176 | textureSender.Cancel = false; |
169 | textureSender.Sending = true; | 177 | textureSender.Sending = true; |
170 | textureSender.counter = 0; | ||
171 | 178 | ||
172 | if (!m_sharedSendersQueue.Contains(textureSender)) | 179 | if (!m_sharedSendersQueue.Contains(textureSender)) |
173 | { | 180 | { |