reduce garbage on WebFetchInvDesc

master
UbitUmarov 2020-05-22 14:00:12 +01:00
parent 3c33d5c448
commit f326cc8901
4 changed files with 111 additions and 120 deletions

View File

@ -38,10 +38,10 @@ using OpenMetaverse;
using OpenMetaverse.StructuredData; using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Capabilities; using OpenSim.Framework.Capabilities;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Framework.Servers.HttpServer; using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps; using OSDMap = OpenMetaverse.StructuredData.OSDMap;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
namespace OpenSim.Capabilities.Handlers namespace OpenSim.Capabilities.Handlers
{ {
@ -50,10 +50,10 @@ namespace OpenSim.Capabilities.Handlers
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static byte[] EmptyResponse = Util.UTF8NBGetbytes("<llsd><map><key>folders</key><array /></map></llsd>");
private IInventoryService m_InventoryService; private IInventoryService m_InventoryService;
private ILibraryService m_LibraryService; private ILibraryService m_LibraryService;
private IScene m_Scene; private IScene m_Scene;
// private object m_fetchLock = new Object();
public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s) public FetchInvDescHandler(IInventoryService invService, ILibraryService libService, IScene s)
{ {
@ -62,62 +62,66 @@ namespace OpenSim.Capabilities.Handlers
m_Scene = s; m_Scene = s;
} }
public string FetchInventoryDescendentsRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) public void FetchInventoryDescendentsRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
using (MemoryStream ms = new MemoryStream(Utils.StringToBytes(request), false))
{
return FetchInventoryDescendentsRequest(ms, path, param, httpRequest, httpResponse);
}
}
public string FetchInventoryDescendentsRequest(Stream 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); //m_log.DebugFormat("[XXX]: FetchInventoryDescendentsRequest in {0}, {1}", (m_Scene == null) ? "none" : m_Scene.Name, request);
ArrayList foldersrequested = null; List<LLSDFetchInventoryDescendents> folders = null;
try try
{ {
Hashtable hash = (Hashtable)LLSD.LLSDDeserialize(request); OSDArray foldersrequested = null;
foldersrequested = (ArrayList)hash["folders"]; OSD tmp = OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
hash = null; OSDMap map = (OSDMap)tmp;
} if(map.TryGetValue("folders", out tmp) && tmp is OSDArray)
catch (Exception e) foldersrequested = tmp as OSDArray;
if (foldersrequested == null || foldersrequested.Count == 0)
{ {
m_log.ErrorFormat("[FETCH INV DESC]: fail parsing request: '{0}'; path: '{1}'; exception: '{2}'", request, path, e.Message); httpResponse.RawBuffer = EmptyResponse;
foldersrequested = null; return;
} }
if(foldersrequested == null || foldersrequested.Count == 0) folders = new List<LLSDFetchInventoryDescendents>(foldersrequested.Count);
return "<llsd><map><key>folders</key><array /></map></llsd>";
List<LLSDFetchInventoryDescendents> folders = new List<LLSDFetchInventoryDescendents>();
for (int i = 0; i < foldersrequested.Count; i++) for (int i = 0; i < foldersrequested.Count; i++)
{ {
Hashtable inventoryhash = (Hashtable)foldersrequested[i];
LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents(); LLSDFetchInventoryDescendents llsdRequest = new LLSDFetchInventoryDescendents();
try try
{ {
LLSDHelpers.DeserialiseOSDMap(inventoryhash, llsdRequest); OSDMap mfolder = (OSDMap)foldersrequested[i];
llsdRequest.folder_id = mfolder["folder_id"].AsUUID();
llsdRequest.owner_id = mfolder["owner_id"].AsUUID();
llsdRequest.sort_order = mfolder["sort_order"].AsInteger();
llsdRequest.fetch_folders = mfolder["fetch_folders"].AsBoolean();
llsdRequest.fetch_items = mfolder["fetch_items"].AsBoolean();
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e.Message); m_log.Debug("[WEB FETCH INV DESC HANDLER]: caught exception doing OSD deserialize" + e.Message);
continue; continue;
} }
folders.Add(llsdRequest); folders.Add(llsdRequest);
} }
foldersrequested = null;
tmp = null;
}
catch (Exception e)
{
m_log.ErrorFormat("[FETCH INV DESC]: fail parsing request: {0}", e.Message);
httpResponse.RawBuffer = EmptyResponse;
return;
}
foldersrequested.Clear(); if (folders == null || folders.Count == 0)
{
if(folders.Count == 0) httpResponse.RawBuffer = EmptyResponse;
return "<llsd><map><key>folders</key><array /></map></llsd>"; return;
}
List<UUID> bad_folders = new List<UUID>(); List<UUID> bad_folders = new List<UUID>();
int total_folders = 0; int total_folders = 0;
int total_items = 0; int total_items = 0;
List<InventoryCollection> invcollSet = Fetch(folders, bad_folders, ref total_folders, ref total_items); List<InventoryCollection> invcollSet = Fetch(folders, bad_folders, ref total_folders, ref total_items);
//m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count); //m_log.DebugFormat("[XXX]: Got {0} folders from a request of {1}", invcollSet.Count, folders.Count);
@ -133,12 +137,12 @@ namespace OpenSim.Capabilities.Handlers
StringBuilder lastresponse = new StringBuilder(mem); StringBuilder lastresponse = new StringBuilder(mem);
lastresponse.Append("<llsd>"); lastresponse.Append("<llsd>");
if(invcollSetCount > 0) if (invcollSetCount > 0)
{ {
lastresponse.Append("<map><key>folders</key><array>"); lastresponse.Append("<map><key>folders</key><array>");
int i = 0; int i = 0;
InventoryCollection thiscoll; InventoryCollection thiscoll;
for(i = 0; i < invcollSetCount; i++) for (i = 0; i < invcollSetCount; i++)
{ {
thiscoll = invcollSet[i]; thiscoll = invcollSet[i];
invcollSet[i] = null; invcollSet[i] = null;
@ -148,7 +152,7 @@ namespace OpenSim.Capabilities.Handlers
LLSDxmlEncode.AddElem("descendents", thiscoll.Descendents, lastresponse); LLSDxmlEncode.AddElem("descendents", thiscoll.Descendents, lastresponse);
LLSDxmlEncode.AddElem("folder_id", thiscoll.FolderID, lastresponse); LLSDxmlEncode.AddElem("folder_id", thiscoll.FolderID, lastresponse);
if(thiscoll.Folders == null || thiscoll.Folders.Count == 0) if (thiscoll.Folders == null || thiscoll.Folders.Count == 0)
LLSDxmlEncode.AddEmptyArray("categories", lastresponse); LLSDxmlEncode.AddEmptyArray("categories", lastresponse);
else else
{ {
@ -169,7 +173,7 @@ namespace OpenSim.Capabilities.Handlers
LLSDxmlEncode.AddEndArray(lastresponse); LLSDxmlEncode.AddEndArray(lastresponse);
} }
if(thiscoll.Items == null || thiscoll.Items.Count == 0) if (thiscoll.Items == null || thiscoll.Items.Count == 0)
LLSDxmlEncode.AddEmptyArray("items", lastresponse); LLSDxmlEncode.AddEmptyArray("items", lastresponse);
else else
{ {
@ -197,7 +201,7 @@ namespace OpenSim.Capabilities.Handlers
} }
//m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders)); //m_log.DebugFormat("[WEB FETCH INV DESC HANDLER]: Bad folders {0}", string.Join(", ", bad_folders));
if(bad_folders.Count > 0) if (bad_folders.Count > 0)
{ {
lastresponse.Append("<map><key>bad_folders</key><array>"); lastresponse.Append("<map><key>bad_folders</key><array>");
foreach (UUID bad in bad_folders) foreach (UUID bad in bad_folders)
@ -210,7 +214,7 @@ namespace OpenSim.Capabilities.Handlers
} }
lastresponse.Append("</llsd>"); lastresponse.Append("</llsd>");
return lastresponse.ToString(); httpResponse.RawBuffer = Util.UTF8NBGetbytes(lastresponse.ToString());
} }
private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> libFolders, List<InventoryCollection> result, ref int total_folders, ref int total_items) private void AddLibraryFolders(List<LLSDFetchInventoryDescendents> libFolders, List<InventoryCollection> result, ref int total_folders, ref int total_items)
@ -400,7 +404,7 @@ namespace OpenSim.Capabilities.Handlers
if (linked != null) if (linked != null)
{ {
List<InventoryItemBase> linkedItems = new List<InventoryItemBase>(); List<InventoryItemBase> linkedItems = new List<InventoryItemBase>(linked.Length);
// check for broken // check for broken
foreach (InventoryItemBase linkedItem in linked) foreach (InventoryItemBase linkedItem in linked)
{ {

View File

@ -68,15 +68,9 @@ namespace OpenSim.Capabilities.Handlers
ServerUtils.LoadPlugin<ILibraryService>(libService, args); ServerUtils.LoadPlugin<ILibraryService>(libService, args);
FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null); FetchInvDescHandler webFetchHandler = new FetchInvDescHandler(m_InventoryService, m_LibraryService, null);
IRequestHandler reqHandler ISimpleStreamHandler reqHandler
= new RestStreamHandler( = new SimpleStreamHandler( "/CAPS/WebFetchInvDesc/", webFetchHandler.FetchInventoryDescendentsRequest);
"POST", server.AddSimpleStreamHandler(reqHandler);
"/CAPS/WebFetchInvDesc/" /*+ UUID.Random()*/,
webFetchHandler.FetchInventoryDescendentsRequest,
"FetchInvDescendents",
null);
server.AddStreamHandler(reqHandler);
} }
} }
} }

