From f2ede8c7e09487436261b249ec093bfd01c3f971 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 11 Apr 2012 08:11:05 -0700 Subject: [PATCH 1/5] HGFriendsModule: add the scaffolding for supporting permissions pertaining to HG friendships. Snoopy take it from here. --- .../Avatar/Friends/FriendsModule.cs | 4 +-- .../Avatar/Friends/HGFriendsModule.cs | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index f64c161271..fc6325dc3d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -162,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected void InitModule(IConfigSource config) + protected virtual void InitModule(IConfigSource config) { IConfig friendsConfig = config.Configs["Friends"]; if (friendsConfig != null) @@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private void OnInstantMessage(IClientAPI client, GridInstantMessage im) + protected virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im) { if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) { diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 9a6d277252..ddb6a71ace 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -87,6 +87,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_StatusNotifier = new HGStatusNotifier(this); } + protected override void InitModule(IConfigSource config) + { + base.InitModule(config); + + // Additionally to the base method + IConfig friendsConfig = config.Configs["HGFriendsModule"]; + if (friendsConfig != null) + { + // TODO: read in all config variables pertaining to + // HG friendship permissions + } + } + #endregion #region IFriendsSimConnector @@ -105,6 +118,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion + protected override void OnInstantMessage(IClientAPI client, GridInstantMessage im) + { + if ((InstantMessageDialog)im.dialog == InstantMessageDialog.FriendshipOffered) + { + // we got a friendship offer + UUID principalID = new UUID(im.fromAgentID); + UUID friendID = new UUID(im.toAgentID); + + // TODO: CHECK IF friendID is foreigner and if principalID has the permission + // to request these kinds of friendships. If not, return immediately. + // Maybe you want to let the client know too with + // client.SendAlertMessage + } + + base.OnInstantMessage(client, im); + } + protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { // Update the local cache. Yes, we need to do it right here From 1f4d3d35822c5ad3dbdd5f363014f1bf9afebdc6 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Wed, 11 Apr 2012 18:52:07 +0200 Subject: [PATCH 2/5] HGFriendsModule: Added optional user level based restriction to send friendship invitations to foreign users. --- .../Avatar/Friends/HGFriendsModule.cs | 24 +++++++++++++++---- bin/config-include/GridCommon.ini.example | 4 ++++ .../StandaloneCommon.ini.example | 4 ++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index ddb6a71ace..f8fbbbbbd4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -50,6 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private int m_levelHGFriends = 0; + IUserManagement m_uMan; public IUserManagement UserManagementModule { @@ -95,6 +97,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends IConfig friendsConfig = config.Configs["HGFriendsModule"]; if (friendsConfig != null) { + m_levelHGFriends = friendsConfig.GetInt("LevelHGFriends", 0); + // TODO: read in all config variables pertaining to // HG friendship permissions } @@ -126,10 +130,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UUID principalID = new UUID(im.fromAgentID); UUID friendID = new UUID(im.toAgentID); - // TODO: CHECK IF friendID is foreigner and if principalID has the permission - // to request these kinds of friendships. If not, return immediately. - // Maybe you want to let the client know too with - // client.SendAlertMessage + // Check if friendID is foreigner and if principalID has the permission + // to request friendships with foreigners. If not, return immediately. + if (!UserManagementModule.IsLocalGridUser(friendID)) + { + ScenePresence avatar = null; + client.Scene.TryGetScenePresence(principalID, out avatar); + + if (avatar == null) + return; + + if (avatar.UserLevel < m_levelHGFriends) + { + client.SendAgentAlertMessage("Unable to send friendship invitation to foreigner. Insufficient permissions.", false); + return; + } + } } base.OnInstantMessage(client, im); diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index fa6f5258c5..8d7f6fc427 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -137,6 +137,10 @@ ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False +[HGFriendsModule] + ; User level required to be able to send friendship invitations to foreign users + ;LevelHGFriends = 0; + [UserAgentService] ; ; === HG ONLY === diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 8fe64df93e..e4bc548967 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -61,6 +61,10 @@ ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False +[HGFriendsModule] + ; User level required to be able to send friendship invitations to foreign users + ;LevelHGFriends = 0; + [GridService] ;; For in-memory region storage (default) StorageProvider = "OpenSim.Data.Null.dll:NullRegionData" From 8be14095fed0d1d9f448d51fede20d13231c02db Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Wed, 11 Apr 2012 18:56:28 +0200 Subject: [PATCH 3/5] HGFriendsModule: Type casts to fix compile error --- OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index f8fbbbbbd4..3728b85a16 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -135,7 +135,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (!UserManagementModule.IsLocalGridUser(friendID)) { ScenePresence avatar = null; - client.Scene.TryGetScenePresence(principalID, out avatar); + ((Scene)client.Scene).TryGetScenePresence(principalID, out avatar); if (avatar == null) return; From 30d8506bc2f04028c1bbdcf57cf5f45fedb3ae7a Mon Sep 17 00:00:00 2001 From: nebadon Date: Thu, 12 Apr 2012 18:27:14 -0700 Subject: [PATCH 4/5] make changes to FlotsamCache.ini.example as noted in mantis #5960 http://opensimulator.org/mantis/view.php?id=5960 --- bin/config-include/FlotsamCache.ini.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index cd39f8c740..b9c6d84808 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -36,7 +36,7 @@ ; How often {in hours} should the disk be checked for expired filed ; Specify 0 to disable expiration checking - FileCleanupTimer = .166 ;roughly every 10 minutes + FileCleanupTimer = 1.0 ;every hour ; If WAIT_ON_INPROGRESS_REQUESTS has been defined then this specifies how ; long (in miliseconds) to block a request thread while trying to complete @@ -60,4 +60,4 @@ ; cache, and request all assets that are found that are not already cached (this ; will cause those assets to be cached) ; - ; DeepScanBeforePurge = false + DeepScanBeforePurge = true From 08e509978d81cb3451c205ed59648e3f5da91344 Mon Sep 17 00:00:00 2001 From: Talun Date: Tue, 10 Apr 2012 21:25:05 +0100 Subject: [PATCH 5/5] Mantis 55025 Implement script time. Signed-off-by: nebadon --- .../Framework/Interfaces/IEntityInventory.cs | 12 ++- .../Framework/Interfaces/IScriptModule.cs | 8 ++ .../Framework/Scenes/SceneObjectGroup.cs | 39 +++++++++ .../Scenes/SceneObjectPartInventory.cs | 14 ++-- .../Region/Framework/Scenes/ScenePresence.cs | 19 +++++ .../Shared/Api/Implementation/LSL_Api.cs | 7 +- .../Region/ScriptEngine/XEngine/XEngine.cs | 84 +++++++++++-------- 7 files changed, 136 insertions(+), 47 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index f5dda34d72..30ed7d100d 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -172,7 +172,17 @@ namespace OpenSim.Region.Framework.Interfaces /// If no inventory item has that name then an empty list is returned. /// List GetInventoryItems(string name); - + + /// + /// Get inventory items by type. + /// + /// + /// + /// A list of inventory items of that type. + /// If no inventory items of that type then an empty list is returned. + /// + List GetInventoryItems(InventoryType type); + /// /// Get the scene object referenced by an inventory item. /// diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index c0616ed2de..0d488dffd7 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -82,6 +82,14 @@ namespace OpenSim.Region.Framework.Interfaces /// void StartProcessing(); + /// + /// Get the execution times of all scripts in the given array if they are currently running. + /// + /// + /// A float the value is a representative execution time in milliseconds of all scripts in that Array. + /// + float GetScriptExecutionTime(List itemIDs); + /// /// Get the execution times of all scripts in each object. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7d14814ffc..a49ed13ed2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3269,6 +3269,45 @@ namespace OpenSim.Region.Framework.Scenes return count; } + /// + /// A float the value is a representative execution time in milliseconds of all scripts in the link set. + /// + public float ScriptExecutionTime() + { + IScriptModule[] engines = Scene.RequestModuleInterfaces(); + + if (engines.Length == 0) // No engine at all + return 0.0f; + + float time = 0.0f; + + // get all the scripts in all parts + SceneObjectPart[] parts = m_parts.GetArray(); + List scripts = new List(); + for (int i = 0; i < parts.Length; i++) + { + scripts.AddRange(parts[i].Inventory.GetInventoryItems(InventoryType.LSL)); + } + // extract the UUIDs + List ids = new List(scripts.Count); + foreach (TaskInventoryItem script in scripts) + { + if (!ids.Contains(script.ItemID)) + { + ids.Add(script.ItemID); + } + } + // Offer the list of script UUIDs to each engine found and accumulate the time + foreach (IScriptModule e in engines) + { + if (e != null) + { + time += e.GetScriptExecutionTime(ids); + } + } + return time; + } + /// /// Returns a count of the number of running scripts in this groups parts. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 9a04c65107..aacad98369 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -222,7 +222,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { - List scripts = GetInventoryScripts(); + List scripts = GetInventoryItems(InventoryType.LSL); foreach (TaskInventoryItem item in scripts) CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); } @@ -255,7 +255,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstances(bool sceneObjectBeingDeleted) { - List scripts = GetInventoryScripts(); + List scripts = GetInventoryItems(InventoryType.LSL); foreach (TaskInventoryItem item in scripts) RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); } @@ -1116,7 +1116,7 @@ namespace OpenSim.Region.Framework.Scenes return 0; int count = 0; - List scripts = GetInventoryScripts(); + List scripts = GetInventoryItems(InventoryType.LSL); foreach (TaskInventoryItem item in scripts) { @@ -1157,14 +1157,14 @@ namespace OpenSim.Region.Framework.Scenes return ret; } - public List GetInventoryScripts() + public List GetInventoryItems(InventoryType type) { List ret = new List(); lock (m_items) { foreach (TaskInventoryItem item in m_items.Values) - if (item.InvType == (int)InventoryType.LSL) + if (item.InvType == (int)type) ret.Add(item); } @@ -1183,7 +1183,7 @@ namespace OpenSim.Region.Framework.Scenes if (engines.Length == 0) // No engine at all return ret; - List scripts = GetInventoryScripts(); + List scripts = GetInventoryItems(InventoryType.LSL); foreach (TaskInventoryItem item in scripts) { @@ -1211,7 +1211,7 @@ namespace OpenSim.Region.Framework.Scenes if (engines.Length == 0) return; - List scripts = GetInventoryScripts(); + List scripts = GetInventoryItems(InventoryType.LSL); foreach (TaskInventoryItem item in scripts) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 8863df116f..641d742f95 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3437,6 +3437,25 @@ namespace OpenSim.Region.Framework.Scenes return count; } + /// + /// A float the value is a representative execution time in milliseconds of all scripts in all attachments. + /// + public float ScriptExecutionTime() + { + float time = 0.0f; + lock (m_attachments) + { + foreach (SceneObjectGroup gobj in m_attachments) + { + if (gobj != null) + { + time += gobj.ScriptExecutionTime(); + } + } + } + return time; + } + /// /// Returns the total count of running scripts in all parts. /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c38a52e62d..078a22a142 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10367,7 +10367,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384)); break; case ScriptBaseClass.OBJECT_SCRIPT_TIME: - ret.Add(new LSL_Float(0)); + ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f)); break; case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: ret.Add(new LSL_Integer(1)); @@ -10435,9 +10435,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384)); break; case ScriptBaseClass.OBJECT_SCRIPT_TIME: - // Average cpu time per simulator frame expended on all scripts in the object - // Not currently available at Object level - ret.Add(new LSL_Float(0)); + // Average cpu time in seconds per simulator frame expended on all scripts in the object + ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f)); break; case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: // according to the SL wiki A prim or linkset will have prim diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 7712076a1b..b7903d5a20 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1907,47 +1907,61 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (!topScripts.ContainsKey(si.LocalID)) topScripts[si.RootLocalID] = 0; -// long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; -// float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond); - - // Execution time of the script adjusted by it's measurement period to make scripts started at - // different times comparable. -// float adjustedExecutionTime -// = (float)si.MeasurementPeriodExecutionTime -// / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod) -// / TimeSpan.TicksPerMillisecond; - - long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; - - // Avoid divide by zerp - if (ticksElapsed == 0) - ticksElapsed = 1; - - // Scale execution time to the ideal 55 fps frame time for these reasons. - // - // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no - // 'script execution time per frame', which is the original purpose of this value. - // - // 2) Giving the raw execution times is misleading since scripts start at different times, making - // it impossible to compare scripts. - // - // 3) Scaling the raw execution time to the time that the script has been running is better but - // is still misleading since a script that has just been rezzed may appear to have been running - // for much longer. - // - // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect - // since the figure does not represent actual execution time and very hard running scripts will - // never exceed 18ms (though this is a very high number for script execution so is a warning sign). - float adjustedExecutionTime - = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f; - - topScripts[si.RootLocalID] += adjustedExecutionTime; + topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow); } } return topScripts; } + public float GetScriptExecutionTime(List itemIDs) + { + if (itemIDs == null|| itemIDs.Count == 0) + { + return 0.0f; + } + float time = 0.0f; + long tickNow = Util.EnvironmentTickCount(); + IScriptInstance si; + // Calculate the time for all scripts that this engine is executing + // Ignore any others + foreach (UUID id in itemIDs) + { + si = GetInstance(id); + if (si != null && si.Running) + { + time += CalculateAdjustedExectionTime(si, tickNow); + } + } + return time; + } + + private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow) + { + long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; + + // Avoid divide by zero + if (ticksElapsed == 0) + ticksElapsed = 1; + + // Scale execution time to the ideal 55 fps frame time for these reasons. + // + // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no + // 'script execution time per frame', which is the original purpose of this value. + // + // 2) Giving the raw execution times is misleading since scripts start at different times, making + // it impossible to compare scripts. + // + // 3) Scaling the raw execution time to the time that the script has been running is better but + // is still misleading since a script that has just been rezzed may appear to have been running + // for much longer. + // + // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect + // since the figure does not represent actual execution time and very hard running scripts will + // never exceed 18ms (though this is a very high number for script execution so is a warning sign). + return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f; + } + public void SuspendScript(UUID itemID) { // m_log.DebugFormat("[XEngine]: Received request to suspend script with ID {0}", itemID);