diff options
Merge branch 'master' into connector_plugin
Conflicts:
OpenSim/Server/Base/ServicesServerBase.cs
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 219 |
1 files changed, 216 insertions, 3 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 419de66..a7628d2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -70,6 +70,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
70 | public void AddScene(IScene scene) | 70 | public void AddScene(IScene scene) |
71 | { | 71 | { |
72 | m_udpServer.AddScene(scene); | 72 | m_udpServer.AddScene(scene); |
73 | |||
74 | StatsManager.RegisterStat( | ||
75 | new Stat( | ||
76 | "IncomingPacketsProcessedCount", | ||
77 | "Number of inbound UDP packets processed", | ||
78 | "Number of inbound UDP packets processed", | ||
79 | "", | ||
80 | "clientstack", | ||
81 | scene.Name, | ||
82 | StatType.Pull, | ||
83 | MeasuresOfInterest.AverageChangeOverTime, | ||
84 | stat => stat.Value = m_udpServer.IncomingPacketsProcessed, | ||
85 | StatVerbosity.Debug)); | ||
73 | } | 86 | } |
74 | 87 | ||
75 | public bool HandlesRegion(Location x) | 88 | public bool HandlesRegion(Location x) |
@@ -170,6 +183,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
170 | 183 | ||
171 | private Pool<IncomingPacket> m_incomingPacketPool; | 184 | private Pool<IncomingPacket> m_incomingPacketPool; |
172 | 185 | ||
186 | /// <summary> | ||
187 | /// Stat for number of packets in the main pool awaiting use. | ||
188 | /// </summary> | ||
189 | private Stat m_poolCountStat; | ||
190 | |||
191 | /// <summary> | ||
192 | /// Stat for number of packets in the inbound packet pool awaiting use. | ||
193 | /// </summary> | ||
194 | private Stat m_incomingPacketPoolStat; | ||
195 | |||
173 | private int m_defaultRTO = 0; | 196 | private int m_defaultRTO = 0; |
174 | private int m_maxRTO = 0; | 197 | private int m_maxRTO = 0; |
175 | private int m_ackTimeout = 0; | 198 | private int m_ackTimeout = 0; |
@@ -214,6 +237,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
214 | 237 | ||
215 | m_circuitManager = circuitManager; | 238 | m_circuitManager = circuitManager; |
216 | int sceneThrottleBps = 0; | 239 | int sceneThrottleBps = 0; |
240 | bool usePools = false; | ||
217 | 241 | ||
218 | IConfig config = configSource.Configs["ClientStack.LindenUDP"]; | 242 | IConfig config = configSource.Configs["ClientStack.LindenUDP"]; |
219 | if (config != null) | 243 | if (config != null) |
@@ -246,7 +270,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
246 | { | 270 | { |
247 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); | 271 | PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); |
248 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); | 272 | PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); |
249 | UsePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", false); | 273 | usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools); |
250 | } | 274 | } |
251 | 275 | ||
252 | #region BinaryStats | 276 | #region BinaryStats |
@@ -277,8 +301,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
277 | m_throttle = new TokenBucket(null, sceneThrottleBps); | 301 | m_throttle = new TokenBucket(null, sceneThrottleBps); |
278 | ThrottleRates = new ThrottleRates(configSource); | 302 | ThrottleRates = new ThrottleRates(configSource); |
279 | 303 | ||
280 | if (UsePools) | 304 | if (usePools) |
281 | m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500); | 305 | EnablePools(); |
282 | } | 306 | } |
283 | 307 | ||
284 | public void Start() | 308 | public void Start() |
@@ -331,6 +355,83 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
331 | base.StopInbound(); | 355 | base.StopInbound(); |
332 | } | 356 | } |
333 | 357 | ||
358 | protected override bool EnablePools() | ||
359 | { | ||
360 | if (!UsePools) | ||
361 | { | ||
362 | base.EnablePools(); | ||
363 | |||
364 | m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500); | ||
365 | |||
366 | return true; | ||
367 | } | ||
368 | |||
369 | return false; | ||
370 | } | ||
371 | |||
372 | protected override bool DisablePools() | ||
373 | { | ||
374 | if (UsePools) | ||
375 | { | ||
376 | base.DisablePools(); | ||
377 | |||
378 | StatsManager.DeregisterStat(m_incomingPacketPoolStat); | ||
379 | |||
380 | // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. | ||
381 | |||
382 | return true; | ||
383 | } | ||
384 | |||
385 | return false; | ||
386 | } | ||
387 | |||
388 | /// <summary> | ||
389 | /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene | ||
390 | /// stats. | ||
391 | /// </summary> | ||
392 | private void EnablePoolStats() | ||
393 | { | ||
394 | m_poolCountStat | ||
395 | = new Stat( | ||
396 | "UDPPacketBufferPoolCount", | ||
397 | "Objects within the UDPPacketBuffer pool", | ||
398 | "The number of objects currently stored within the UDPPacketBuffer pool", | ||
399 | "", | ||
400 | "clientstack", | ||
401 | m_scene.Name, | ||
402 | StatType.Pull, | ||
403 | stat => stat.Value = Pool.Count, | ||
404 | StatVerbosity.Debug); | ||
405 | |||
406 | StatsManager.RegisterStat(m_poolCountStat); | ||
407 | |||
408 | m_incomingPacketPoolStat | ||
409 | = new Stat( | ||
410 | "IncomingPacketPoolCount", | ||
411 | "Objects within incoming packet pool", | ||
412 | "The number of objects currently stored within the incoming packet pool", | ||
413 | "", | ||
414 | "clientstack", | ||
415 | m_scene.Name, | ||
416 | StatType.Pull, | ||
417 | stat => stat.Value = m_incomingPacketPool.Count, | ||
418 | StatVerbosity.Debug); | ||
419 | |||
420 | StatsManager.RegisterStat(m_incomingPacketPoolStat); | ||
421 | } | ||
422 | |||
423 | /// <summary> | ||
424 | /// Disables pool stats. | ||
425 | /// </summary> | ||
426 | private void DisablePoolStats() | ||
427 | { | ||
428 | StatsManager.DeregisterStat(m_poolCountStat); | ||
429 | m_poolCountStat = null; | ||
430 | |||
431 | StatsManager.DeregisterStat(m_incomingPacketPoolStat); | ||
432 | m_incomingPacketPoolStat = null; | ||
433 | } | ||
434 | |||
334 | /// <summary> | 435 | /// <summary> |
335 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. | 436 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. |
336 | /// </summary> | 437 | /// </summary> |
@@ -370,6 +471,65 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
370 | m_scene = (Scene)scene; | 471 | m_scene = (Scene)scene; |
371 | m_location = new Location(m_scene.RegionInfo.RegionHandle); | 472 | m_location = new Location(m_scene.RegionInfo.RegionHandle); |
372 | 473 | ||
474 | // XXX: These stats are also pool stats but we register them separately since they are currently not | ||
475 | // turned on and off by EnablePools()/DisablePools() | ||
476 | StatsManager.RegisterStat( | ||
477 | new PercentageStat( | ||
478 | "PacketsReused", | ||
479 | "Packets reused", | ||
480 | "Number of packets reused out of all requests to the packet pool", | ||
481 | "clientstack", | ||
482 | m_scene.Name, | ||
483 | StatType.Pull, | ||
484 | stat => | ||
485 | { PercentageStat pstat = (PercentageStat)stat; | ||
486 | pstat.Consequent = PacketPool.Instance.PacketsRequested; | ||
487 | pstat.Antecedent = PacketPool.Instance.PacketsReused; }, | ||
488 | StatVerbosity.Debug)); | ||
489 | |||
490 | StatsManager.RegisterStat( | ||
491 | new PercentageStat( | ||
492 | "PacketDataBlocksReused", | ||
493 | "Packet data blocks reused", | ||
494 | "Number of data blocks reused out of all requests to the packet pool", | ||
495 | "clientstack", | ||
496 | m_scene.Name, | ||
497 | StatType.Pull, | ||
498 | stat => | ||
499 | { PercentageStat pstat = (PercentageStat)stat; | ||
500 | pstat.Consequent = PacketPool.Instance.BlocksRequested; | ||
501 | pstat.Antecedent = PacketPool.Instance.BlocksReused; }, | ||
502 | StatVerbosity.Debug)); | ||
503 | |||
504 | StatsManager.RegisterStat( | ||
505 | new Stat( | ||
506 | "PacketsPoolCount", | ||
507 | "Objects within the packet pool", | ||
508 | "The number of objects currently stored within the packet pool", | ||
509 | "", | ||
510 | "clientstack", | ||
511 | m_scene.Name, | ||
512 | StatType.Pull, | ||
513 | stat => stat.Value = PacketPool.Instance.PacketsPooled, | ||
514 | StatVerbosity.Debug)); | ||
515 | |||
516 | StatsManager.RegisterStat( | ||
517 | new Stat( | ||
518 | "PacketDataBlocksPoolCount", | ||
519 | "Objects within the packet data block pool", | ||
520 | "The number of objects currently stored within the packet data block pool", | ||
521 | "", | ||
522 | "clientstack", | ||
523 | m_scene.Name, | ||
524 | StatType.Pull, | ||
525 | stat => stat.Value = PacketPool.Instance.BlocksPooled, | ||
526 | StatVerbosity.Debug)); | ||
527 | |||
528 | // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by | ||
529 | // scene name | ||
530 | if (UsePools) | ||
531 | EnablePoolStats(); | ||
532 | |||
373 | MainConsole.Instance.Commands.AddCommand( | 533 | MainConsole.Instance.Commands.AddCommand( |
374 | "Debug", | 534 | "Debug", |
375 | false, | 535 | false, |
@@ -397,6 +557,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
397 | MainConsole.Instance.Commands.AddCommand( | 557 | MainConsole.Instance.Commands.AddCommand( |
398 | "Debug", | 558 | "Debug", |
399 | false, | 559 | false, |
560 | "debug lludp pool", | ||
561 | "debug lludp pool <on|off>", | ||
562 | "Turn object pooling within the lludp component on or off.", | ||
563 | HandlePoolCommand); | ||
564 | |||
565 | MainConsole.Instance.Commands.AddCommand( | ||
566 | "Debug", | ||
567 | false, | ||
400 | "debug lludp status", | 568 | "debug lludp status", |
401 | "debug lludp status", | 569 | "debug lludp status", |
402 | "Return status of LLUDP packet processing.", | 570 | "Return status of LLUDP packet processing.", |
@@ -437,6 +605,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
437 | StopOutbound(); | 605 | StopOutbound(); |
438 | } | 606 | } |
439 | 607 | ||
608 | private void HandlePoolCommand(string module, string[] args) | ||
609 | { | ||
610 | if (args.Length != 4) | ||
611 | { | ||
612 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
613 | return; | ||
614 | } | ||
615 | |||
616 | string enabled = args[3]; | ||
617 | |||
618 | if (enabled == "on") | ||
619 | { | ||
620 | if (EnablePools()) | ||
621 | { | ||
622 | EnablePoolStats(); | ||
623 | MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); | ||
624 | } | ||
625 | } | ||
626 | else if (enabled == "off") | ||
627 | { | ||
628 | if (DisablePools()) | ||
629 | { | ||
630 | DisablePoolStats(); | ||
631 | MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); | ||
632 | } | ||
633 | } | ||
634 | else | ||
635 | { | ||
636 | MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); | ||
637 | } | ||
638 | } | ||
639 | |||
440 | private void HandleStatusCommand(string module, string[] args) | 640 | private void HandleStatusCommand(string module, string[] args) |
441 | { | 641 | { |
442 | MainConsole.Instance.OutputFormat( | 642 | MainConsole.Instance.OutputFormat( |
@@ -444,6 +644,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
444 | 644 | ||
445 | MainConsole.Instance.OutputFormat( | 645 | MainConsole.Instance.OutputFormat( |
446 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); | 646 | "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); |
647 | |||
648 | MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); | ||
447 | } | 649 | } |
448 | 650 | ||
449 | public bool HandlesRegion(Location x) | 651 | public bool HandlesRegion(Location x) |
@@ -1473,6 +1675,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1473 | private int npacksSent = 0; | 1675 | private int npacksSent = 0; |
1474 | private int npackNotSent = 0; | 1676 | private int npackNotSent = 0; |
1475 | 1677 | ||
1678 | /// <summary> | ||
1679 | /// Number of inbound packets processed since startup. | ||
1680 | /// </summary> | ||
1681 | public long IncomingPacketsProcessed { get; private set; } | ||
1682 | |||
1476 | private void MonitoredClientOutgoingPacketHandler(IClientAPI client) | 1683 | private void MonitoredClientOutgoingPacketHandler(IClientAPI client) |
1477 | { | 1684 | { |
1478 | nticks++; | 1685 | nticks++; |
@@ -1532,7 +1739,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1532 | npacksSent++; | 1739 | npacksSent++; |
1533 | } | 1740 | } |
1534 | else | 1741 | else |
1742 | { | ||
1535 | npackNotSent++; | 1743 | npackNotSent++; |
1744 | } | ||
1536 | 1745 | ||
1537 | watch2.Stop(); | 1746 | watch2.Stop(); |
1538 | avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks); | 1747 | avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks); |
@@ -1540,7 +1749,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1540 | 1749 | ||
1541 | } | 1750 | } |
1542 | else | 1751 | else |
1752 | { | ||
1543 | m_log.WarnFormat("[LLUDPSERVER]: Client is not connected"); | 1753 | m_log.WarnFormat("[LLUDPSERVER]: Client is not connected"); |
1754 | } | ||
1544 | } | 1755 | } |
1545 | } | 1756 | } |
1546 | catch (Exception ex) | 1757 | catch (Exception ex) |
@@ -1604,6 +1815,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1604 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", | 1815 | "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", |
1605 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); | 1816 | packet.Type, client.Name, m_scene.RegionInfo.RegionName); |
1606 | } | 1817 | } |
1818 | |||
1819 | IncomingPacketsProcessed++; | ||
1607 | } | 1820 | } |
1608 | 1821 | ||
1609 | protected void LogoutHandler(IClientAPI client) | 1822 | protected void LogoutHandler(IClientAPI client) |