diff options
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 58 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | 15 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 165 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/OutgoingQueueRefillEngine.cs | 286 | ||||
-rw-r--r-- | OpenSim/Tools/pCampBot/BotManager.cs | 18 |
5 files changed, 488 insertions, 54 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index bfdb24f..c839c05 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -4201,6 +4201,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4201 | } | 4201 | } |
4202 | } | 4202 | } |
4203 | 4203 | ||
4204 | // m_log.DebugFormat( | ||
4205 | // "[LLCLIENTVIEW]: Sent {0} updates in ProcessEntityUpdates() for {1} {2} in {3}", | ||
4206 | // updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); | ||
4207 | // | ||
4204 | #endregion Packet Sending | 4208 | #endregion Packet Sending |
4205 | } | 4209 | } |
4206 | 4210 | ||
@@ -12337,6 +12341,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12337 | /// provide your own method.</param> | 12341 | /// provide your own method.</param> |
12338 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) | 12342 | protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting, UnackedPacketMethod method) |
12339 | { | 12343 | { |
12344 | if (m_outPacketsToDrop != null) | ||
12345 | if (m_outPacketsToDrop.Contains(packet.Type.ToString())) | ||
12346 | return; | ||
12347 | |||
12340 | if (DebugPacketLevel > 0) | 12348 | if (DebugPacketLevel > 0) |
12341 | { | 12349 | { |
12342 | bool logPacket = true; | 12350 | bool logPacket = true; |
@@ -12395,6 +12403,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
12395 | /// <param name="Pack">OpenMetaverse.packet</param> | 12403 | /// <param name="Pack">OpenMetaverse.packet</param> |
12396 | public void ProcessInPacket(Packet packet) | 12404 | public void ProcessInPacket(Packet packet) |
12397 | { | 12405 | { |
12406 | if (m_inPacketsToDrop != null) | ||
12407 | if (m_inPacketsToDrop.Contains(packet.Type.ToString())) | ||
12408 | return; | ||
12409 | |||
12398 | if (DebugPacketLevel > 0) | 12410 | if (DebugPacketLevel > 0) |
12399 | { | 12411 | { |
12400 | bool logPacket = true; | 12412 | bool logPacket = true; |
@@ -13119,5 +13131,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
13119 | eq.Enqueue(BuildEvent("BulkUpdateInventory", | 13131 | eq.Enqueue(BuildEvent("BulkUpdateInventory", |
13120 | llsd), AgentId); | 13132 | llsd), AgentId); |
13121 | } | 13133 | } |
13134 | |||
13135 | private HashSet<string> m_outPacketsToDrop; | ||
13136 | |||
13137 | public bool AddOutPacketToDropSet(string packetName) | ||
13138 | { | ||
13139 | if (m_outPacketsToDrop == null) | ||
13140 | m_outPacketsToDrop = new HashSet<string>(); | ||
13141 | |||
13142 | return m_outPacketsToDrop.Add(packetName); | ||
13143 | } | ||
13144 | |||
13145 | public bool RemoveOutPacketFromDropSet(string packetName) | ||
13146 | { | ||
13147 | if (m_outPacketsToDrop == null) | ||
13148 | return false; | ||
13149 | |||
13150 | return m_outPacketsToDrop.Remove(packetName); | ||
13151 | } | ||
13152 | |||
13153 | public HashSet<string> GetOutPacketDropSet() | ||
13154 | { | ||
13155 | return new HashSet<string>(m_outPacketsToDrop); | ||
13156 | } | ||
13157 | |||
13158 | private HashSet<string> m_inPacketsToDrop; | ||
13159 | |||
13160 | public bool AddInPacketToDropSet(string packetName) | ||
13161 | { | ||
13162 | if (m_inPacketsToDrop == null) | ||
13163 | m_inPacketsToDrop = new HashSet<string>(); | ||
13164 | |||
13165 | return m_inPacketsToDrop.Add(packetName); | ||
13166 | } | ||
13167 | |||
13168 | public bool RemoveInPacketFromDropSet(string packetName) | ||
13169 | { | ||
13170 | if (m_inPacketsToDrop == null) | ||
13171 | return false; | ||
13172 | |||
13173 | return m_inPacketsToDrop.Remove(packetName); | ||
13174 | } | ||
13175 | |||
13176 | public HashSet<string> GetInPacketDropSet() | ||
13177 | { | ||
13178 | return new HashSet<string>(m_inPacketsToDrop); | ||
13179 | } | ||
13122 | } | 13180 | } |
13123 | } | 13181 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index 39c9cb1..c34bafa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -650,8 +650,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
650 | 650 | ||
651 | if (HasUpdates(m_categories)) | 651 | if (HasUpdates(m_categories)) |
652 | { | 652 | { |
653 | // Asynchronously run the callback | 653 | if (!m_udpServer.OqrEngine.IsRunning) |
654 | Util.FireAndForget(FireQueueEmpty, categories); | 654 | { |
655 | // Asynchronously run the callback | ||
656 | Util.FireAndForget(FireQueueEmpty, categories); | ||
657 | } | ||
658 | else | ||
659 | { | ||
660 | m_udpServer.OqrEngine.QueueRequest(this, categories); | ||
661 | } | ||
655 | } | 662 | } |
656 | else | 663 | else |
657 | { | 664 | { |
@@ -670,8 +677,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
670 | /// <param name="o">Throttle categories to fire the callback for, | 677 | /// <param name="o">Throttle categories to fire the callback for, |
671 | /// stored as an object to match the WaitCallback delegate | 678 | /// stored as an object to match the WaitCallback delegate |
672 | /// signature</param> | 679 | /// signature</param> |
673 | private void FireQueueEmpty(object o) | 680 | public void FireQueueEmpty(object o) |
674 | { | 681 | { |
682 | // m_log.DebugFormat("[LLUDPCLIENT]: FireQueueEmpty for {0} in {1}", AgentID, m_udpServer.Scene.Name); | ||
683 | |||
675 | // int start = Environment.TickCount & Int32.MaxValue; | 684 | // int start = Environment.TickCount & Int32.MaxValue; |
676 | // const int MIN_CALLBACK_MS = 30; | 685 | // const int MIN_CALLBACK_MS = 30; |
677 | 686 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 708a0a1..87aa37d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -250,7 +250,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
250 | private AgentCircuitManager m_circuitManager; | 250 | private AgentCircuitManager m_circuitManager; |
251 | 251 | ||
252 | /// <summary>Reference to the scene this UDP server is attached to</summary> | 252 | /// <summary>Reference to the scene this UDP server is attached to</summary> |
253 | protected Scene m_scene; | 253 | public Scene Scene { get; private set; } |
254 | 254 | ||
255 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> | 255 | /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> |
256 | private Location m_location; | 256 | private Location m_location; |
@@ -355,6 +355,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
355 | /// </summary> | 355 | /// </summary> |
356 | private IClientAPI m_currentIncomingClient; | 356 | private IClientAPI m_currentIncomingClient; |
357 | 357 | ||
358 | /// <summary> | ||
359 | /// Experimental facility to run queue empty processing within a controlled number of threads rather than | ||
360 | /// requiring massive numbers of short-lived threads from the threadpool when there are a high number of | ||
361 | /// connections. | ||
362 | /// </summary> | ||
363 | public OutgoingQueueRefillEngine OqrEngine { get; private set; } | ||
364 | |||
358 | public LLUDPServer( | 365 | public LLUDPServer( |
359 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, | 366 | IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, |
360 | IConfigSource configSource, AgentCircuitManager circuitManager) | 367 | IConfigSource configSource, AgentCircuitManager circuitManager) |
@@ -432,6 +439,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
432 | 439 | ||
433 | if (usePools) | 440 | if (usePools) |
434 | EnablePools(); | 441 | EnablePools(); |
442 | |||
443 | OqrEngine = new OutgoingQueueRefillEngine(this); | ||
435 | } | 444 | } |
436 | 445 | ||
437 | public void Start() | 446 | public void Start() |
@@ -453,7 +462,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
453 | // This thread will process the packets received that are placed on the packetInbox | 462 | // This thread will process the packets received that are placed on the packetInbox |
454 | Watchdog.StartThread( | 463 | Watchdog.StartThread( |
455 | IncomingPacketHandler, | 464 | IncomingPacketHandler, |
456 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), | 465 | string.Format("Incoming Packets ({0})", Scene.Name), |
457 | ThreadPriority.Normal, | 466 | ThreadPriority.Normal, |
458 | false, | 467 | false, |
459 | true, | 468 | true, |
@@ -469,7 +478,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
469 | 478 | ||
470 | Watchdog.StartThread( | 479 | Watchdog.StartThread( |
471 | OutgoingPacketHandler, | 480 | OutgoingPacketHandler, |
472 | string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), | 481 | string.Format("Outgoing Packets ({0})", Scene.Name), |
473 | ThreadPriority.Normal, | 482 | ThreadPriority.Normal, |
474 | false, | 483 | false, |
475 | true, | 484 | true, |
@@ -479,7 +488,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
479 | 488 | ||
480 | public void Stop() | 489 | public void Stop() |
481 | { | 490 | { |
482 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | 491 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name); |
483 | base.StopOutbound(); | 492 | base.StopOutbound(); |
484 | base.StopInbound(); | 493 | base.StopInbound(); |
485 | } | 494 | } |
@@ -527,7 +536,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
527 | "The number of objects currently stored within the UDPPacketBuffer pool", | 536 | "The number of objects currently stored within the UDPPacketBuffer pool", |
528 | "", | 537 | "", |
529 | "clientstack", | 538 | "clientstack", |
530 | m_scene.Name, | 539 | Scene.Name, |
531 | StatType.Pull, | 540 | StatType.Pull, |
532 | stat => stat.Value = Pool.Count, | 541 | stat => stat.Value = Pool.Count, |
533 | StatVerbosity.Debug); | 542 | StatVerbosity.Debug); |
@@ -541,7 +550,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
541 | "The number of objects currently stored within the incoming packet pool", | 550 | "The number of objects currently stored within the incoming packet pool", |
542 | "", | 551 | "", |
543 | "clientstack", | 552 | "clientstack", |
544 | m_scene.Name, | 553 | Scene.Name, |
545 | StatType.Pull, | 554 | StatType.Pull, |
546 | stat => stat.Value = m_incomingPacketPool.Count, | 555 | stat => stat.Value = m_incomingPacketPool.Count, |
547 | StatVerbosity.Debug); | 556 | StatVerbosity.Debug); |
@@ -585,7 +594,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
585 | 594 | ||
586 | public void AddScene(IScene scene) | 595 | public void AddScene(IScene scene) |
587 | { | 596 | { |
588 | if (m_scene != null) | 597 | if (Scene != null) |
589 | { | 598 | { |
590 | m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); | 599 | m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); |
591 | return; | 600 | return; |
@@ -597,8 +606,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
597 | return; | 606 | return; |
598 | } | 607 | } |
599 | 608 | ||
600 | m_scene = (Scene)scene; | 609 | Scene = (Scene)scene; |
601 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 610 | m_location = new Location(Scene.RegionInfo.RegionHandle); |
602 | 611 | ||
603 | StatsManager.RegisterStat( | 612 | StatsManager.RegisterStat( |
604 | new Stat( | 613 | new Stat( |
@@ -621,7 +630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
621 | "Packets reused", | 630 | "Packets reused", |
622 | "Number of packets reused out of all requests to the packet pool", | 631 | "Number of packets reused out of all requests to the packet pool", |
623 | "clientstack", | 632 | "clientstack", |
624 | m_scene.Name, | 633 | Scene.Name, |
625 | StatType.Pull, | 634 | StatType.Pull, |
626 | stat => | 635 | stat => |
627 | { PercentageStat pstat = (PercentageStat)stat; | 636 | { PercentageStat pstat = (PercentageStat)stat; |
@@ -635,7 +644,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
635 | "Packet data blocks reused", | 644 | "Packet data blocks reused", |
636 | "Number of data blocks reused out of all requests to the packet pool", | 645 | "Number of data blocks reused out of all requests to the packet pool", |
637 | "clientstack", | 646 | "clientstack", |
638 | m_scene.Name, | 647 | Scene.Name, |
639 | StatType.Pull, | 648 | StatType.Pull, |
640 | stat => | 649 | stat => |
641 | { PercentageStat pstat = (PercentageStat)stat; | 650 | { PercentageStat pstat = (PercentageStat)stat; |
@@ -650,7 +659,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
650 | "The number of objects currently stored within the packet pool", | 659 | "The number of objects currently stored within the packet pool", |
651 | "", | 660 | "", |
652 | "clientstack", | 661 | "clientstack", |
653 | m_scene.Name, | 662 | Scene.Name, |
654 | StatType.Pull, | 663 | StatType.Pull, |
655 | stat => stat.Value = PacketPool.Instance.PacketsPooled, | 664 | stat => stat.Value = PacketPool.Instance.PacketsPooled, |
656 | StatVerbosity.Debug)); | 665 | StatVerbosity.Debug)); |
@@ -662,7 +671,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
662 | "The number of objects currently stored within the packet data block pool", | 671 | "The number of objects currently stored within the packet data block pool", |
663 | "", | 672 | "", |
664 | "clientstack", | 673 | "clientstack", |
665 | m_scene.Name, | 674 | Scene.Name, |
666 | StatType.Pull, | 675 | StatType.Pull, |
667 | stat => stat.Value = PacketPool.Instance.BlocksPooled, | 676 | stat => stat.Value = PacketPool.Instance.BlocksPooled, |
668 | StatVerbosity.Debug)); | 677 | StatVerbosity.Debug)); |
@@ -689,6 +698,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
689 | HandlePacketCommand); | 698 | HandlePacketCommand); |
690 | 699 | ||
691 | MainConsole.Instance.Commands.AddCommand( | 700 | MainConsole.Instance.Commands.AddCommand( |
701 | "Debug", false, "debug lludp drop", | ||
702 | "debug lludp drop <in|out> <add|remove> <packet-name>", | ||
703 | "Drop all in or outbound packets that match the given name", | ||
704 | "For test purposes.", | ||
705 | HandleDropCommand); | ||
706 | |||
707 | MainConsole.Instance.Commands.AddCommand( | ||
692 | "Debug", | 708 | "Debug", |
693 | false, | 709 | false, |
694 | "debug lludp start", | 710 | "debug lludp start", |
@@ -739,7 +755,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
739 | 755 | ||
740 | private void HandlePacketCommand(string module, string[] args) | 756 | private void HandlePacketCommand(string module, string[] args) |
741 | { | 757 | { |
742 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 758 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
743 | return; | 759 | return; |
744 | 760 | ||
745 | bool setAsDefaultLevel = false; | 761 | bool setAsDefaultLevel = false; |
@@ -775,15 +791,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
775 | 791 | ||
776 | MainConsole.Instance.OutputFormat( | 792 | MainConsole.Instance.OutputFormat( |
777 | "Packet debug for {0} clients set to {1} in {2}", | 793 | "Packet debug for {0} clients set to {1} in {2}", |
778 | (setAll ? "all" : "future"), DefaultClientPacketDebugLevel, m_scene.Name); | 794 | (setAll ? "all" : "future"), DefaultClientPacketDebugLevel, Scene.Name); |
779 | 795 | ||
780 | if (setAll) | 796 | if (setAll) |
781 | { | 797 | { |
782 | m_scene.ForEachScenePresence(sp => | 798 | Scene.ForEachScenePresence(sp => |
783 | { | 799 | { |
784 | MainConsole.Instance.OutputFormat( | 800 | MainConsole.Instance.OutputFormat( |
785 | "Packet debug for {0} ({1}) set to {2} in {3}", | 801 | "Packet debug for {0} ({1}) set to {2} in {3}", |
786 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name); | 802 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, Scene.Name); |
787 | 803 | ||
788 | sp.ControllingClient.DebugPacketLevel = newDebug; | 804 | sp.ControllingClient.DebugPacketLevel = newDebug; |
789 | }); | 805 | }); |
@@ -791,13 +807,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
791 | } | 807 | } |
792 | else | 808 | else |
793 | { | 809 | { |
794 | m_scene.ForEachScenePresence(sp => | 810 | Scene.ForEachScenePresence(sp => |
795 | { | 811 | { |
796 | if (name == null || sp.Name == name) | 812 | if (name == null || sp.Name == name) |
797 | { | 813 | { |
798 | MainConsole.Instance.OutputFormat( | 814 | MainConsole.Instance.OutputFormat( |
799 | "Packet debug for {0} ({1}) set to {2} in {3}", | 815 | "Packet debug for {0} ({1}) set to {2} in {3}", |
800 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name); | 816 | sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, Scene.Name); |
801 | 817 | ||
802 | sp.ControllingClient.DebugPacketLevel = newDebug; | 818 | sp.ControllingClient.DebugPacketLevel = newDebug; |
803 | } | 819 | } |
@@ -811,9 +827,60 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
811 | } | 827 | } |
812 | } | 828 | } |
813 | 829 | ||
830 | private void HandleDropCommand(string module, string[] args) | ||
831 | { | ||
832 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) | ||
833 | return; | ||
834 | |||
835 | if (args.Length != 6) | ||
836 | { | ||
837 | MainConsole.Instance.Output("Usage: debug lludp drop <in|out> <add|remove> <packet-name>"); | ||
838 | return; | ||
839 | } | ||
840 | |||
841 | string direction = args[3]; | ||
842 | string subCommand = args[4]; | ||
843 | string packetName = args[5]; | ||
844 | |||
845 | if (subCommand == "add") | ||
846 | { | ||
847 | MainConsole.Instance.OutputFormat( | ||
848 | "Adding packet {0} to {1} drop list for all connections in {2}", direction, packetName, Scene.Name); | ||
849 | |||
850 | Scene.ForEachScenePresence( | ||
851 | sp => | ||
852 | { | ||
853 | LLClientView llcv = (LLClientView)sp.ControllingClient; | ||
854 | |||
855 | if (direction == "in") | ||
856 | llcv.AddInPacketToDropSet(packetName); | ||
857 | else if (direction == "out") | ||
858 | llcv.AddOutPacketToDropSet(packetName); | ||
859 | } | ||
860 | ); | ||
861 | } | ||
862 | else if (subCommand == "remove") | ||
863 | { | ||
864 | MainConsole.Instance.OutputFormat( | ||
865 | "Removing packet {0} from {1} drop list for all connections in {2}", direction, packetName, Scene.Name); | ||
866 | |||
867 | Scene.ForEachScenePresence( | ||
868 | sp => | ||
869 | { | ||
870 | LLClientView llcv = (LLClientView)sp.ControllingClient; | ||
871 | |||
872 | if (direction == "in") | ||
873 | llcv.RemoveInPacketFromDropSet(packetName); | ||
874 | else if (direction == "out") | ||
875 | llcv.RemoveOutPacketFromDropSet(packetName); | ||
876 | } | ||
877 | ); | ||
878 | } | ||
879 | } | ||
880 | |||
814 | private void HandleStartCommand(string module, string[] args) | 881 | private void HandleStartCommand(string module, string[] args) |
815 | { | 882 | { |
816 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 883 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
817 | return; | 884 | return; |
818 | 885 | ||
819 | if (args.Length != 4) | 886 | if (args.Length != 4) |
@@ -833,7 +900,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
833 | 900 | ||
834 | private void HandleStopCommand(string module, string[] args) | 901 | private void HandleStopCommand(string module, string[] args) |
835 | { | 902 | { |
836 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 903 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
837 | return; | 904 | return; |
838 | 905 | ||
839 | if (args.Length != 4) | 906 | if (args.Length != 4) |
@@ -853,7 +920,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
853 | 920 | ||
854 | private void HandlePoolCommand(string module, string[] args) | 921 | private void HandlePoolCommand(string module, string[] args) |
855 | { | 922 | { |
856 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 923 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
857 | return; | 924 | return; |
858 | 925 | ||
859 | if (args.Length != 4) | 926 | if (args.Length != 4) |
@@ -869,7 +936,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
869 | if (EnablePools()) | 936 | if (EnablePools()) |
870 | { | 937 | { |
871 | EnablePoolStats(); | 938 | EnablePoolStats(); |
872 | MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); | 939 | MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", Scene.Name); |
873 | } | 940 | } |
874 | } | 941 | } |
875 | else if (enabled == "off") | 942 | else if (enabled == "off") |
@@ -877,7 +944,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
877 | if (DisablePools()) | 944 | if (DisablePools()) |
878 | { | 945 | { |
879 | DisablePoolStats(); | 946 | DisablePoolStats(); |
880 | MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); | 947 | MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", Scene.Name); |
881 | } | 948 | } |
882 | } | 949 | } |
883 | else | 950 | else |
@@ -890,27 +957,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
890 | 957 | ||
891 | private void HandleAgentUpdateCommand(string module, string[] args) | 958 | private void HandleAgentUpdateCommand(string module, string[] args) |
892 | { | 959 | { |
893 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 960 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
894 | return; | 961 | return; |
895 | 962 | ||
896 | m_discardAgentUpdates = !m_discardAgentUpdates; | 963 | m_discardAgentUpdates = !m_discardAgentUpdates; |
897 | 964 | ||
898 | MainConsole.Instance.OutputFormat( | 965 | MainConsole.Instance.OutputFormat( |
899 | "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name); | 966 | "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, Scene.Name); |
900 | } | 967 | } |
901 | 968 | ||
902 | private void HandleStatusCommand(string module, string[] args) | 969 | private void HandleStatusCommand(string module, string[] args) |
903 | { | 970 | { |
904 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene) | 971 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != Scene) |
905 | return; | 972 | return; |
906 | 973 | ||
907 | MainConsole.Instance.OutputFormat( | 974 | MainConsole.Instance.OutputFormat( |
908 | "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); | 975 | "IN LLUDP packet processing for {0} is {1}", Scene.Name, IsRunningInbound ? "enabled" : "disabled"); |
909 | 976 | ||
910 | MainConsole.Instance.OutputFormat( | 977 | MainConsole.Instance.OutputFormat( |
911 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); | 978 | "OUT LLUDP packet processing for {0} is {1}", Scene.Name, IsRunningOutbound ? "enabled" : "disabled"); |
912 | 979 | ||
913 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); | 980 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", Scene.Name, UsePools ? "on" : "off"); |
914 | 981 | ||
915 | MainConsole.Instance.OutputFormat( | 982 | MainConsole.Instance.OutputFormat( |
916 | "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel); | 983 | "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel); |
@@ -1420,7 +1487,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1420 | 1487 | ||
1421 | // Determine which agent this packet came from | 1488 | // Determine which agent this packet came from |
1422 | IClientAPI client; | 1489 | IClientAPI client; |
1423 | if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) | 1490 | if (!Scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) |
1424 | { | 1491 | { |
1425 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); | 1492 | //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); |
1426 | 1493 | ||
@@ -1715,7 +1782,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1715 | 1782 | ||
1716 | m_log.DebugFormat( | 1783 | m_log.DebugFormat( |
1717 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", | 1784 | "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", |
1718 | uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); | 1785 | uccp.CircuitCode.Code, Scene.RegionInfo.RegionName, endPoint); |
1719 | 1786 | ||
1720 | AuthenticateResponse sessionInfo; | 1787 | AuthenticateResponse sessionInfo; |
1721 | if (IsClientAuthorized(uccp, out sessionInfo)) | 1788 | if (IsClientAuthorized(uccp, out sessionInfo)) |
@@ -1737,7 +1804,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1737 | // We only want to send initial data to new clients, not ones which are being converted from child to root. | 1804 | // We only want to send initial data to new clients, not ones which are being converted from child to root. |
1738 | if (client != null) | 1805 | if (client != null) |
1739 | { | 1806 | { |
1740 | AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); | 1807 | AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code); |
1741 | bool tp = (aCircuit.teleportFlags > 0); | 1808 | bool tp = (aCircuit.teleportFlags > 0); |
1742 | // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from | 1809 | // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from |
1743 | if (!tp && !client.SceneAgent.SentInitialDataToClient) | 1810 | if (!tp && !client.SceneAgent.SentInitialDataToClient) |
@@ -1749,7 +1816,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1749 | // Don't create clients for unauthorized requesters. | 1816 | // Don't create clients for unauthorized requesters. |
1750 | m_log.WarnFormat( | 1817 | m_log.WarnFormat( |
1751 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", | 1818 | "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", |
1752 | uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); | 1819 | uccp.CircuitCode.ID, Scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); |
1753 | } | 1820 | } |
1754 | 1821 | ||
1755 | // m_log.DebugFormat( | 1822 | // m_log.DebugFormat( |
@@ -1781,7 +1848,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1781 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; | 1848 | CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; |
1782 | 1849 | ||
1783 | m_log.DebugFormat( | 1850 | m_log.DebugFormat( |
1784 | "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name); | 1851 | "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, Scene.Name); |
1785 | 1852 | ||
1786 | // Determine which agent this packet came from | 1853 | // Determine which agent this packet came from |
1787 | // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination | 1854 | // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination |
@@ -1792,7 +1859,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1792 | int count = 40; | 1859 | int count = 40; |
1793 | while (count-- > 0) | 1860 | while (count-- > 0) |
1794 | { | 1861 | { |
1795 | if (m_scene.TryGetClient(endPoint, out client)) | 1862 | if (Scene.TryGetClient(endPoint, out client)) |
1796 | { | 1863 | { |
1797 | if (!client.IsActive) | 1864 | if (!client.IsActive) |
1798 | { | 1865 | { |
@@ -1801,7 +1868,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1801 | // not yet been established). | 1868 | // not yet been established). |
1802 | m_log.DebugFormat( | 1869 | m_log.DebugFormat( |
1803 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.", | 1870 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.", |
1804 | endPoint, client.Name, m_scene.Name); | 1871 | endPoint, client.Name, Scene.Name); |
1805 | } | 1872 | } |
1806 | else if (client.SceneAgent == null) | 1873 | else if (client.SceneAgent == null) |
1807 | { | 1874 | { |
@@ -1813,7 +1880,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1813 | // the client manager | 1880 | // the client manager |
1814 | m_log.DebugFormat( | 1881 | m_log.DebugFormat( |
1815 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", | 1882 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.", |
1816 | endPoint, client.Name, m_scene.Name); | 1883 | endPoint, client.Name, Scene.Name); |
1817 | } | 1884 | } |
1818 | else | 1885 | else |
1819 | { | 1886 | { |
@@ -1824,7 +1891,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1824 | { | 1891 | { |
1825 | m_log.DebugFormat( | 1892 | m_log.DebugFormat( |
1826 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", | 1893 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.", |
1827 | endPoint, m_scene.Name); | 1894 | endPoint, Scene.Name); |
1828 | } | 1895 | } |
1829 | 1896 | ||
1830 | Thread.Sleep(200); | 1897 | Thread.Sleep(200); |
@@ -1834,7 +1901,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1834 | { | 1901 | { |
1835 | m_log.DebugFormat( | 1902 | m_log.DebugFormat( |
1836 | "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.", | 1903 | "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.", |
1837 | endPoint, m_scene.Name); | 1904 | endPoint, Scene.Name); |
1838 | 1905 | ||
1839 | return; | 1906 | return; |
1840 | } | 1907 | } |
@@ -1846,7 +1913,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1846 | // purposes. | 1913 | // purposes. |
1847 | m_log.DebugFormat( | 1914 | m_log.DebugFormat( |
1848 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.", | 1915 | "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.", |
1849 | endPoint, client.Name, m_scene.Name); | 1916 | endPoint, client.Name, Scene.Name); |
1850 | 1917 | ||
1851 | return; | 1918 | return; |
1852 | } | 1919 | } |
@@ -1941,11 +2008,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1941 | // consistently, this lock could probably be removed. | 2008 | // consistently, this lock could probably be removed. |
1942 | lock (this) | 2009 | lock (this) |
1943 | { | 2010 | { |
1944 | if (!m_scene.TryGetClient(agentID, out client)) | 2011 | if (!Scene.TryGetClient(agentID, out client)) |
1945 | { | 2012 | { |
1946 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); | 2013 | LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); |
1947 | 2014 | ||
1948 | client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); | 2015 | client = new LLClientView(Scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); |
1949 | client.OnLogout += LogoutHandler; | 2016 | client.OnLogout += LogoutHandler; |
1950 | client.DebugPacketLevel = DefaultClientPacketDebugLevel; | 2017 | client.DebugPacketLevel = DefaultClientPacketDebugLevel; |
1951 | 2018 | ||
@@ -1975,13 +2042,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1975 | 2042 | ||
1976 | m_log.WarnFormat( | 2043 | m_log.WarnFormat( |
1977 | "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", | 2044 | "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.", |
1978 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name); | 2045 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, Scene.Name); |
1979 | 2046 | ||
1980 | if (!client.SceneAgent.IsChildAgent) | 2047 | if (!client.SceneAgent.IsChildAgent) |
1981 | client.Kick("Simulator logged you out due to connection timeout."); | 2048 | client.Kick("Simulator logged you out due to connection timeout."); |
1982 | } | 2049 | } |
1983 | 2050 | ||
1984 | m_scene.CloseAgent(client.AgentId, true); | 2051 | Scene.CloseAgent(client.AgentId, true); |
1985 | } | 2052 | } |
1986 | 2053 | ||
1987 | private void IncomingPacketHandler() | 2054 | private void IncomingPacketHandler() |
@@ -2093,7 +2160,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2093 | 2160 | ||
2094 | // Handle outgoing packets, resends, acknowledgements, and pings for each | 2161 | // Handle outgoing packets, resends, acknowledgements, and pings for each |
2095 | // client. m_packetSent will be set to true if a packet is sent | 2162 | // client. m_packetSent will be set to true if a packet is sent |
2096 | m_scene.ForEachClient(clientPacketHandler); | 2163 | Scene.ForEachClient(clientPacketHandler); |
2097 | 2164 | ||
2098 | m_currentOutgoingClient = null; | 2165 | m_currentOutgoingClient = null; |
2099 | 2166 | ||
@@ -2260,7 +2327,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2260 | watch1.Reset(); | 2327 | watch1.Reset(); |
2261 | 2328 | ||
2262 | // reuse this -- it's every ~100ms | 2329 | // reuse this -- it's every ~100ms |
2263 | if (m_scene.EmergencyMonitoring && nticks % 100 == 0) | 2330 | if (Scene.EmergencyMonitoring && nticks % 100 == 0) |
2264 | { | 2331 | { |
2265 | m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})", | 2332 | m_log.InfoFormat("[LLUDPSERVER]: avg processing ticks: {0} avg unacked: {1} avg acks: {2} avg ping: {3} avg dequeue: {4} (TickCountRes: {5} sent: {6} notsent: {7})", |
2266 | avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); | 2333 | avgProcessingTicks, avgResendUnackedTicks, avgSendAcksTicks, avgSendPingTicks, avgDequeueTicks, TickCountResolution, npacksSent, npackNotSent); |
@@ -2309,7 +2376,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2309 | { | 2376 | { |
2310 | m_log.DebugFormat( | 2377 | m_log.DebugFormat( |
2311 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 2378 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
2312 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 2379 | packet.Type, client.Name, Scene.RegionInfo.RegionName); |
2313 | } | 2380 | } |
2314 | 2381 | ||
2315 | IncomingPacketsProcessed++; | 2382 | IncomingPacketsProcessed++; |
@@ -2322,7 +2389,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2322 | if (!client.IsLoggingOut) | 2389 | if (!client.IsLoggingOut) |
2323 | { | 2390 | { |
2324 | client.IsLoggingOut = true; | 2391 | client.IsLoggingOut = true; |
2325 | m_scene.CloseAgent(client.AgentId, false); | 2392 | Scene.CloseAgent(client.AgentId, false); |
2326 | } | 2393 | } |
2327 | } | 2394 | } |
2328 | } | 2395 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OutgoingQueueRefillEngine.cs b/OpenSim/Region/ClientStack/Linden/UDP/OutgoingQueueRefillEngine.cs new file mode 100644 index 0000000..0659d8e --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/OutgoingQueueRefillEngine.cs | |||
@@ -0,0 +1,286 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Concurrent; | ||
30 | using System.Reflection; | ||
31 | using System.Threading; | ||
32 | using log4net; | ||
33 | using OpenSim.Framework; | ||
34 | using OpenSim.Framework.Monitoring; | ||
35 | using OpenSim.Region.Framework.Scenes; | ||
36 | |||
37 | namespace OpenSim.Region.ClientStack.LindenUDP | ||
38 | { | ||
39 | public struct RefillRequest | ||
40 | { | ||
41 | public LLUDPClient Client; | ||
42 | public ThrottleOutPacketTypeFlags Categories; | ||
43 | |||
44 | public RefillRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories) | ||
45 | { | ||
46 | Client = client; | ||
47 | Categories = categories; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | public class OutgoingQueueRefillEngine | ||
52 | { | ||
53 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
54 | |||
55 | public bool IsRunning { get; private set; } | ||
56 | |||
57 | /// <summary> | ||
58 | /// The timeout in milliseconds to wait for at least one event to be written when the recorder is stopping. | ||
59 | /// </summary> | ||
60 | public int RequestProcessTimeoutOnStop { get; set; } | ||
61 | |||
62 | /// <summary> | ||
63 | /// Controls whether we need to warn in the log about exceeding the max queue size. | ||
64 | /// </summary> | ||
65 | /// <remarks> | ||
66 | /// This is flipped to false once queue max has been exceeded and back to true when it falls below max, in | ||
67 | /// order to avoid spamming the log with lots of warnings. | ||
68 | /// </remarks> | ||
69 | private bool m_warnOverMaxQueue = true; | ||
70 | |||
71 | private BlockingCollection<RefillRequest> m_requestQueue; | ||
72 | |||
73 | private CancellationTokenSource m_cancelSource = new CancellationTokenSource(); | ||
74 | |||
75 | private LLUDPServer m_udpServer; | ||
76 | |||
77 | private Stat m_oqreRequestsWaitingStat; | ||
78 | |||
79 | /// <summary> | ||
80 | /// Used to signal that we are ready to complete stop. | ||
81 | /// </summary> | ||
82 | private ManualResetEvent m_finishedProcessingAfterStop = new ManualResetEvent(false); | ||
83 | |||
84 | public OutgoingQueueRefillEngine(LLUDPServer server) | ||
85 | { | ||
86 | RequestProcessTimeoutOnStop = 5000; | ||
87 | m_udpServer = server; | ||
88 | |||
89 | MainConsole.Instance.Commands.AddCommand( | ||
90 | "Debug", | ||
91 | false, | ||
92 | "debug lludp oqre", | ||
93 | "debug lludp oqre <start|stop|status>", | ||
94 | "Start, stop or get status of OutgoingQueueRefillEngine.", | ||
95 | "Experimental.", | ||
96 | HandleOqreCommand); | ||
97 | } | ||
98 | |||
99 | public void Start() | ||
100 | { | ||
101 | lock (this) | ||
102 | { | ||
103 | if (IsRunning) | ||
104 | return; | ||
105 | |||
106 | IsRunning = true; | ||
107 | |||
108 | m_finishedProcessingAfterStop.Reset(); | ||
109 | |||
110 | m_requestQueue = new BlockingCollection<RefillRequest>(new ConcurrentQueue<RefillRequest>(), 5000); | ||
111 | |||
112 | m_oqreRequestsWaitingStat = | ||
113 | new Stat( | ||
114 | "OQRERequestsWaiting", | ||
115 | "Number of outgong queue refill requests waiting for processing.", | ||
116 | "", | ||
117 | "", | ||
118 | "clientstack", | ||
119 | m_udpServer.Scene.Name, | ||
120 | StatType.Pull, | ||
121 | MeasuresOfInterest.None, | ||
122 | stat => stat.Value = m_requestQueue.Count, | ||
123 | StatVerbosity.Debug); | ||
124 | |||
125 | StatsManager.RegisterStat(m_oqreRequestsWaitingStat); | ||
126 | |||
127 | Watchdog.StartThread( | ||
128 | ProcessRequests, | ||
129 | String.Format("OutgoingQueueRefillEngineThread ({0})", m_udpServer.Scene.Name), | ||
130 | ThreadPriority.Normal, | ||
131 | false, | ||
132 | true, | ||
133 | null, | ||
134 | int.MaxValue); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | public void Stop() | ||
139 | { | ||
140 | lock (this) | ||
141 | { | ||
142 | try | ||
143 | { | ||
144 | if (!IsRunning) | ||
145 | return; | ||
146 | |||
147 | IsRunning = false; | ||
148 | |||
149 | int requestsLeft = m_requestQueue.Count; | ||
150 | |||
151 | if (requestsLeft <= 0) | ||
152 | { | ||
153 | m_cancelSource.Cancel(); | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | m_log.InfoFormat("[OUTGOING QUEUE REFILL ENGINE]: Waiting to write {0} events after stop.", requestsLeft); | ||
158 | |||
159 | while (requestsLeft > 0) | ||
160 | { | ||
161 | if (!m_finishedProcessingAfterStop.WaitOne(RequestProcessTimeoutOnStop)) | ||
162 | { | ||
163 | // After timeout no events have been written | ||
164 | if (requestsLeft == m_requestQueue.Count) | ||
165 | { | ||
166 | m_log.WarnFormat( | ||
167 | "[OUTGOING QUEUE REFILL ENGINE]: No requests processed after {0} ms wait. Discarding remaining {1} requests", | ||
168 | RequestProcessTimeoutOnStop, requestsLeft); | ||
169 | |||
170 | break; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | requestsLeft = m_requestQueue.Count; | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | finally | ||
179 | { | ||
180 | m_cancelSource.Dispose(); | ||
181 | StatsManager.DeregisterStat(m_oqreRequestsWaitingStat); | ||
182 | m_oqreRequestsWaitingStat = null; | ||
183 | m_requestQueue = null; | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | |||
188 | public bool QueueRequest(LLUDPClient client, ThrottleOutPacketTypeFlags categories) | ||
189 | { | ||
190 | if (m_requestQueue.Count < m_requestQueue.BoundedCapacity) | ||
191 | { | ||
192 | // m_log.DebugFormat( | ||
193 | // "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}", | ||
194 | // categories, client.AgentID, m_udpServer.Scene.Name); | ||
195 | |||
196 | m_requestQueue.Add(new RefillRequest(client, categories)); | ||
197 | |||
198 | if (!m_warnOverMaxQueue) | ||
199 | m_warnOverMaxQueue = true; | ||
200 | |||
201 | return true; | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | if (m_warnOverMaxQueue) | ||
206 | { | ||
207 | m_log.WarnFormat( | ||
208 | "[OUTGOING QUEUE REFILL ENGINE]: Request queue at maximum capacity, not recording request from {0} in {1}", | ||
209 | client.AgentID, m_udpServer.Scene.Name); | ||
210 | |||
211 | m_warnOverMaxQueue = false; | ||
212 | } | ||
213 | |||
214 | return false; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | private void ProcessRequests() | ||
219 | { | ||
220 | try | ||
221 | { | ||
222 | while (IsRunning || m_requestQueue.Count > 0) | ||
223 | { | ||
224 | RefillRequest req = m_requestQueue.Take(m_cancelSource.Token); | ||
225 | |||
226 | // QueueEmpty callback = req.Client.OnQueueEmpty; | ||
227 | // | ||
228 | // if (callback != null) | ||
229 | // { | ||
230 | // try | ||
231 | // { | ||
232 | // callback(req.Categories); | ||
233 | // } | ||
234 | // catch (Exception e) | ||
235 | // { | ||
236 | // m_log.Error("[OUTGOING QUEUE REFILL ENGINE]: ProcessRequests(" + req.Categories + ") threw an exception: " + e.Message, e); | ||
237 | // } | ||
238 | // } | ||
239 | |||
240 | req.Client.FireQueueEmpty(req.Categories); | ||
241 | } | ||
242 | } | ||
243 | catch (OperationCanceledException) | ||
244 | { | ||
245 | } | ||
246 | |||
247 | m_finishedProcessingAfterStop.Set(); | ||
248 | } | ||
249 | |||
250 | private void HandleOqreCommand(string module, string[] args) | ||
251 | { | ||
252 | if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_udpServer.Scene) | ||
253 | return; | ||
254 | |||
255 | if (args.Length != 4) | ||
256 | { | ||
257 | MainConsole.Instance.Output("Usage: debug lludp oqre <stop|start|status>"); | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | string subCommand = args[3]; | ||
262 | |||
263 | if (subCommand == "stop") | ||
264 | { | ||
265 | Stop(); | ||
266 | MainConsole.Instance.OutputFormat("Stopped OQRE for {0}", m_udpServer.Scene.Name); | ||
267 | } | ||
268 | else if (subCommand == "start") | ||
269 | { | ||
270 | Start(); | ||
271 | MainConsole.Instance.OutputFormat("Started OQRE for {0}", m_udpServer.Scene.Name); | ||
272 | } | ||
273 | else if (subCommand == "status") | ||
274 | { | ||
275 | MainConsole.Instance.OutputFormat("OQRE in {0}", m_udpServer.Scene.Name); | ||
276 | MainConsole.Instance.OutputFormat("Running: {0}", IsRunning); | ||
277 | MainConsole.Instance.OutputFormat( | ||
278 | "Requests waiting: {0}", IsRunning ? m_requestQueue.Count.ToString() : "n/a"); | ||
279 | } | ||
280 | else | ||
281 | { | ||
282 | MainConsole.Instance.OutputFormat("Unrecognized OQRE subcommand {0}", subCommand); | ||
283 | } | ||
284 | } | ||
285 | } | ||
286 | } \ No newline at end of file | ||
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs index b10f552..29739dc 100644 --- a/OpenSim/Tools/pCampBot/BotManager.cs +++ b/OpenSim/Tools/pCampBot/BotManager.cs | |||
@@ -690,7 +690,14 @@ namespace pCampBot | |||
690 | { | 690 | { |
691 | lock (m_bots) | 691 | lock (m_bots) |
692 | { | 692 | { |
693 | m_bots.ForEach(b => b.SitOnGround()); | 693 | foreach (Bot bot in m_bots) |
694 | { | ||
695 | if (bot.ConnectionState == ConnectionState.Connected) | ||
696 | { | ||
697 | MainConsole.Instance.OutputFormat("Sitting bot {0} on ground.", bot.Name); | ||
698 | bot.SitOnGround(); | ||
699 | } | ||
700 | } | ||
694 | } | 701 | } |
695 | } | 702 | } |
696 | 703 | ||
@@ -698,7 +705,14 @@ namespace pCampBot | |||
698 | { | 705 | { |
699 | lock (m_bots) | 706 | lock (m_bots) |
700 | { | 707 | { |
701 | m_bots.ForEach(b => b.Stand()); | 708 | foreach (Bot bot in m_bots) |
709 | { | ||
710 | if (bot.ConnectionState == ConnectionState.Connected) | ||
711 | { | ||
712 | MainConsole.Instance.OutputFormat("Standing bot {0} from ground.", bot.Name); | ||
713 | bot.Stand(); | ||
714 | } | ||
715 | } | ||
702 | } | 716 | } |
703 | } | 717 | } |
704 | 718 | ||