diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 711a574521..3d085c3dd4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -357,7 +357,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods /// cannot retain a reference to it outside of that method. /// - private AgentUpdateArgs m_lastAgentUpdateArgs; + private AgentUpdateArgs m_lastAgentUpdateArgs = new AgentUpdateArgs(); + + private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs(); protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -5565,81 +5567,128 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Packet Handlers + public int TotalSignificantAgentUpdates { get; private set; } + #region Scene/Avatar + /// + /// This checks the update significance against the last update made. + /// + /// Can only be called by one thread at a time + /// /returns> + /// + public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) + { + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. + if ( + (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || + (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || + (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || + (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || + (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || + (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.Far != m_lastAgentUpdateArgs.Far) || + (x.Flags != m_lastAgentUpdateArgs.Flags) || + (x.State != m_lastAgentUpdateArgs.State) || + (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || + (x.SessionID != m_lastAgentUpdateArgs.SessionID) || + (x.AgentID != m_lastAgentUpdateArgs.AgentID) + ) + { +// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); + TotalSignificantAgentUpdates++; + + m_lastAgentUpdateArgs.AgentID = x.AgentID; + m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_lastAgentUpdateArgs.Far = x.Far; + m_lastAgentUpdateArgs.Flags = x.Flags; + m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_lastAgentUpdateArgs.SessionID = x.SessionID; + m_lastAgentUpdateArgs.State = x.State; + + return true; + } + + return false; + } + private bool HandleAgentUpdate(IClientAPI sener, Packet packet) { if (OnAgentUpdate != null) { AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; - #region Packet Session and User Check - if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) - { - PacketPool.Instance.ReturnPacket(packet); - return false; - } - #endregion - - bool update = false; + // Now done earlier +// #region Packet Session and User Check +// if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) +// { +// PacketPool.Instance.ReturnPacket(packet); +// return false; +// } +// #endregion +// +// bool update = false; AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; +// +// if (m_lastAgentUpdateArgs != null) +// { +// // These should be ordered from most-likely to +// // least likely to change. I've made an initial +// // guess at that. +// update = +// ( +// (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || +// (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || +// (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || +// (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || +// (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || +// (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || +// (x.Far != m_lastAgentUpdateArgs.Far) || +// (x.Flags != m_lastAgentUpdateArgs.Flags) || +// (x.State != m_lastAgentUpdateArgs.State) || +// (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || +// (x.SessionID != m_lastAgentUpdateArgs.SessionID) || +// (x.AgentID != m_lastAgentUpdateArgs.AgentID) +// ); +// } +// +// if (update) +// { +//// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); + TotalSignificantAgentUpdates++; - if (m_lastAgentUpdateArgs != null) - { - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. - update = - ( - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || - (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || - (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || - (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || - (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || - (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || - (x.Far != m_lastAgentUpdateArgs.Far) || - (x.Flags != m_lastAgentUpdateArgs.Flags) || - (x.State != m_lastAgentUpdateArgs.State) || - (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || - (x.SessionID != m_lastAgentUpdateArgs.SessionID) || - (x.AgentID != m_lastAgentUpdateArgs.AgentID) - ); - } - else - { - m_lastAgentUpdateArgs = new AgentUpdateArgs(); - update = true; - } - - if (update) - { -// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - - m_lastAgentUpdateArgs.AgentID = x.AgentID; - m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; - m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; - m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; - m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; - m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; - m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; - m_lastAgentUpdateArgs.Far = x.Far; - m_lastAgentUpdateArgs.Flags = x.Flags; - m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; - m_lastAgentUpdateArgs.SessionID = x.SessionID; - m_lastAgentUpdateArgs.State = x.State; + m_thisAgentUpdateArgs.AgentID = x.AgentID; + m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation; + m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; + m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter; + m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; + m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; + m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags; + m_thisAgentUpdateArgs.Far = x.Far; + m_thisAgentUpdateArgs.Flags = x.Flags; + m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation; + m_thisAgentUpdateArgs.SessionID = x.SessionID; + m_thisAgentUpdateArgs.State = x.State; UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, m_lastAgentUpdateArgs); + OnPreAgentUpdate(this, m_thisAgentUpdateArgs); if (handlerAgentUpdate != null) - OnAgentUpdate(this, m_lastAgentUpdateArgs); + OnAgentUpdate(this, m_thisAgentUpdateArgs); handlerAgentUpdate = null; handlerPreAgentUpdate = null; - } +// } } PacketPool.Instance.ReturnPacket(packet); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index e871ca287f..766c2fed8b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -572,6 +572,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP "debug lludp status", "Return status of LLUDP packet processing.", HandleStatusCommand); + + MainConsole.Instance.Commands.AddCommand( + "Debug", + false, + "debug lludp toggle agentupdate", + "debug lludp toggle agentupdate", + "Toggle whether agentupdate packets are processed or simply discarded.", + HandleAgentUpdateCommand); } private void HandlePacketCommand(string module, string[] args) @@ -706,6 +714,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } + bool m_discardAgentUpdates; + + private void HandleAgentUpdateCommand(string module, string[] args) + { + if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) + return; + + m_discardAgentUpdates = !m_discardAgentUpdates; + + MainConsole.Instance.OutputFormat( + "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name); + } + private void HandleStatusCommand(string module, string[] args) { if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) @@ -1286,6 +1307,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); #endregion BinaryStats + if (packet.Type == PacketType.AgentUpdate) + { + if (m_discardAgentUpdates) + return; + + AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; + + if (agentUpdate.AgentData.SessionID != client.SessionId + || agentUpdate.AgentData.AgentID != client.AgentId + || !((LLClientView)client).CheckAgentUpdateSignificance(agentUpdate.AgentData)) + { + PacketPool.Instance.ReturnPacket(packet); + return; + } + } + #region Ping Check Handling if (packet.Type == PacketType.StartPingCheck) @@ -1662,8 +1699,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Action generic every round Action clientPacketHandler = ClientOutgoingPacketHandler; - while (true) -// while (base.IsRunningOutbound) + while (base.IsRunningOutbound) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 512f60df20..a91914140a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -111,6 +111,8 @@ namespace OpenMetaverse if (!IsRunningInbound) { + m_log.DebugFormat("[UDPBASE]: Starting inbound UDP loop"); + const int SIO_UDP_CONNRESET = -1744830452; IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); @@ -155,6 +157,8 @@ namespace OpenMetaverse /// public void StartOutbound() { + m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop"); + IsRunningOutbound = true; } @@ -162,10 +166,8 @@ namespace OpenMetaverse { if (IsRunningInbound) { - // wait indefinitely for a writer lock. Once this is called, the .NET runtime - // will deny any more reader locks, in effect blocking all other send/receive - // threads. Once we have the lock, we set IsRunningInbound = false to inform the other - // threads that the socket is closed. + m_log.DebugFormat("[UDPBASE]: Stopping inbound UDP loop"); + IsRunningInbound = false; m_udpSocket.Close(); } @@ -173,6 +175,8 @@ namespace OpenMetaverse public void StopOutbound() { + m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop"); + IsRunningOutbound = false; } diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index 79509ab0a0..3e6067d6ee 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -611,7 +611,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden // if (showParams.Length <= 4) { - m_log.InfoFormat("[INFO]: {0,-12} {1,20} {2,6} {3,11} {4, 10}", "Region", "Name", "Root", "Time", "Reqs/min"); + m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "Sig. AgentUpdates"); foreach (Scene scene in m_scenes.Values) { scene.ForEachClient( @@ -624,9 +624,15 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); - m_log.InfoFormat("[INFO]: {0,-12} {1,20} {2,4} {3,9}min {4,10}", + m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", scene.RegionInfo.RegionName, llClient.Name, - (llClient.SceneAgent.IsChildAgent ? "N" : "Y"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs); + llClient.SceneAgent.IsChildAgent ? "N" : "Y", + (DateTime.Now - cinfo.StartedTime).Minutes, + avg_reqs, + string.Format( + "{0}, {1}%", + llClient.TotalSignificantAgentUpdates, + (float)llClient.TotalSignificantAgentUpdates / cinfo.SyncRequests["AgentUpdate"] * 100)); } }); }