diff --git a/OpenSim/Framework/LandStatReportItem.cs b/OpenSim/Framework/LandStatReportItem.cs index 9f92ab4b8a..14bf505c58 100644 --- a/OpenSim/Framework/LandStatReportItem.cs +++ b/OpenSim/Framework/LandStatReportItem.cs @@ -36,10 +36,15 @@ namespace OpenSim.Framework public float LocationY; public float LocationZ; public string OwnerName; + public UUID OwnerID; public float Score; public UUID TaskID; public uint TaskLocalID; public string TaskName; + public int Bytes; + public int Urls; + public uint Time; + public string Parcel; public LandStatReportItem() { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 440ad66743..319428c5d6 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3485,29 +3485,83 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia) { - LandStatReplyPacket lsrp = new LandStatReplyPacket(); - // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); - LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; - //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - // lsrepdb. - lsrp.RequestData.ReportType = reportType; - lsrp.RequestData.RequestFlags = requestFlags; - lsrp.RequestData.TotalObjectCount = resultCount; - for (int i = 0; i < lsrpia.Length; i++) + IEventQueue eq = Scene.RequestModuleInterface(); + if (eq == null) { - LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); - lsrepdb.LocationX = lsrpia[i].LocationX; - lsrepdb.LocationY = lsrpia[i].LocationY; - lsrepdb.LocationZ = lsrpia[i].LocationZ; - lsrepdb.Score = lsrpia[i].Score; - lsrepdb.TaskID = lsrpia[i].TaskID; - lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; - lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName); - lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName); - lsrepdba[i] = lsrepdb; + LandStatReplyPacket lsrp = new LandStatReplyPacket(); + // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock(); + LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length]; + //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + // lsrepdb. + lsrp.RequestData.ReportType = reportType; + lsrp.RequestData.RequestFlags = requestFlags; + lsrp.RequestData.TotalObjectCount = resultCount; + for (int i = 0; i < lsrpia.Length; i++) + { + LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock(); + lsrepdb.LocationX = lsrpia[i].LocationX; + lsrepdb.LocationY = lsrpia[i].LocationY; + lsrepdb.LocationZ = lsrpia[i].LocationZ; + lsrepdb.Score = lsrpia[i].Score; + lsrepdb.TaskID = lsrpia[i].TaskID; + lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; + lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName); + lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName); + lsrepdba[i] = lsrepdb; + } + lsrp.ReportData = lsrepdba; + OutPacket(lsrp, ThrottleOutPacketType.Task); + } + else + { + StringBuilder sb = eq.StartEvent("LandStatReply"); + + LLSDxmlEncode.AddArrayAndMap("RequestData", sb); + LLSDxmlEncode.AddElem("ReportType", reportType, sb); + LLSDxmlEncode.AddElem("RequestFlags", requestFlags, sb); + LLSDxmlEncode.AddElem("TotalObjectCount", (uint)lsrpia.Length, sb); + LLSDxmlEncode.AddEndMapAndArray(sb); + + if (lsrpia.Length > 0) + { + LLSDxmlEncode.AddArray("ReportData", sb); + + foreach (var item in lsrpia) + { + LLSDxmlEncode.AddMap(sb); + LLSDxmlEncode.AddElem("LocationX", item.LocationX, sb); + LLSDxmlEncode.AddElem("LocationY", item.LocationY, sb); + LLSDxmlEncode.AddElem("LocationZ", item.LocationZ, sb); + LLSDxmlEncode.AddElem("OwnerName", item.OwnerName, sb); + LLSDxmlEncode.AddElem("Score", item.Score, sb); + LLSDxmlEncode.AddElem("TaskID", item.TaskID, sb); + LLSDxmlEncode.AddElem("TaskLocalID", item.TaskLocalID, sb); + LLSDxmlEncode.AddElem("TaskName", item.TaskName, sb); + LLSDxmlEncode.AddEndMap(sb); + } + + LLSDxmlEncode.AddEndArray(sb); + + LLSDxmlEncode.AddArray("DataExtended", sb); + + foreach (var item in lsrpia) + { + LLSDxmlEncode.AddMap(sb); + LLSDxmlEncode.AddElem("MonoScore", 0.0f, sb); + LLSDxmlEncode.AddElem("OwnerID", item.OwnerID, sb); + LLSDxmlEncode.AddElem("ParcelName", item.Parcel, sb); + LLSDxmlEncode.AddElem("PublicURLs", item.Urls, sb); + LLSDxmlEncode.AddElem("Size", (float)item.Bytes, sb); + LLSDxmlEncode.AddElem("TimeStamp", item.Time, sb); + LLSDxmlEncode.AddEndMap(sb); + } + + LLSDxmlEncode.AddEndArray(sb); + } + + OSD ev = new OSDllsdxml(eq.EndEvent(sb)); + eq.Enqueue(ev, AgentId); } - lsrp.ReportData = lsrepdba; - OutPacket(lsrp, ThrottleOutPacketType.Task); } public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running) diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 2a54308013..e2d960b17b 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -771,5 +771,21 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { ScriptRemoved(itemID); } + + public Dictionary GetUrlCountForHosts() + { + Dictionary dict = new Dictionary(); + foreach(var data in m_UrlMap) + { + int count = 0; + if(dict.ContainsKey(data.Value.hostID)) + { + count = dict[data.Value.hostID]; + } + count++; + dict[data.Value.hostID] = count; + } + return dict; + } } } diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index b8aefc1932..40c32145a1 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -1419,6 +1419,8 @@ namespace OpenSim.Region.CoreModules.World.Estate return; Dictionary sceneData = null; + Dictionary bytesUsed = null; + Dictionary urlsInUse = null; if (reportType == 1) { @@ -1429,9 +1431,26 @@ namespace OpenSim.Region.CoreModules.World.Estate IScriptModule scriptModule = Scene.RequestModuleInterface(); if (scriptModule != null) + { sceneData = scriptModule.GetObjectScriptsExecutionTimes(); + bytesUsed = scriptModule.GetObjectScriptsBytesUsed(); + } + + IUrlModule urlModule = Scene.RequestModuleInterface(); + if(urlModule != null) + { + urlsInUse = urlModule.GetUrlCountForHosts(); + } } + // hack: reformat the name so we don't have to do it on every item + if((requestFlags & 0x00000002) != 0) + { + filter = string.Join(" ", filter.Split(new[] { '.' }, 2)); + } + + filter = filter.ToLower(); + List SceneReport = new List(); if (sceneData != null) { @@ -1449,14 +1468,47 @@ namespace OpenSim.Region.CoreModules.World.Estate if (entry.Part == null) continue; + int bytes_used = 0; + if (bytesUsed.ContainsKey(entry.Part.LocalId)) + bytes_used = bytesUsed[entry.Part.LocalId]; + + int urls_used = 0; + if (urlsInUse.ContainsKey(entry.Part.UUID)) + urls_used = urlsInUse[entry.Part.UUID]; + // Don't show scripts that haven't executed or where execution time is below one microsecond in // order to produce a more readable report. - if (entry.Measurement < 0.001) + // Unless they are using URLs or using 1024 bytes or more. + if (entry.Measurement < 0.001 && bytes_used < 1024 && urls_used == 0) continue; - items++; SceneObjectGroup so = entry.Part.ParentGroup; + ILandObject land = Scene.LandChannel.GetLandObject(entry.Part.AbsolutePosition); + + string owner_name = UserManager.GetUserName(so.OwnerID); + string task_name = entry.Part.Name; + string parcel_name = land != null ? land.LandData.Name : "unknown"; + + if (filter.Length != 0 && requestFlags != 0) + { + if ((requestFlags & 0x00000002) != 0) + { + if (!owner_name.ToLower().Contains(filter)) + continue; + } + else if ((requestFlags & 0x00000004) != 0) + { + if (!task_name.ToLower().Contains(filter)) + continue; + } + else if ((requestFlags & 0x00000008) != 0) + { + if (!parcel_name.ToLower().Contains(filter)) + continue; + } + } + LandStatReportItem lsri = new LandStatReportItem() { LocationX = so.AbsolutePosition.X, @@ -1465,21 +1517,16 @@ namespace OpenSim.Region.CoreModules.World.Estate Score = entry.Measurement, TaskID = so.UUID, TaskLocalID = so.LocalId, - TaskName = entry.Part.Name, - OwnerName = UserManager.GetUserName(so.OwnerID) + TaskName = task_name, + OwnerName = owner_name, + OwnerID = so.OwnerID, + Bytes = bytes_used, + Urls = urls_used, + Time = Utils.DateTimeToUnixTime(entry.Part.Rezzed), + Parcel = parcel_name }; - if (filter.Length != 0) - { - if ((lsri.OwnerName.Contains(filter) || lsri.TaskName.Contains(filter))) - { - } - else - { - continue; - } - } - + items++; SceneReport.Add(lsri); if (items >= 100) diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index fd54ed52bd..bbfdbf36b1 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -111,5 +111,14 @@ namespace OpenSim.Region.Framework.Interfaces /// and the value is a representative execution time in milliseconds of all scripts in that linkset. /// Dictionary GetObjectScriptsExecutionTimes(); + + /// + /// Get the used memory of all scripts in each object. + /// + /// + /// A dictionary where the key is the root object ID of a linkset + /// and the value is a amount of bytes being used by the script + /// + Dictionary GetObjectScriptsBytesUsed(); } } diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs index 3fc0c44ed8..ccd0fbe1b3 100644 --- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs @@ -47,5 +47,6 @@ namespace OpenSim.Region.Framework.Interfaces void ScriptRemoved(UUID itemID); void ObjectRemoved(UUID objectID); + Dictionary GetUrlCountForHosts(); } } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index f8dd72581a..d25ebd26db 100755 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -2510,5 +2510,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.ExecutionTimer.Start(); } } + + public Dictionary GetObjectScriptsBytesUsed() + { + return new Dictionary(); + } } } diff --git a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs index 327bcacc8f..c823d18acb 100644 --- a/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs +++ b/OpenSim/Region/ScriptEngine/YEngine/XMREngine.cs @@ -1874,6 +1874,27 @@ namespace OpenSim.Region.ScriptEngine.Yengine return topScripts; } + /** + * @brief Return a list of all script used bytes + */ + public Dictionary GetObjectScriptsBytesUsed() + { + Dictionary topScripts = new Dictionary(); + lock (m_InstancesDict) + { + foreach (XMRInstance instance in m_InstancesDict.Values) + { + uint rootLocalID = instance.m_Part.ParentGroup.LocalId; + int oldTotal; + if (!topScripts.TryGetValue(rootLocalID, out oldTotal)) + oldTotal = 0; + + topScripts[rootLocalID] = instance.xmrHeapUsed() + oldTotal; + } + } + return topScripts; + } + /** * @brief A float the value is a representative execution time in * milliseconds of all scripts in the link set. diff --git a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs index a69d0b5f24..2cc731a082 100644 --- a/OpenSim/Tests/Common/Mock/MockScriptEngine.cs +++ b/OpenSim/Tests/Common/Mock/MockScriptEngine.cs @@ -273,5 +273,10 @@ namespace OpenSim.Tests.Common public void SleepScript(UUID itemID, int delay) { } + + public Dictionary GetObjectScriptsBytesUsed() + { + return new Dictionary(); + } } }