aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs193
1 files changed, 104 insertions, 89 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index b01c7dc..b206739 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Collections.Concurrent;
31using System.Reflection; 32using System.Reflection;
32using System.Threading; 33using System.Threading;
33using log4net; 34using log4net;
@@ -51,7 +52,7 @@ namespace OpenSim.Region.ClientStack.Linden
51 public class GetTextureModule : INonSharedRegionModule 52 public class GetTextureModule : INonSharedRegionModule
52 { 53 {
53 54
54 struct aPollRequest 55 class APollRequest
55 { 56 {
56 public PollServiceTextureEventArgs thepoll; 57 public PollServiceTextureEventArgs thepoll;
57 public UUID reqID; 58 public UUID reqID;
@@ -59,7 +60,7 @@ namespace OpenSim.Region.ClientStack.Linden
59 public bool send503; 60 public bool send503;
60 } 61 }
61 62
62 public class aPollResponse 63 public class APollResponse
63 { 64 {
64 public Hashtable response; 65 public Hashtable response;
65 public int bytes; 66 public int bytes;
@@ -77,8 +78,7 @@ namespace OpenSim.Region.ClientStack.Linden
77 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); 78 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
78 private static Thread[] m_workerThreads = null; 79 private static Thread[] m_workerThreads = null;
79 private static int m_NumberScenes = 0; 80 private static int m_NumberScenes = 0;
80 private static OpenSim.Framework.BlockingQueue<aPollRequest> m_queue = 81 private static BlockingCollection<APollRequest> m_queue = new BlockingCollection<APollRequest>();
81 new OpenSim.Framework.BlockingQueue<aPollRequest>();
82 82
83 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>(); 83 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
84 84
@@ -107,26 +107,29 @@ namespace OpenSim.Region.ClientStack.Linden
107 public void AddRegion(Scene s) 107 public void AddRegion(Scene s)
108 { 108 {
109 m_scene = s; 109 m_scene = s;
110 m_assetService = s.AssetService;
111 } 110 }
112 111
113 public void RemoveRegion(Scene s) 112 public void RemoveRegion(Scene s)
114 { 113 {
115 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 114 s.EventManager.OnRegisterCaps -= RegisterCaps;
116 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 115 s.EventManager.OnDeregisterCaps -= DeregisterCaps;
117 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate; 116 s.EventManager.OnThrottleUpdate -= ThrottleUpdate;
118 m_NumberScenes--; 117 m_NumberScenes--;
119 m_scene = null; 118 m_scene = null;
120 } 119 }
121 120
122 public void RegionLoaded(Scene s) 121 public void RegionLoaded(Scene s)
123 { 122 {
124 // We'll reuse the same handler for all requests. 123 if(m_assetService == null)
125 m_getTextureHandler = new GetTextureHandler(m_assetService); 124 {
125 m_assetService = s.RequestModuleInterface<IAssetService>();
126 // We'll reuse the same handler for all requests.
127 m_getTextureHandler = new GetTextureHandler(m_assetService);
128 }
126 129
127 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 130 s.EventManager.OnRegisterCaps += RegisterCaps;
128 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; 131 s.EventManager.OnDeregisterCaps += DeregisterCaps;
129 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate; 132 s.EventManager.OnThrottleUpdate += ThrottleUpdate;
130 133
131 m_NumberScenes++; 134 m_NumberScenes++;
132 135
@@ -146,39 +149,13 @@ namespace OpenSim.Region.ClientStack.Linden
146 } 149 }
147 } 150 }
148 } 151 }
149 private int ExtractImageThrottle(byte[] pthrottles) 152
150 {
151
152 byte[] adjData;
153 int pos = 0;
154
155 if (!BitConverter.IsLittleEndian)
156 {
157 byte[] newData = new byte[7 * 4];
158 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
159
160 for (int i = 0; i < 7; i++)
161 Array.Reverse(newData, i * 4, 4);
162
163 adjData = newData;
164 }
165 else
166 {
167 adjData = pthrottles;
168 }
169
170 pos = pos + 20;
171 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
172 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
173 return texture;
174 }
175
176 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent. 153 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
177 public void ThrottleUpdate(ScenePresence p) 154 public void ThrottleUpdate(ScenePresence p)
178 { 155 {
179 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1); 156 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
180 UUID user = p.UUID; 157 UUID user = p.UUID;
181 int imagethrottle = ExtractImageThrottle(throttles); 158 int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Texture);
182 PollServiceTextureEventArgs args; 159 PollServiceTextureEventArgs args;
183 if (m_pollservices.TryGetValue(user,out args)) 160 if (m_pollservices.TryGetValue(user,out args))
184 { 161 {
@@ -199,7 +176,7 @@ namespace OpenSim.Region.ClientStack.Linden
199 foreach (Thread t in m_workerThreads) 176 foreach (Thread t in m_workerThreads)
200 Watchdog.AbortThread(t.ManagedThreadId); 177 Watchdog.AbortThread(t.ManagedThreadId);
201 178
202 m_queue.Clear(); 179 m_queue.Dispose();
203 } 180 }
204 } 181 }
205 182
@@ -216,15 +193,17 @@ namespace OpenSim.Region.ClientStack.Linden
216 { 193 {
217 private List<Hashtable> requests = 194 private List<Hashtable> requests =
218 new List<Hashtable>(); 195 new List<Hashtable>();
219 private Dictionary<UUID, aPollResponse> responses = 196 private Dictionary<UUID, APollResponse> responses =
220 new Dictionary<UUID, aPollResponse>(); 197 new Dictionary<UUID, APollResponse>();
198 private HashSet<UUID> dropedResponses = new HashSet<UUID>();
221 199
222 private Scene m_scene; 200 private Scene m_scene;
223 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000); 201 private CapsDataThrottler m_throttler;
224 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 202 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
225 base(null, "", null, null, null, pId, int.MaxValue) 203 base(null, "", null, null, null, null, pId, int.MaxValue)
226 { 204 {
227 m_scene = scene; 205 m_scene = scene;
206 m_throttler = new CapsDataThrottler(100000);
228 // x is request id, y is userid 207 // x is request id, y is userid
229 HasEvents = (x, y) => 208 HasEvents = (x, y) =>
230 { 209 {
@@ -235,6 +214,16 @@ namespace OpenSim.Region.ClientStack.Linden
235 214
236 } 215 }
237 }; 216 };
217
218 Drop = (x, y) =>
219 {
220 lock (responses)
221 {
222 responses.Remove(x);
223 dropedResponses.Add(x);
224 }
225 };
226
238 GetEvents = (x, y) => 227 GetEvents = (x, y) =>
239 { 228 {
240 lock (responses) 229 lock (responses)
@@ -253,7 +242,7 @@ namespace OpenSim.Region.ClientStack.Linden
253 // x is request id, y is request data hashtable 242 // x is request id, y is request data hashtable
254 Request = (x, y) => 243 Request = (x, y) =>
255 { 244 {
256 aPollRequest reqinfo = new aPollRequest(); 245 APollRequest reqinfo = new APollRequest();
257 reqinfo.thepoll = this; 246 reqinfo.thepoll = this;
258 reqinfo.reqID = x; 247 reqinfo.reqID = x;
259 reqinfo.request = y; 248 reqinfo.request = y;
@@ -263,14 +252,14 @@ namespace OpenSim.Region.ClientStack.Linden
263 { 252 {
264 if (responses.Count > 0) 253 if (responses.Count > 0)
265 { 254 {
266 if (m_queue.Count() >= 4) 255 if (m_queue.Count >= 4)
267 { 256 {
268 // Never allow more than 4 fetches to wait 257 // Never allow more than 4 fetches to wait
269 reqinfo.send503 = true; 258 reqinfo.send503 = true;
270 } 259 }
271 } 260 }
272 } 261 }
273 m_queue.Enqueue(reqinfo); 262 m_queue.Add(reqinfo);
274 m_throttler.PassTime(); 263 m_throttler.PassTime();
275 }; 264 };
276 265
@@ -296,7 +285,7 @@ namespace OpenSim.Region.ClientStack.Linden
296 }; 285 };
297 } 286 }
298 287
299 public void Process(aPollRequest requestinfo) 288 public void Process(APollRequest requestinfo)
300 { 289 {
301 Hashtable response; 290 Hashtable response;
302 291
@@ -305,53 +294,71 @@ namespace OpenSim.Region.ClientStack.Linden
305 if(m_scene.ShuttingDown) 294 if(m_scene.ShuttingDown)
306 return; 295 return;
307 296
308 if (requestinfo.send503) 297 lock (responses)
309 { 298 {
310 response = new Hashtable(); 299 lock(dropedResponses)
300 {
301 if(dropedResponses.Contains(requestID))
302 {
303 dropedResponses.Remove(requestID);
304 return;
305 }
306 }
311 307
312 response["int_response_code"] = 503; 308 if (requestinfo.send503)
313 response["str_response_string"] = "Throttled"; 309 {
314 response["content_type"] = "text/plain"; 310 response = new Hashtable();
315 response["keepalive"] = false;
316 response["reusecontext"] = false;
317 311
318 Hashtable headers = new Hashtable(); 312 response["int_response_code"] = 503;
319 headers["Retry-After"] = 30; 313 response["str_response_string"] = "Throttled";
320 response["headers"] = headers; 314 response["content_type"] = "text/plain";
315 response["keepalive"] = false;
316 response["reusecontext"] = false;
321 317
322 lock (responses) 318 Hashtable headers = new Hashtable();
323 responses[requestID] = new aPollResponse() {bytes = 0, response = response}; 319 headers["Retry-After"] = 30;
320 response["headers"] = headers;
324 321
325 return; 322 responses[requestID] = new APollResponse() {bytes = 0, response = response};
326 } 323
324 return;
325 }
327 326
328 // If the avatar is gone, don't bother to get the texture 327 // If the avatar is gone, don't bother to get the texture
329 if (m_scene.GetScenePresence(Id) == null) 328 if (m_scene.GetScenePresence(Id) == null)
330 { 329 {
331 response = new Hashtable(); 330 response = new Hashtable();
332 331
333 response["int_response_code"] = 500; 332 response["int_response_code"] = 500;
334 response["str_response_string"] = "Script timeout"; 333 response["str_response_string"] = "Script timeout";
335 response["content_type"] = "text/plain"; 334 response["content_type"] = "text/plain";
336 response["keepalive"] = false; 335 response["keepalive"] = false;
337 response["reusecontext"] = false;
338 336
339 lock (responses) 337 responses[requestID] = new APollResponse() {bytes = 0, response = response};
340 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
341 338
342 return; 339 return;
340 }
343 } 341 }
344 342
345 response = m_getTextureHandler.Handle(requestinfo.request); 343 response = m_getTextureHandler.Handle(requestinfo.request);
344
346 lock (responses) 345 lock (responses)
347 { 346 {
348 responses[requestID] = new aPollResponse() 347 lock(dropedResponses)
349 { 348 {
350 bytes = (int) response["int_bytes"], 349 if(dropedResponses.Contains(requestID))
351 response = response 350 {
352 }; 351 dropedResponses.Remove(requestID);
353 352 m_throttler.PassTime();
354 } 353 return;
354 }
355 }
356 responses[requestID] = new APollResponse()
357 {
358 bytes = (int) response["int_bytes"],
359 response = response
360 };
361 }
355 m_throttler.PassTime(); 362 m_throttler.PassTime();
356 } 363 }
357 364
@@ -415,12 +422,20 @@ namespace OpenSim.Region.ClientStack.Linden
415 422
416 private static void DoTextureRequests() 423 private static void DoTextureRequests()
417 { 424 {
418 while (true) 425 APollRequest poolreq;
426 while (m_NumberScenes > 0)
419 { 427 {
420 aPollRequest poolreq = m_queue.Dequeue(4500); 428 poolreq = null;
421 Watchdog.UpdateThread(); 429 if(!m_queue.TryTake(out poolreq, 4500) || poolreq == null)
430 {
431 Watchdog.UpdateThread();
432 continue;
433 }
434
422 if(m_NumberScenes <= 0) 435 if(m_NumberScenes <= 0)
423 return; 436 break;
437
438 Watchdog.UpdateThread();
424 if(poolreq.reqID != UUID.Zero) 439 if(poolreq.reqID != UUID.Zero)
425 poolreq.thepoll.Process(poolreq); 440 poolreq.thepoll.Process(poolreq);
426 } 441 }
@@ -437,7 +452,7 @@ namespace OpenSim.Region.ClientStack.Linden
437 ThrottleBytes = pBytes; 452 ThrottleBytes = pBytes;
438 lastTimeElapsed = Util.GetTimeStampMS(); 453 lastTimeElapsed = Util.GetTimeStampMS();
439 } 454 }
440 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses) 455 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.APollResponse> responses)
441 { 456 {
442 PassTime(); 457 PassTime();
443 // Note, this is called IN LOCK 458 // Note, this is called IN LOCK
@@ -446,7 +461,7 @@ namespace OpenSim.Region.ClientStack.Linden
446 { 461 {
447 return false; 462 return false;
448 } 463 }
449 GetTextureModule.aPollResponse response; 464 GetTextureModule.APollResponse response;
450 if (responses.TryGetValue(key, out response)) 465 if (responses.TryGetValue(key, out response))
451 { 466 {
452 // This is any error response 467 // This is any error response
@@ -476,7 +491,7 @@ namespace OpenSim.Region.ClientStack.Linden
476 return; 491 return;
477 int add = (int)(ThrottleBytes * timeElapsed * 0.001); 492 int add = (int)(ThrottleBytes * timeElapsed * 0.001);
478 if (add >= 1000) 493 if (add >= 1000)
479 { 494 {
480 lastTimeElapsed = currenttime; 495 lastTimeElapsed = currenttime;
481 BytesSent -= add; 496 BytesSent -= add;
482 if (BytesSent < 0) BytesSent = 0; 497 if (BytesSent < 0) BytesSent = 0;