aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-19 15:19:09 -0700
committerJohn Hurliman2009-10-19 15:19:09 -0700
commit142008121e2e9c5ca5fca5de07b8a14e37279800 (patch)
tree003824e2639ba00636e3133d2f991b62d8b79bdc
parentMerge branch 'prioritization' of ssh://opensimulator.org/var/git/opensim into... (diff)
downloadopensim-SC_OLD-142008121e2e9c5ca5fca5de07b8a14e37279800.zip
opensim-SC_OLD-142008121e2e9c5ca5fca5de07b8a14e37279800.tar.gz
opensim-SC_OLD-142008121e2e9c5ca5fca5de07b8a14e37279800.tar.bz2
opensim-SC_OLD-142008121e2e9c5ca5fca5de07b8a14e37279800.tar.xz
* Change Util.FireAndForget to use ThreadPool.UnsafeQueueUserWorkItem(). This avoids .NET remoting and a managed->unmanaged->managed jump. Overall, a night and day performance difference
* Initialize the LLClientView prim full update queue to the number of prims in the scene for a big performance boost * Reordered some comparisons on hot code paths for a minor speed boost * Removed an unnecessary call to the expensive DateTime.Now function (if you *have* to get the current time as opposed to Environment.TickCount, always use DateTime.UtcNow) * Don't fire the queue empty callback for the Resend category * Run the outgoing packet handler thread loop for each client synchronously. It seems like more time was being spent doing the execution asynchronously, and it made deadlocks very difficult to track down * Rewrote some expensive math in LandObject.cs * Optimized EntityManager to only lock on operations that need locking, and use TryGetValue() where possible * Only update the attachment database when an object is attached or detached * Other small misc. performance improvements
-rw-r--r--OpenSim/Framework/Util.cs18
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs88
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs9
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs19
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs69
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
12 files changed, 127 insertions, 128 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 3203fc1..d5ae3b7 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1273,7 +1273,7 @@ namespace OpenSim.Framework
1273 /// <summary> 1273 /// <summary>
1274 /// Created to work around a limitation in Mono with nested delegates 1274 /// Created to work around a limitation in Mono with nested delegates
1275 /// </summary> 1275 /// </summary>
1276 private class FireAndForgetWrapper 1276 /*private class FireAndForgetWrapper
1277 { 1277 {
1278 public void FireAndForget(System.Threading.WaitCallback callback) 1278 public void FireAndForget(System.Threading.WaitCallback callback)
1279 { 1279 {
@@ -1284,21 +1284,23 @@ namespace OpenSim.Framework
1284 { 1284 {
1285 callback.BeginInvoke(obj, EndFireAndForget, callback); 1285 callback.BeginInvoke(obj, EndFireAndForget, callback);
1286 } 1286 }
1287 } 1287 }*/
1288 1288
1289 public static void FireAndForget(System.Threading.WaitCallback callback) 1289 public static void FireAndForget(System.Threading.WaitCallback callback)
1290 { 1290 {
1291 FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); 1291 //FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
1292 wrapper.FireAndForget(callback); 1292 //wrapper.FireAndForget(callback);
1293 System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null);
1293 } 1294 }
1294 1295
1295 public static void FireAndForget(System.Threading.WaitCallback callback, object obj) 1296 public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
1296 { 1297 {
1297 FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); 1298 //FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
1298 wrapper.FireAndForget(callback, obj); 1299 //wrapper.FireAndForget(callback, obj);
1300 System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
1299 } 1301 }
1300 1302
1301 private static void EndFireAndForget(IAsyncResult ar) 1303 /*private static void EndFireAndForget(IAsyncResult ar)
1302 { 1304 {
1303 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; 1305 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
1304 1306
@@ -1306,7 +1308,7 @@ namespace OpenSim.Framework
1306 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } 1308 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
1307 1309
1308 ar.AsyncWaitHandle.Close(); 1310 ar.AsyncWaitHandle.Close();
1309 } 1311 }*/
1310 1312
1311 #endregion FireAndForget Threading Pattern 1313 #endregion FireAndForget Threading Pattern
1312 } 1314 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 1c463ea..b027882 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -321,12 +321,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
321 private readonly IGroupsModule m_GroupsModule; 321 private readonly IGroupsModule m_GroupsModule;
322 322
323 private int m_cachedTextureSerial; 323 private int m_cachedTextureSerial;
324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = 324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
325 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
326 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = 326 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
327 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
328 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates =
329 new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>();
330 private int m_moneyBalance; 327 private int m_moneyBalance;
331 private int m_animationSequenceNumber = 1; 328 private int m_animationSequenceNumber = 1;
332 private bool m_SendLogoutPacketWhenClosing = true; 329 private bool m_SendLogoutPacketWhenClosing = true;
@@ -335,7 +332,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
335 332
336 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); 333 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
337 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 334 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
338 protected IScene m_scene; 335 protected Scene m_scene;
339 protected LLImageManager m_imageManager; 336 protected LLImageManager m_imageManager;
340 protected string m_firstName; 337 protected string m_firstName;
341 protected string m_lastName; 338 protected string m_lastName;
@@ -408,16 +405,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
408 /// <summary> 405 /// <summary>
409 /// Constructor 406 /// Constructor
410 /// </summary> 407 /// </summary>
411 public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, 408 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
412 UUID agentId, UUID sessionId, uint circuitCode) 409 UUID agentId, UUID sessionId, uint circuitCode)
413 { 410 {
414 RegisterInterface<IClientIM>(this); 411 RegisterInterface<IClientIM>(this);
415 RegisterInterface<IClientChat>(this); 412 RegisterInterface<IClientChat>(this);
416 RegisterInterface<IClientIPEndpoint>(this); 413 RegisterInterface<IClientIPEndpoint>(this);
417 414
418 InitDefaultAnimations(); 415 InitDefaultAnimations();
419 416
420 m_scene = scene; 417 m_scene = scene;
418
419 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
420 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
421 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
422
421 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 423 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
422 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>(); 424 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>();
423 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); 425 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
@@ -3288,10 +3290,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3288 } 3290 }
3289 3291
3290 Quaternion rotation = data.Rotation; 3292 Quaternion rotation = data.Rotation;
3291 3293 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3292 if (rotation.X == rotation.Y &&
3293 rotation.Y == rotation.Z &&
3294 rotation.Z == rotation.W && rotation.W == 0.0f)
3295 rotation = Quaternion.Identity; 3294 rotation = Quaternion.Identity;
3296 3295
3297 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data); 3296 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
@@ -3377,15 +3376,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3377 } 3376 }
3378 3377
3379 Quaternion rotation = data.rotation; 3378 Quaternion rotation = data.rotation;
3379 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3380 rotation = Quaternion.Identity;
3380 3381
3381 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD 3382 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3382 return; 3383 return;
3383 if (data.primShape.PCode == 9 && data.primShape.State != 0 && data.parentID == 0) 3384 if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
3384 return; 3385 return;
3385 3386
3386 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0.0f)
3387 rotation = Quaternion.Identity;
3388
3389 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data); 3387 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
3390 3388
3391 lock (m_primFullUpdates.SyncRoot) 3389 lock (m_primFullUpdates.SyncRoot)
@@ -3397,7 +3395,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3397 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3395 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3398 outPacket.Header.Zerocoded = true; 3396 outPacket.Header.Zerocoded = true;
3399 3397
3400 //outPacket.RegionData = new ObjectUpdatePacket.RegionDataBlock();
3401 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3398 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3402 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); 3399 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3403 3400
@@ -3424,13 +3421,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3424 } 3421 }
3425 3422
3426 Quaternion rotation = data.Rotation; 3423 Quaternion rotation = data.Rotation;
3424 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3425 rotation = Quaternion.Identity;
3427 3426
3428 if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD 3427 if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
3429 return; 3428 return;
3430 3429
3431 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
3432 rotation = Quaternion.Identity;
3433
3434 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data); 3430 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
3435 3431
3436 lock (m_primTerseUpdates.SyncRoot) 3432 lock (m_primTerseUpdates.SyncRoot)
@@ -10238,10 +10234,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10238 { 10234 {
10239 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id); 10235 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
10240 10236
10241 private MinHeap<MinHeapItem>[] heaps = new MinHeap<MinHeapItem>[1]; 10237 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
10242 private Dictionary<uint, LookupItem> lookup_table = new Dictionary<uint, LookupItem>(); 10238 private Dictionary<uint, LookupItem> m_lookupTable;
10243 private Comparison<TPriority> comparison; 10239 private Comparison<TPriority> m_comparison;
10244 private object sync_root = new object(); 10240 private object m_syncRoot = new object();
10245 10241
10246 internal PriorityQueue() : 10242 internal PriorityQueue() :
10247 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<TPriority>.Default) { } 10243 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<TPriority>.Default) { }
@@ -10255,19 +10251,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10255 this(capacity, new Comparison<TPriority>(comparer.Compare)) { } 10251 this(capacity, new Comparison<TPriority>(comparer.Compare)) { }
10256 internal PriorityQueue(int capacity, Comparison<TPriority> comparison) 10252 internal PriorityQueue(int capacity, Comparison<TPriority> comparison)
10257 { 10253 {
10258 for (int i = 0; i < heaps.Length; ++i) 10254 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
10259 heaps[i] = new MinHeap<MinHeapItem>(capacity); 10255
10260 this.comparison = comparison; 10256 for (int i = 0; i < m_heaps.Length; ++i)
10257 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
10258 this.m_comparison = comparison;
10261 } 10259 }
10262 10260
10263 internal object SyncRoot { get { return this.sync_root; } } 10261 internal object SyncRoot { get { return this.m_syncRoot; } }
10264 internal int Count 10262 internal int Count
10265 { 10263 {
10266 get 10264 get
10267 { 10265 {
10268 int count = 0; 10266 int count = 0;
10269 for (int i = 0; i < heaps.Length; ++i) 10267 for (int i = 0; i < m_heaps.Length; ++i)
10270 count = heaps[i].Count; 10268 count = m_heaps[i].Count;
10271 return count; 10269 return count;
10272 } 10270 }
10273 } 10271 }
@@ -10276,36 +10274,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10276 { 10274 {
10277 LookupItem item; 10275 LookupItem item;
10278 10276
10279 if (lookup_table.TryGetValue(local_id, out item)) 10277 if (m_lookupTable.TryGetValue(local_id, out item))
10280 { 10278 {
10281 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.comparison); 10279 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
10282 return false; 10280 return false;
10283 } 10281 }
10284 else 10282 else
10285 { 10283 {
10286 item.Heap = heaps[0]; 10284 item.Heap = m_heaps[0];
10287 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.comparison), ref item.Handle); 10285 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
10288 lookup_table.Add(local_id, item); 10286 m_lookupTable.Add(local_id, item);
10289 return true; 10287 return true;
10290 } 10288 }
10291 } 10289 }
10292 10290
10293 internal TValue Peek() 10291 internal TValue Peek()
10294 { 10292 {
10295 for (int i = 0; i < heaps.Length; ++i) 10293 for (int i = 0; i < m_heaps.Length; ++i)
10296 if (heaps[i].Count > 0) 10294 if (m_heaps[i].Count > 0)
10297 return heaps[i].Min().Value; 10295 return m_heaps[i].Min().Value;
10298 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); 10296 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10299 } 10297 }
10300 10298
10301 internal TValue Dequeue() 10299 internal TValue Dequeue()
10302 { 10300 {
10303 for (int i = 0; i < heaps.Length; ++i) 10301 for (int i = 0; i < m_heaps.Length; ++i)
10304 { 10302 {
10305 if (heaps[i].Count > 0) 10303 if (m_heaps[i].Count > 0)
10306 { 10304 {
10307 MinHeapItem item = heaps[i].RemoveMin(); 10305 MinHeapItem item = m_heaps[i].RemoveMin();
10308 lookup_table.Remove(item.LocalID); 10306 m_lookupTable.Remove(item.LocalID);
10309 return item.Value; 10307 return item.Value;
10310 } 10308 }
10311 } 10309 }
@@ -10317,7 +10315,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10317 MinHeapItem item; 10315 MinHeapItem item;
10318 TPriority priority; 10316 TPriority priority;
10319 10317
10320 foreach (LookupItem lookup in new List<LookupItem>(this.lookup_table.Values)) 10318 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
10321 { 10319 {
10322 if (lookup.Heap.TryGetValue(lookup.Handle, out item)) 10320 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
10323 { 10321 {
@@ -10332,7 +10330,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10332 { 10330 {
10333 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update"); 10331 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
10334 lookup.Heap.Remove(lookup.Handle); 10332 lookup.Heap.Remove(lookup.Handle);
10335 this.lookup_table.Remove(item.LocalID); 10333 this.m_lookupTable.Remove(item.LocalID);
10336 } 10334 }
10337 } 10335 }
10338 } 10336 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index d25bf95..938cf50 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -51,7 +51,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
51 51
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private bool m_shuttingdown; 53 private bool m_shuttingdown;
54 private long m_lastloopprocessed;
55 private AssetBase m_missingImage; 54 private AssetBase m_missingImage;
56 private LLClientView m_client; //Client we're assigned to 55 private LLClientView m_client; //Client we're assigned to
57 private IAssetService m_assetCache; //Asset Cache 56 private IAssetService m_assetCache; //Asset Cache
@@ -169,7 +168,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
169 168
170 public bool ProcessImageQueue(int packetsToSend) 169 public bool ProcessImageQueue(int packetsToSend)
171 { 170 {
172 m_lastloopprocessed = DateTime.Now.Ticks;
173 int packetsSent = 0; 171 int packetsSent = 0;
174 172
175 while (packetsSent < packetsToSend) 173 while (packetsSent < packetsToSend)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 9476eed..4b6a358 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -506,8 +506,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
506 /// for</param> 506 /// for</param>
507 private void BeginFireQueueEmpty(int throttleIndex) 507 private void BeginFireQueueEmpty(int throttleIndex)
508 { 508 {
509 if (!m_onQueueEmptyRunning[throttleIndex]) 509 // Unknown is -1 and Resend is 0. Make sure we are only firing the
510 Util.FireAndForget(FireQueueEmpty, throttleIndex); 510 // callback for categories other than those
511 if (throttleIndex > 0)
512 {
513 if (!m_onQueueEmptyRunning[throttleIndex])
514 Util.FireAndForget(FireQueueEmpty, throttleIndex);
515 }
511 } 516 }
512 517
513 /// <summary> 518 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 66e1468..74175d0 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -107,7 +107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
107 /// <summary>Manages authentication for agent circuits</summary> 107 /// <summary>Manages authentication for agent circuits</summary>
108 private AgentCircuitManager m_circuitManager; 108 private AgentCircuitManager m_circuitManager;
109 /// <summary>Reference to the scene this UDP server is attached to</summary> 109 /// <summary>Reference to the scene this UDP server is attached to</summary>
110 private IScene m_scene; 110 private Scene m_scene;
111 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 111 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
112 private Location m_location; 112 private Location m_location;
113 /// <summary>The measured resolution of Environment.TickCount</summary> 113 /// <summary>The measured resolution of Environment.TickCount</summary>
@@ -184,15 +184,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
184 184
185 public void AddScene(IScene scene) 185 public void AddScene(IScene scene)
186 { 186 {
187 if (m_scene == null) 187 if (m_scene != null)
188 { 188 {
189 m_scene = scene; 189 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
190 m_location = new Location(m_scene.RegionInfo.RegionHandle); 190 return;
191 } 191 }
192 else 192
193 if (!(scene is Scene))
193 { 194 {
194 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); 195 m_log.Error("[LLUDPSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType());
196 return;
195 } 197 }
198
199 m_scene = (Scene)scene;
200 m_location = new Location(m_scene.RegionInfo.RegionHandle);
196 } 201 }
197 202
198 public bool HandlesRegion(Location x) 203 public bool HandlesRegion(Location x)
@@ -794,7 +799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
794 elapsed500MS = 0; 799 elapsed500MS = 0;
795 } 800 }
796 801
797 m_scene.ClientManager.ForEach( 802 m_scene.ClientManager.ForEachSync(
798 delegate(IClientAPI client) 803 delegate(IClientAPI client)
799 { 804 {
800 if (client is LLClientView) 805 if (client is LLClientView)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 332d3ce..53c64cb 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -147,9 +147,10 @@ namespace OpenSim.Region.CoreModules.World.Land
147 client.OnParcelDwellRequest += ClientOnParcelDwellRequest; 147 client.OnParcelDwellRequest += ClientOnParcelDwellRequest;
148 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; 148 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
149 149
150 if (m_scene.Entities.ContainsKey(client.AgentId)) 150 EntityBase presenceEntity;
151 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
151 { 152 {
152 SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true); 153 SendLandUpdate((ScenePresence)presenceEntity, true);
153 SendParcelOverlay(client); 154 SendParcelOverlay(client);
154 } 155 }
155 } 156 }
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index b9b7da5..bfe85f1 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -139,10 +139,8 @@ namespace OpenSim.Region.CoreModules.World.Land
139 } 139 }
140 else 140 else
141 { 141 {
142 //Normal Calculations 142 // Normal Calculations
143 return Convert.ToInt32( 143 return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.objectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
144 Math.Round((Convert.ToDecimal(LandData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
145 Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ;
146 } 144 }
147 } 145 }
148 public int GetSimulatorMaxPrimCount(ILandObject thisObject) 146 public int GetSimulatorMaxPrimCount(ILandObject thisObject)
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index 0ceef39..099fcce 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -93,40 +93,31 @@ namespace OpenSim.Region.Framework.Scenes
93 { 93 {
94 get 94 get
95 { 95 {
96 lock (m_lock) 96 return m_eb_uuid.Count;
97 {
98 return m_eb_uuid.Count;
99 }
100 } 97 }
101 } 98 }
102 99
103 public bool ContainsKey(UUID id) 100 public bool ContainsKey(UUID id)
104 { 101 {
105 lock (m_lock) 102 try
106 { 103 {
107 try 104 return m_eb_uuid.ContainsKey(id);
108 { 105 }
109 return m_eb_uuid.ContainsKey(id); 106 catch
110 } 107 {
111 catch 108 return false;
112 {
113 return false;
114 }
115 } 109 }
116 } 110 }
117 111
118 public bool ContainsKey(uint localID) 112 public bool ContainsKey(uint localID)
119 { 113 {
120 lock (m_lock) 114 try
121 { 115 {
122 try 116 return m_eb_localID.ContainsKey(localID);
123 { 117 }
124 return m_eb_localID.ContainsKey(localID); 118 catch
125 } 119 {
126 catch 120 return false;
127 {
128 return false;
129 }
130 } 121 }
131 } 122 }
132 123
@@ -136,7 +127,11 @@ namespace OpenSim.Region.Framework.Scenes
136 { 127 {
137 try 128 try
138 { 129 {
139 bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID); 130 bool a = false;
131 EntityBase entity;
132 if (m_eb_localID.TryGetValue(localID, out entity))
133 a = m_eb_uuid.Remove(entity.UUID);
134
140 bool b = m_eb_localID.Remove(localID); 135 bool b = m_eb_localID.Remove(localID);
141 return a && b; 136 return a && b;
142 } 137 }
@@ -154,7 +149,11 @@ namespace OpenSim.Region.Framework.Scenes
154 { 149 {
155 try 150 try
156 { 151 {
157 bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId); 152 bool a = false;
153 EntityBase entity;
154 if (m_eb_uuid.TryGetValue(id, out entity))
155 a = m_eb_localID.Remove(entity.LocalId);
156
158 bool b = m_eb_uuid.Remove(id); 157 bool b = m_eb_uuid.Remove(id);
159 return a && b; 158 return a && b;
160 } 159 }
@@ -206,14 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
206 { 205 {
207 lock (m_lock) 206 lock (m_lock)
208 { 207 {
209 try 208 EntityBase entity;
210 { 209 if (m_eb_uuid.TryGetValue(id, out entity))
211 return m_eb_uuid[id]; 210 return entity;
212 } 211 else
213 catch
214 {
215 return null; 212 return null;
216 }
217 } 213 }
218 } 214 }
219 set 215 set
@@ -228,14 +224,11 @@ namespace OpenSim.Region.Framework.Scenes
228 { 224 {
229 lock (m_lock) 225 lock (m_lock)
230 { 226 {
231 try 227 EntityBase entity;
232 { 228 if (m_eb_localID.TryGetValue(localID, out entity))
233 return m_eb_localID[localID]; 229 return entity;
234 } 230 else
235 catch
236 {
237 return null; 231 return null;
238 }
239 } 232 }
240 } 233 }
241 set 234 set
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index c44c4c7..c2b9e73 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -2351,12 +2351,6 @@ namespace OpenSim.Region.Framework.Scenes
2351 item = InventoryService.GetItem(item); 2351 item = InventoryService.GetItem(item);
2352 2352
2353 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); 2353 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/);
2354 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>();
2355 if (ava != null)
2356 {
2357 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2358 }
2359
2360 } 2354 }
2361 return att.UUID; 2355 return att.UUID;
2362 } 2356 }
@@ -2402,12 +2396,6 @@ namespace OpenSim.Region.Framework.Scenes
2402 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 2396 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
2403 item = InventoryService.GetItem(item); 2397 item = InventoryService.GetItem(item);
2404 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); 2398 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/);
2405
2406 if (m_AvatarFactory != null)
2407 {
2408 m_log.InfoFormat("[SCENE INVENTORY]: Saving avatar attachment. AgentID:{0} ItemID:{1} AttachmentPoint:{2}", remoteClient.AgentId, itemID, AttachmentPt);
2409 m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2410 }
2411 } 2399 }
2412 } 2400 }
2413 2401
@@ -2447,12 +2435,13 @@ namespace OpenSim.Region.Framework.Scenes
2447 if (TryGetAvatar(remoteClient.AgentId, out presence)) 2435 if (TryGetAvatar(remoteClient.AgentId, out presence))
2448 { 2436 {
2449 presence.Appearance.DetachAttachment(itemID); 2437 presence.Appearance.DetachAttachment(itemID);
2450 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>(); 2438
2451 if (ava != null) 2439 // Save avatar attachment information
2440 if (m_AvatarFactory != null)
2452 { 2441 {
2453 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); 2442 m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", ItemID: " + itemID);
2443 m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2454 } 2444 }
2455
2456 } 2445 }
2457 2446
2458 m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient); 2447 m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 70b11c3..4f3cc98 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -228,6 +228,10 @@ namespace OpenSim.Region.Framework.Scenes
228 protected IXMLRPC m_xmlrpcModule; 228 protected IXMLRPC m_xmlrpcModule;
229 protected IWorldComm m_worldCommModule; 229 protected IWorldComm m_worldCommModule;
230 protected IAvatarFactory m_AvatarFactory; 230 protected IAvatarFactory m_AvatarFactory;
231 public IAvatarFactory AvatarFactory
232 {
233 get { return m_AvatarFactory; }
234 }
231 protected IConfigSource m_config; 235 protected IConfigSource m_config;
232 protected IRegionSerialiserModule m_serialiser; 236 protected IRegionSerialiserModule m_serialiser;
233 protected IInterregionCommsOut m_interregionCommsOut; 237 protected IInterregionCommsOut m_interregionCommsOut;
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 8ee26c3..e51f6ef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -467,7 +467,6 @@ namespace OpenSim.Region.Framework.Scenes
467 protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) 467 protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent)
468 { 468 {
469 // If we can't take it, we can't attach it! 469 // If we can't take it, we can't attach it!
470 //
471 SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID); 470 SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID);
472 if (part == null) 471 if (part == null)
473 return; 472 return;
@@ -477,9 +476,16 @@ namespace OpenSim.Region.Framework.Scenes
477 return; 476 return;
478 477
479 // Calls attach with a Zero position 478 // Calls attach with a Zero position
480 //
481 AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false); 479 AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false);
482 m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); 480 m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
481
482 // Save avatar attachment information
483 ScenePresence presence;
484 if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence))
485 {
486 m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", AttachmentPoint: " + AttachmentPt);
487 m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
488 }
483 } 489 }
484 490
485 public SceneObjectGroup RezSingleAttachment( 491 public SceneObjectGroup RezSingleAttachment(
@@ -574,7 +580,7 @@ namespace OpenSim.Region.Framework.Scenes
574 } 580 }
575 581
576 582
577 group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); 583 group.SetAttachmentPoint((byte)AttachmentPt);
578 group.AbsolutePosition = attachPos; 584 group.AbsolutePosition = attachPos;
579 585
580 // Saves and gets itemID 586 // Saves and gets itemID
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 2153b9b..810dfd1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -899,7 +899,7 @@ namespace OpenSim.Region.Framework.Scenes
899 SetAttachmentPoint(Convert.ToByte(attachmentpoint)); 899 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
900 900
901 avatar.AddAttachment(this); 901 avatar.AddAttachment(this);
902 m_log.DebugFormat("[SOG]: Added att {0} to avie {1}", UUID, avatar.UUID); 902 m_log.Debug("[SOG]: Added attachment " + UUID + " to avatar " + avatar.UUID);
903 903
904 if (!silent) 904 if (!silent)
905 { 905 {