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
fsassets
Diva Canto 2015-06-03 17:42:41 -07:00
parent 3141664d6b
commit bac53387a9
6 changed files with 57 additions and 29 deletions

View File

@ -50,17 +50,20 @@ namespace OpenSim.Capabilities.Handlers
private IInventoryService m_InventoryService; private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService; private ILibraryService m_LibraryService;
private IScene m_Scene;
// private object m_fetchLock = new Object(); // private object m_fetchLock = new Object();
public FetchInvDescHandler(IInventoryService invService, ILibraryService libService) public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s)
{ {
m_InventoryService = invService; m_InventoryService = invService;
m_LibraryService = libService; m_LibraryService = libService;
m_Scene = s;
} }
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 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 // nasty temporary hack here, the linden client falsely
// identifies the uuid 00000000-0000-0000-0000-000000000000 // identifies the uuid 00000000-0000-0000-0000-000000000000
@ -725,20 +728,20 @@ namespace OpenSim.Capabilities.Handlers
itemsToReturn.InsertRange(0, links); itemsToReturn.InsertRange(0, links);
//foreach (InventoryItemBase link in linkedFolderContents.Items) foreach (InventoryItemBase link in linkedFolderContents.Items)
//{ {
// // Take care of genuinely broken links where the target doesn't exist // 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, // 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 // 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. // rather than having to keep track of every folder requested in the recursion.
// if (link != null && link.AssetType == (int)AssetType.Link) if (link != null && link.AssetType == (int)AssetType.Link)
// { {
// //m_log.DebugFormat( //m_log.DebugFormat(
// // "[WEB FETCH INV DESC HANDLER]: Adding item {0} {1} from folder {2} linked from {3} ({4} {5})", // "[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); // link.Name, (AssetType)link.AssetType, linkedFolderContents.FolderID, contents.FolderID, link.ID, link.AssetID);
// itemIDs.Add(link.AssetID); itemIDs.Add(link.AssetID);
// } }
//} }
} }
} }

View File

@ -67,7 +67,7 @@ namespace OpenSim.Capabilities.Handlers
m_LibraryService = m_LibraryService =
ServerUtils.LoadPlugin<ILibraryService>(libService, args); ServerUtils.LoadPlugin<ILibraryService>(libService, args);
FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService); FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
IRequestHandler reqHandler IRequestHandler reqHandler
= new RestStreamHandler( = new RestStreamHandler(
"POST", "POST",

View File

@ -54,7 +54,7 @@ namespace OpenSim.Capabilities.Handlers
public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 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)); OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request));
OSDArray itemsRequested = (OSDArray)requestmap["items"]; OSDArray itemsRequested = (OSDArray)requestmap["items"];

View File

@ -133,7 +133,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
Init(); Init();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse(); TestOSHttpResponse resp = new TestOSHttpResponse();
@ -157,7 +157,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse(); TestOSHttpResponse resp = new TestOSHttpResponse();
@ -187,7 +187,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse(); TestOSHttpResponse resp = new TestOSHttpResponse();
@ -230,7 +230,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest(); TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse(); TestOSHttpResponse resp = new TestOSHttpResponse();

View File

@ -197,7 +197,7 @@ namespace OpenSim.Region.ClientStack.Linden
m_LibraryService = Scene.LibraryService; m_LibraryService = Scene.LibraryService;
// We'll reuse the same handler for all requests. // 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; Scene.EventManager.OnRegisterCaps += RegisterCaps;

View File

@ -62,6 +62,9 @@ namespace OpenSim.Services.Connectors
/// </remarks> /// </remarks>
private int m_requestTimeoutSecs = -1; private int m_requestTimeoutSecs = -1;
private const double CACHE_EXPIRATION_SECONDS = 8.0;
private ExpiringCache<UUID, InventoryItemBase> m_ItemCache = new ExpiringCache<UUID,InventoryItemBase>();
public XInventoryServicesConnector() public XInventoryServicesConnector()
{ {
} }
@ -511,6 +514,10 @@ namespace OpenSim.Services.Connectors
public InventoryItemBase GetItem(InventoryItemBase item) public InventoryItemBase GetItem(InventoryItemBase item)
{ {
InventoryItemBase retrieved = null;
if (m_ItemCache.TryGetValue(item.ID, out retrieved))
return retrieved;
try try
{ {
Dictionary<string, object> ret = MakeRequest("GETITEM", Dictionary<string, object> ret = MakeRequest("GETITEM",
@ -521,39 +528,57 @@ namespace OpenSim.Services.Connectors
if (!CheckReturn(ret)) if (!CheckReturn(ret))
return null; return null;
return BuildItem((Dictionary<string, object>)ret["item"]); retrieved = BuildItem((Dictionary<string, object>)ret["item"]);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", 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) public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
{ {
InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length]; InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length];
// Try to get them from the cache
List<UUID> pending = new List<UUID>();
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 try
{ {
Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS", Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS",
new Dictionary<string, object> { new Dictionary<string, object> {
{ "PRINCIPAL", principalID.ToString() }, { "PRINCIPAL", principalID.ToString() },
{ "ITEMS", String.Join(",", itemIDs) }, { "ITEMS", String.Join(",", pending.ToArray()) },
{ "COUNT", itemIDs.Length.ToString() } { "COUNT", pending.Count.ToString() }
}); });
if (!CheckReturn(resultSet)) if (!CheckReturn(resultSet))
return null; return null;
int i = 0; // carry over index i where we left above
foreach (KeyValuePair<string, object> kvp in resultSet) foreach (KeyValuePair<string, object> kvp in resultSet)
{ {
InventoryCollection inventory = new InventoryCollection(); InventoryCollection inventory = new InventoryCollection();
if (kvp.Key.StartsWith("item_")) if (kvp.Key.StartsWith("item_"))
{ {
if (kvp.Value is Dictionary<string, object>) if (kvp.Value is Dictionary<string, object>)
itemArr[i++] = BuildItem((Dictionary<string, object>)kvp.Value); {
item = BuildItem((Dictionary<string, object>)kvp.Value);
m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS);
itemArr[i++] = item;
}
else else
itemArr[i++] = null; itemArr[i++] = null;
} }