From 903fbd1f06b990141a90b539a2dbe77ab6be830e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 18 Sep 2008 18:50:39 +0000 Subject: XEngine: fix collisions, add event coalescing for collision events. Fix a nasty concurrency issue that could cause a high event frequency to start more than one thread pool job for a single script. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 10 +- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 244 ++++++++++++--------- .../Region/ScriptEngine/XEngine/EventManager.cs | 25 ++- 3 files changed, 154 insertions(+), 125 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 21e514b..79c4041 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -2294,14 +2294,12 @@ namespace OpenSim.Region.Physics.OdePlugin if (CollisionEventsThisFrame == null) return; - //if (CollisionEventsThisFrame.m_objCollisionList == null) - // return; + base.SendCollisionUpdate(CollisionEventsThisFrame); - if (CollisionEventsThisFrame.m_objCollisionList.Count > 0) - { - base.SendCollisionUpdate(CollisionEventsThisFrame); + if(CollisionEventsThisFrame.m_objCollisionList.Count == 0) + CollisionEventsThisFrame = null; + else CollisionEventsThisFrame = new CollisionEventUpdate(); - } } public override bool SubscribedEvents() diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 71bdd6e..506f0f5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -79,6 +79,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private bool m_ShuttingDown = false; private int m_ControlEventsInQueue = 0; private int m_LastControlLevel = 0; + private bool m_CollisionInQueue = false; private Dictionary m_Apis = new Dictionary(); @@ -495,6 +496,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_ControlEventsInQueue++; } + if (data.EventName == "collision") + { + if (m_CollisionInQueue) + return; + if (data.DetectParams == null) + return; + + m_CollisionInQueue = true; + } + m_EventQueue.Enqueue(data); if (m_CurrentResult == null) @@ -510,146 +521,159 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// public object EventProcessor() { - EventParams data = null; - - lock (m_EventQueue) + lock(m_Script) { - data = (EventParams) m_EventQueue.Dequeue(); - if (data == null) // Shouldn't happen - { - m_CurrentResult = null; - return 0; - } - if (data.EventName == "timer") - m_TimerQueued = false; - if (data.EventName == "control") + EventParams data = null; + + lock (m_EventQueue) { - if (m_ControlEventsInQueue > 0) - m_ControlEventsInQueue--; + 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_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); - m_DetectParams = data.DetectParams; + m_DetectParams = data.DetectParams; - if (data.EventName == "state") // Hardcoded state change - { -// m_Engine.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 async = (AsyncCommandManager)m_Engine.AsyncCommands; - async.RemoveScript( - m_LocalID, m_ItemID); - - SceneObjectPart part = m_Engine.World.GetSceneObjectPart( - m_LocalID); - if (part != null) + if (data.EventName == "state") // Hardcoded state change { - part.SetScriptEvents(m_ItemID, - (int)m_Script.GetStateEventFlags(State)); + // m_Engine.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 async = (AsyncCommandManager)m_Engine.AsyncCommands; + async.RemoveScript( + 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 - { - SceneObjectPart part = m_Engine.World.GetSceneObjectPart( - m_LocalID); -// m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", -// m_PrimName, m_ScriptName, data.EventName, m_State); - - try + else { - m_CurrentEvent = data.EventName; - m_EventStart = DateTime.Now; - m_InEvent = true; + SceneObjectPart part = m_Engine.World.GetSceneObjectPart( + m_LocalID); + // m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", + // m_PrimName, m_ScriptName, data.EventName, m_State); - m_Script.ExecuteEvent(State, data.EventName, data.Params); + try + { + m_CurrentEvent = data.EventName; + m_EventStart = DateTime.Now; + m_InEvent = true; - m_InEvent = false; - m_CurrentEvent = String.Empty; + m_Script.ExecuteEvent(State, data.EventName, data.Params); - if (m_SaveState) - { - // This will be the very first event we deliver - // (state_entry) in defualt state - // + m_InEvent = false; + m_CurrentEvent = String.Empty; - SaveState(m_Assembly); + if (m_SaveState) + { + // This will be the very first event we deliver + // (state_entry) in defualt state + // - m_SaveState = false; - } - } - catch (Exception e) - { - m_InEvent = false; - m_CurrentEvent = String.Empty; + SaveState(m_Assembly); - if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) + m_SaveState = false; + } + } + catch (Exception e) { - if (e is System.Threading.ThreadAbortException) + m_InEvent = false; + m_CurrentEvent = String.Empty; + + if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) { - lock (m_EventQueue) + if (e is System.Threading.ThreadAbortException) { - if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) + lock (m_EventQueue) { - m_CurrentResult=m_Engine.QueueEventHandler(this); + if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) + { + m_CurrentResult=m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult = null; + } } - else - { - m_CurrentResult = null; - } - } - m_DetectParams = null; + m_DetectParams = null; - return 0; - } + return 0; + } - try - { - // DISPLAY ERROR INWORLD - string text = "Runtime error:\n" + e.InnerException.ToString(); - 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); + try + { + // DISPLAY ERROR INWORLD + string text = "Runtime error:\n" + e.InnerException.ToString(); + 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 e2) // LEGIT: User Scripting + { + m_Engine.Log.Error("[Script]: "+ + "Error displaying error in-world: " + + e2.ToString()); + m_Engine.Log.Error("[Script]: " + + "Errormessage: Error compiling script:\r\n" + + e.ToString()); + } } - catch (Exception e2) // LEGIT: User Scripting + else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) { - m_Engine.Log.Error("[Script]: "+ - "Error displaying error in-world: " + - e2.ToString()); - m_Engine.Log.Error("[Script]: " + - "Errormessage: Error compiling script:\r\n" + - e.ToString()); + m_InSelfDelete = true; + if (part != null && part.ParentGroup != null) + m_Engine.World.DeleteSceneObject(part.ParentGroup); } } - else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) - { - m_InSelfDelete = true; - if (part != null && part.ParentGroup != null) - m_Engine.World.DeleteSceneObject(part.ParentGroup); - } } - } - lock (m_EventQueue) - { - if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) - { - m_CurrentResult = m_Engine.QueueEventHandler(this); - } - else + lock (m_EventQueue) { - m_CurrentResult = null; + if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) + { + m_CurrentResult = m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult = null; + } } - } - m_DetectParams = null; + m_DetectParams = null; - return 0; + return 0; + } } public int EventTime() @@ -730,6 +754,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public DetectParams GetDetectParams(int idx) { + if (m_DetectParams == null) + return null; if (idx < 0 || idx >= m_DetectParams.Length) return null; @@ -738,6 +764,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public UUID GetDetectID(int idx) { + if (m_DetectParams == null) + return UUID.Zero; if (idx < 0 || idx >= m_DetectParams.Length) return UUID.Zero; diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 22abd79..9ed2fbb 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -198,10 +198,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine det.Add(d); } - myScriptEngine.PostObjectEvent(localID, new EventParams( - "collision_start", - new Object[] { new LSL_Types.LSLInteger(1) }, - det.ToArray())); + if (det.Count > 0) + myScriptEngine.PostObjectEvent(localID, new EventParams( + "collision_start", + new Object[] { new LSL_Types.LSLInteger(det.Count) }, + det.ToArray())); } public void collision(uint localID, ColliderArgs col) @@ -217,9 +218,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine det.Add(d); } - myScriptEngine.PostObjectEvent(localID, new EventParams( - "collision", new Object[] { new LSL_Types.LSLInteger(1) }, - det.ToArray())); + if (det.Count > 0) + myScriptEngine.PostObjectEvent(localID, new EventParams( + "collision", new Object[] { new LSL_Types.LSLInteger(det.Count) }, + det.ToArray())); } public void collision_end(uint localID, ColliderArgs col) @@ -235,10 +237,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine det.Add(d); } - myScriptEngine.PostObjectEvent(localID, new EventParams( - "collision_end", - new Object[] { new LSL_Types.LSLInteger(1) }, - det.ToArray())); + if (det.Count > 0) + myScriptEngine.PostObjectEvent(localID, new EventParams( + "collision_end", + new Object[] { new LSL_Types.LSLInteger(det.Count) }, + det.ToArray())); } public void land_collision_start(uint localID, UUID itemID) -- cgit v1.1