View File

@ -28,7 +28,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using log4net; using log4net;
using log4net.Config; using log4net.Config;
@ -127,6 +127,18 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
Console.WriteLine("Number of descendents: " + m_rootDescendents); Console.WriteLine("Number of descendents: " + m_rootDescendents);
} }
private string dorequest(FetchInvDescHandler handler, string request)
{
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
using (MemoryStream ms = new MemoryStream(Utils.StringToBytes(request), false))
{
req.InputStream = ms;
handler.FetchInventoryDescendentsRequest(req, resp);
}
return Util.UTF8.GetString(resp.RawBuffer);
}
[Test] [Test]
public void Test_001_SimpleFolder() public void Test_001_SimpleFolder()
{ {
@ -135,8 +147,6 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
Init(); Init();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += m_rootFolderID; request += m_rootFolderID;
@ -144,7 +154,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
request += m_userID.ToString(); request += m_userID.ToString();
request += "</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>"; request += "</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); string llsdresponse = dorequest(handler, request);
Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");
@ -161,8 +171,6 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>folders</key><array>"; string request = "<llsd><map><key>folders</key><array>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
@ -173,7 +181,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map>"; request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map>";
request += "</array></map></llsd>"; request += "</array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); string llsdresponse = dorequest(handler, request);
Console.WriteLine(llsdresponse); Console.WriteLine(llsdresponse);
string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>"; string descendents = "descendents</key><integer>" + m_rootDescendents + "</integer>";
@ -191,14 +199,12 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += "f0000000-0000-0000-0000-00000000000f"; request += "f0000000-0000-0000-0000-00000000000f";
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>"; request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000001</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); string llsdresponse = dorequest(handler, request);
Console.WriteLine(llsdresponse); Console.WriteLine(llsdresponse);
string descendents = "descendents</key><integer>2</integer>"; string descendents = "descendents</key><integer>2</integer>";
@ -235,8 +241,6 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>folders</key><array>"; string request = "<llsd><map><key>folders</key><array>";
request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; request += "<map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
@ -253,7 +257,7 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>"; request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map>";
request += "</array></map></llsd>"; request += "</array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); string llsdresponse = dorequest(handler, request);
Console.WriteLine(llsdresponse); Console.WriteLine(llsdresponse);
string root_folder = "<key>folder_id</key><uuid>" + m_rootFolderID + "</uuid>"; string root_folder = "<key>folder_id</key><uuid>" + m_rootFolderID + "</uuid>";
@ -276,14 +280,12 @@ namespace OpenSim.Capabilities.Handlers.FetchInventory.Tests
Init(); Init();
FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene); FetchInvDescHandler handler = new FetchInvDescHandler(m_scene.InventoryService, null, m_scene);
TestOSHttpRequest req = new TestOSHttpRequest();
TestOSHttpResponse resp = new TestOSHttpResponse();
string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>"; string request = "<llsd><map><key>folders</key><array><map><key>fetch_folders</key><integer>1</integer><key>fetch_items</key><boolean>1</boolean><key>folder_id</key><uuid>";
request += UUID.Zero; request += UUID.Zero;
request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>"; request += "</uuid><key>owner_id</key><uuid>00000000-0000-0000-0000-000000000000</uuid><key>sort_order</key><integer>1</integer></map></array></map></llsd>";
string llsdresponse = handler.FetchInventoryDescendentsRequest(request, "/FETCH", string.Empty, req, resp); string llsdresponse = dorequest(handler, request);
Assert.That(llsdresponse != null, Is.True, "Incorrect null response"); Assert.That(llsdresponse != null, Is.True, "Incorrect null response");
Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response"); Assert.That(llsdresponse != string.Empty, Is.True, "Incorrect empty response");

View File

@ -330,17 +330,8 @@ namespace OpenSim.Region.ClientStack.Linden
} }
} }
Hashtable response = new Hashtable(); OSHttpResponse osresponse = new OSHttpResponse(requestinfo.request);
m_webFetchHandler.FetchInventoryDescendentsRequest(requestinfo.request, osresponse);
response["int_response_code"] = 200;
response["content_type"] = "text/plain";
response["bin_response_data"] = Encoding.UTF8.GetBytes(
m_webFetchHandler.FetchInventoryDescendentsRequest(
requestinfo.request.InputStream,
String.Empty, String.Empty, null, null)
);
requestinfo.request.InputStream.Dispose(); requestinfo.request.InputStream.Dispose();
lock (responses) lock (responses)
@ -350,16 +341,16 @@ namespace OpenSim.Region.ClientStack.Linden
if(dropedResponses.Contains(requestID)) if(dropedResponses.Contains(requestID))
{ {
dropedResponses.Remove(requestID); dropedResponses.Remove(requestID);
WebFetchInvDescModule.ProcessedRequestsCount++; ProcessedRequestsCount++;
return; return;
} }
} }
if (responses.ContainsKey(requestID)) Hashtable response = new Hashtable();
m_log.WarnFormat("[FETCH INVENTORY DESCENDENTS2 MODULE]: Caught in the act of loosing responses! Please report this on mantis #7054"); response["h"] = osresponse;
responses[requestID] = response; responses[requestID] = response;
} }
WebFetchInvDescModule.ProcessedRequestsCount++; ProcessedRequestsCount++;
} }
} }