From c20f7d6171a9df151c3ccde063336338da9ae322 Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Sun, 25 May 2008 20:50:45 +0000
Subject: * A hacky Top Scripts display.  It isn't accurate as far as ms
 accounting, however you can use it to help find out what scripts are causing
 your simulator to cry. * Access it from the Estate tools/Debug tab.

---
 .../Region/ClientStack/LindenUDP/LLClientView.cs   |  7 +++++
 .../Modules/World/Estate/EstateManagementModule.cs | 36 ++++++++++++++++------
 OpenSim/Region/Environment/Scenes/EventManager.cs  | 15 +++++++++
 OpenSim/Region/Environment/Scenes/InnerScene.cs    | 31 +++++++++++++++++++
 .../Region/Environment/Scenes/SceneObjectGroup.cs  |  5 +++
 .../Region/Environment/Scenes/SceneObjectPart.cs   | 32 +++++++++++++++++++
 .../ScriptEngine/Common/LSL_BuiltIn_Commands.cs    |  8 ++---
 .../AsyncCommandPlugins/SensorRepeat.cs            |  1 +
 .../ScriptEngineBase/AsyncCommandPlugins/Timer.cs  |  1 +
 9 files changed, 123 insertions(+), 13 deletions(-)

(limited to 'OpenSim')

diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 484518a..11fb5be 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -5652,6 +5652,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                                     handlerLandStatRequest(0, 1, 0, "", this);
                                 }
                                 break;
+                            case "scripts":
+                                handlerLandStatRequest = OnLandStatRequest;
+                                if (handlerLandStatRequest != null)
+                                {
+                                    handlerLandStatRequest(0, 0, 0, "", this);
+                                }
+                                break;
                             default:
                                 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket.ToString());
                                 break;
diff --git a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs
index d3aa4aa..ab5898d 100644
--- a/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/Environment/Modules/World/Estate/EstateManagementModule.cs
@@ -313,12 +313,21 @@ namespace OpenSim.Region.Environment.Modules.World.Estate
         }
         private void HandleLandStatRequest(int parcelID, uint reportType, uint requestFlags, string filter, IClientAPI remoteClient)
         {
-            Dictionary<uint, float> colliders = m_scene.PhysicsScene.GetTopColliders();
-            
-            List<LandStatReportItem> collidera = new List<LandStatReportItem>();
-            lock (colliders)
+            Dictionary<uint, float> SceneData = new Dictionary<uint,float>();
+
+            if (reportType == 1)
+            {
+                SceneData = m_scene.PhysicsScene.GetTopColliders();
+            }
+            else if (reportType == 0)
             {
-                foreach (uint obj in colliders.Keys)
+                SceneData = m_scene.m_innerScene.GetTopScripts();
+            }
+
+            List<LandStatReportItem> SceneReport = new List<LandStatReportItem>();
+            lock (SceneData)
+            {
+                foreach (uint obj in SceneData.Keys)
                 {
                     SceneObjectPart prt = m_scene.GetSceneObjectPart(obj);
                     if (prt != null)
@@ -332,21 +341,30 @@ namespace OpenSim.Region.Environment.Modules.World.Estate
                                 lsri.LocationX = sog.AbsolutePosition.X;
                                 lsri.LocationY = sog.AbsolutePosition.Y;
                                 lsri.LocationZ = sog.AbsolutePosition.Z;
-                                lsri.Score = colliders[obj];
+                                lsri.Score = SceneData[obj];
                                 lsri.TaskID = sog.UUID;
                                 lsri.TaskLocalID = sog.LocalId;
                                 lsri.TaskName = sog.GetPartName(obj);
                                 lsri.OwnerName = m_scene.CommsManager.UUIDNameRequestString(sog.OwnerID);
-
+                                if (filter.Length != 0)
+                                {
+                                    if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter)))
+                                    {
+                                    }
+                                    else
+                                    {
+                                        continue;
+                                    }
+                                }
                                 
-                                collidera.Add(lsri);
+                                SceneReport.Add(lsri);
                             }
                         }
                     }
 
                 }
             }
-            remoteClient.SendLandStatReply(reportType, requestFlags, (uint)collidera.Count,collidera.ToArray());
+            remoteClient.SendLandStatReply(reportType, requestFlags, (uint)SceneReport.Count,SceneReport.ToArray());
 
         }
 
diff --git a/OpenSim/Region/Environment/Scenes/EventManager.cs b/OpenSim/Region/Environment/Scenes/EventManager.cs
index a3f5d2f..1c345ba 100644
--- a/OpenSim/Region/Environment/Scenes/EventManager.cs
+++ b/OpenSim/Region/Environment/Scenes/EventManager.cs
@@ -174,6 +174,9 @@ namespace OpenSim.Region.Environment.Scenes
 
         public event AvatarKillData OnAvatarKilled;
 
+        public delegate void ScriptTimerEvent(uint localID, double timerinterval);
+
+        public event ScriptTimerEvent OnScriptTimerEvent;
 
 
         public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
@@ -332,6 +335,7 @@ namespace OpenSim.Region.Environment.Scenes
         private RequestParcelPrimCountUpdate handlerRequestParcelPrimCountUpdate = null;
         private ParcelPrimCountTainted handlerParcelPrimCountTainted = null;
         private ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = null;
+        private ScriptTimerEvent handlerScriptTimerEvent = null;
 
         public void TriggerOnScriptChangedEvent(uint localID, uint change)
         {
@@ -755,5 +759,16 @@ namespace OpenSim.Region.Environment.Scenes
 
             }
         }
