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 prefetchedfsassets
parent
3141664d6b
commit
bac53387a9
|
@ -50,18 +50,21 @@ 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
|
||||||
// as a string which breaks us
|
// as a string which breaks us
|
||||||
|
@ -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);
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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"];
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue