From 60a924f3c65fe2f0dc04e861d1dc4ee4d5283a9c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 21 Feb 2020 19:11:29 +0000 Subject: [PATCH] change part inventory adding some scripts speed up and controls release --- .../Framework/Interfaces/IEntityInventory.cs | 4 +- .../Scenes/SceneObjectPartInventory.cs | 345 ++++++++++++------ 2 files changed, 239 insertions(+), 110 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 5f1bd15311..38d3a4797c 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -105,6 +105,7 @@ namespace OpenSim.Region.Framework.Interfaces /// void StopScriptInstances(); + void SendReleaseScriptsControl(); void RemoveScriptsPermissions(int permissions); void RemoveScriptsPermissions(ScenePresence sp, int permissions); @@ -119,8 +120,7 @@ namespace OpenSim.Region.Framework.Interfaces /// true if the script instance was valid for starting, false otherwise. This does not guarantee /// that the script was actually started, just that the script was valid (i.e. its asset data could be found, etc.) /// - bool CreateScriptInstance( - TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource); + bool CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource); /// /// Start a script which is in this entity's inventory. diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 437fbcf743..28df2fa363 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -71,7 +71,7 @@ namespace OpenSim.Region.Framework.Scenes /// Holds in memory prim inventory /// protected TaskInventoryDictionary m_items = new TaskInventoryDictionary(); - + protected Dictionary m_scripts = null; /// /// Tracks whether inventory has changed since the last persistent backup /// @@ -99,7 +99,7 @@ namespace OpenSim.Region.Framework.Scenes { m_items = value; m_inventorySerial++; - QueryScriptStates(); + gatherScriptsAndQueryStates(); } } @@ -107,8 +107,10 @@ namespace OpenSim.Region.Framework.Scenes { get { - lock (m_items) - return m_items.Count; + m_items.LockItemsForRead(true); + int c = m_items.Count; + m_items.LockItemsForRead(false); + return c; } } @@ -155,11 +157,26 @@ namespace OpenSim.Region.Framework.Scenes UUID partID = m_part.UUID; IList items = new List(m_items.Values); m_items.Clear(); - - foreach (TaskInventoryItem item in items) + if(m_scripts == null) { - item.ResetIDs(partID); - m_items.Add(item.ItemID, item); + for (int i = 0; i < items.Count; ++i) + { + TaskInventoryItem item = items[i]; + item.ResetIDs(partID); + m_items.Add(item.ItemID, item); + } + } + else + { + m_scripts.Clear(); + for (int i = 0; i < items.Count; ++i) + { + TaskInventoryItem item = items[i]; + item.ResetIDs(partID); + m_items.Add(item.ItemID, item); + if (item.InvType == (int)InventoryType.LSL) + m_scripts.Add(item.ItemID, item); + } } m_inventorySerial++; m_items.LockItemsForWrite(false); @@ -170,6 +187,8 @@ namespace OpenSim.Region.Framework.Scenes if (m_part == null) return; + UUID partID = m_part.UUID; + m_items.LockItemsForWrite(true); if (m_items.Count == 0) @@ -177,16 +196,10 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(false); return; } - - IList items = new List(m_items.Values); - m_items.Clear(); - - UUID partID = m_part.UUID; - foreach (TaskInventoryItem item in items) + foreach(TaskInventoryItem item in m_items.Values) { item.ParentPartID = partID; item.ParentID = partID; - m_items.Add(item.ItemID, item); } m_inventorySerial++; m_items.LockItemsForWrite(false); @@ -218,6 +231,7 @@ namespace OpenSim.Region.Framework.Scenes item.PermsGranter = UUID.Zero; item.OwnerChanged = true; } + HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; m_inventorySerial++; @@ -255,20 +269,46 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(false); } - private void QueryScriptStates() + private void gatherScriptsAndQueryStates() { - if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) - return; - - m_items.LockItemsForRead(true); + m_items.LockItemsForWrite(true); + m_scripts = new Dictionary(); foreach (TaskInventoryItem item in m_items.Values) { if (item.InvType == (int)InventoryType.LSL) + m_scripts[item.ItemID] = item; + } + if (m_scripts.Count == 0) + { + m_items.LockItemsForWrite(false); + m_scripts = null; + return; + } + m_items.LockItemsForWrite(false); + + if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) + return; + + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines == null) // No engine at all + return; + + bool running; + + m_items.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_scripts.Values) + { + //running = false; + foreach (IScriptModule e in engines) { - bool running; - if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) + if (e.HasScript(item.ItemID, out running)) + { item.ScriptRunning = running; + break; + } } + //item.ScriptRunning = running; } m_items.LockItemsForRead(false); @@ -308,13 +348,21 @@ namespace OpenSim.Region.Framework.Scenes public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { + m_items.LockItemsForRead(true); + if(m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForRead(false); + return 0; + } + List scripts = new List(m_scripts.Values); + m_items.LockItemsForRead(false); + int scriptsValidForStarting = 0; - - List scripts = GetInventoryItems(InventoryType.LSL); - foreach (TaskInventoryItem item in scripts) - if (CreateScriptInstance(item, startParam, postOnRez, engine, stateSource)) + for (int i = 0; i < scripts.Count; ++i) + { + if (CreateScriptInstance(scripts[i], startParam, postOnRez, engine, stateSource)) scriptsValidForStarting++; - + } return scriptsValidForStarting; } @@ -346,7 +394,15 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstances(bool sceneObjectBeingDeleted) { - List scripts = GetInventoryItems(InventoryType.LSL); + m_items.LockItemsForRead(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForRead(false); + return; + } + List scripts = new List(m_scripts.Values); + m_items.LockItemsForRead(false); + foreach (TaskInventoryItem item in scripts) { RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); @@ -359,7 +415,15 @@ namespace OpenSim.Region.Framework.Scenes /// public void StopScriptInstances() { - List scripts = GetInventoryItems(InventoryType.LSL); + m_items.LockItemsForRead(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForRead(false); + return; + } + List scripts = new List(m_scripts.Values); + m_items.LockItemsForRead(false); + foreach (TaskInventoryItem item in scripts) StopScriptInstance(item); } @@ -385,26 +449,30 @@ namespace OpenSim.Region.Framework.Scenes if (m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts) return false; - if (stateSource == 2 && // Prim crossing - m_part.ParentGroup.Scene.m_trustBinaries) + UUID itemID = item.ItemID; + TaskInventoryItem it; + + if (stateSource == 2 && m_part.ParentGroup.Scene.m_trustBinaries) { + // Prim crossing m_items.LockItemsForWrite(true); - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; + it = m_items[itemID]; + it.PermsMask = 0; + it.PermsGranter = UUID.Zero; m_items.LockItemsForWrite(false); + m_part.ParentGroup.Scene.EventManager.TriggerRezScript( - m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); - StoreScriptErrors(item.ItemID, null); + m_part.LocalId, itemID, String.Empty, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(itemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); return true; } AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); - if (null == asset) + if (asset == null) { - string msg = String.Format("asset ID {0} could not be found", item.AssetID); - StoreScriptError(item.ItemID, msg); + StoreScriptError(itemID, String.Format("asset ID {0} could not be found", item.AssetID)); m_log.ErrorFormat( "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", item.Name, item.ItemID, m_part.AbsolutePosition, @@ -412,31 +480,27 @@ namespace OpenSim.Region.Framework.Scenes return false; } - else - { - if (m_part.ParentGroup.m_savedScriptState != null) - item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); - m_items.LockItemsForWrite(true); + if (m_part.ParentGroup.m_savedScriptState != null) + item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, itemID); - m_items[item.ItemID].OldItemID = item.OldItemID; - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(true); + it = m_items[itemID]; + it.OldItemID = item.OldItemID; + it.PermsMask = 0; + it.PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(false); - m_items.LockItemsForWrite(false); + string script = Utils.BytesToString(asset.Data); + m_part.ParentGroup.Scene.EventManager.TriggerRezScript( + m_part.LocalId, itemID, script, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(itemID, null); + if (!item.ScriptRunning) + m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, itemID); + m_part.ParentGroup.AddActiveScriptCount(1); + m_part.ScheduleFullUpdate(); - string script = Utils.BytesToString(asset.Data); - m_part.ParentGroup.Scene.EventManager.TriggerRezScript( - m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); - StoreScriptErrors(item.ItemID, null); - if (!item.ScriptRunning) - m_part.ParentGroup.Scene.EventManager.TriggerStopScript( - m_part.LocalId, item.ItemID); - m_part.ParentGroup.AddActiveScriptCount(1); - m_part.ScheduleFullUpdate(); - - return true; - } + return true; } private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID) @@ -678,10 +742,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void StopScriptInstance(UUID itemId) { - TaskInventoryItem scriptItem; - - lock (m_items) - m_items.TryGetValue(itemId, out scriptItem); + m_items.LockItemsForRead(true); + m_items.TryGetValue(itemId, out TaskInventoryItem scriptItem); + m_items.LockItemsForRead(false); if (scriptItem != null) { @@ -714,18 +777,54 @@ namespace OpenSim.Region.Framework.Scenes // m_part.ParentGroup.AddActiveScriptCount(-1); } + public void SendReleaseScriptsControl() + { + m_items.LockItemsForRead(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForWrite(false); + return; + } + + List grants = new List(); + List items = new List(); + + foreach (TaskInventoryItem item in m_scripts.Values) + { + if (((item.PermsMask & 4) == 0)) + continue; + grants.Add(item.PermsGranter); + items.Add(item.ItemID); + } + m_items.LockItemsForRead(false); + + if (grants.Count > 0) + { + for (int i = 0; i < grants.Count; ++i) + { + ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(grants[i]); + if (presence != null && !presence.IsDeleted && presence.ParentPart != m_part) // last check mb needed for vehicle crossing ??? + presence.UnRegisterControlEventsToScript(m_part.LocalId, items[i]); + } + } + } + public void RemoveScriptsPermissions(int permissions) { + m_items.LockItemsForWrite(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForWrite(false); + return; + } + bool removeControl = ((permissions & 4) != 0); //takecontrol List grants = new List(); List items = new List(); permissions = ~permissions; - m_items.LockItemsForWrite(true); - foreach (TaskInventoryItem item in m_items.Values) + foreach (TaskInventoryItem item in m_scripts.Values) { - if (item.InvType != (int)InventoryType.LSL) - continue; int curmask = item.PermsMask; UUID curGrant = item.PermsGranter; if (removeControl && ((curmask & 4) != 0)) @@ -753,16 +852,20 @@ namespace OpenSim.Region.Framework.Scenes public void RemoveScriptsPermissions(ScenePresence sp, int permissions) { + m_items.LockItemsForWrite(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForWrite(false); + return; + } + bool removeControl = ((permissions & 4) != 0); //takecontrol UUID grant = sp.UUID; List items = new List(); permissions = ~permissions; - m_items.LockItemsForWrite(true); - foreach (TaskInventoryItem item in m_items.Values) + foreach (TaskInventoryItem item in m_scripts.Values) { - if (item.InvType != (int) InventoryType.LSL) - continue; if(grant != item.PermsGranter) continue; int curmask = item.PermsMask; @@ -884,8 +987,17 @@ namespace OpenSim.Region.Framework.Scenes item.GroupID = m_part.GroupID; m_items.LockItemsForWrite(true); + m_items.Add(item.ItemID, item); + if (item.InvType == (int)InventoryType.LSL) + { + if (m_scripts == null) + m_scripts = new Dictionary(); + m_scripts.Add(item.ItemID, item); + } + m_items.LockItemsForWrite(false); + if (allowedDrop) m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP, item.ItemID); else @@ -907,10 +1019,16 @@ namespace OpenSim.Region.Framework.Scenes public void RestoreInventoryItems(ICollection items) { m_items.LockItemsForWrite(true); + foreach (TaskInventoryItem item in items) { m_items.Add(item.ItemID, item); -// m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + if (item.InvType == (int)InventoryType.LSL) + { + if (m_scripts == null) + m_scripts = new Dictionary(); + m_scripts.Add(item.ItemID, item); + } } m_items.LockItemsForWrite(false); m_part.AggregateInnerPerms(); @@ -1109,6 +1227,12 @@ namespace OpenSim.Region.Framework.Scenes item.AssetID = m_items[item.ItemID].AssetID; m_items[item.ItemID] = item; + if(item.InvType == (int)InventoryType.LSL) + { + if(m_scripts == null) + m_scripts = new Dictionary(); + m_scripts[item.ItemID] = item; + } m_inventorySerial++; if (fireScriptEvents) @@ -1157,32 +1281,24 @@ namespace OpenSim.Region.Framework.Scenes } m_items.LockItemsForWrite(true); m_items.Remove(itemID); + if(m_scripts != null) + { + m_scripts.Remove(itemID); + if(m_scripts.Count == 0) + m_scripts = null; + } + if (m_scripts == null) + { + m_part.RemFlag(PrimFlags.Scripted); + } + m_inventorySerial++; m_items.LockItemsForWrite(false); m_part.ParentGroup.InvalidateDeepEffectivePerms(); - m_inventorySerial++; HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; - - int scriptcount = 0; - m_items.LockItemsForRead(true); - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.Type == (int)InventoryType.LSL) - { - scriptcount++; - } - } - m_items.LockItemsForRead(false); - - - if (scriptcount <= 0) - { - m_part.RemFlag(PrimFlags.Scripted); - } - m_part.ScheduleFullUpdate(); m_part.TriggerScriptChangedEvent(Changed.INVENTORY); @@ -1501,15 +1617,11 @@ namespace OpenSim.Region.Framework.Scenes /// public bool ContainsScripts() { - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.InvType == (int)InventoryType.LSL) - { - return true; - } - } + m_items.LockItemsForRead(true); + bool res = (m_scripts != null && m_scripts.Count >0); + m_items.LockItemsForRead(false); - return false; + return res; } /// @@ -1520,11 +1632,8 @@ namespace OpenSim.Region.Framework.Scenes { int count = 0; m_items.LockItemsForRead(true); - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.InvType == (int)InventoryType.LSL) - count++; - } + if(m_scripts != null) + count = m_scripts.Count; m_items.LockItemsForRead(false); return count; } @@ -1539,7 +1648,14 @@ namespace OpenSim.Region.Framework.Scenes return 0; int count = 0; - List scripts = GetInventoryItems(InventoryType.LSL); + m_items.LockItemsForRead(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForRead(false); + return 0; + } + List scripts = new List(m_scripts.Values); + m_items.LockItemsForRead(false); foreach (TaskInventoryItem item in scripts) { @@ -1602,11 +1718,17 @@ namespace OpenSim.Region.Framework.Scenes return ret; IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); - if (engines.Length == 0) // No engine at all return ret; - List scripts = GetInventoryItems(InventoryType.LSL); + m_items.LockItemsForRead(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForRead(false); + return ret; + } + List scripts = new List(m_scripts.Values); + m_items.LockItemsForRead(false); foreach (TaskInventoryItem item in scripts) { @@ -1645,7 +1767,14 @@ namespace OpenSim.Region.Framework.Scenes if (engines.Length == 0) return; - List scripts = GetInventoryItems(InventoryType.LSL); + m_items.LockItemsForRead(true); + if (m_scripts == null || m_scripts.Count == 0) + { + m_items.LockItemsForRead(false); + return; + } + List scripts = new List(m_scripts.Values); + m_items.LockItemsForRead(false); foreach (TaskInventoryItem item in scripts) {