diff options
author | Melanie Thielker | 2008-09-18 18:50:39 +0000 |
---|---|---|
committer | Melanie Thielker | 2008-09-18 18:50:39 +0000 |
commit | 903fbd1f06b990141a90b539a2dbe77ab6be830e (patch) | |
tree | 9e33425216bd3a5631cf561d279ba503565c1e05 | |
parent | * Updates the SQLite region database to support the same properties that the ... (diff) | |
download | opensim-SC-903fbd1f06b990141a90b539a2dbe77ab6be830e.zip opensim-SC-903fbd1f06b990141a90b539a2dbe77ab6be830e.tar.gz opensim-SC-903fbd1f06b990141a90b539a2dbe77ab6be830e.tar.bz2 opensim-SC-903fbd1f06b990141a90b539a2dbe77ab6be830e.tar.xz |
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.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 10 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 244 | ||||
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/EventManager.cs | 25 |
3 files changed, 154 insertions, 125 deletions
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 | |||
2294 | if (CollisionEventsThisFrame == null) | 2294 | if (CollisionEventsThisFrame == null) |
2295 | return; | 2295 | return; |
2296 | 2296 | ||
2297 | //if (CollisionEventsThisFrame.m_objCollisionList == null) | 2297 | base.SendCollisionUpdate(CollisionEventsThisFrame); |
2298 | // return; | ||
2299 | 2298 | ||
2300 | if (CollisionEventsThisFrame.m_objCollisionList.Count > 0) | 2299 | if(CollisionEventsThisFrame.m_objCollisionList.Count == 0) |
2301 | { | 2300 | CollisionEventsThisFrame = null; |
2302 | base.SendCollisionUpdate(CollisionEventsThisFrame); | 2301 | else |
2303 | CollisionEventsThisFrame = new CollisionEventUpdate(); | 2302 | CollisionEventsThisFrame = new CollisionEventUpdate(); |
2304 | } | ||
2305 | } | 2303 | } |
2306 | 2304 | ||
2307 | public override bool SubscribedEvents() | 2305 | 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 | |||
79 | private bool m_ShuttingDown = false; | 79 | private bool m_ShuttingDown = false; |
80 | private int m_ControlEventsInQueue = 0; | 80 | private int m_ControlEventsInQueue = 0; |
81 | private int m_LastControlLevel = 0; | 81 | private int m_LastControlLevel = 0; |
82 | private bool m_CollisionInQueue = false; | ||
82 | 83 | ||
83 | private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); | 84 | private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); |
84 | 85 | ||
@@ -495,6 +496,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
495 | m_ControlEventsInQueue++; | 496 | m_ControlEventsInQueue++; |
496 | } | 497 | } |
497 | 498 | ||
499 | if (data.EventName == "collision") | ||
500 | { | ||
501 | if (m_CollisionInQueue) | ||
502 | return; | ||
503 | if (data.DetectParams == null) | ||
504 | return; | ||
505 | |||
506 | m_CollisionInQueue = true; | ||
507 | } | ||
508 | |||
498 | m_EventQueue.Enqueue(data); | 509 | m_EventQueue.Enqueue(data); |
499 | 510 | ||
500 | if (m_CurrentResult == null) | 511 | if (m_CurrentResult == null) |
@@ -510,146 +521,159 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
510 | /// <returns></returns> | 521 | /// <returns></returns> |
511 | public object EventProcessor() | 522 | public object EventProcessor() |
512 | { | 523 | { |
513 | EventParams data = null; | 524 | lock(m_Script) |
514 | |||
515 | lock (m_EventQueue) | ||
516 | { | 525 | { |
517 | data = (EventParams) m_EventQueue.Dequeue(); | 526 | EventParams data = null; |
518 | if (data == null) // Shouldn't happen | 527 | |
519 | { | 528 | lock (m_EventQueue) |
520 | m_CurrentResult = null; | ||
521 | return 0; | ||
522 | } | ||
523 | if (data.EventName == "timer") | ||
524 | m_TimerQueued = false; | ||
525 | if (data.EventName == "control") | ||
526 | { | 529 | { |
527 | if (m_ControlEventsInQueue > 0) | 530 | data = (EventParams) m_EventQueue.Dequeue(); |
528 | m_ControlEventsInQueue--; | 531 | if (data == null) // Shouldn't happen |
532 | { | ||
533 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) | ||
534 | { | ||
535 | m_CurrentResult = m_Engine.QueueEventHandler(this); | ||
536 | } | ||
537 | else | ||
538 | { | ||
539 | m_CurrentResult = null; | ||
540 | } | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | if (data.EventName == "timer") | ||
545 | m_TimerQueued = false; | ||
546 | if (data.EventName == "control") | ||
547 | { | ||
548 | if (m_ControlEventsInQueue > 0) | ||
549 | m_ControlEventsInQueue--; | ||
550 | } | ||
551 | if (data.EventName == "collision") | ||
552 | m_CollisionInQueue = false; | ||
529 | } | 553 | } |
530 | } | 554 | |
531 | 555 | //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); | |
532 | //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); | ||
533 | 556 | ||
534 | m_DetectParams = data.DetectParams; | 557 | m_DetectParams = data.DetectParams; |
535 | 558 | ||
536 | if (data.EventName == "state") // Hardcoded state change | 559 | if (data.EventName == "state") // Hardcoded state change |
537 | { | ||
538 | // m_Engine.Log.DebugFormat("[Script] Script {0}.{1} state set to {2}", | ||
539 | // m_PrimName, m_ScriptName, data.Params[0].ToString()); | ||
540 | m_State=data.Params[0].ToString(); | ||
541 | AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands; | ||
542 | async.RemoveScript( | ||
543 | m_LocalID, m_ItemID); | ||
544 | |||
545 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart( | ||
546 | m_LocalID); | ||
547 | if (part != null) | ||
548 | { | 560 | { |
549 | part.SetScriptEvents(m_ItemID, | 561 | // m_Engine.Log.DebugFormat("[Script] Script {0}.{1} state set to {2}", |
550 | (int)m_Script.GetStateEventFlags(State)); | 562 | // m_PrimName, m_ScriptName, data.Params[0].ToString()); |
563 | m_State=data.Params[0].ToString(); | ||
564 | AsyncCommandManager async = (AsyncCommandManager)m_Engine.AsyncCommands; | ||
565 | async.RemoveScript( | ||
566 | m_LocalID, m_ItemID); | ||
567 | |||
568 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart( | ||
569 | m_LocalID); | ||
570 | if (part != null) | ||
571 | { | ||
572 | part.SetScriptEvents(m_ItemID, | ||
573 | (int)m_Script.GetStateEventFlags(State)); | ||
574 | } | ||
551 | } | 575 | } |
552 | } | 576 | else |
553 | else | ||
554 | { | ||
555 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart( | ||
556 | m_LocalID); | ||
557 | // m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", | ||
558 | // m_PrimName, m_ScriptName, data.EventName, m_State); | ||
559 | |||
560 | try | ||
561 | { | 577 | { |
562 | m_CurrentEvent = data.EventName; | 578 | SceneObjectPart part = m_Engine.World.GetSceneObjectPart( |
563 | m_EventStart = DateTime.Now; | 579 | m_LocalID); |
564 | m_InEvent = true; | 580 | // m_Engine.Log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", |
581 | // m_PrimName, m_ScriptName, data.EventName, m_State); | ||
565 | 582 | ||
566 | m_Script.ExecuteEvent(State, data.EventName, data.Params); | 583 | try |
584 | { | ||
585 | m_CurrentEvent = data.EventName; | ||
586 | m_EventStart = DateTime.Now; | ||
587 | m_InEvent = true; | ||
567 | 588 | ||
568 | m_InEvent = false; | 589 | m_Script.ExecuteEvent(State, data.EventName, data.Params); |
569 | m_CurrentEvent = String.Empty; | ||
570 | 590 | ||
571 | if (m_SaveState) | 591 | m_InEvent = false; |
572 | { | 592 | m_CurrentEvent = String.Empty; |
573 | // This will be the very first event we deliver | ||
574 | // (state_entry) in defualt state | ||
575 | // | ||
576 | 593 | ||
577 | SaveState(m_Assembly); | 594 | if (m_SaveState) |
595 | { | ||
596 | // This will be the very first event we deliver | ||
597 | // (state_entry) in defualt state | ||
598 | // | ||
578 | 599 | ||
579 | m_SaveState = false; | 600 | SaveState(m_Assembly); |
580 | } | ||
581 | } | ||
582 | catch (Exception e) | ||
583 | { | ||
584 | m_InEvent = false; | ||
585 | m_CurrentEvent = String.Empty; | ||
586 | 601 | ||
587 | if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) | 602 | m_SaveState = false; |
603 | } | ||
604 | } | ||
605 | catch (Exception e) | ||
588 | { | 606 | { |
589 | if (e is System.Threading.ThreadAbortException) | 607 | m_InEvent = false; |
608 | m_CurrentEvent = String.Empty; | ||
609 | |||
610 | if (!(e is TargetInvocationException) || (!(e.InnerException is EventAbortException) && (!(e.InnerException is SelfDeleteException)))) | ||
590 | { | 611 | { |
591 | lock (m_EventQueue) | 612 | if (e is System.Threading.ThreadAbortException) |
592 | { | 613 | { |
593 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) | 614 | lock (m_EventQueue) |
594 | { | 615 | { |
595 | m_CurrentResult=m_Engine.QueueEventHandler(this); | 616 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) |
617 | { | ||
618 | m_CurrentResult=m_Engine.QueueEventHandler(this); | ||
619 | } | ||
620 | else | ||
621 | { | ||
622 | m_CurrentResult = null; | ||
623 | } | ||
596 | } | 624 | } |
597 | else | ||
598 | { | ||
599 | m_CurrentResult = null; | ||
600 | } | ||
601 | } | ||
602 | 625 | ||
603 | m_DetectParams = null; | 626 | m_DetectParams = null; |
604 | 627 | ||
605 | return 0; | 628 | return 0; |
606 | } | 629 | } |
607 | 630 | ||
608 | try | 631 | try |
609 | { | 632 | { |
610 | // DISPLAY ERROR INWORLD | 633 | // DISPLAY ERROR INWORLD |
611 | string text = "Runtime error:\n" + e.InnerException.ToString(); | 634 | string text = "Runtime error:\n" + e.InnerException.ToString(); |
612 | if (text.Length > 1000) | 635 | if (text.Length > 1000) |
613 | text = text.Substring(0, 1000); | 636 | text = text.Substring(0, 1000); |
614 | m_Engine.World.SimChat(Utils.StringToBytes(text), | 637 | m_Engine.World.SimChat(Utils.StringToBytes(text), |
615 | ChatTypeEnum.DebugChannel, 2147483647, | 638 | ChatTypeEnum.DebugChannel, 2147483647, |
616 | part.AbsolutePosition, | 639 | part.AbsolutePosition, |
617 | part.Name, part.UUID, false); | 640 | part.Name, part.UUID, false); |
641 | } | ||
642 | catch (Exception e2) // LEGIT: User Scripting | ||
643 | { | ||
644 | m_Engine.Log.Error("[Script]: "+ | ||
645 | "Error displaying error in-world: " + | ||
646 | e2.ToString()); | ||
647 | m_Engine.Log.Error("[Script]: " + | ||
648 | "Errormessage: Error compiling script:\r\n" + | ||
649 | e.ToString()); | ||
650 | } | ||
618 | } | 651 | } |
619 | catch (Exception e2) // LEGIT: User Scripting | 652 | else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) |
620 | { | 653 | { |
621 | m_Engine.Log.Error("[Script]: "+ | 654 | m_InSelfDelete = true; |
622 | "Error displaying error in-world: " + | 655 | if (part != null && part.ParentGroup != null) |
623 | e2.ToString()); | 656 | m_Engine.World.DeleteSceneObject(part.ParentGroup); |
624 | m_Engine.Log.Error("[Script]: " + | ||
625 | "Errormessage: Error compiling script:\r\n" + | ||
626 | e.ToString()); | ||
627 | } | 657 | } |
628 | } | 658 | } |
629 | else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) | ||
630 | { | ||
631 | m_InSelfDelete = true; | ||
632 | if (part != null && part.ParentGroup != null) | ||
633 | m_Engine.World.DeleteSceneObject(part.ParentGroup); | ||
634 | } | ||
635 | } | 659 | } |
636 | } | ||
637 | 660 | ||
638 | lock (m_EventQueue) | 661 | lock (m_EventQueue) |
639 | { | ||
640 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) | ||
641 | { | ||
642 | m_CurrentResult = m_Engine.QueueEventHandler(this); | ||
643 | } | ||
644 | else | ||
645 | { | 662 | { |
646 | m_CurrentResult = null; | 663 | if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) |
664 | { | ||
665 | m_CurrentResult = m_Engine.QueueEventHandler(this); | ||
666 | } | ||
667 | else | ||
668 | { | ||
669 | m_CurrentResult = null; | ||
670 | } | ||
647 | } | 671 | } |
648 | } | ||
649 | 672 | ||
650 | m_DetectParams = null; | 673 | m_DetectParams = null; |
651 | 674 | ||
652 | return 0; | 675 | return 0; |
676 | } | ||
653 | } | 677 | } |
654 | 678 | ||
655 | public int EventTime() | 679 | public int EventTime() |
@@ -730,6 +754,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
730 | 754 | ||
731 | public DetectParams GetDetectParams(int idx) | 755 | public DetectParams GetDetectParams(int idx) |
732 | { | 756 | { |
757 | if (m_DetectParams == null) | ||
758 | return null; | ||
733 | if (idx < 0 || idx >= m_DetectParams.Length) | 759 | if (idx < 0 || idx >= m_DetectParams.Length) |
734 | return null; | 760 | return null; |
735 | 761 | ||
@@ -738,6 +764,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
738 | 764 | ||
739 | public UUID GetDetectID(int idx) | 765 | public UUID GetDetectID(int idx) |
740 | { | 766 | { |
767 | if (m_DetectParams == null) | ||
768 | return UUID.Zero; | ||
741 | if (idx < 0 || idx >= m_DetectParams.Length) | 769 | if (idx < 0 || idx >= m_DetectParams.Length) |
742 | return UUID.Zero; | 770 | return UUID.Zero; |
743 | 771 | ||
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 | |||
198 | det.Add(d); | 198 | det.Add(d); |
199 | } | 199 | } |
200 | 200 | ||
201 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 201 | if (det.Count > 0) |
202 | "collision_start", | 202 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
203 | new Object[] { new LSL_Types.LSLInteger(1) }, | 203 | "collision_start", |
204 | det.ToArray())); | 204 | new Object[] { new LSL_Types.LSLInteger(det.Count) }, |
205 | det.ToArray())); | ||
205 | } | 206 | } |
206 | 207 | ||
207 | public void collision(uint localID, ColliderArgs col) | 208 | public void collision(uint localID, ColliderArgs col) |
@@ -217,9 +218,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
217 | det.Add(d); | 218 | det.Add(d); |
218 | } | 219 | } |
219 | 220 | ||
220 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 221 | if (det.Count > 0) |
221 | "collision", new Object[] { new LSL_Types.LSLInteger(1) }, | 222 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
222 | det.ToArray())); | 223 | "collision", new Object[] { new LSL_Types.LSLInteger(det.Count) }, |
224 | det.ToArray())); | ||
223 | } | 225 | } |
224 | 226 | ||
225 | public void collision_end(uint localID, ColliderArgs col) | 227 | public void collision_end(uint localID, ColliderArgs col) |
@@ -235,10 +237,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
235 | det.Add(d); | 237 | det.Add(d); |
236 | } | 238 | } |
237 | 239 | ||
238 | myScriptEngine.PostObjectEvent(localID, new EventParams( | 240 | if (det.Count > 0) |
239 | "collision_end", | 241 | myScriptEngine.PostObjectEvent(localID, new EventParams( |
240 | new Object[] { new LSL_Types.LSLInteger(1) }, | 242 | "collision_end", |
241 | det.ToArray())); | 243 | new Object[] { new LSL_Types.LSLInteger(det.Count) }, |
244 | det.ToArray())); | ||
242 | } | 245 | } |
243 | 246 | ||
244 | public void land_collision_start(uint localID, UUID itemID) | 247 | public void land_collision_start(uint localID, UUID itemID) |