From cb7a9eaa09fba301ba6b6838cb9e3cedfc29a32a Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Mon, 6 Oct 2008 19:52:54 +0000 Subject: * Stop the sim stats reporter reusing the same SimStatsPacket for all clients * I believe this was the cause of the remaining packet_out_of_order messages in the Linden client logs * There were race conditions where multiple clientstacks would overwrite each other's sequence numbers --- OpenSim/Framework/IClientAPI.cs | 8 +- OpenSim/Framework/SimStats.cs | 88 ++++++++++++++++++++++ .../Framework/Statistics/SimExtraStatsCollector.cs | 48 ++++++------ .../Region/ClientStack/LindenUDP/LLClientView.cs | 14 +++- .../Environment/Modules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Region/Environment/Scenes/Scene.cs | 4 +- .../Region/Environment/Scenes/SimStatsReporter.cs | 44 +++++------ .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 2 +- 8 files changed, 155 insertions(+), 55 deletions(-) create mode 100644 OpenSim/Framework/SimStats.cs diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1a6a5a4..4071e47 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -722,7 +722,13 @@ namespace OpenSim.Framework void SendImagePart(ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec); void SendShutdownConnectionNotice(); - void SendSimStats(Packet pack); + + /// + /// Send statistical information about the sim to the client. + /// + /// + void SendSimStats(SimStats stats); + void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, diff --git a/OpenSim/Framework/SimStats.cs b/OpenSim/Framework/SimStats.cs new file mode 100644 index 0000000..c77d0d4 --- /dev/null +++ b/OpenSim/Framework/SimStats.cs @@ -0,0 +1,88 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse.Packets; + +namespace OpenSim.Framework +{ + /// + /// Enapsulate statistics for a simulator/scene. + /// + /// TODO: This looks very much like the OpenMetaverse SimStatsPacket. It should be much more generic stats + /// storage. + /// + public class SimStats + { + public uint RegionX + { + get { return m_regionX; } + } + private uint m_regionX; + + public uint RegionY + { + get { return m_regionY; } + } + private uint m_regionY; + + public SimStatsPacket.RegionBlock RegionBlock + { + get { return m_regionBlock; } + } + private SimStatsPacket.RegionBlock m_regionBlock; + + public SimStatsPacket.StatBlock[] StatsBlock + { + get { return m_statsBlock; } + } + private SimStatsPacket.StatBlock[] m_statsBlock; + + public uint RegionFlags + { + get { return m_regionFlags; } + } + private uint m_regionFlags; + + public uint ObjectCapacity + { + get { return m_objectCapacity; } + } + private uint m_objectCapacity; + + public SimStats( + uint regionX, uint regionY, uint regionFlags, uint objectCapacity, + SimStatsPacket.RegionBlock regionBlock, SimStatsPacket.StatBlock[] statsBlock) + { + m_regionX = regionX; + m_regionY = regionY; + m_regionFlags = regionFlags; + m_objectCapacity = objectCapacity; + m_regionBlock = regionBlock; + m_statsBlock = statsBlock; + } + } +} diff --git a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs b/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs index 2f6bb7e..48bed81 100644 --- a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs @@ -216,31 +216,31 @@ namespace OpenSim.Framework.Statistics /// client purposes) sends information to listeners. /// /// - public void ReceiveClassicSimStatsPacket(SimStatsPacket statsPacket) + public void ReceiveClassicSimStatsPacket(SimStats stats) { - // FIXME: Really shouldn't rely on the probably arbitrary order in which - // stats are packed into the packet - timeDilation = statsPacket.Stat[0].StatValue; - simFps = statsPacket.Stat[1].StatValue; - physicsFps = statsPacket.Stat[2].StatValue; - agentUpdates = statsPacket.Stat[3].StatValue; - rootAgents = statsPacket.Stat[4].StatValue; - childAgents = statsPacket.Stat[5].StatValue; - totalPrims = statsPacket.Stat[6].StatValue; - activePrims = statsPacket.Stat[7].StatValue; - totalFrameTime = statsPacket.Stat[8].StatValue; - netFrameTime = statsPacket.Stat[9].StatValue; - physicsFrameTime = statsPacket.Stat[10].StatValue; - otherFrameTime = statsPacket.Stat[11].StatValue; - imageFrameTime = statsPacket.Stat[12].StatValue; - inPacketsPerSecond = statsPacket.Stat[13].StatValue; - outPacketsPerSecond = statsPacket.Stat[14].StatValue; - unackedBytes = statsPacket.Stat[15].StatValue; - agentFrameTime = statsPacket.Stat[16].StatValue; - pendingDownloads = statsPacket.Stat[17].StatValue; - pendingUploads = statsPacket.Stat[18].StatValue; - activeScripts = statsPacket.Stat[19].StatValue; - scriptLinesPerSecond = statsPacket.Stat[20].StatValue; + // FIXME: SimStats shouldn't allow an arbitrary stat packing order (which is inherited from the original + // SimStatsPacket that was being used). + timeDilation = stats.StatsBlock[0].StatValue; + simFps = stats.StatsBlock[1].StatValue; + physicsFps = stats.StatsBlock[2].StatValue; + agentUpdates = stats.StatsBlock[3].StatValue; + rootAgents = stats.StatsBlock[4].StatValue; + childAgents = stats.StatsBlock[5].StatValue; + totalPrims = stats.StatsBlock[6].StatValue; + activePrims = stats.StatsBlock[7].StatValue; + totalFrameTime = stats.StatsBlock[8].StatValue; + netFrameTime = stats.StatsBlock[9].StatValue; + physicsFrameTime = stats.StatsBlock[10].StatValue; + otherFrameTime = stats.StatsBlock[11].StatValue; + imageFrameTime = stats.StatsBlock[12].StatValue; + inPacketsPerSecond = stats.StatsBlock[13].StatValue; + outPacketsPerSecond = stats.StatsBlock[14].StatValue; + unackedBytes = stats.StatsBlock[15].StatValue; + agentFrameTime = stats.StatsBlock[16].StatValue; + pendingDownloads = stats.StatsBlock[17].StatValue; + pendingUploads = stats.StatsBlock[18].StatValue; + activeScripts = stats.StatsBlock[19].StatValue; + scriptLinesPerSecond = stats.StatsBlock[20].StatValue; } /// diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index ff35c32..cbba661 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -2610,9 +2610,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown); } - public void SendSimStats(Packet pack) - { + public void SendSimStats(SimStats stats) + { + SimStatsPacket pack = new SimStatsPacket(); + + pack.Region.RegionX = stats.RegionX; + pack.Region.RegionY = stats.RegionY; + pack.Region.RegionFlags = stats.RegionFlags; + pack.Region.ObjectCapacity = stats.ObjectCapacity; + pack.Region = stats.RegionBlock; + pack.Stat = stats.StatsBlock; + pack.Header.Reliable = false; + OutPacket(pack, ThrottleOutPacketType.Task); } diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs index a236ccd..b59b013 100644 --- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs @@ -706,7 +706,7 @@ namespace OpenSim.Region.Environment.Modules.World.NPC { } - public void SendSimStats(Packet pack) + public void SendSimStats(SimStats stats) { } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index bf1dbcd..da6da1e 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -837,14 +837,14 @@ namespace OpenSim.Region.Environment.Scenes } } - private void SendSimStatsPackets(SimStatsPacket pack) + private void SendSimStatsPackets(SimStats stats) { List StatSendAgents = GetScenePresences(); foreach (ScenePresence agent in StatSendAgents) { if (!agent.IsChildAgent) { - agent.ControllingClient.SendSimStats(pack); + agent.ControllingClient.SendSimStats(stats); } } } diff --git a/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs b/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs index 5f0f316..4c9c59d 100644 --- a/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Environment/Scenes/SimStatsReporter.cs @@ -36,7 +36,7 @@ namespace OpenSim.Region.Environment.Scenes { public class SimStatsReporter { - public delegate void SendStatResult(SimStatsPacket pack); + public delegate void SendStatResult(SimStats stats); public event SendStatResult OnSendStatsResult; @@ -100,12 +100,6 @@ namespace OpenSim.Region.Environment.Scenes private int objectCapacity = 45000; - - SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21]; - SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); - SimStatsPacket statpack = (SimStatsPacket)PacketPool.Instance.GetPacket(PacketType.SimStats); - - private Scene m_scene; private RegionInfo ReportingRegion; @@ -118,10 +112,7 @@ namespace OpenSim.Region.Environment.Scenes statsUpdateFactor = (float)(statsUpdatesEveryMS / 1000); m_scene = scene; ReportingRegion = scene.RegionInfo; - for (int i = 0; i<21;i++) - { - sb[i] = new SimStatsPacket.StatBlock(); - } + m_report.AutoReset = true; m_report.Interval = statsUpdatesEveryMS; m_report.Elapsed += new ElapsedEventHandler(statsHeartBeat); @@ -140,26 +131,24 @@ namespace OpenSim.Region.Environment.Scenes private void statsHeartBeat(object sender, EventArgs e) { + SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21]; + SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); + // Know what's not thread safe in Mono... modifying timers. // System.Console.WriteLine("Firing Stats Heart Beat"); lock (m_report) { - // Packet is already initialized and ready for data insert - - - statpack.Region = rb; - statpack.Region.RegionX = ReportingRegion.RegionLocX; - statpack.Region.RegionY = ReportingRegion.RegionLocY; + uint regionFlags = 0; + try { IEstateModule estateModule = m_scene.RequestModuleInterface(); - statpack.Region.RegionFlags = estateModule != null ? estateModule.GetRegionFlags() : (uint) 0; + regionFlags = estateModule != null ? estateModule.GetRegionFlags() : (uint) 0; } catch (Exception) { - statpack.Region.RegionFlags = (uint) 0; + // leave region flags at 0 } - statpack.Region.ObjectCapacity = (uint) objectCapacity; #region various statistic googly moogly @@ -182,7 +171,7 @@ namespace OpenSim.Region.Environment.Scenes physfps = 0; #endregion - + //Our time dilation is 0.91 when we're running a full speed, // therefore to make sure we get an appropriate range, // we have to factor in our error. (0.10f * statsUpdateFactor) @@ -190,6 +179,11 @@ namespace OpenSim.Region.Environment.Scenes // / 10 divides the value by the number of times the sim heartbeat runs (10fps) // Then we divide the whole amount by the amount of seconds pass in between stats updates. + for (int i = 0; i<21;i++) + { + sb[i] = new SimStatsPacket.StatBlock(); + } + sb[0].StatID = (uint) Stats.TimeDilation; sb[0].StatValue = m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); @@ -252,13 +246,15 @@ namespace OpenSim.Region.Environment.Scenes sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor; - - statpack.Stat = sb; + + SimStats simStats + = new SimStats( + ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)objectCapacity, rb, sb); handlerSendStatResult = OnSendStatsResult; if (handlerSendStatResult != null) { - handlerSendStatResult(statpack); + handlerSendStatResult(simStats); } resetvalues(); } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 9c8152d..87478c7 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -625,7 +625,7 @@ namespace OpenSim.Region.Examples.SimpleModule { } - public void SendSimStats(Packet pack) + public void SendSimStats(SimStats stats) { } -- cgit v1.1