From bac53387a9868f3765175179aecd3b97981d54a0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Wed, 3 Jun 2015 17:42:41 -0700 Subject: Mantis #7567: added an 8-sec expiring item cache to the inventory network connector. This fixed the problem on my local test grid and generally made things faster. This cache has been needed for a while... there are many parts in the code where the sim gets an item multiple times in a short amount of time (rezzing attachs and objects, for example). Other minor changes: - added the scene as a parameter to the constructor od FetchInvDescHandler, so that I could see in which scene the handler was being called - brought linked items in linked folders back to being prefetched --- .../Handlers/FetchInventory/FetchInvDescHandler.cs | 35 ++++++++++---------- .../FetchInventory/FetchInvDescServerConnector.cs | 2 +- .../FetchInventory/FetchInventory2Handler.cs | 2 +- .../FetchInventoryDescendents2HandlerTests.cs | 8 ++--- .../Linden/Caps/WebFetchInvDescModule.cs | 2 +- .../Inventory/XInventoryServicesConnector.cs | 37 ++++++++++++++++++---- 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs index 1b7d3f5..62ca8a3 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescHandler.cs @@ -50,18 +50,21 @@ namespace OpenSim.Capabilities.Handlers private IInventoryService m_InventoryService; private ILibraryService m_LibraryService; + private IScene m_Scene; // private object m_fetchLock = new Object(); - public FetchInvDescHandler(IInventoryService invService, ILibraryService libService) + public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s) { m_InventoryService = invService; m_LibraryService = libService; + m_Scene = s; } public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - + //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request); + // nasty temporary hack here, the linden client falsely // identifies the uuid 00000000-0000-0000-0000-000000000000 // as a string which breaks us @@ -725,20 +728,20 @@ namespace OpenSim.Capabilities.Handlers itemsToReturn.InsertRange(0, links); - //foreach (InventoryItemBase link in linkedFolderContents.Items) - //{ - // // Take care of genuinely broken links where the target doesn't exist - // // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, - // // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles - // // rather than having to keep track of every folder requested in the recursion. - // if (link != null && link.AssetType == (int)AssetType.Link) - // { - // //m_log.DebugFormat( - // // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", - // // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID); - // itemIDs.Add(link.AssetID); - // } - //} + foreach (InventoryItemBase link in linkedFolderContents.Items) + { + // Take care of genuinely broken links where the target doesn't exist + // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, + // but no viewer has been observed to set these up and this is the lazy way of avoiding cycles + // rather than having to keep track of every folder requested in the recursion. + if (link != null && link.AssetType == (int)AssetType.Link) + { + //m_log.DebugFormat( + // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", + // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID); + itemIDs.Add(link.AssetID); + } + } } } diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs index 6fbe173..9dcfaa4 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInvDescServerConnector.cs @@ -67,7 +67,7 @@ namespace OpenSim.Capabilities.Handlers m_LibraryService = ServerUtils.LoadPlugin(libService, args); - FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService); + FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null); IRequestHandler reqHandler = new RestStreamHandler( "POST", diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs index 0832b02..c904392 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventory/FetchInventory2Handler.cs @@ -54,7 +54,7 @@ namespace OpenSim.Capabilities.Handlers public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { -// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); + //m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capability request {0}", request); OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); OSDArray itemsRequested = (OSDArray)requestmap["items"]; diff --git a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs index 056b4db..380c54a 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventory/Tests/FetchInventoryDescendents2HandlerTests.cs @@ -133,7 +133,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests Init(); - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpResponse resp = new TestOSHttpResponse(); @@ -157,7 +157,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests { TestHelpers.InMethod(); - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpResponse resp = new TestOSHttpResponse(); @@ -187,7 +187,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests { TestHelpers.InMethod(); - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpResponse resp = new TestOSHttpResponse(); @@ -230,7 +230,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests { TestHelpers.InMethod(); - FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); + FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpResponse resp = new TestOSHttpResponse(); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 30d1921..299b4f6 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -197,7 +197,7 @@ namespace OpenSim.Region.ClientStack.Linden m_LibraryService = Scene.LibraryService; // We'll reuse the same handler for all requests. - m_webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService); + m_webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, Scene); Scene.EventManager.OnRegisterCaps += RegisterCaps; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index db3c857..b123e9d 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -62,6 +62,9 @@ namespace OpenSim.Services.Connectors /// private int m_requestTimeoutSecs = -1; + private const double CACHE_EXPIRATION_SECONDS = 8.0; + private ExpiringCache m_ItemCache = new ExpiringCache(); + public XInventoryServicesConnector() { } @@ -511,6 +514,10 @@ namespace OpenSim.Services.Connectors public InventoryItemBase GetItem(InventoryItemBase item) { + InventoryItemBase retrieved = null; + if (m_ItemCache.TryGetValue(item.ID, out retrieved)) + return retrieved; + try { Dictionary ret = MakeRequest("GETITEM", @@ -521,39 +528,57 @@ namespace OpenSim.Services.Connectors if (!CheckReturn(ret)) return null; - return BuildItem((Dictionary)ret["item"]); + retrieved = BuildItem((Dictionary)ret["item"]); } catch (Exception e) { m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e); } - return null; + m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS); + + return retrieved; } public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs) { InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length]; + // Try to get them from the cache + List pending = new List(); + InventoryItemBase item = null; + int i = 0; + foreach (UUID id in itemIDs) + { + if (m_ItemCache.TryGetValue(id, out item)) + itemArr[i++] = item; + else + pending.Add(id); + } + try { Dictionary resultSet = MakeRequest("GETMULTIPLEITEMS", new Dictionary { { "PRINCIPAL", principalID.ToString() }, - { "ITEMS", String.Join(",", itemIDs) }, - { "COUNT", itemIDs.Length.ToString() } + { "ITEMS", String.Join(",", pending.ToArray()) }, + { "COUNT", pending.Count.ToString() } }); if (!CheckReturn(resultSet)) return null; - int i = 0; + // carry over index i where we left above foreach (KeyValuePair kvp in resultSet) { InventoryCollection inventory = new InventoryCollection(); if (kvp.Key.StartsWith("item_")) { if (kvp.Value is Dictionary) - itemArr[i++] = BuildItem((Dictionary)kvp.Value); + { + item = BuildItem((Dictionary)kvp.Value); + m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS); + itemArr[i++] = item; + } else itemArr[i++] = null; } -- cgit v1.1