aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs13
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs85
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs67
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs20
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs10
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs (renamed from OpenSim/Region/CoreModules/Framework/GridServiceThrottle/GridServiceThrottleModule.cs)169
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs122
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs19
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs17
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs8
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs13
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs3
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs6
20 files changed, 437 insertions, 242 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 87c2792..6dd1f5b 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -86,6 +86,7 @@ namespace OpenSim
86 IConfig startupConfig = Config.Configs["Startup"]; 86 IConfig startupConfig = Config.Configs["Startup"];
87 IConfig networkConfig = Config.Configs["Network"]; 87 IConfig networkConfig = Config.Configs["Network"];
88 88
89 int stpMinThreads = 2;
89 int stpMaxThreads = 15; 90 int stpMaxThreads = 15;
90 91
91 if (startupConfig != null) 92 if (startupConfig != null)
@@ -112,12 +113,13 @@ namespace OpenSim
112 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 113 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
113 Util.FireAndForgetMethod = asyncCallMethod; 114 Util.FireAndForgetMethod = asyncCallMethod;
114 115
116 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
115 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15); 117 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
116 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) "); 118 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
117 } 119 }
118 120
119 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 121 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
120 Util.InitThreadPool(stpMaxThreads); 122 Util.InitThreadPool(stpMinThreads, stpMaxThreads);
121 123
122 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod); 124 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
123 } 125 }
@@ -423,8 +425,8 @@ namespace OpenSim
423 { 425 {
424 RegionInfo regionInfo = presence.Scene.RegionInfo; 426 RegionInfo regionInfo = presence.Scene.RegionInfo;
425 427
426 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && 428 if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
427 presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) 429 presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
428 { 430 {
429 MainConsole.Instance.Output( 431 MainConsole.Instance.Output(
430 String.Format( 432 String.Format(
@@ -438,6 +440,7 @@ namespace OpenSim
438 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 440 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
439 441
440 presence.Scene.IncomingCloseAgent(presence.UUID, force); 442 presence.Scene.IncomingCloseAgent(presence.UUID, force);
443 break;
441 } 444 }
442 } 445 }
443 446
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 98ab433..762e22a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -367,18 +367,7 @@ namespace OpenSim.Region.ClientStack.Linden
367 foreach (OSD c in capsRequested) 367 foreach (OSD c in capsRequested)
368 validCaps.Add(c.AsString()); 368 validCaps.Add(c.AsString());
369 369
370 Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps); 370 string result = LLSDHelpers.SerialiseLLSDReply(m_HostCapsObj.GetCapsDetails(true, validCaps));
371
372 // Add the external too
373 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
374 {
375 if (!validCaps.Contains(kvp.Key))
376 continue;
377
378 caps[kvp.Key] = kvp.Value;
379 }
380
381 string result = LLSDHelpers.SerialiseLLSDReply(caps);
382 371
383 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result); 372 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
384 373
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index d6689d4..e98a470 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -65,6 +65,13 @@ namespace OpenSim.Region.ClientStack.Linden
65 /// </value> 65 /// </value>
66 public int DebugLevel { get; set; } 66 public int DebugLevel { get; set; }
67 67
68 // Viewer post requests timeout in 60 secs
69 // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
70 //
71 private const int VIEWER_TIMEOUT = 60 * 1000;
72 // Just to be safe, we work on a 10 sec shorter cycle
73 private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
74
68 protected Scene m_scene; 75 protected Scene m_scene;
69 76
70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 77 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
@@ -252,29 +259,32 @@ namespace OpenSim.Region.ClientStack.Linden
252 259
253 List<UUID> removeitems = new List<UUID>(); 260 List<UUID> removeitems = new List<UUID>();
254 lock (m_AvatarQueueUUIDMapping) 261 lock (m_AvatarQueueUUIDMapping)
255 { 262 m_AvatarQueueUUIDMapping.Remove(agentID);
256 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
257 {
258// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
259 if (ky == agentID)
260 {
261 removeitems.Add(ky);
262 }
263 }
264 263
265 foreach (UUID ky in removeitems) 264// lock (m_AvatarQueueUUIDMapping)
266 { 265// {
267 UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky]; 266// foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
268 m_AvatarQueueUUIDMapping.Remove(ky); 267// {
269 268//// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
270 string eqgPath = GenerateEqgCapPath(eventQueueGetUuid); 269// if (ky == agentID)
271 MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath); 270// {
272 271// removeitems.Add(ky);
273// m_log.DebugFormat( 272// }
274// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}", 273// }
275// eqgPath, agentID, m_scene.RegionInfo.RegionName); 274//
276 } 275// foreach (UUID ky in removeitems)
277 } 276// {
277// UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
278// m_AvatarQueueUUIDMapping.Remove(ky);
279//
280// string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
281// MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
282//
283//// m_log.DebugFormat(
284//// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
285//// eqgPath, agentID, m_scene.RegionInfo.RegionName);
286// }
287// }
278 288
279 UUID searchval = UUID.Zero; 289 UUID searchval = UUID.Zero;
280 290
@@ -359,29 +369,9 @@ namespace OpenSim.Region.ClientStack.Linden
359 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); 369 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
360 } 370 }
361 371
362 string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID); 372 caps.RegisterPollHandler(
363 373 "EventQueueGet",
364 // Register this as a caps handler 374 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
365 // FIXME: Confusingly, we need to register separate as a capability so that the client is told about
366 // EventQueueGet when it receive capability information, but then we replace the rest handler immediately
367 // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
368 // really it should be possible to directly register the poll handler as a capability.
369 caps.RegisterHandler(
370 "EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null, "EventQueueGet", null));
371// delegate(Hashtable m_dhttpMethod)
372// {
373// return ProcessQueue(m_dhttpMethod, agentID, caps);
374// }));
375
376 // This will persist this beyond the expiry of the caps handlers
377 // TODO: Add EventQueueGet name/description for diagnostics
378 MainServer.Instance.AddPollServiceHTTPHandler(
379 eventQueueGetPath,
380 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 40000));
381
382// m_log.DebugFormat(
383// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
384// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
385 375
386 Random rnd = new Random(Environment.TickCount); 376 Random rnd = new Random(Environment.TickCount);
387 lock (m_ids) 377 lock (m_ids)
@@ -399,7 +389,10 @@ namespace OpenSim.Region.ClientStack.Linden
399 Queue<OSD> queue = GetQueue(agentID); 389 Queue<OSD> queue = GetQueue(agentID);
400 if (queue != null) 390 if (queue != null)
401 lock (queue) 391 lock (queue)
392 {
393 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
402 return queue.Count > 0; 394 return queue.Count > 0;
395 }
403 396
404 return false; 397 return false;
405 } 398 }
@@ -422,7 +415,7 @@ namespace OpenSim.Region.ClientStack.Linden
422 public Hashtable GetEvents(UUID requestID, UUID pAgentId) 415 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
423 { 416 {
424 if (DebugLevel >= 2) 417 if (DebugLevel >= 2)
425 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); 418 m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName);
426 419
427 Queue<OSD> queue = TryGetQueue(pAgentId); 420 Queue<OSD> queue = TryGetQueue(pAgentId);
428 OSD element; 421 OSD element;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 6ec1115..7b15284 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -246,8 +246,8 @@ namespace OpenSim.Region.ClientStack.Linden
246 246
247 private Scene m_scene; 247 private Scene m_scene;
248 private MeshCapsDataThrottler m_throttler; 248 private MeshCapsDataThrottler m_throttler;
249 public PollServiceMeshEventArgs(UUID pId, Scene scene) : 249 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
250 base(null, null, null, null, pId, int.MaxValue) 250 base(null, uri, null, null, null, pId, int.MaxValue)
251 { 251 {
252 m_scene = scene; 252 m_scene = scene;
253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); 253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
@@ -361,7 +361,7 @@ namespace OpenSim.Region.ClientStack.Linden
361 string capUrl = "/CAPS/" + UUID.Random() + "/"; 361 string capUrl = "/CAPS/" + UUID.Random() + "/";
362 362
363 // Register this as a poll service 363 // Register this as a poll service
364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene); 364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
365 365
366 args.Type = PollServiceEventArgs.EventType.Mesh; 366 args.Type = PollServiceEventArgs.EventType.Mesh;
367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index a42c96c..c12b8d6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -210,7 +210,7 @@ namespace OpenSim.Region.ClientStack.Linden
210 private Scene m_scene; 210 private Scene m_scene;
211 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); 211 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
212 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 212 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
213 base(null, null, null, null, pId, int.MaxValue) 213 base(null, "", null, null, null, pId, int.MaxValue)
214 { 214 {
215 m_scene = scene; 215 m_scene = scene;
216 // x is request id, y is userid 216 // x is request id, y is userid
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 27b09a6..f816ad3 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -78,7 +78,6 @@ namespace OpenSim.Region.ClientStack.Linden
78 78
79 private static WebFetchInvDescHandler m_webFetchHandler; 79 private static WebFetchInvDescHandler m_webFetchHandler;
80 80
81 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
82 private static Thread[] m_workerThreads = null; 81 private static Thread[] m_workerThreads = null;
83 82
84 private static DoubleQueue<aPollRequest> m_queue = 83 private static DoubleQueue<aPollRequest> m_queue =
@@ -115,7 +114,6 @@ namespace OpenSim.Region.ClientStack.Linden
115 return; 114 return;
116 115
117 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 116 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
118 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
119 117
120 foreach (Thread t in m_workerThreads) 118 foreach (Thread t in m_workerThreads)
121 Watchdog.AbortThread(t.ManagedThreadId); 119 Watchdog.AbortThread(t.ManagedThreadId);
@@ -135,7 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden
135 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); 133 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
136 134
137 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
138 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
139 136
140 if (m_workerThreads == null) 137 if (m_workerThreads == null)
141 { 138 {
@@ -178,8 +175,8 @@ namespace OpenSim.Region.ClientStack.Linden
178 175
179 private Scene m_scene; 176 private Scene m_scene;
180 177
181 public PollServiceInventoryEventArgs(Scene scene, UUID pId) : 178 public PollServiceInventoryEventArgs(Scene scene, string url, UUID pId) :
182 base(null, null, null, null, pId, int.MaxValue) 179 base(null, url, null, null, null, pId, int.MaxValue)
183 { 180 {
184 m_scene = scene; 181 m_scene = scene;
185 182
@@ -310,40 +307,39 @@ namespace OpenSim.Region.ClientStack.Linden
310 if (m_fetchInventoryDescendents2Url == "") 307 if (m_fetchInventoryDescendents2Url == "")
311 return; 308 return;
312 309
313 string capUrl = "/CAPS/" + UUID.Random() + "/";
314
315 // Register this as a poll service 310 // Register this as a poll service
316 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID); 311 PollServiceInventoryEventArgs args
317 312 = new PollServiceInventoryEventArgs(m_scene, "/CAPS/" + UUID.Random() + "/", agentID);
318 args.Type = PollServiceEventArgs.EventType.Inventory; 313 args.Type = PollServiceEventArgs.EventType.Inventory;
319 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
320
321 string hostName = m_scene.RegionInfo.ExternalHostName;
322 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
323 string protocol = "http";
324
325 if (MainServer.Instance.UseSSL)
326 {
327 hostName = MainServer.Instance.SSLCommonName;
328 port = MainServer.Instance.SSLPort;
329 protocol = "https";
330 }
331
332 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
333 314
334 m_capsDict[agentID] = capUrl; 315 caps.RegisterPollHandler("FetchInventoryDescendents2", args);
316
317// MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
318//
319// string hostName = m_scene.RegionInfo.ExternalHostName;
320// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
321// string protocol = "http";
322//
323// if (MainServer.Instance.UseSSL)
324// {
325// hostName = MainServer.Instance.SSLCommonName;
326// port = MainServer.Instance.SSLPort;
327// protocol = "https";
328// }
329//
330// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
335 } 331 }
336 332
337 private void DeregisterCaps(UUID agentID, Caps caps) 333// private void DeregisterCaps(UUID agentID, Caps caps)
338 { 334// {
339 string capUrl; 335// string capUrl;
340 336//
341 if (m_capsDict.TryGetValue(agentID, out capUrl)) 337// if (m_capsDict.TryGetValue(agentID, out capUrl))
342 { 338// {
343 MainServer.Instance.RemoveHTTPHandler("", capUrl); 339// MainServer.Instance.RemoveHTTPHandler("", capUrl);
344 m_capsDict.Remove(agentID); 340// m_capsDict.Remove(agentID);
345 } 341// }
346 } 342// }
347 343
348 private void DoInventoryRequests() 344 private void DoInventoryRequests()
349 { 345 {
@@ -353,7 +349,8 @@ namespace OpenSim.Region.ClientStack.Linden
353 349
354 aPollRequest poolreq = m_queue.Dequeue(); 350 aPollRequest poolreq = m_queue.Dequeue();
355 351
356 poolreq.thepoll.Process(poolreq); 352 if (poolreq != null && poolreq.thepoll != null)
353 poolreq.thepoll.Process(poolreq);
357 } 354 }
358 } 355 }
359 } 356 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index dfad485..ac5e77e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -3816,6 +3816,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3816 ResendPrimUpdate(update); 3816 ResendPrimUpdate(update);
3817 } 3817 }
3818 3818
3819// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3820// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3821// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3822// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3823//
3824// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3825// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3826// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3827// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3828
3829
3819 private void ProcessEntityUpdates(int maxUpdates) 3830 private void ProcessEntityUpdates(int maxUpdates)
3820 { 3831 {
3821 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3832 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3828,6 +3839,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3828 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3839 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3829 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3840 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3830 3841
3842// objectUpdateBlocks.Value.Clear();
3843// compressedUpdateBlocks.Value.Clear();
3844// terseUpdateBlocks.Value.Clear();
3845// terseAgentUpdateBlocks.Value.Clear();
3846// objectUpdates.Value.Clear();
3847// compressedUpdates.Value.Clear();
3848// terseUpdates.Value.Clear();
3849// terseAgentUpdates.Value.Clear();
3850
3831 // Check to see if this is a flush 3851 // Check to see if this is a flush
3832 if (maxUpdates <= 0) 3852 if (maxUpdates <= 0)
3833 { 3853 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 77b07ed..b4ac021 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -809,8 +809,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
809 } 809 }
810 810
811 PacketPool.Instance.ReturnPacket(packet); 811 PacketPool.Instance.ReturnPacket(packet);
812 m_dataPresentEvent.Set();
813
812 } 814 }
813 815
816 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
817
814 /// <summary> 818 /// <summary>
815 /// Start the process of sending a packet to the client. 819 /// Start the process of sending a packet to the client.
816 /// </summary> 820 /// </summary>
@@ -1730,6 +1734,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1730 // Action generic every round 1734 // Action generic every round
1731 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1735 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1732 1736
1737// while (true)
1733 while (base.IsRunningOutbound) 1738 while (base.IsRunningOutbound)
1734 { 1739 {
1735 m_scene.ThreadAlive(2); 1740 m_scene.ThreadAlive(2);
@@ -1791,8 +1796,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1791 1796
1792 // If nothing was sent, sleep for the minimum amount of time before a 1797 // If nothing was sent, sleep for the minimum amount of time before a
1793 // token bucket could get more tokens 1798 // token bucket could get more tokens
1794 if (!m_packetSent) 1799 //if (!m_packetSent)
1795 Thread.Sleep((int)TickCountResolution); 1800 // Thread.Sleep((int)TickCountResolution);
1801 m_dataPresentEvent.WaitOne(100);
1796 1802
1797 Watchdog.UpdateThread(); 1803 Watchdog.UpdateThread();
1798 } 1804 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a60b314..505bb53 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -75,10 +75,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
75 public void AddRegion(Scene scene) 75 public void AddRegion(Scene scene)
76 { 76 {
77 m_scene = scene; 77 m_scene = scene;
78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
79
80 if (Enabled) 78 if (Enabled)
81 { 79 {
80 // Only register module with scene if it is enabled. All callers check for a null attachments module.
81 // Ideally, there should be a null attachments module for when this core attachments module has been
82 // disabled. Registering only when enabled allows for other attachments module implementations.
83 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 84 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); 85 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); 86 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 6ce6227..0c759df 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Region.CoreModules.Framework
80 80
81 MainConsole.Instance.Commands.AddCommand( 81 MainConsole.Instance.Commands.AddCommand(
82 "Comms", false, "show caps stats by user", 82 "Comms", false, "show caps stats by user",
83 "show caps stats [<first-name> <last-name>]", 83 "show caps stats by user [<first-name> <last-name>]",
84 "Shows statistics on capabilities use by user.", 84 "Shows statistics on capabilities use by user.",
85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.", 85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.",
86 HandleShowCapsStatsByUserCommand); 86 HandleShowCapsStatsByUserCommand);
@@ -296,27 +296,31 @@ namespace OpenSim.Region.CoreModules.Framework
296 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) 296 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
297 return; 297 return;
298 298
299 StringBuilder caps = new StringBuilder(); 299 StringBuilder capsReport = new StringBuilder();
300 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); 300 capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
301 301
302 lock (m_capsObjects) 302 lock (m_capsObjects)
303 { 303 {
304 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) 304 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
305 { 305 {
306 caps.AppendFormat("** Circuit {0}:\n", kvp.Key); 306 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
307 Caps caps = kvp.Value;
307 308
308 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 309 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
309 { 310 {
310 Uri uri = new Uri(kvp2.Value.ToString()); 311 Uri uri = new Uri(kvp2.Value.ToString());
311 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); 312 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
312 } 313 }
313 314
314 foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) 315 foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers())
315 caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value); 316 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url);
317
318 foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers)
319 capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
316 } 320 }
317 } 321 }
318 322
319 MainConsole.Instance.Output(caps.ToString()); 323 MainConsole.Instance.Output(capsReport.ToString());
320 } 324 }
321 325
322 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams) 326 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams)
@@ -374,7 +378,16 @@ namespace OpenSim.Region.CoreModules.Framework
374 { 378 {
375 receivedStats[sp.Name] = reqHandler.RequestsReceived; 379 receivedStats[sp.Name] = reqHandler.RequestsReceived;
376 handledStats[sp.Name] = reqHandler.RequestsHandled; 380 handledStats[sp.Name] = reqHandler.RequestsHandled;
377 } 381 }
382 else
383 {
384 PollServiceEventArgs pollHandler = null;
385 if (caps.TryGetPollHandler(capName, out pollHandler))
386 {
387 receivedStats[sp.Name] = pollHandler.RequestsReceived;
388 handledStats[sp.Name] = pollHandler.RequestsHandled;
389 }
390 }
378 } 391 }
379 ); 392 );
380 393
@@ -405,11 +418,9 @@ namespace OpenSim.Region.CoreModules.Framework
405 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID); 418 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
406 419
407 if (caps == null) 420 if (caps == null)
408 return; 421 return;
409
410 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
411 422
412 foreach (IRequestHandler reqHandler in capsHandlers.Values) 423 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
413 { 424 {
414 string reqName = reqHandler.Name ?? ""; 425 string reqName = reqHandler.Name ?? "";
415 426
@@ -424,6 +435,23 @@ namespace OpenSim.Region.CoreModules.Framework
424 handledStats[reqName] += reqHandler.RequestsHandled; 435 handledStats[reqName] += reqHandler.RequestsHandled;
425 } 436 }
426 } 437 }
438
439 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
440 {
441 string name = kvp.Key;
442 PollServiceEventArgs pollHandler = kvp.Value;
443
444 if (!receivedStats.ContainsKey(name))
445 {
446 receivedStats[name] = pollHandler.RequestsReceived;
447 handledStats[name] = pollHandler.RequestsHandled;
448 }
449 else
450 {
451 receivedStats[name] += pollHandler.RequestsReceived;
452 handledStats[name] += pollHandler.RequestsHandled;
453 }
454 }
427 } 455 }
428 ); 456 );
429 457
@@ -486,12 +514,16 @@ namespace OpenSim.Region.CoreModules.Framework
486 if (caps == null) 514 if (caps == null)
487 return; 515 return;
488 516
489 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers(); 517 List<CapTableRow> capRows = new List<CapTableRow>();
490 518
491 foreach (IRequestHandler reqHandler in capsHandlers.Values.OrderByDescending(rh => rh.RequestsReceived)) 519 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
492 { 520 capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled));
493 cdt.AddRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled); 521
494 } 522 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
523 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
524
525 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
526 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
495 527
496 sb.Append(cdt.ToString()); 528 sb.Append(cdt.ToString());
497 */ 529 */
@@ -525,6 +557,14 @@ namespace OpenSim.Region.CoreModules.Framework
525 totalRequestsReceived += reqHandler.RequestsReceived; 557 totalRequestsReceived += reqHandler.RequestsReceived;
526 totalRequestsHandled += reqHandler.RequestsHandled; 558 totalRequestsHandled += reqHandler.RequestsHandled;
527 } 559 }
560
561 Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers();
562
563 foreach (PollServiceEventArgs handler in capsPollHandlers.Values)
564 {
565 totalRequestsReceived += handler.RequestsReceived;
566 totalRequestsHandled += handler.RequestsHandled;
567 }
528 568
529 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled); 569 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
530 } 570 }
@@ -533,5 +573,19 @@ namespace OpenSim.Region.CoreModules.Framework
533 sb.Append(cdt.ToString()); 573 sb.Append(cdt.ToString());
534 */ 574 */
535 } 575 }
576
577 private class CapTableRow
578 {
579 public string Name { get; set; }
580 public int RequestsReceived { get; set; }
581 public int RequestsHandled { get; set; }
582
583 public CapTableRow(string name, int requestsReceived, int requestsHandled)
584 {
585 Name = name;
586 RequestsReceived = requestsReceived;
587 RequestsHandled = requestsHandled;
588 }
589 }
536 } 590 }
537} 591}
diff --git a/OpenSim/Region/CoreModules/Framework/GridServiceThrottle/GridServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
index f1eb1ad..a70261e 100644
--- a/OpenSim/Region/CoreModules/Framework/GridServiceThrottle/GridServiceThrottleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
@@ -42,23 +42,37 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42namespace OpenSim.Region.CoreModules.Framework 42namespace OpenSim.Region.CoreModules.Framework
43{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
45 public class GridServiceThrottleModule : ISharedRegionModule 45 public class ServiceThrottleModule : ISharedRegionModule, IServiceThrottleModule
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger( 47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private readonly List<Scene> m_scenes = new List<Scene>(); 50 private readonly List<Scene> m_scenes = new List<Scene>();
51 private System.Timers.Timer m_timer = new System.Timers.Timer();
51 52
52 private OpenSim.Framework.BlockingQueue<GridRegionRequest> m_RequestQueue = new OpenSim.Framework.BlockingQueue<GridRegionRequest>(); 53 private Queue<Action> m_RequestQueue = new Queue<Action>();
54 private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55 private int m_Interval;
56
57 #region ISharedRegionModule
53 58
54 public void Initialise(IConfigSource config) 59 public void Initialise(IConfigSource config)
55 { 60 {
56 Watchdog.StartThread( 61 m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
57 ProcessQueue, 62
58 "GridServiceRequestThread", 63 m_timer = new System.Timers.Timer();
59 ThreadPriority.BelowNormal, 64 m_timer.AutoReset = false;
60 true, 65 m_timer.Enabled = true;
61 false); 66 m_timer.Interval = 15000; // 15 secs at first
67 m_timer.Elapsed += ProcessQueue;
68 m_timer.Start();
69
70 //Watchdog.StartThread(
71 // ProcessQueue,
72 // "GridServiceRequestThread",
73 // ThreadPriority.BelowNormal,
74 // true,
75 // false);
62 } 76 }
63 77
64 public void AddRegion(Scene scene) 78 public void AddRegion(Scene scene)
@@ -66,7 +80,9 @@ namespace OpenSim.Region.CoreModules.Framework
66 lock (m_scenes) 80 lock (m_scenes)
67 { 81 {
68 m_scenes.Add(scene); 82 m_scenes.Add(scene);
83 scene.RegisterModuleInterface<IServiceThrottleModule>(this);
69 scene.EventManager.OnNewClient += OnNewClient; 84 scene.EventManager.OnNewClient += OnNewClient;
85 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
70 } 86 }
71 } 87 }
72 88
@@ -83,11 +99,6 @@ namespace OpenSim.Region.CoreModules.Framework
83 } 99 }
84 } 100 }
85 101
86 void OnNewClient(IClientAPI client)
87 {
88 client.OnRegionHandleRequest += OnRegionHandleRequest;
89 }
90
91 public void PostInitialise() 102 public void PostInitialise()
92 { 103 {
93 } 104 }
@@ -98,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Framework
98 109
99 public string Name 110 public string Name
100 { 111 {
101 get { return "GridServiceThrottleModule"; } 112 get { return "ServiceThrottleModule"; }
102 } 113 }
103 114
104 public Type ReplaceableInterface 115 public Type ReplaceableInterface
@@ -106,9 +117,31 @@ namespace OpenSim.Region.CoreModules.Framework
106 get { return null; } 117 get { return null; }
107 } 118 }
108 119
120 #endregion ISharedRegionMOdule
121
122 #region Events
123
124 void OnNewClient(IClientAPI client)
125 {
126 client.OnRegionHandleRequest += OnRegionHandleRequest;
127 }
128
129 void OnMakeRootAgent(ScenePresence obj)
130 {
131 lock (m_timer)
132 {
133 if (!m_timer.Enabled)
134 {
135 m_timer.Interval = m_Interval;
136 m_timer.Enabled = true;
137 m_timer.Start();
138 }
139 }
140 }
141
109 public void OnRegionHandleRequest(IClientAPI client, UUID regionID) 142 public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
110 { 143 {
111 //m_log.DebugFormat("[GRIDSERVICE THROTTLE]: RegionHandleRequest {0}", regionID); 144 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
112 ulong handle = 0; 145 ulong handle = 0;
113 if (IsLocalRegionHandle(regionID, out handle)) 146 if (IsLocalRegionHandle(regionID, out handle))
114 { 147 {
@@ -116,11 +149,83 @@ namespace OpenSim.Region.CoreModules.Framework
116 return; 149 return;
117 } 150 }
118 151
119 GridRegionRequest request = new GridRegionRequest(client, regionID); 152 Action action = delegate
120 m_RequestQueue.Enqueue(request); 153 {
154 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
155
156 if (r != null && r.RegionHandle != 0)
157 client.SendRegionHandle(regionID, r.RegionHandle);
158 };
159
160 Enqueue("region", regionID.ToString(), action);
161 }
162
163 #endregion Events
164
165 #region IServiceThrottleModule
166
167 public void Enqueue(string category, string itemid, Action continuation)
168 {
169 lock (m_RequestQueue)
170 {
171 if (m_Pending.ContainsKey(category))
172 {
173 if (m_Pending[category].Contains(itemid))
174 // Don't enqueue, it's already pending
175 return;
176 }
177 else
178 m_Pending.Add(category, new List<string>());
179
180 m_Pending[category].Add(itemid);
181
182 m_RequestQueue.Enqueue(delegate
183 {
184 lock (m_RequestQueue)
185 m_Pending[category].Remove(itemid);
186
187 continuation();
188 });
189 }
190 }
191
192 #endregion IServiceThrottleModule
193
194 #region Process Continuation Queue
195
196 private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197 {
198 //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199
200 while (m_RequestQueue.Count > 0)
201 {
202 Action continuation = null;
203 lock (m_RequestQueue)
204 continuation = m_RequestQueue.Dequeue();
205
206 if (continuation != null)
207 continuation();
208 }
209
210 if (AreThereRootAgents())
211 {
212 lock (m_timer)
213 {
214 m_timer.Interval = 1000; // 1 sec
215 m_timer.Enabled = true;
216 m_timer.Start();
217 }
218 }
219 else
220 lock (m_timer)
221 m_timer.Enabled = false;
121 222
122 } 223 }
123 224
225 #endregion Process Continuation Queue
226
227 #region Misc
228
124 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle) 229 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
125 { 230 {
126 regionHandle = 0; 231 regionHandle = 0;
@@ -133,31 +238,19 @@ namespace OpenSim.Region.CoreModules.Framework
133 return false; 238 return false;
134 } 239 }
135 240
136 private void ProcessQueue() 241 private bool AreThereRootAgents()
137 { 242 {
138 while (true) 243 foreach (Scene s in m_scenes)
139 { 244 {
140 Watchdog.UpdateThread(); 245 foreach (ScenePresence sp in s.GetScenePresences())
141 246 if (!sp.IsChildAgent)
142 GridRegionRequest request = m_RequestQueue.Dequeue(); 247 return true;
143 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, request.regionID);
144
145 if (r != null && r.RegionHandle != 0)
146 request.client.SendRegionHandle(request.regionID, r.RegionHandle);
147
148 } 248 }
149 }
150 }
151
152 class GridRegionRequest
153 {
154 public IClientAPI client;
155 public UUID regionID;
156 249
157 public GridRegionRequest(IClientAPI c, UUID r) 250 return false;
158 {
159 client = c;
160 regionID = r;
161 } 251 }
252
253 #endregion Misc
162 } 254 }
255
163} 256}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index a528093..a91adfa 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -56,13 +56,10 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
56 protected bool m_Enabled; 56 protected bool m_Enabled;
57 protected List<Scene> m_Scenes = new List<Scene>(); 57 protected List<Scene> m_Scenes = new List<Scene>();
58 58
59 protected IServiceThrottleModule m_ServiceThrottle;
59 // The cache 60 // The cache
60 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); 61 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
61 62
62 // Throttle the name requests
63 private OpenSim.Framework.BlockingQueue<NameRequest> m_RequestQueue = new OpenSim.Framework.BlockingQueue<NameRequest>();
64
65
66 #region ISharedRegionModule 63 #region ISharedRegionModule
67 64
68 public void Initialise(IConfigSource config) 65 public void Initialise(IConfigSource config)
@@ -115,6 +112,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
115 112
116 public void RegionLoaded(Scene s) 113 public void RegionLoaded(Scene s)
117 { 114 {
115 if (m_Enabled && m_ServiceThrottle == null)
116 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
118 } 117 }
119 118
120 public void PostInitialise() 119 public void PostInitialise()
@@ -154,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
154 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); 153 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
155 } 154 }
156 155
157 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 156 void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
158 { 157 {
159// m_log.DebugFormat( 158// m_log.DebugFormat(
160// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}", 159// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
@@ -162,12 +161,31 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
162 161
163 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 162 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
164 { 163 {
165 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 164 client.SendNameReply(uuid, "Mr", "OpenSim");
166 } 165 }
167 else 166 else
168 { 167 {
169 NameRequest request = new NameRequest(remote_client, uuid); 168 string[] names = new string[2];
170 m_RequestQueue.Enqueue(request); 169 if (TryGetUserNamesFromCache(uuid, names))
170 {
171 client.SendNameReply(uuid, names[0], names[1]);
172 return;
173 }
174
175 // Not found in cache, queue continuation
176 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
177 {
178 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
179 bool foundRealName = TryGetUserNames(uuid, names);
180
181 if (names.Length == 2)
182 {
183 if (!foundRealName)
184 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, client.Name);
185
186 client.SendNameReply(uuid, names[0], names[1]);
187 }
188 });
171 189
172 } 190 }
173 } 191 }
@@ -283,15 +301,27 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
283 } 301 }
284 302
285 /// <summary> 303 /// <summary>
286 /// Try to get the names bound to the given uuid. 304 ///
287 /// </summary> 305 /// </summary>
288 /// <returns>True if the name was found, false if not.</returns> 306 /// <param name="uuid"></param>
289 /// <param name='uuid'></param> 307 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
290 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param> 308 /// <returns></returns>
291 private bool TryGetUserNames(UUID uuid, out string[] names) 309 private bool TryGetUserNames(UUID uuid, string[] names)
292 { 310 {
293 names = new string[2]; 311 if (names == null)
312 names = new string[2];
313
314 if (TryGetUserNamesFromCache(uuid, names))
315 return true;
316
317 if (TryGetUserNamesFromServices(uuid, names))
318 return true;
319
320 return false;
321 }
294 322
323 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
324 {
295 lock (m_UserCache) 325 lock (m_UserCache)
296 { 326 {
297 if (m_UserCache.ContainsKey(uuid)) 327 if (m_UserCache.ContainsKey(uuid))
@@ -303,6 +333,17 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
303 } 333 }
304 } 334 }
305 335
336 return false;
337 }
338
339 /// <summary>
340 /// Try to get the names bound to the given uuid, from the services.
341 /// </summary>
342 /// <returns>True if the name was found, false if not.</returns>
343 /// <param name='uuid'></param>
344 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
345 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
346 {
306 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); 347 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
307 348
308 if (account != null) 349 if (account != null)
@@ -387,18 +428,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
387 428
388 public string GetUserName(UUID uuid) 429 public string GetUserName(UUID uuid)
389 { 430 {
390 string[] names; 431 string[] names = new string[2];
391 TryGetUserNames(uuid, out names); 432 TryGetUserNames(uuid, names);
392 433
393 if (names.Length == 2) 434 return names[0] + " " + names[1];
394 {
395 string firstname = names[0];
396 string lastname = names[1];
397
398 return firstname + " " + lastname;
399 }
400 435
401 return "(hippos)";
402 } 436 }
403 437
404 public string GetUserHomeURL(UUID userID) 438 public string GetUserHomeURL(UUID userID)
@@ -598,13 +632,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
598 protected void Init() 632 protected void Init()
599 { 633 {
600 RegisterConsoleCmds(); 634 RegisterConsoleCmds();
601 Watchdog.StartThread(
602 ProcessQueue,
603 "NameRequestThread",
604 ThreadPriority.BelowNormal,
605 true,
606 false);
607
608 } 635 }
609 636
610 protected void RegisterConsoleCmds() 637 protected void RegisterConsoleCmds()
@@ -674,39 +701,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
674 MainConsole.Instance.Output(cdt.ToString()); 701 MainConsole.Instance.Output(cdt.ToString());
675 } 702 }
676 703
677 private void ProcessQueue()
678 {
679 while (true)
680 {
681 Watchdog.UpdateThread();
682
683 NameRequest request = m_RequestQueue.Dequeue();
684 string[] names;
685 bool foundRealName = TryGetUserNames(request.uuid, out names);
686
687 if (names.Length == 2)
688 {
689 if (!foundRealName)
690 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], request.uuid, request.client.Name);
691
692 request.client.SendNameReply(request.uuid, names[0], names[1]);
693 }
694
695 }
696 }
697
698 }
699
700 class NameRequest
701 {
702 public IClientAPI client;
703 public UUID uuid;
704
705 public NameRequest(IClientAPI c, UUID n)
706 {
707 client = c;
708 uuid = n;
709 }
710 } 704 }
711 705
712} \ No newline at end of file 706} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 2a4d440..1983fed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -219,7 +219,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
219 219
220 string uri = "/lslhttp/" + urlcode.ToString(); 220 string uri = "/lslhttp/" + urlcode.ToString();
221 221
222 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 222 PollServiceEventArgs args
223 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
223 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
224 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
225 226
@@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
266 267
267 string uri = "/lslhttps/" + urlcode.ToString(); 268 string uri = "/lslhttps/" + urlcode.ToString();
268 269
269 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 270 PollServiceEventArgs args
271 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
270 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
271 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
272 274
diff --git a/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
new file mode 100644
index 0000000..198256f
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
@@ -0,0 +1,19 @@
1using System;
2using System.Collections.Generic;
3
4namespace OpenSim.Region.Framework.Interfaces
5{
6 public interface IServiceThrottleModule
7 {
8 /// <summary>
9 /// Enqueue a continuation meant to get a resource from elsewhere.
10 /// As usual with CPS, caller beware: if that continuation is a never-ending computation,
11 /// the whole thread will be blocked, and no requests are processed
12 /// </summary>
13 /// <param name="category">Category of the resource (e.g. name, region)</param>
14 /// <param name="itemid">The resource identifier</param>
15 /// <param name="continuation">The continuation to be executed</param>
16 void Enqueue(string category, string itemid, Action continuation);
17 }
18
19}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 8c9c006..b0a29c0 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -116,7 +116,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
116 return false; 116 return false;
117 117
118 // Delete existing npc attachments 118 // Delete existing npc attachments
119 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); 119 if(scene.AttachmentsModule != null)
120 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
120 121
121 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet 122 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
122 // since it doesn't transfer attachments 123 // since it doesn't transfer attachments
@@ -125,7 +126,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
125 npc.Appearance = npcAppearance; 126 npc.Appearance = npcAppearance;
126 127
127 // Rez needed npc attachments 128 // Rez needed npc attachments
128 scene.AttachmentsModule.RezAttachments(npc); 129 if (scene.AttachmentsModule != null)
130 scene.AttachmentsModule.RezAttachments(npc);
129 131
130 IAvatarFactoryModule module = 132 IAvatarFactoryModule module =
131 scene.RequestModuleInterface<IAvatarFactoryModule>(); 133 scene.RequestModuleInterface<IAvatarFactoryModule>();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index 928b350..0f11c4a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -130,6 +130,7 @@ public class BSActorAvatarMove : BSActor
130 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); 130 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
131 131
132 m_physicsScene.BeforeStep += Mover; 132 m_physicsScene.BeforeStep += Mover;
133 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
133 134
134 m_walkingUpStairs = 0; 135 m_walkingUpStairs = 0;
135 } 136 }
@@ -139,6 +140,7 @@ public class BSActorAvatarMove : BSActor
139 { 140 {
140 if (m_velocityMotor != null) 141 if (m_velocityMotor != null)
141 { 142 {
143 m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty;
142 m_physicsScene.BeforeStep -= Mover; 144 m_physicsScene.BeforeStep -= Mover;
143 m_velocityMotor = null; 145 m_velocityMotor = null;
144 } 146 }
@@ -197,7 +199,7 @@ public class BSActorAvatarMove : BSActor
197 { 199 {
198 if (m_controllingPrim.Flying) 200 if (m_controllingPrim.Flying)
199 { 201 {
200 // Flying and not collising and velocity nearly zero. 202 // Flying and not colliding and velocity nearly zero.
201 m_controllingPrim.ZeroMotion(true /* inTaintTime */); 203 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
202 } 204 }
203 } 205 }
@@ -266,6 +268,19 @@ public class BSActorAvatarMove : BSActor
266 } 268 }
267 } 269 }
268 270
271 // Called just as the property update is received from the physics engine.
272 // Do any mode necessary for avatar movement.
273 private void Process_OnPreUpdateProperty(ref EntityProperties entprop)
274 {
275 // Don't change position if standing on a stationary object.
276 if (m_controllingPrim.IsStationary)
277 {
278 entprop.Position = m_controllingPrim.RawPosition;
279 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
280 }
281
282 }
283
269 // Decide if the character is colliding with a low object and compute a force to pop the 284 // Decide if the character is colliding with a low object and compute a force to pop the
270 // avatar up so it can walk up and over the low objects. 285 // avatar up so it can walk up and over the low objects.
271 private OMV.Vector3 WalkUpStairs() 286 private OMV.Vector3 WalkUpStairs()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index c9e3ca0..59e7f5f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -709,10 +709,10 @@ public sealed class BSCharacter : BSPhysObject
709 // the world that things have changed. 709 // the world that things have changed.
710 public override void UpdateProperties(EntityProperties entprop) 710 public override void UpdateProperties(EntityProperties entprop)
711 { 711 {
712 // Don't change position if standing on a stationary object. 712 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
713 if (!IsStationary) 713 TriggerPreUpdatePropertyAction(ref entprop);
714 RawPosition = entprop.Position;
715 714
715 RawPosition = entprop.Position;
716 RawOrientation = entprop.Rotation; 716 RawOrientation = entprop.Rotation;
717 717
718 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar 718 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
@@ -740,7 +740,7 @@ public sealed class BSCharacter : BSPhysObject
740 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 740 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
741 741
742 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 742 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
743 // base.RequestPhysicsterseUpdate(); 743 // PhysScene.PostUpdate(this);
744 744
745 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 745 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
746 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity); 746 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index a41eaf8..fc4545f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -103,9 +103,10 @@ public abstract class BSPhysObject : PhysicsActor
103 CollisionsLastTickStep = -1; 103 CollisionsLastTickStep = -1;
104 104
105 SubscribedEventsMs = 0; 105 SubscribedEventsMs = 0;
106 CollidingStep = 0; 106 // Crazy values that will never be true
107 CollidingGroundStep = 0; 107 CollidingStep = BSScene.NotASimulationStep;
108 CollisionAccumulation = 0; 108 CollidingGroundStep = BSScene.NotASimulationStep;
109 CollisionAccumulation = BSScene.NotASimulationStep;
109 ColliderIsMoving = false; 110 ColliderIsMoving = false;
110 CollisionScore = 0; 111 CollisionScore = 0;
111 112
@@ -349,7 +350,7 @@ public abstract class BSPhysObject : PhysicsActor
349 if (value) 350 if (value)
350 CollidingStep = PhysScene.SimulationStep; 351 CollidingStep = PhysScene.SimulationStep;
351 else 352 else
352 CollidingStep = 0; 353 CollidingStep = BSScene.NotASimulationStep;
353 } 354 }
354 } 355 }
355 public override bool CollidingGround { 356 public override bool CollidingGround {
@@ -359,7 +360,7 @@ public abstract class BSPhysObject : PhysicsActor
359 if (value) 360 if (value)
360 CollidingGroundStep = PhysScene.SimulationStep; 361 CollidingGroundStep = PhysScene.SimulationStep;
361 else 362 else
362 CollidingGroundStep = 0; 363 CollidingGroundStep = BSScene.NotASimulationStep;
363 } 364 }
364 } 365 }
365 public override bool CollidingObj { 366 public override bool CollidingObj {
@@ -368,7 +369,7 @@ public abstract class BSPhysObject : PhysicsActor
368 if (value) 369 if (value)
369 CollidingObjectStep = PhysScene.SimulationStep; 370 CollidingObjectStep = PhysScene.SimulationStep;
370 else 371 else
371 CollidingObjectStep = 0; 372 CollidingObjectStep = BSScene.NotASimulationStep;
372 } 373 }
373 } 374 }
374 375
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 214271b..41aca3b 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -97,6 +97,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
97 97
98 internal long m_simulationStep = 0; // The current simulation step. 98 internal long m_simulationStep = 0; // The current simulation step.
99 public long SimulationStep { get { return m_simulationStep; } } 99 public long SimulationStep { get { return m_simulationStep; } }
100 // A number to use for SimulationStep that is probably not any step value
101 // Used by the collision code (which remembers the step when a collision happens) to remember not any simulation step.
102 public static long NotASimulationStep = -1234;
100 103
101 internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate() 104 internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate()
102 105
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
index f424e7f..83732e2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.RegionCombinerModule
51 m_virtScene.UnSubscribeToClientPrimEvents(client); 51 m_virtScene.UnSubscribeToClientPrimEvents(client);
52 m_virtScene.UnSubscribeToClientPrimRezEvents(client); 52 m_virtScene.UnSubscribeToClientPrimRezEvents(client);
53 m_virtScene.UnSubscribeToClientInventoryEvents(client); 53 m_virtScene.UnSubscribeToClientInventoryEvents(client);
54 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client); 54 if(m_virtScene.AttachmentsModule != null)
55 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client);
55 //m_virtScene.UnSubscribeToClientTeleportEvents(client); 56 //m_virtScene.UnSubscribeToClientTeleportEvents(client);
56 m_virtScene.UnSubscribeToClientScriptEvents(client); 57 m_virtScene.UnSubscribeToClientScriptEvents(client);
57 58
@@ -66,7 +67,8 @@ namespace OpenSim.Region.RegionCombinerModule
66 client.OnRezObject += LocalRezObject; 67 client.OnRezObject += LocalRezObject;
67 68
68 m_rootScene.SubscribeToClientInventoryEvents(client); 69 m_rootScene.SubscribeToClientInventoryEvents(client);
69 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client); 70 if (m_rootScene.AttachmentsModule != null)
71 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client);
70 //m_rootScene.SubscribeToClientTeleportEvents(client); 72 //m_rootScene.SubscribeToClientTeleportEvents(client);
71 m_rootScene.SubscribeToClientScriptEvents(client); 73 m_rootScene.SubscribeToClientScriptEvents(client);
72 74