From 889ce36afa67c521f3e50e4833a894ffd39af490 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 23 Nov 2009 16:02:05 +0100 Subject: [PATCH 1/5] Added some [DebuggerNonUserCode] modifiers to functions that throw EventAbortException() to ease debugging on Visual Studio --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++++ OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs | 2 ++ OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs | 2 ++ .../Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 5 ++++- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 3 +++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 50b2fb5a2a..b549b5c5e3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Runtime.Remoting.Lifetime; using System.Text; using System.Threading; @@ -151,6 +152,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api get { return m_ScriptEngine.World; } } + [DebuggerNonUserCode] public void state(string newState) { m_ScriptEngine.SetState(m_itemID, newState); @@ -160,6 +162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Reset the named script. The script must be present /// in the same prim. /// + [DebuggerNonUserCode] public void llResetScript() { m_host.AddScriptLPS(1); @@ -3755,6 +3758,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(3000); } + [DebuggerNonUserCode] public void llRemoveInventory(string name) { m_host.AddScriptLPS(1); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs index 7f67599c92..15e0408ea9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Reflection; using System.Runtime.Remoting.Lifetime; using OpenSim.Region.ScriptEngine.Shared; @@ -131,6 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return (eventFlags); } + [DebuggerNonUserCode] public void ExecuteEvent(string state, string FunctionName, object[] args) { // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs index 121159c0d8..a44abb05b5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs @@ -33,6 +33,7 @@ using System.Threading; using System.Reflection; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; @@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return (int)m_Executor.GetStateEventFlags(state); } + [DebuggerNonUserCode] public void ExecuteEvent(string state, string FunctionName, object[] args) { m_Executor.ExecuteEvent(state, FunctionName, args); diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 41b5d497da..ed3fdbed37 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -27,6 +27,7 @@ using System; using System.IO; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Runtime.Remoting; using System.Runtime.Remoting.Lifetime; using System.Threading; @@ -544,6 +545,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance return true; } + [DebuggerNonUserCode] //Prevents the debugger from farting in this function public void SetState(string state) { if (state == State) @@ -555,7 +557,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance new DetectParams[0])); PostEvent(new EventParams("state_entry", new Object[0], new DetectParams[0])); - + throw new EventAbortException(); } @@ -824,6 +826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance new Object[0], new DetectParams[0])); } + [DebuggerNonUserCode] //Stops the VS debugger from farting in this function public void ApiResetScript() { // bool running = Running; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index a60c0bac73..8b94f283f6 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -30,6 +30,7 @@ using System.IO; using System.Threading; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Security; using System.Security.Policy; using System.Reflection; @@ -1119,6 +1120,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } + [DebuggerNonUserCode] public void ApiResetScript(UUID itemID) { IScriptInstance instance = GetInstance(itemID); @@ -1170,6 +1172,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return UUID.Zero; } + [DebuggerNonUserCode] public void SetState(UUID itemID, string newState) { IScriptInstance instance = GetInstance(itemID); From 73c2162ff60850d96761aa07a1950dbbb2ec3e80 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 23 Nov 2009 19:51:40 +0100 Subject: [PATCH 2/5] Fixed nullrefs --- .../CoreModules/Avatar/Chat/ChatModule.cs | 42 ++++++++++--------- .../Framework/Scenes/Scene.Inventory.cs | 8 +++- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index cd59bdb613..5c24f03347 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -266,25 +266,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); - - ((Scene)c.Scene).ForEachScenePresence( - delegate(ScenePresence presence) - { - // ignore chat from child agents - if (presence.IsChildAgent) return; - - IClientAPI client = presence.ControllingClient; - - // don't forward SayOwner chat from objects to - // non-owner agents - if ((c.Type == ChatTypeEnum.Owner) && - (null != c.SenderObject) && - (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) - return; - - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, - (byte)sourceType, (byte)ChatAudibleLevel.Fully); - }); + if (c.Scene != null) + { + ((Scene)c.Scene).ForEachScenePresence + ( + delegate(ScenePresence presence) + { + // ignore chat from child agents + if (presence.IsChildAgent) return; + + IClientAPI client = presence.ControllingClient; + + // don't forward SayOwner chat from objects to + // non-owner agents + if ((c.Type == ChatTypeEnum.Owner) && + (null != c.SenderObject) && + (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) + return; + + client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, + (byte)sourceType, (byte)ChatAudibleLevel.Fully); + } + ); + } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 66fb918bd7..83208e9747 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -840,8 +840,12 @@ namespace OpenSim.Region.Framework.Scenes public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) { SceneObjectPart part = GetSceneObjectPart(localID); - SceneObjectGroup group = part.ParentGroup; - if (group != null) + SceneObjectGroup group = null; + if (part != null) + { + group = part.ParentGroup; + } + if (part != null && group != null) { TaskInventoryItem item = group.GetInventoryItem(localID, itemID); if (item == null) From 247c66b3fe792692468ede6a516d85c6c9852d23 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 23 Nov 2009 20:25:53 +0100 Subject: [PATCH 3/5] Swap the locking of m_EventQueue and m_Script to ease locks on script inventory operations --- .../Shared/Instance/ScriptInstance.cs | 272 +++++++++--------- 1 file changed, 138 insertions(+), 134 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index ed3fdbed37..063d50f231 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -639,140 +639,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// /// public object EventProcessor() + { + + EventParams data = null; + + lock (m_EventQueue) { lock (m_Script) { - EventParams data = null; - - lock (m_EventQueue) - { - data = (EventParams) m_EventQueue.Dequeue(); - if (data == null) // Shouldn't happen - { - if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) - { - m_CurrentResult = m_Engine.QueueEventHandler(this); - } - else - { - m_CurrentResult = null; - } - return 0; - } - - if (data.EventName == "timer") - m_TimerQueued = false; - if (data.EventName == "control") - { - if (m_ControlEventsInQueue > 0) - m_ControlEventsInQueue--; - } - if (data.EventName == "collision") - m_CollisionInQueue = false; - } - - //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); - - m_DetectParams = data.DetectParams; - - if (data.EventName == "state") // Hardcoded state change - { - // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", - // m_PrimName, m_ScriptName, data.Params[0].ToString()); - m_State=data.Params[0].ToString(); - AsyncCommandManager.RemoveScript(m_Engine, - m_LocalID, m_ItemID); - - SceneObjectPart part = m_Engine.World.GetSceneObjectPart( - m_LocalID); - if (part != null) - { - part.SetScriptEvents(m_ItemID, - (int)m_Script.GetStateEventFlags(State)); - } - } - else - { - if (m_Engine.World.PipeEventsForScript(m_LocalID) || - data.EventName == "control") // Don't freeze avies! - { - SceneObjectPart part = m_Engine.World.GetSceneObjectPart( - m_LocalID); - // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", - // m_PrimName, m_ScriptName, data.EventName, m_State); - - try - { - m_CurrentEvent = data.EventName; - m_EventStart = DateTime.Now; - m_InEvent = true; - - m_Script.ExecuteEvent(State, data.EventName, data.Params); - - m_InEvent = false; - m_CurrentEvent = String.Empty; - - if (m_SaveState) - { - // This will be the very first event we deliver - // (state_entry) in default state - // - - SaveState(m_Assembly); - - m_SaveState = false; - } - } - catch (Exception e) - { - // m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message); - m_InEvent = false; - m_CurrentEvent = String.Empty; - - if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) - { - try - { - // DISPLAY ERROR INWORLD - string text = FormatException(e); - - if (text.Length > 1000) - text = text.Substring(0, 1000); - m_Engine.World.SimChat(Utils.StringToBytes(text), - ChatTypeEnum.DebugChannel, 2147483647, - part.AbsolutePosition, - part.Name, part.UUID, false); - } - catch (Exception) - { - } - // catch (Exception e2) // LEGIT: User Scripting - // { - // m_log.Error("[SCRIPT]: "+ - // "Error displaying error in-world: " + - // e2.ToString()); - // m_log.Error("[SCRIPT]: " + - // "Errormessage: Error compiling script:\r\n" + - // e.ToString()); - // } - } - else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) - { - m_InSelfDelete = true; - if (part != null && part.ParentGroup != null) - m_Engine.World.DeleteSceneObject(part.ParentGroup, false); - } - else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) - { - m_InSelfDelete = true; - if (part != null && part.ParentGroup != null) - part.Inventory.RemoveInventoryItem(m_ItemID); - } - } - } - } - - lock (m_EventQueue) + data = (EventParams) m_EventQueue.Dequeue(); + if (data == null) // Shouldn't happen { if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) { @@ -782,13 +658,141 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { m_CurrentResult = null; } + return 0; } - m_DetectParams = null; - - return 0; + if (data.EventName == "timer") + m_TimerQueued = false; + if (data.EventName == "control") + { + if (m_ControlEventsInQueue > 0) + m_ControlEventsInQueue--; + } + if (data.EventName == "collision") + m_CollisionInQueue = false; } } + lock(m_Script) + { + + //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); + + m_DetectParams = data.DetectParams; + + if (data.EventName == "state") // Hardcoded state change + { +// m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", +// m_PrimName, m_ScriptName, data.Params[0].ToString()); + m_State=data.Params[0].ToString(); + AsyncCommandManager.RemoveScript(m_Engine, + m_LocalID, m_ItemID); + + SceneObjectPart part = m_Engine.World.GetSceneObjectPart( + m_LocalID); + if (part != null) + { + part.SetScriptEvents(m_ItemID, + (int)m_Script.GetStateEventFlags(State)); + } + } + else + { + if (m_Engine.World.PipeEventsForScript(m_LocalID) || + data.EventName == "control") // Don't freeze avies! + { + SceneObjectPart part = m_Engine.World.GetSceneObjectPart( + m_LocalID); + // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", + // m_PrimName, m_ScriptName, data.EventName, m_State); + + try + { + m_CurrentEvent = data.EventName; + m_EventStart = DateTime.Now; + m_InEvent = true; + + m_Script.ExecuteEvent(State, data.EventName, data.Params); + + m_InEvent = false; + m_CurrentEvent = String.Empty; + + if (m_SaveState) + { + // This will be the very first event we deliver + // (state_entry) in default state + // + + SaveState(m_Assembly); + + m_SaveState = false; + } + } + catch (Exception e) + { + // m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message); + m_InEvent = false; + m_CurrentEvent = String.Empty; + + if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) + { + try + { + // DISPLAY ERROR INWORLD + string text = FormatException(e); + + if (text.Length > 1000) + text = text.Substring(0, 1000); + m_Engine.World.SimChat(Utils.StringToBytes(text), + ChatTypeEnum.DebugChannel, 2147483647, + part.AbsolutePosition, + part.Name, part.UUID, false); + } + catch (Exception) + { + } + // catch (Exception e2) // LEGIT: User Scripting + // { + // m_log.Error("[SCRIPT]: "+ + // "Error displaying error in-world: " + + // e2.ToString()); + // m_log.Error("[SCRIPT]: " + + // "Errormessage: Error compiling script:\r\n" + + // e.ToString()); + // } + } + else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) + { + m_InSelfDelete = true; + if (part != null && part.ParentGroup != null) + m_Engine.World.DeleteSceneObject(part.ParentGroup, false); + } + else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) + { + m_InSelfDelete = true; + if (part != null && part.ParentGroup != null) + part.Inventory.RemoveInventoryItem(m_ItemID); + } + } + } + } + + lock (m_EventQueue) + { + if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) + { + m_CurrentResult = m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult = null; + } + } + + m_DetectParams = null; + + return 0; + } + } public int EventTime() { From d1147136946daf14724183b3191119be44ff8b16 Mon Sep 17 00:00:00 2001 From: CasperW Date: Tue, 24 Nov 2009 18:02:12 +0100 Subject: [PATCH 4/5] Drop all locking of part.TaskInventory in favour of a ReaderWriterLockSlim lock handler. This gives us: - Faster prim inventory actions. Multiple threads can read at once. - Fixes the known prim inventory thread locks - In the event of a thread lock occurring, it will usually self heal after sixty seconds with an error message in the console --- OpenSim/Framework/TaskInventoryDictionary.cs | 111 +++- .../World/Archiver/ArchiveReadRequest.cs | 21 +- .../Framework/Scenes/SceneObjectPart.cs | 38 +- .../Scenes/SceneObjectPartInventory.cs | 404 ++++++------- .../Region/Framework/Scenes/ScenePresence.cs | 16 +- .../Shared/Api/Implementation/LSL_Api.cs | 534 ++++++++++-------- .../Shared/Api/Implementation/OSSL_Api.cs | 36 +- .../Shared/Instance/ScriptInstance.cs | 22 +- 8 files changed, 693 insertions(+), 489 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 25ae6b05c6..efe5f0cb47 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -27,9 +27,12 @@ using System; using System.Collections.Generic; +using System.Threading; +using System.Reflection; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; +using log4net; using OpenMetaverse; namespace OpenSim.Framework @@ -45,6 +48,105 @@ namespace OpenSim.Framework // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Thread LockedByThread; + /// + /// An advanced lock for inventory data + /// + private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim(); + + /// + /// Are we readlocked by the calling thread? + /// + public bool IsReadLockedByMe() + { + if (m_itemLock.RecursiveReadCount > 0) + { + return true; + } + else + { + return false; + } + } + + /// + /// Lock our inventory list for reading (many can read, one can write) + /// + public void LockItemsForRead(bool locked) + { + if (locked) + { + if (m_itemLock.IsWriteLockHeld && LockedByThread != null) + { + if (!LockedByThread.IsAlive) + { + //Locked by dead thread, reset. + m_itemLock = new System.Threading.ReaderWriterLockSlim(); + } + } + + if (m_itemLock.RecursiveReadCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_itemLock.ExitReadLock(); + } + if (m_itemLock.RecursiveWriteCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_itemLock.ExitWriteLock(); + } + + while (!m_itemLock.TryEnterReadLock(60000)) + { + m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_itemLock.IsWriteLockHeld) + { + m_itemLock = new System.Threading.ReaderWriterLockSlim(); + } + } + } + else + { + m_itemLock.ExitReadLock(); + } + } + + /// + /// Lock our inventory list for writing (many can read, one can write) + /// + public void LockItemsForWrite(bool locked) + { + if (locked) + { + //Enter a write lock, wait indefinately for one to open. + if (m_itemLock.RecursiveReadCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_itemLock.ExitReadLock(); + } + if (m_itemLock.RecursiveWriteCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_itemLock.ExitWriteLock(); + } + while (!m_itemLock.TryEnterWriteLock(60000)) + { + m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_itemLock.IsWriteLockHeld) + { + m_itemLock = new System.Threading.ReaderWriterLockSlim(); + } + } + + LockedByThread = Thread.CurrentThread; + } + else + { + m_itemLock.ExitWriteLock(); + } + } #region ICloneable Members @@ -52,13 +154,12 @@ namespace OpenSim.Framework { TaskInventoryDictionary clone = new TaskInventoryDictionary(); - lock (this) + m_itemLock.EnterReadLock(); + foreach (UUID uuid in Keys) { - foreach (UUID uuid in Keys) - { - clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); - } + clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); } + m_itemLock.ExitReadLock(); return clone; } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 70a225e7c1..f204faf0c3 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -246,21 +246,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Fix ownership/creator of inventory items // Not doing so results in inventory items // being no copy/no mod for everyone - lock (part.TaskInventory) + part.TaskInventory.LockItemsForRead(true); + TaskInventoryDictionary inv = part.TaskInventory; + foreach (KeyValuePair kvp in inv) { - TaskInventoryDictionary inv = part.TaskInventory; - foreach (KeyValuePair kvp in inv) + if (!ResolveUserUuid(kvp.Value.OwnerID)) { - if (!ResolveUserUuid(kvp.Value.OwnerID)) - { - kvp.Value.OwnerID = masterAvatarId; - } - if (!ResolveUserUuid(kvp.Value.CreatorID)) - { - kvp.Value.CreatorID = masterAvatarId; - } + kvp.Value.OwnerID = masterAvatarId; + } + if (!ResolveUserUuid(kvp.Value.CreatorID)) + { + kvp.Value.CreatorID = masterAvatarId; } } + part.TaskInventory.LockItemsForRead(false); } if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cdec135785..bbece2f59b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -389,12 +389,16 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes + /// Get the inventory list /// public TaskInventoryDictionary TaskInventory { - get { return m_inventory.Items; } - set { m_inventory.Items = value; } + get { + return m_inventory.Items; + } + set { + m_inventory.Items = value; + } } public uint ObjectFlags @@ -2101,17 +2105,18 @@ namespace OpenSim.Region.Framework.Scenes //Trys to fetch sound id from prim's inventory. //Prim's inventory doesn't support non script items yet - lock (TaskInventory) + TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair item in TaskInventory) { - foreach (KeyValuePair item in TaskInventory) + if (item.Value.Name == sound) { - if (item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } + soundID = item.Value.ItemID; + break; } } + + TaskInventory.LockItemsForRead(false); } List avatarts = m_parentGroup.Scene.GetAvatars(); @@ -2457,17 +2462,16 @@ namespace OpenSim.Region.Framework.Scenes if (!UUID.TryParse(sound, out soundID)) { // search sound file from inventory - lock (TaskInventory) + TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair item in TaskInventory) { - foreach (KeyValuePair item in TaskInventory) + if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) { - if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) - { - soundID = item.Value.ItemID; - break; - } + soundID = item.Value.ItemID; + break; } } + TaskInventory.LockItemsForRead(false); } if (soundID == UUID.Zero) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index f4ca877941..4dc709e142 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -80,7 +80,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal TaskInventoryDictionary Items { - get { return m_items; } + get { + return m_items; + } set { m_items = value; @@ -116,22 +118,25 @@ namespace OpenSim.Region.Framework.Scenes /// Link number for the part public void ResetInventoryIDs() { - lock (Items) + m_items.LockItemsForWrite(true); + + if (0 == Items.Count) { - if (0 == Items.Count) - return; - - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - IList items = new List(Items.Values); - Items.Clear(); - - foreach (TaskInventoryItem item in items) - { - item.ResetIDs(m_part.UUID); - Items.Add(item.ItemID, item); - } + m_items.LockItemsForWrite(false); + return; } + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + Items.Clear(); + + foreach (TaskInventoryItem item in items) + { + item.ResetIDs(m_part.UUID); + Items.Add(item.ItemID, item); + } + m_items.LockItemsForWrite(false); } /// @@ -140,25 +145,25 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryOwner(UUID ownerId) { - lock (Items) + m_items.LockItemsForWrite(true); + if (0 == Items.Count) { - if (0 == Items.Count) - { - return; - } + m_items.LockItemsForWrite(false); + return; + } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - IList items = new List(Items.Values); - foreach (TaskInventoryItem item in items) + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + foreach (TaskInventoryItem item in items) + { + if (ownerId != item.OwnerID) { - if (ownerId != item.OwnerID) - { - item.LastOwnerID = item.OwnerID; - item.OwnerID = ownerId; - } + item.LastOwnerID = item.OwnerID; + item.OwnerID = ownerId; } } + m_items.LockItemsForWrite(false); } /// @@ -167,24 +172,24 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryGroup(UUID groupID) { - lock (Items) + m_items.LockItemsForWrite(true); + if (0 == Items.Count) { - if (0 == Items.Count) - { - return; - } + m_items.LockItemsForWrite(false); + return; + } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - IList items = new List(Items.Values); - foreach (TaskInventoryItem item in items) + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + foreach (TaskInventoryItem item in items) + { + if (groupID != item.GroupID) { - if (groupID != item.GroupID) - { - item.GroupID = groupID; - } + item.GroupID = groupID; } } + m_items.LockItemsForWrite(false); } /// @@ -192,14 +197,14 @@ namespace OpenSim.Region.Framework.Scenes /// public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { - lock (m_items) + Items.LockItemsForRead(true); + IList items = new List(Items.Values); + Items.LockItemsForRead(false); + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in Items.Values) + if ((int)InventoryType.LSL == item.InvType) { - if ((int)InventoryType.LSL == item.InvType) - { - CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); - } + CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); } } } @@ -209,17 +214,20 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstances() { - lock (Items) + Items.LockItemsForRead(true); + IList items = new List(Items.Values); + Items.LockItemsForRead(false); + + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in Items.Values) + if ((int)InventoryType.LSL == item.InvType) { - if ((int)InventoryType.LSL == item.InvType) - { - RemoveScriptInstance(item.ItemID); - m_part.RemoveScriptEvents(item.ItemID); - } + RemoveScriptInstance(item.ItemID); + m_part.RemoveScriptEvents(item.ItemID); } } + + } /// @@ -244,8 +252,10 @@ namespace OpenSim.Region.Framework.Scenes if (stateSource == 1 && // Prim crossing m_part.ParentGroup.Scene.m_trustBinaries) { + m_items.LockItemsForWrite(true); m_items[item.ItemID].PermsMask = 0; m_items[item.ItemID].PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(false); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); m_part.ParentGroup.AddActiveScriptCount(1); @@ -266,8 +276,10 @@ namespace OpenSim.Region.Framework.Scenes { if (m_part.ParentGroup.m_savedScriptState != null) RestoreSavedScriptState(item.OldItemID, item.ItemID); + m_items.LockItemsForWrite(true); m_items[item.ItemID].PermsMask = 0; m_items[item.ItemID].PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(false); string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); @@ -302,20 +314,22 @@ namespace OpenSim.Region.Framework.Scenes /// public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) { - lock (m_items) + m_items.LockItemsForRead(true); + if (m_items.ContainsKey(itemId)) { - if (m_items.ContainsKey(itemId)) - { - CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", - itemId, m_part.Name, m_part.UUID); - } + TaskInventoryItem item = m_items[itemId]; + m_items.LockItemsForRead(false); + CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); } + else + { + m_items.LockItemsForRead(false); + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", + itemId, m_part.Name, m_part.UUID); + } + } /// @@ -346,11 +360,16 @@ namespace OpenSim.Region.Framework.Scenes /// private bool InventoryContainsName(string name) { - foreach (TaskInventoryItem item in Items.Values) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { if (item.Name == name) + { + m_items.LockItemsForRead(false); return true; + } } + m_items.LockItemsForRead(false); return false; } @@ -392,7 +411,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) { + m_items.LockItemsForRead(true); List il = new List(m_items.Values); + m_items.LockItemsForRead(false); foreach (TaskInventoryItem i in il) { if (i.Name == item.Name) @@ -429,15 +450,14 @@ namespace OpenSim.Region.Framework.Scenes item.ParentPartID = m_part.UUID; item.Name = name; - lock (m_items) - { - m_items.Add(item.ItemID, item); - + m_items.LockItemsForWrite(true); + m_items.Add(item.ItemID, item); + m_items.LockItemsForWrite(false); if (allowedDrop) m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); else m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - } + m_inventorySerial++; //m_inventorySerial += 2; @@ -454,14 +474,13 @@ namespace OpenSim.Region.Framework.Scenes /// public void RestoreInventoryItems(ICollection items) { - lock (m_items) + m_items.LockItemsForWrite(true); + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in items) - { - m_items.Add(item.ItemID, item); - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - } + m_items.Add(item.ItemID, item); + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); } + m_items.LockItemsForWrite(false); m_inventorySerial++; } @@ -474,8 +493,9 @@ namespace OpenSim.Region.Framework.Scenes public TaskInventoryItem GetInventoryItem(UUID itemId) { TaskInventoryItem item; + m_items.LockItemsForRead(true); m_items.TryGetValue(itemId, out item); - + m_items.LockItemsForRead(false); return item; } @@ -487,45 +507,45 @@ namespace OpenSim.Region.Framework.Scenes /// false if the item did not exist, true if the update occurred successfully public bool UpdateInventoryItem(TaskInventoryItem item) { - lock (m_items) + m_items.LockItemsForWrite(true); + + if (m_items.ContainsKey(item.ItemID)) { - if (m_items.ContainsKey(item.ItemID)) + item.ParentID = m_part.UUID; + item.ParentPartID = m_part.UUID; + item.Flags = m_items[item.ItemID].Flags; + if (item.AssetID == UUID.Zero) { - item.ParentID = m_part.UUID; - item.ParentPartID = m_part.UUID; - item.Flags = m_items[item.ItemID].Flags; - if (item.AssetID == UUID.Zero) - { - item.AssetID = m_items[item.ItemID].AssetID; - } - else if ((InventoryType)item.Type == InventoryType.Notecard) - { - ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); - - if (presence != null) - { - presence.ControllingClient.SendAgentAlertMessage( - "Notecard saved", false); - } - } - - m_items[item.ItemID] = item; - m_inventorySerial++; - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - - return true; + item.AssetID = m_items[item.ItemID].AssetID; } - else + else if ((InventoryType)item.Type == InventoryType.Notecard) { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", - item.ItemID, m_part.Name, m_part.UUID); + ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); + + if (presence != null) + { + presence.ControllingClient.SendAgentAlertMessage( + "Notecard saved", false); + } } + + m_items[item.ItemID] = item; + m_inventorySerial++; + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + m_items.LockItemsForWrite(false); + return true; } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + item.ItemID, m_part.Name, m_part.UUID); + } + m_items.LockItemsForWrite(false); return false; } @@ -538,51 +558,54 @@ namespace OpenSim.Region.Framework.Scenes /// in this prim's inventory. public int RemoveInventoryItem(UUID itemID) { - lock (m_items) + m_items.LockItemsForRead(true); + + if (m_items.ContainsKey(itemID)) { - if (m_items.ContainsKey(itemID)) + int type = m_items[itemID].InvType; + m_items.LockItemsForRead(false); + if (type == 10) // Script { - int type = m_items[itemID].InvType; - if (type == 10) // Script - { - m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); - } - m_items.Remove(itemID); - m_inventorySerial++; - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - - int scriptcount = 0; - lock (m_items) - { - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.Type == 10) - { - scriptcount++; - } - } - } - - if (scriptcount <= 0) - { - m_part.RemFlag(PrimFlags.Scripted); - } - - m_part.ScheduleFullUpdate(); - - return type; + m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); } - else + m_items.LockItemsForWrite(true); + m_items.Remove(itemID); + m_items.LockItemsForWrite(false); + m_inventorySerial++; + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + + int scriptcount = 0; + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", - itemID, m_part.Name, m_part.UUID); + if (item.Type == 10) + { + scriptcount++; + } } + m_items.LockItemsForRead(false); + + + if (scriptcount <= 0) + { + m_part.RemFlag(PrimFlags.Scripted); + } + + m_part.ScheduleFullUpdate(); + + return type; } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + itemID, m_part.Name, m_part.UUID); + } + m_items.LockItemsForWrite(false); return -1; } @@ -635,52 +658,53 @@ namespace OpenSim.Region.Framework.Scenes // isn't available (such as drag from prim inventory to agent inventory) InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); - lock (m_items) + m_items.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - UUID ownerID = item.OwnerID; - uint everyoneMask = 0; - uint baseMask = item.BasePermissions; - uint ownerMask = item.CurrentPermissions; + UUID ownerID = item.OwnerID; + uint everyoneMask = 0; + uint baseMask = item.BasePermissions; + uint ownerMask = item.CurrentPermissions; - invString.AddItemStart(); - invString.AddNameValueLine("item_id", item.ItemID.ToString()); - invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); + invString.AddItemStart(); + invString.AddNameValueLine("item_id", item.ItemID.ToString()); + invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); - invString.AddPermissionsStart(); + invString.AddPermissionsStart(); - invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); - invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); - invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); - invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); + invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); + invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); + invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); + invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); - invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); - invString.AddNameValueLine("owner_id", ownerID.ToString()); + invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); + invString.AddNameValueLine("owner_id", ownerID.ToString()); - invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); - invString.AddNameValueLine("group_id", item.GroupID.ToString()); - invString.AddSectionEnd(); + invString.AddNameValueLine("group_id", item.GroupID.ToString()); + invString.AddSectionEnd(); - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); - invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); - invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); - invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); + invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); + invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); - invString.AddSaleStart(); - invString.AddNameValueLine("sale_type", "not"); - invString.AddNameValueLine("sale_price", "0"); - invString.AddSectionEnd(); + invString.AddSaleStart(); + invString.AddNameValueLine("sale_type", "not"); + invString.AddNameValueLine("sale_price", "0"); + invString.AddSectionEnd(); - invString.AddNameValueLine("name", item.Name + "|"); - invString.AddNameValueLine("desc", item.Description + "|"); + invString.AddNameValueLine("name", item.Name + "|"); + invString.AddNameValueLine("desc", item.Description + "|"); - invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); - invString.AddSectionEnd(); - } + invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); + invString.AddSectionEnd(); } + int count = m_items.Count; + m_items.LockItemsForRead(false); fileData = Utils.StringToBytes(invString.BuildString); @@ -689,6 +713,7 @@ namespace OpenSim.Region.Framework.Scenes if (fileData.Length > 2) { + m_log.Debug("Sending task inventory list of " + count.ToString() + " items to client " + client.AgentId.ToString()); xferManager.AddNewFile(m_inventoryFileName, fileData); } } @@ -701,10 +726,9 @@ namespace OpenSim.Region.Framework.Scenes { if (HasInventoryChanged) { - lock (Items) - { - datastore.StorePrimInventory(m_part.UUID, Items.Values); - } + Items.LockItemsForRead(true); + datastore.StorePrimInventory(m_part.UUID, Items.Values); + Items.LockItemsForRead(false); HasInventoryChanged = false; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4e5fee15ab..4c8c94f9fb 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1615,21 +1615,19 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); if (part != null) { + part.TaskInventory.LockItemsForRead(true); TaskInventoryDictionary taskIDict = part.TaskInventory; if (taskIDict != null) { - lock (taskIDict) + foreach (UUID taskID in taskIDict.Keys) { - foreach (UUID taskID in taskIDict.Keys) - { - UnRegisterControlEventsToScript(LocalId, taskID); - taskIDict[taskID].PermsMask &= ~( - 2048 | //PERMISSION_CONTROL_CAMERA - 4); // PERMISSION_TAKE_CONTROLS - } + UnRegisterControlEventsToScript(LocalId, taskID); + taskIDict[taskID].PermsMask &= ~( + 2048 | //PERMISSION_CONTROL_CAMERA + 4); // PERMISSION_TAKE_CONTROLS } - } + part.TaskInventory.LockItemsForRead(false); // Reset sit target. if (part.GetAvatarOnSitTarget() == UUID) part.SetAvatarOnSitTarget(UUID.Zero); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b549b5c5e3..a94cd46a49 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -275,40 +275,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected UUID InventorySelf() { UUID invItemID = new UUID(); - - lock (m_host.TaskInventory) + bool unlock = false; + if (!m_host.TaskInventory.IsReadLockedByMe()) { - foreach (KeyValuePair inv in m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + unlock = true; + } + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) { - if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) - { - invItemID = inv.Key; - break; - } + invItemID = inv.Key; + break; } } - + if (unlock) + { + m_host.TaskInventory.LockItemsForRead(false); + } return invItemID; } protected UUID InventoryKey(string name, int type) { m_host.AddScriptLPS(1); - - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) + m_host.TaskInventory.LockItemsForRead(false); + + if (inv.Value.Type != type) { - if (inv.Value.Type != type) - return UUID.Zero; - - return inv.Value.AssetID; + return UUID.Zero; } + + return inv.Value.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero; } @@ -316,17 +324,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + + m_host.TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) - { - return inv.Value.AssetID; - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); + + return UUID.Zero; } @@ -2537,12 +2549,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); + m_host.TaskInventory.LockItemsForRead(true); TaskInventoryItem item = m_host.TaskInventory[invItemID]; - - lock (m_host.TaskInventory) - { - item = m_host.TaskInventory[invItemID]; - } + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter == UUID.Zero) return 0; @@ -2617,6 +2626,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (dist > m_ScriptDistanceFactor * 10.0f) return; + //Clone is thread-safe TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); foreach (KeyValuePair inv in partInventory) @@ -2750,13 +2760,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter != UUID.Zero) { @@ -2778,13 +2792,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { TaskInventoryItem item; + m_host.TaskInventory.LockItemsForRead(true); lock (m_host.TaskInventory) { + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + { + m_host.TaskInventory.LockItemsForRead(false); return; + } else + { item = m_host.TaskInventory[InventorySelf()]; + } } + m_host.TaskInventory.LockItemsForRead(false); m_host.AddScriptLPS(1); @@ -2821,13 +2843,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter != m_host.OwnerID) return; @@ -2853,13 +2881,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + m_host.TaskInventory.LockItemsForRead(false); + if (item.PermsGranter != m_host.OwnerID) return; @@ -3083,14 +3117,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } - + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter == UUID.Zero) return; @@ -3120,13 +3157,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + m_host.TaskInventory.LockItemsForRead(false); + if (item.PermsGranter == UUID.Zero) return; @@ -3199,10 +3241,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(invItemID)) + { + m_host.TaskInventory.LockItemsForRead(false); + return; + } + else { item = m_host.TaskInventory[invItemID]; } + m_host.TaskInventory.LockItemsForRead(false); if (agentID == UUID.Zero || perm == 0) // Releasing permissions { @@ -3234,11 +3284,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsGranter = agentID; - m_host.TaskInventory[invItemID].PermsMask = perm; - } + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = perm; + m_host.TaskInventory.LockItemsForWrite(false); m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3258,11 +3307,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsGranter = agentID; - m_host.TaskInventory[invItemID].PermsMask = perm; - } + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = perm; + m_host.TaskInventory.LockItemsForWrite(false); m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3283,11 +3331,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_waitingForScriptAnswer) { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsGranter = agentID; - m_host.TaskInventory[invItemID].PermsMask = 0; - } + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = 0; + m_host.TaskInventory.LockItemsForWrite(false); presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; m_waitingForScriptAnswer=true; @@ -3322,10 +3369,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) llReleaseControls(); - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsMask = answer; - } + + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsMask = answer; + m_host.TaskInventory.LockItemsForWrite(false); + m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3337,16 +3385,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.ItemID == m_itemID) { - if (item.Type == 10 && item.ItemID == m_itemID) - { - return item.PermsGranter.ToString(); - } + m_host.TaskInventory.LockItemsForRead(false); + return item.PermsGranter.ToString(); } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero.ToString(); } @@ -3355,19 +3404,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.ItemID == m_itemID) { - if (item.Type == 10 && item.ItemID == m_itemID) - { - int perms = item.PermsMask; - if (m_automaticLinkPermission) - perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; - return perms; - } + int perms = item.PermsMask; + if (m_automaticLinkPermission) + perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; + m_host.TaskInventory.LockItemsForRead(false); + return perms; } } + m_host.TaskInventory.LockItemsForRead(false); return 0; } @@ -3400,11 +3450,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID invItemID = InventorySelf(); TaskInventoryItem item; - lock (m_host.TaskInventory) - { - item = m_host.TaskInventory[invItemID]; - } - + m_host.TaskInventory.LockItemsForRead(true); + item = m_host.TaskInventory[invItemID]; + m_host.TaskInventory.LockItemsForRead(false); + if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { @@ -3457,16 +3506,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); UUID invItemID = InventorySelf(); - lock (m_host.TaskInventory) - { + m_host.TaskInventory.LockItemsForRead(true); if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); + m_host.TaskInventory.LockItemsForRead(false); return; } - } - + m_host.TaskInventory.LockItemsForRead(false); + if (linknum < ScriptBaseClass.LINK_THIS) return; @@ -3635,17 +3684,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); int count = 0; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Type == type || type == -1) { - if (inv.Value.Type == type || type == -1) - { - count = count + 1; - } + count = count + 1; } } - + + m_host.TaskInventory.LockItemsForRead(false); return count; } @@ -3654,16 +3702,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); ArrayList keys = new ArrayList(); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Type == type || type == -1) { - if (inv.Value.Type == type || type == -1) - { - keys.Add(inv.Value.Name); - } + keys.Add(inv.Value.Name); } } + m_host.TaskInventory.LockItemsForRead(false); if (keys.Count == 0) { @@ -3700,20 +3747,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // move the first object found with this inventory name - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == inventory) { - if (inv.Value.Name == inventory) - { - found = true; - objId = inv.Key; - assetType = inv.Value.Type; - objName = inv.Value.Name; - break; - } + found = true; + objId = inv.Key; + assetType = inv.Value.Type; + objName = inv.Value.Name; + break; } } + m_host.TaskInventory.LockItemsForRead(false); if (!found) { @@ -3763,20 +3809,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Name == name) { - if (item.Name == name) - { - if (item.ItemID == m_itemID) - throw new ScriptDeleteException(); - else - m_host.Inventory.RemoveInventoryItem(item.ItemID); - return; - } + if (item.ItemID == m_itemID) + throw new ScriptDeleteException(); + else + m_host.Inventory.RemoveInventoryItem(item.ItemID); + + m_host.TaskInventory.LockItemsForRead(false); + return; } } + m_host.TaskInventory.LockItemsForRead(false); } public void llSetText(string text, LSL_Vector color, double alpha) @@ -3865,6 +3912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + //Clone is thread safe TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); foreach (TaskInventoryItem item in itemDictionary.Values) @@ -3955,17 +4003,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID soundId = UUID.Zero; if (!UUID.TryParse(impact_sound, out soundId)) { - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) { - if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) - { - soundId = item.AssetID; - break; - } + soundId = item.AssetID; + break; } } + m_host.TaskInventory.LockItemsForRead(false); } m_host.CollisionSound = soundId; m_host.CollisionSoundVolume = (float)impact_volume; @@ -4011,6 +4058,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID partItemID; foreach (SceneObjectPart part in parts) { + //Clone is thread safe TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); foreach (TaskInventoryItem item in itemsDictionary.Values) @@ -4218,17 +4266,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.ItemID == m_itemID) { - if (item.Type == 10 && item.ItemID == m_itemID) - { - result = item.Name!=null?item.Name:String.Empty; - break; - } + result = item.Name!=null?item.Name:String.Empty; + break; } } + m_host.TaskInventory.LockItemsForRead(false); return result; } @@ -4486,23 +4533,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) + if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) { - if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) - { - return inv.Value.AssetID.ToString(); - } - else - { - return UUID.Zero.ToString(); - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.AssetID.ToString(); + } + else + { + m_host.TaskInventory.LockItemsForRead(false); + return UUID.Zero.ToString(); } } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero.ToString(); } @@ -5997,14 +6045,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected UUID GetTaskInventoryItem(string name) { - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) - return inv.Key; + m_host.TaskInventory.LockItemsForRead(false); + return inv.Key; } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero; } @@ -6315,22 +6365,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // copy the first script found with this inventory name - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) + // make sure the object is a script + if (10 == inv.Value.Type) { - // make sure the object is a script - if (10 == inv.Value.Type) - { - found = true; - srcId = inv.Key; - break; - } + found = true; + srcId = inv.Key; + break; } } } + m_host.TaskInventory.LockItemsForRead(false); if (!found) { @@ -8133,28 +8182,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == item) { - if (inv.Value.Name == item) + m_host.TaskInventory.LockItemsForRead(false); + switch (mask) { - switch (mask) - { - case 0: - return (int)inv.Value.BasePermissions; - case 1: - return (int)inv.Value.CurrentPermissions; - case 2: - return (int)inv.Value.GroupPermissions; - case 3: - return (int)inv.Value.EveryonePermissions; - case 4: - return (int)inv.Value.NextPermissions; - } + case 0: + return (int)inv.Value.BasePermissions; + case 1: + return (int)inv.Value.CurrentPermissions; + case 2: + return (int)inv.Value.GroupPermissions; + case 3: + return (int)inv.Value.EveryonePermissions; + case 4: + return (int)inv.Value.NextPermissions; } } } + m_host.TaskInventory.LockItemsForRead(false); return -1; } @@ -8169,16 +8218,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == item) { - if (inv.Value.Name == item) - { - return inv.Value.CreatorID.ToString(); - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.CreatorID.ToString(); } } + m_host.TaskInventory.LockItemsForRead(false); llSay(0, "No item name '" + item + "'"); @@ -8702,16 +8751,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) - { - return inv.Value.Type; - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.Type; } } + m_host.TaskInventory.LockItemsForRead(false); return -1; } @@ -8742,18 +8791,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (invItemID == UUID.Zero) return new LSL_Vector(); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) { - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) - return new LSL_Vector(); - - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) - { - ShoutError("No permissions to track the camera"); - return new LSL_Vector(); - } + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Vector(); } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + { + ShoutError("No permissions to track the camera"); + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Vector(); + } + m_host.TaskInventory.LockItemsForRead(false); + ScenePresence presence = World.GetScenePresence(m_host.OwnerID); if (presence != null) { @@ -8770,17 +8822,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (invItemID == UUID.Zero) return new LSL_Rotation(); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) { - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) - return new LSL_Rotation(); - - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) - { - ShoutError("No permissions to track the camera"); - return new LSL_Rotation(); - } + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Rotation(); } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + { + ShoutError("No permissions to track the camera"); + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Rotation(); + } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(m_host.OwnerID); if (presence != null) @@ -8930,14 +8984,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (objectID == UUID.Zero) return; UUID agentID; - lock (m_host.TaskInventory) - { - // we need the permission first, to know which avatar we want to set the camera for - agentID = m_host.TaskInventory[invItemID].PermsGranter; + m_host.TaskInventory.LockItemsForRead(true); + // we need the permission first, to know which avatar we want to set the camera for + agentID = m_host.TaskInventory[invItemID].PermsGranter; - if (agentID == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + if (agentID == UUID.Zero) + { + m_host.TaskInventory.LockItemsForRead(false); + return; } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) + { + m_host.TaskInventory.LockItemsForRead(false); + return; + } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(agentID); @@ -8987,12 +9048,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // we need the permission first, to know which avatar we want to clear the camera for UUID agentID; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + agentID = m_host.TaskInventory[invItemID].PermsGranter; + if (agentID == UUID.Zero) { - agentID = m_host.TaskInventory[invItemID].PermsGranter; - if (agentID == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + m_host.TaskInventory.LockItemsForRead(false); + return; } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) + { + m_host.TaskInventory.LockItemsForRead(false); + return; + } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(agentID); @@ -9449,15 +9517,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal UUID ScriptByName(string name) { - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.Name == name) { - if (item.Type == 10 && item.Name == name) - return item.ItemID; + m_host.TaskInventory.LockItemsForRead(false); + return item.ItemID; } } + m_host.TaskInventory.LockItemsForRead(false); + return UUID.Zero; } @@ -9498,6 +9570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + //Clone is thread safe TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); UUID assetID = UUID.Zero; @@ -9560,6 +9633,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + //Clone is thread safe TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); UUID assetID = UUID.Zero; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 7fdbac8d86..83322eb587 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -728,18 +728,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (target != null) { UUID animID=UUID.Zero; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == animation) { - if (inv.Value.Name == animation) - { - if (inv.Value.Type == (int)AssetType.Animation) - animID = inv.Value.AssetID; - continue; - } + if (inv.Value.Type == (int)AssetType.Animation) + animID = inv.Value.AssetID; + continue; } } + m_host.TaskInventory.LockItemsForRead(false); if (animID == UUID.Zero) target.Animator.AddAnimation(animation, m_host.UUID); else @@ -761,18 +760,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (target != null) { UUID animID=UUID.Zero; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == animation) { - if (inv.Value.Name == animation) - { - if (inv.Value.Type == (int)AssetType.Animation) - animID = inv.Value.AssetID; - continue; - } + if (inv.Value.Type == (int)AssetType.Animation) + animID = inv.Value.AssetID; + continue; } } + m_host.TaskInventory.LockItemsForRead(false); if (animID == UUID.Zero) target.Animator.RemoveAnimation(animation); @@ -1541,6 +1539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(name, out assetID)) { + m_host.TaskInventory.LockItemsForRead(true); foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { if (item.Type == 7 && item.Name == name) @@ -1548,6 +1547,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api assetID = item.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); } if (assetID == UUID.Zero) @@ -1594,6 +1594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(name, out assetID)) { + m_host.TaskInventory.LockItemsForRead(true); foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { if (item.Type == 7 && item.Name == name) @@ -1601,6 +1602,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api assetID = item.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); } if (assetID == UUID.Zero) @@ -1651,6 +1653,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(name, out assetID)) { + m_host.TaskInventory.LockItemsForRead(true); foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { if (item.Type == 7 && item.Name == name) @@ -1658,6 +1661,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api assetID = item.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); } if (assetID == UUID.Zero) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 063d50f231..0f4a9adf5c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -238,13 +238,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance if (part != null) { - lock (part.TaskInventory) + part.TaskInventory.LockItemsForRead(true); + if (part.TaskInventory.ContainsKey(m_ItemID)) { - if (part.TaskInventory.ContainsKey(m_ItemID)) - { - m_thisScriptTask = part.TaskInventory[m_ItemID]; - } + m_thisScriptTask = part.TaskInventory[m_ItemID]; } + part.TaskInventory.LockItemsForRead(false); } ApiManager am = new ApiManager(); @@ -429,14 +428,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { int permsMask; UUID permsGranter; - lock (part.TaskInventory) + part.TaskInventory.LockItemsForRead(true); + if (!part.TaskInventory.ContainsKey(m_ItemID)) { - if (!part.TaskInventory.ContainsKey(m_ItemID)) - return; - - permsGranter = part.TaskInventory[m_ItemID].PermsGranter; - permsMask = part.TaskInventory[m_ItemID].PermsMask; + part.TaskInventory.LockItemsForRead(false); + return; } + permsGranter = part.TaskInventory[m_ItemID].PermsGranter; + permsMask = part.TaskInventory[m_ItemID].PermsMask; + part.TaskInventory.LockItemsForRead(false); if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) { From 8383bde76880fc94a6644422d45baa28252b0231 Mon Sep 17 00:00:00 2001 From: CasperW Date: Tue, 24 Nov 2009 18:18:19 +0100 Subject: [PATCH 5/5] Removed some extra debug chatter --- .../Avatar/Inventory/Transfer/InventoryTransferModule.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index d9a021fc02..b60b32b974 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -389,7 +389,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { // Check if this is ours to handle // - m_log.Info("OnFridInstantMessage"); + //m_log.Info("OnFridInstantMessage"); if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered) return; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 4dc709e142..abb04cd564 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -713,7 +713,6 @@ namespace OpenSim.Region.Framework.Scenes if (fileData.Length > 2) { - m_log.Debug("Sending task inventory list of " + count.ToString() + " items to client " + client.AgentId.ToString()); xferManager.AddNewFile(m_inventoryFileName, fileData); } }