+        // this lets us keep track of nasty script events like timer, etc.
+        public void TriggerTimerEvent(uint objLocalID, double Interval)
+        {
+            handlerScriptTimerEvent = OnScriptTimerEvent;
+            if (handlerScriptTimerEvent != null)
+            {
+                handlerScriptTimerEvent(objLocalID, Interval);
+
+            }
+            
+        }
     }
 }
diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs
index 84de71f..d6e905b 100644
--- a/OpenSim/Region/Environment/Scenes/InnerScene.cs
+++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs
@@ -846,6 +846,37 @@ namespace OpenSim.Region.Environment.Scenes
             return result;
         }
 
+        public Dictionary<uint, float> GetTopScripts()
+        {
+            Dictionary<uint, float> topScripts = new Dictionary<uint, float>();
+
+            List<EntityBase> EntityList = GetEntities();
+            int limit = 0;
+            foreach (EntityBase ent in EntityList)
+            {
+                if (ent is SceneObjectGroup)
+                {
+                    SceneObjectGroup grp = (SceneObjectGroup)ent;
+                    if ((grp.RootPart.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Scripted) != 0)
+                    {
+                        if (grp.scriptScore >= 0.01)
+                        {
+                            topScripts.Add(grp.LocalId, grp.scriptScore);
+                            limit++;
+                            if (limit >= 100)
+                            {
+                                break;
+                            }
+                            
+                        }
+                        grp.scriptScore = 0;
+                    }
+                }
+            }
+
+            return topScripts;
+        }
+
         #endregion
 
         #region Other Methods
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index 25b3d16..cd4be99 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -90,6 +90,7 @@ namespace OpenSim.Region.Environment.Scenes
         /// since the group's last persistent backup
         /// </summary>
         public bool HasGroupChanged = false;
+        public float scriptScore = 0f;
 
 
 
@@ -959,6 +960,10 @@ namespace OpenSim.Region.Environment.Scenes
 
         public void AddScriptLPS(int count)
         {
+            if (scriptScore + count >= float.MaxValue - count)
+                scriptScore = 0;
+
+            scriptScore += (float)count;
             InnerScene d = m_scene.m_innerScene;
             d.AddToScriptLPS(count);
         }
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index b724bda..c6b3059 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -2752,6 +2752,14 @@ namespace OpenSim.Region.Environment.Scenes
                     PhysActor.OnCollisionUpdate -= PhysicsCollision;
                 }
             }
+            if ((GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Scripted) != 0)
+            {
+                m_parentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
+            }
+            else
+            {
+                m_parentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
+            }
 
             LocalFlags=(LLObject.ObjectFlags)objectflagupdate;
 
@@ -2812,6 +2820,30 @@ namespace OpenSim.Region.Environment.Scenes
             GetProperties(client);
             m_updateFlag = 2;
         }
+        private void handleTimerAccounting(uint localID, double interval)
+        {
+            if (localID == LocalId)
+            {
+
+                float sec = (float)interval;
+                if (m_parentGroup != null)
+                {
+                    if (sec == 0)
+                    {
+                        if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001)
+                            m_parentGroup.scriptScore = 0;
+
+                        m_parentGroup.scriptScore += 0.001f;
+                        return;
+                    }
+
+                    if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec))
+                        m_parentGroup.scriptScore = 0;
+                    m_parentGroup.scriptScore += (0.001f / sec);
+                }
+
+            }
+        }
 
     }
 }
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
index 3fa65f5..fbfb400 100644
--- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
+++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs
@@ -474,7 +474,7 @@ namespace OpenSim.Region.ScriptEngine.Common
 
         public void llSensor(string name, string id, int type, double range, double arc)
         {
-            m_host.AddScriptLPS(1);
+            m_host.AddScriptLPS(300);
             LLUUID keyID = LLUUID.Zero;
             LLUUID.TryParse(id, out keyID);
 
@@ -1818,7 +1818,7 @@ namespace OpenSim.Region.ScriptEngine.Common
 
         public void llSleep(double sec)
         {
-            m_host.AddScriptLPS(1);
+            m_host.AddScriptLPS((int)(sec * 100));
             Thread.Sleep((int)(sec * 1000));
         }
 
@@ -2582,7 +2582,7 @@ namespace OpenSim.Region.ScriptEngine.Common
 
         public void llResetScript()
         {
-            m_host.AddScriptLPS(1);
+            m_host.AddScriptLPS(800);
             m_ScriptEngine.m_ScriptManager.ResetScript(m_localID, m_itemID);
         }
 
@@ -4279,7 +4279,7 @@ namespace OpenSim.Region.ScriptEngine.Common
             ScriptManager sm;
             IScript script = null;
 
-            m_host.AddScriptLPS(1);
+            m_host.AddScriptLPS(8000);
 
             // These functions are supposed to be robust,
             // so get the state one step at a time.
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/SensorRepeat.cs
index 13c9d25..82bd3ac 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/SensorRepeat.cs
@@ -316,6 +316,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.AsyncCommandPlugin
                     m_CmdManager.m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "sensor", EventQueueManager.llDetectNull,
                                                                         new object[] { new LSL_Types.LSLInteger(SensedObjects.Length) });
                 }
+                m_CmdManager.m_ScriptEngine.World.EventManager.TriggerTimerEvent(ts.localID, ts.interval);
             }
         }
     }
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/Timer.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/Timer.cs
index 6f88e11..f6de3c6 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/Timer.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncCommandPlugins/Timer.cs
@@ -126,6 +126,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase.AsyncCommandPlugin
                         // Add it to queue
                         m_CmdManager.m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(ts.localID, ts.itemID, "timer", EventQueueManager.llDetectNull,
                                                                             null);
+                        m_CmdManager.m_ScriptEngine.World.EventManager.TriggerTimerEvent(ts.localID, ((double)ts.interval / 10000000));
                         // set next interval
 
                         //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
-- 
cgit v1.1