From 7db5ba77026ddc3f6ef5ce901e8b137b5506c93d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 8 Mar 2012 19:31:53 -0800 Subject: [PATCH 1/3] More on the freeze on HG inventory transfers: spawn a threadlet on the functional asset posts so that the client threads doesn't freeze (but the network posts are serialized). --- .../Framework/InventoryAccess/HGInventoryAccessModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index d2fe3888fa..9921e1171a 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_assMapper.Get(item.AssetID, sender, userAssetServer); if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) - m_assMapper.Post(item.AssetID, receiver, userAssetServer); + Util.FireAndForget(delegate { m_assMapper.Post(item.AssetID, receiver, userAssetServer); }); } public override bool IsForeignUser(UUID userID, out string assetServerURL) From 81869c4a3fbb3bfbc2a767e381a0820165b461b2 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 9 Mar 2012 09:48:12 -0800 Subject: [PATCH 2/3] More on HG inventory transfers. Move the FireAndForget higher up. --- .../Framework/InventoryAccess/HGInventoryAccessModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 9921e1171a..d2fe3888fa 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_assMapper.Get(item.AssetID, sender, userAssetServer); if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) - Util.FireAndForget(delegate { m_assMapper.Post(item.AssetID, receiver, userAssetServer); }); + m_assMapper.Post(item.AssetID, receiver, userAssetServer); } public override bool IsForeignUser(UUID userID, out string assetServerURL) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 23f39a8c6d..6ae4adc227 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -633,7 +633,7 @@ namespace OpenSim.Region.Framework.Scenes { IInventoryAccessModule invAccess = RequestModuleInterface(); if (invAccess != null) - invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); + Util.FireAndForget(delegate { invAccess.TransferInventoryAssets(itemCopy, senderId, recipient); }); } if (!Permissions.BypassPermissions()) From a58152bd2af64493e655d6f559bc366c38433187 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 9 Mar 2012 12:59:24 -0800 Subject: [PATCH 3/3] More on inventory transfer hold ups: - Added an inventory cache for caching root and system folders - Synchronized the remote inventory connector, so that all the remote inventory calls are serialized This will not make much difference in the hold ups. We'd have to move the FireAndForget high up to AddInventoryItem, but that opens up a can of worms regarding the notification of the recipient... the recipient would be notified of the offer before the items are effectively in his inventory, which could lead to surprises. --- .../Inventory/HGInventoryBroker.cs | 20 ++++++- .../Inventory/InventoryCache.cs | 59 +++++++++++++++++++ .../Inventory/XInventoryConnector.cs | 10 +++- 3 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index b5c0af6686..4be3804c1f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -58,6 +58,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory private List m_Scenes = new List(); + private InventoryCache m_Cache = new InventoryCache(); + protected IUserManagement m_UserManagement; protected IUserManagement UserManagementModule { @@ -312,6 +314,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryFolderBase GetRootFolder(UUID userID) { //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetRootFolder for {0}", userID); + InventoryFolderBase root = m_Cache.GetRootFolder(userID); + if (root != null) + return root; string invURL = GetInventoryServiceURL(userID); @@ -320,12 +325,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory IInventoryService connector = GetConnector(invURL); - return connector.GetRootFolder(userID); + root = connector.GetRootFolder(userID); + + m_Cache.Cache(userID, root); + + return root; } public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) { //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetFolderForType {0} type {1}", userID, type); + InventoryFolderBase f = m_Cache.GetFolderForType(userID, type); + if (f != null) + return f; string invURL = GetInventoryServiceURL(userID); @@ -334,7 +346,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory IInventoryService connector = GetConnector(invURL); - return connector.GetFolderForType(userID, type); + f = connector.GetFolderForType(userID, type); + + m_Cache.Cache(userID, type, f); + + return f; } public InventoryCollection GetFolderContent(UUID userID, UUID folderID) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs new file mode 100644 index 0000000000..0fe778dfa6 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory +{ + public class InventoryCache + { + private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour + + private static ExpiringCache m_RootFolders = new ExpiringCache(); + private static ExpiringCache> m_FolderTypes = new ExpiringCache>(); + + public void Cache(UUID userID, InventoryFolderBase root) + { + lock (m_RootFolders) + m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS); + } + + public InventoryFolderBase GetRootFolder(UUID userID) + { + InventoryFolderBase root = null; + if (m_RootFolders.TryGetValue(userID, out root)) + return root; + + return null; + } + + public void Cache(UUID userID, AssetType type, InventoryFolderBase folder) + { + lock (m_FolderTypes) + { + Dictionary ff = null; + if (!m_FolderTypes.TryGetValue(userID, out ff)) + { + ff = new Dictionary(); + m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS); + } + if (!ff.ContainsKey(type)) + ff.Add(type, folder); + } + } + + public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) + { + Dictionary ff = null; + if (m_FolderTypes.TryGetValue(userID, out ff)) + { + InventoryFolderBase f = null; + if (ff.TryGetValue(type, out f)) + return f; + } + + return null; + } + } +} diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs index a662abb867..39e983bfd9 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs @@ -48,6 +48,8 @@ namespace OpenSim.Services.Connectors private string m_ServerURI = String.Empty; + private object m_Lock = new object(); + public XInventoryServicesConnector() { } @@ -514,9 +516,11 @@ namespace OpenSim.Services.Connectors { sendData["METHOD"] = method; - string reply = SynchronousRestFormsRequester.MakeRequest("POST", - m_ServerURI + "/xinventory", - ServerUtils.BuildQueryString(sendData)); + string reply = string.Empty; + lock (m_Lock) + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/xinventory", + ServerUtils.BuildQueryString(sendData)); Dictionary replyData = ServerUtils.ParseXmlResponse( reply);