aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
diff options
context:
space:
mode:
authorUbitUmarov2015-09-01 14:54:35 +0100
committerUbitUmarov2015-09-01 14:54:35 +0100
commit371c9dd2af01a2e7422ec901ee1f80757284a78c (patch)
tree058d2a513cacb12efcce0c0df0ae14ad135dbfe2 /OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
parentremove lixo (diff)
parentdont change camera on crossings (diff)
downloadopensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.zip
opensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.gz
opensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.bz2
opensim-SC-371c9dd2af01a2e7422ec901ee1f80757284a78c.tar.xz
bad merge?
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs410
1 files changed, 410 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index f57d857..91efe8a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Reflection; 32using System.Reflection;
32using System.IO; 33using System.IO;
34using System.Threading;
33using System.Web; 35using System.Web;
34using Mono.Addins; 36using Mono.Addins;
37using OpenSim.Framework.Monitoring;
35using log4net; 38using log4net;
36using Nini.Config; 39using Nini.Config;
37using OpenMetaverse; 40using OpenMetaverse;
@@ -57,12 +60,51 @@ namespace OpenSim.Region.ClientStack.Linden
57 private IAssetService m_AssetService; 60 private IAssetService m_AssetService;
58 private bool m_Enabled = true; 61 private bool m_Enabled = true;
59 private string m_URL; 62 private string m_URL;
63<<<<<<< HEAD
60 private string m_URL2; 64 private string m_URL2;
61 private string m_RedirectURL = null; 65 private string m_RedirectURL = null;
62 private string m_RedirectURL2 = null; 66 private string m_RedirectURL2 = null;
67=======
68
69 struct aPollRequest
70 {
71 public PollServiceMeshEventArgs thepoll;
72 public UUID reqID;
73 public Hashtable request;
74 }
75
76 public class aPollResponse
77 {
78 public Hashtable response;
79 public int bytes;
80 public int lod;
81 }
82
83
84 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
85
86 private static GetMeshHandler m_getMeshHandler;
87
88 private IAssetService m_assetService = null;
89
90 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
91 private static Thread[] m_workerThreads = null;
92
93 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
94 new OpenMetaverse.BlockingQueue<aPollRequest>();
95
96 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
97>>>>>>> avn/ubitvar
63 98
64 #region Region Module interfaceBase Members 99 #region Region Module interfaceBase Members
65 100
101 ~GetMeshModule()
102 {
103 foreach (Thread t in m_workerThreads)
104 Watchdog.AbortThread(t.ManagedThreadId);
105
106 }
107
66 public Type ReplaceableInterface 108 public Type ReplaceableInterface
67 { 109 {
68 get { return null; } 110 get { return null; }
@@ -87,8 +129,12 @@ namespace OpenSim.Region.ClientStack.Linden
87 if (m_URL2 != string.Empty) 129 if (m_URL2 != string.Empty)
88 { 130 {
89 m_Enabled = true; 131 m_Enabled = true;
132<<<<<<< HEAD
90 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL"); 133 m_RedirectURL2 = config.GetString("GetMesh2RedirectURL");
91 } 134 }
135=======
136
137>>>>>>> avn/ubitvar
92 } 138 }
93 139
94 public void AddRegion(Scene pScene) 140 public void AddRegion(Scene pScene)
@@ -97,6 +143,8 @@ namespace OpenSim.Region.ClientStack.Linden
97 return; 143 return;
98 144
99 m_scene = pScene; 145 m_scene = pScene;
146
147 m_assetService = pScene.AssetService;
100 } 148 }
101 149
102 public void RemoveRegion(Scene scene) 150 public void RemoveRegion(Scene scene)
@@ -105,6 +153,9 @@ namespace OpenSim.Region.ClientStack.Linden
105 return; 153 return;
106 154
107 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 155 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
156 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
157 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
158
108 m_scene = null; 159 m_scene = null;
109 } 160 }
110 161
@@ -115,6 +166,27 @@ namespace OpenSim.Region.ClientStack.Linden
115 166
116 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 167 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
117 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 168 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
169 // We'll reuse the same handler for all requests.
170 m_getMeshHandler = new GetMeshHandler(m_assetService);
171 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
172 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
173
174 if (m_workerThreads == null)
175 {
176 m_workerThreads = new Thread[2];
177
178 for (uint i = 0; i < 2; i++)
179 {
180 m_workerThreads[i] = Watchdog.StartThread(DoMeshRequests,
181 String.Format("MeshWorkerThread{0}", i),
182 ThreadPriority.Normal,
183 false,
184 false,
185 null,
186 int.MaxValue);
187 }
188 }
189
118 } 190 }
119 191
120 192
@@ -124,9 +196,147 @@ namespace OpenSim.Region.ClientStack.Linden
124 196
125 #endregion 197 #endregion
126 198
199 private void DoMeshRequests()
200 {
201 while (true)
202 {
203 aPollRequest poolreq = m_queue.Dequeue();
204
205 poolreq.thepoll.Process(poolreq);
206 }
207 }
208
209 // 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.
210 public void ThrottleUpdate(ScenePresence p)
211 {
212 UUID user = p.UUID;
213 int imagethrottle = p.ControllingClient.GetAgentThrottleSilent((int)ThrottleOutPacketType.Asset);
214 PollServiceMeshEventArgs args;
215 if (m_pollservices.TryGetValue(user, out args))
216 {
217 args.UpdateThrottle(imagethrottle, p);
218 }
219 }
220
221 private class PollServiceMeshEventArgs : PollServiceEventArgs
222 {
223 private List<Hashtable> requests =
224 new List<Hashtable>();
225 private Dictionary<UUID, aPollResponse> responses =
226 new Dictionary<UUID, aPollResponse>();
227
228 private Scene m_scene;
229 private MeshCapsDataThrottler m_throttler;
230 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
231 base(null, uri, null, null, null, pId, int.MaxValue)
232 {
233 m_scene = scene;
234 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
235 // x is request id, y is userid
236 HasEvents = (x, y) =>
237 {
238 lock (responses)
239 {
240 bool ret = m_throttler.hasEvents(x, responses);
241 m_throttler.ProcessTime();
242 return ret;
243
244 }
245 };
246 GetEvents = (x, y) =>
247 {
248 lock (responses)
249 {
250 try
251 {
252 return responses[x].response;
253 }
254 finally
255 {
256 m_throttler.ProcessTime();
257 responses.Remove(x);
258 }
259 }
260 };
261 // x is request id, y is request data hashtable
262 Request = (x, y) =>
263 {
264 aPollRequest reqinfo = new aPollRequest();
265 reqinfo.thepoll = this;
266 reqinfo.reqID = x;
267 reqinfo.request = y;
268
269 m_queue.Enqueue(reqinfo);
270 };
271
272 // this should never happen except possible on shutdown
273 NoEvents = (x, y) =>
274 {
275 /*
276 lock (requests)
277 {
278 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
279 requests.Remove(request);
280 }
281 */
282 Hashtable response = new Hashtable();
283
284 response["int_response_code"] = 500;
285 response["str_response_string"] = "Script timeout";
286 response["content_type"] = "text/plain";
287 response["keepalive"] = false;
288 response["reusecontext"] = false;
289
290 return response;
291 };
292 }
293
294 public void Process(aPollRequest requestinfo)
295 {
296 Hashtable response;
297
298 UUID requestID = requestinfo.reqID;
299
300 // If the avatar is gone, don't bother to get the texture
301 if (m_scene.GetScenePresence(Id) == null)
302 {
303 response = new Hashtable();
304
305 response["int_response_code"] = 500;
306 response["str_response_string"] = "Script timeout";
307 response["content_type"] = "text/plain";
308 response["keepalive"] = false;
309 response["reusecontext"] = false;
310
311 lock (responses)
312 responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
313
314 return;
315 }
316
317 response = m_getMeshHandler.Handle(requestinfo.request);
318 lock (responses)
319 {
320 responses[requestID] = new aPollResponse()
321 {
322 bytes = (int)response["int_bytes"],
323 lod = (int)response["int_lod"],
324 response = response
325 };
326
327 }
328 m_throttler.ProcessTime();
329 }
330
331 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
332 {
333 m_throttler.UpdateThrottle(pimagethrottle, p);
334 }
335 }
127 336
128 public void RegisterCaps(UUID agentID, Caps caps) 337 public void RegisterCaps(UUID agentID, Caps caps)
129 { 338 {
339<<<<<<< HEAD
130 UUID capID = UUID.Random(); 340 UUID capID = UUID.Random();
131 bool getMeshRegistered = false; 341 bool getMeshRegistered = false;
132 342
@@ -140,6 +350,35 @@ namespace OpenSim.Region.ClientStack.Linden
140 caps.RegisterHandler( 350 caps.RegisterHandler(
141 "GetMesh", 351 "GetMesh",
142 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh", agentID.ToString(), m_RedirectURL)); 352 new GetMeshHandler("/CAPS/" + capID + "/", m_AssetService, "GetMesh", agentID.ToString(), m_RedirectURL));
353=======
354// UUID capID = UUID.Random();
355 if (m_URL == "localhost")
356 {
357 string capUrl = "/CAPS/" + UUID.Random() + "/";
358
359 // Register this as a poll service
360 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
361
362 args.Type = PollServiceEventArgs.EventType.Mesh;
363 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
364
365 string hostName = m_scene.RegionInfo.ExternalHostName;
366 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
367 string protocol = "http";
368
369 if (MainServer.Instance.UseSSL)
370 {
371 hostName = MainServer.Instance.SSLCommonName;
372 port = MainServer.Instance.SSLPort;
373 protocol = "https";
374 }
375 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
376 m_pollservices[agentID] = args;
377 m_capsDict[agentID] = capUrl;
378
379
380
381>>>>>>> avn/ubitvar
143 } 382 }
144 else 383 else
145 { 384 {
@@ -164,6 +403,177 @@ namespace OpenSim.Region.ClientStack.Linden
164 caps.RegisterHandler("GetMesh2", m_URL2); 403 caps.RegisterHandler("GetMesh2", m_URL2);
165 } 404 }
166 } 405 }
406 private void DeregisterCaps(UUID agentID, Caps caps)
407 {
408 string capUrl;
409 PollServiceMeshEventArgs args;
410 if (m_capsDict.TryGetValue(agentID, out capUrl))
411 {
412 MainServer.Instance.RemoveHTTPHandler("", capUrl);
413 m_capsDict.Remove(agentID);
414 }
415 if (m_pollservices.TryGetValue(agentID, out args))
416 {
417 m_pollservices.Remove(agentID);
418 }
419 }
420
421 internal sealed class MeshCapsDataThrottler
422 {
423
424 private volatile int currenttime = 0;
425 private volatile int lastTimeElapsed = 0;
426 private volatile int BytesSent = 0;
427 private int Lod3 = 0;
428 private int Lod2 = 0;
429 private int Lod1 = 0;
430 private int UserSetThrottle = 0;
431 private int UDPSetThrottle = 0;
432 private int CapSetThrottle = 0;
433 private float CapThrottleDistributon = 0.30f;
434 private readonly Scene m_scene;
435 private ThrottleOutPacketType Throttle;
436 private readonly UUID User;
437
438 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
439 {
440 ThrottleBytes = pBytes;
441 lastTimeElapsed = Util.EnvironmentTickCount();
442 Throttle = ThrottleOutPacketType.Asset;
443 m_scene = pScene;
444 User = puser;
445 }
446
447
448 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
449 {
450 const float ThirtyPercent = 0.30f;
451 const float FivePercent = 0.05f;
452 PassTime();
453 // Note, this is called IN LOCK
454 bool haskey = responses.ContainsKey(key);
455
456 if (responses.Count > 2)
457 {
458 SplitThrottle(ThirtyPercent);
459 }
460 else
461 {
462 SplitThrottle(FivePercent);
463 }
464
465 if (!haskey)
466 {
467 return false;
468 }
469 aPollResponse response;
470 if (responses.TryGetValue(key, out response))
471 {
472 float LOD3Over = (((ThrottleBytes*CapThrottleDistributon)%50000) + 1);
473 float LOD2Over = (((ThrottleBytes*CapThrottleDistributon)%10000) + 1);
474 // Normal
475 if (BytesSent + response.bytes <= ThrottleBytes)
476 {
477 BytesSent += response.bytes;
478
479 return true;
480 }
481 // Lod3 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
482 else if (response.bytes > ThrottleBytes && Lod3 <= ((LOD3Over < 1)? 1: LOD3Over) )
483 {
484 Interlocked.Increment(ref Lod3);
485 BytesSent += response.bytes;
486
487 return true;
488 }
489 // Lod2 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
490 else if (response.bytes > ThrottleBytes && Lod2 <= ((LOD2Over < 1) ? 1 : LOD2Over))
491 {
492 Interlocked.Increment(ref Lod2);
493 BytesSent += response.bytes;
494
495 return true;
496 }
497 else
498 {
499 return false;
500 }
501 }
502
503 return haskey;
504 }
505 public void SubtractBytes(int bytes,int lod)
506 {
507 BytesSent -= bytes;
508 }
509 private void SplitThrottle(float percentMultiplier)
510 {
511
512 if (CapThrottleDistributon != percentMultiplier) // don't switch it if it's already set at the % multipler
513 {
514 CapThrottleDistributon = percentMultiplier;
515 ScenePresence p;
516 if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore.
517 {
518// AlterThrottle(UserSetThrottle, p);
519 UpdateThrottle(UserSetThrottle, p);
520 }
521 }
522 }
523
524 public void ProcessTime()
525 {
526 PassTime();
527 }
528
529
530 private void PassTime()
531 {
532 currenttime = Util.EnvironmentTickCount();
533 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
534 //processTimeBasedActions(responses);
535 if (currenttime - timeElapsed >= 1000)
536 {
537 lastTimeElapsed = Util.EnvironmentTickCount();
538 BytesSent -= ThrottleBytes;
539 if (BytesSent < 0) BytesSent = 0;
540 if (BytesSent < ThrottleBytes)
541 {
542 Lod3 = 0;
543 Lod2 = 0;
544 Lod1 = 0;
545 }
546 }
547 }
548 private void AlterThrottle(int setting, ScenePresence p)
549 {
550 p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
551 }
552
553 public int ThrottleBytes
554 {
555 get { return CapSetThrottle; }
556 set { CapSetThrottle = value; }
557 }
558
559 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
560 {
561 // Client set throttle !
562 UserSetThrottle = pimagethrottle;
563 CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon);
564// UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon));
565
566 float udp = 1.0f - CapThrottleDistributon;
567 if(udp < 0.7f)
568 udp = 0.7f;
569 UDPSetThrottle = (int) ((float)pimagethrottle * udp);
570 if (CapSetThrottle < 4068)
571 CapSetThrottle = 4068; // at least two discovery mesh
572 p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle);
573 ProcessTime();
574
575 }
576 }
167 577
168 } 578 }
169} 579}