From 0d2fd0d914581f755661455b8db2b9e399154632 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 22:39:00 +0100 Subject: [PATCH 01/29] Make general server stats available on the robust console as well as the simulator console This means the "show stats" command is now active on the robust console. --- .../Monitoring/ServerStatsCollector.cs | 309 ++++++++++++++++ OpenSim/Framework/Monitoring/StatsManager.cs | 72 ++-- .../Framework/Servers/BaseOpenSimServer.cs | 46 +-- OpenSim/Framework/Servers/ServerBase.cs | 32 ++ OpenSim/Region/Application/Application.cs | 1 + OpenSim/Region/Application/OpenSim.cs | 2 +- OpenSim/Region/Application/OpenSimBase.cs | 7 +- .../Framework/Monitoring/ServerStats.cs | 339 ------------------ OpenSim/Server/Base/ServicesServerBase.cs | 16 +- prebuild.xml | 1 + 10 files changed, 404 insertions(+), 421 deletions(-) create mode 100644 OpenSim/Framework/Monitoring/ServerStatsCollector.cs delete mode 100644 OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs new file mode 100644 index 0000000000..80d0a89fe4 --- /dev/null +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -0,0 +1,309 @@ +/* + * 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 OpenSimulator 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 System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading; +using log4net; +using Nini.Config; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; + +namespace OpenSim.Framework.Monitoring +{ + public class ServerStatsCollector + { + private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private readonly string LogHeader = "[SERVER STATS]"; + + public bool Enabled = false; + private static Dictionary RegisteredStats = new Dictionary(); + + public readonly string CategoryServer = "server"; + + public readonly string ContainerProcessor = "processor"; + public readonly string ContainerMemory = "memory"; + public readonly string ContainerNetwork = "network"; + public readonly string ContainerProcess = "process"; + + public string NetworkInterfaceTypes = "Ethernet"; + + readonly int performanceCounterSampleInterval = 500; +// int lastperformanceCounterSampleTime = 0; + + private class PerfCounterControl + { + public PerformanceCounter perfCounter; + public int lastFetch; + public string name; + public PerfCounterControl(PerformanceCounter pPc) + : this(pPc, String.Empty) + { + } + public PerfCounterControl(PerformanceCounter pPc, string pName) + { + perfCounter = pPc; + lastFetch = 0; + name = pName; + } + } + + PerfCounterControl processorPercentPerfCounter = null; + + // IRegionModuleBase.Initialize + public void Initialise(IConfigSource source) + { + IConfig cfg = source.Configs["Monitoring"]; + + if (cfg != null) + Enabled = cfg.GetBoolean("ServerStatsEnabled", true); + + if (Enabled) + { + NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet"); + } + } + + public void Start() + { + if (RegisteredStats.Count == 0) + RegisterServerStats(); + } + + public void Close() + { + if (RegisteredStats.Count > 0) + { + foreach (Stat stat in RegisteredStats.Values) + { + StatsManager.DeregisterStat(stat); + stat.Dispose(); + } + RegisteredStats.Clear(); + } + } + + private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act) + { + string desc = pDesc; + if (desc == null) + desc = pName; + Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); + StatsManager.RegisterStat(stat); + RegisteredStats.Add(pName, stat); + } + + public void RegisterServerStats() + { +// lastperformanceCounterSampleTime = Util.EnvironmentTickCount(); + PerformanceCounter tempPC; + Stat tempStat; + string tempName; + + try + { + tempName = "CPUPercent"; + tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total"); + processorPercentPerfCounter = new PerfCounterControl(tempPC); + // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy. + tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, + StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, + StatVerbosity.Info); + StatsManager.RegisterStat(tempStat); + RegisteredStats.Add(tempName, tempStat); + + MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); + + MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); + + MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); + + MakeStat("Threads", null, "threads", ContainerProcessor, + (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); + } + catch (Exception e) + { + m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); + } + + try + { + List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); + + IEnumerable nics = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface nic in nics) + { + if (nic.OperationalStatus != OperationalStatus.Up) + continue; + + string nicInterfaceType = nic.NetworkInterfaceType.ToString(); + if (!okInterfaceTypes.Contains(nicInterfaceType)) + { + m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.", + LogHeader, nic.Name, nicInterfaceType); + m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}", + LogHeader, NetworkInterfaceTypes); + continue; + } + + if (nic.Supports(NetworkInterfaceComponent.IPv4)) + { + IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); + if (nicStats != null) + { + MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork, + (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); + MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork, + (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); + MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork, + (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); + } + } + // TODO: add IPv6 (it may actually happen someday) + } + } + catch (Exception e) + { + m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); + } + + MakeStat("ProcessMemory", null, "MB", ContainerMemory, + (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); + MakeStat("ObjectMemory", null, "MB", ContainerMemory, + (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); + MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); + MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); + } + + // Notes on performance counters: + // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx + // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c + // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters + private delegate double PerfCounterNextValue(); + private void GetNextValue(Stat stat, PerfCounterControl perfControl) + { + GetNextValue(stat, perfControl, 1.0); + } + private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor) + { + if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) + { + if (perfControl != null && perfControl.perfCounter != null) + { + try + { + // Kludge for factor to run double duty. If -1, subtract the value from one + if (factor == -1) + stat.Value = 1 - perfControl.perfCounter.NextValue(); + else + stat.Value = perfControl.perfCounter.NextValue() / factor; + } + catch (Exception e) + { + m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); + } + perfControl.lastFetch = Util.EnvironmentTickCount(); + } + } + } + + // Lookup the nic that goes with this stat and set the value by using a fetch action. + // Not sure about closure with delegates inside delegates. + private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); + private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) + { + // Get the one nic that has the name of this stat + IEnumerable nics = NetworkInterface.GetAllNetworkInterfaces().Where( + (network) => network.Name == stat.Description); + try + { + foreach (NetworkInterface nic in nics) + { + IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); + if (intrStats != null) + { + double newVal = Math.Round(getter(intrStats) / factor, 3); + stat.Value = newVal; + } + break; + } + } + catch + { + // There are times interfaces go away so we just won't update the stat for this + m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description); + } + } + } + + public class ServerStatsAggregator : Stat + { + public ServerStatsAggregator( + string shortName, + string name, + string description, + string unitName, + string category, + string container + ) + : base( + shortName, + name, + description, + unitName, + category, + container, + StatType.Push, + MeasuresOfInterest.None, + null, + StatVerbosity.Info) + { + } + public override string ToConsoleString() + { + StringBuilder sb = new StringBuilder(); + + return sb.ToString(); + } + + public override OSDMap ToOSDMap() + { + OSDMap ret = new OSDMap(); + + return ret; + } + } +} diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 24db6d44c0..3aee984cf8 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -54,13 +54,13 @@ namespace OpenSim.Framework.Monitoring public static SortedDictionary>> RegisteredStats = new SortedDictionary>>(); - private static AssetStatsCollector assetStats; - private static UserStatsCollector userStats; - private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); +// private static AssetStatsCollector assetStats; +// private static UserStatsCollector userStats; +// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); - public static AssetStatsCollector AssetStats { get { return assetStats; } } - public static UserStatsCollector UserStats { get { return userStats; } } - public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } +// public static AssetStatsCollector AssetStats { get { return assetStats; } } +// public static UserStatsCollector UserStats { get { return userStats; } } + public static SimExtraStatsCollector SimExtraStats { get; set; } public static void RegisterConsoleCommands(ICommandConsole console) { @@ -89,10 +89,7 @@ namespace OpenSim.Framework.Monitoring if (categoryName == AllSubCommand) { - foreach (var category in RegisteredStats.Values) - { - OutputCategoryStatsToConsole(con, category); - } + OutputAllStatsToConsole(con); } else if (categoryName == ListSubCommand) { @@ -129,7 +126,18 @@ namespace OpenSim.Framework.Monitoring else { // Legacy - con.Output(SimExtraStats.Report()); + if (SimExtraStats != null) + con.Output(SimExtraStats.Report()); + else + OutputAllStatsToConsole(con); + } + } + + private static void OutputAllStatsToConsole(ICommandConsole con) + { + foreach (var category in RegisteredStats.Values) + { + OutputCategoryStatsToConsole(con, category); } } @@ -150,27 +158,27 @@ namespace OpenSim.Framework.Monitoring } } - /// - /// Start collecting statistics related to assets. - /// Should only be called once. - /// - public static AssetStatsCollector StartCollectingAssetStats() - { - assetStats = new AssetStatsCollector(); - - return assetStats; - } - - /// - /// Start collecting statistics related to users. - /// Should only be called once. - /// - public static UserStatsCollector StartCollectingUserStats() - { - userStats = new UserStatsCollector(); - - return userStats; - } +// /// +// /// Start collecting statistics related to assets. +// /// Should only be called once. +// /// +// public static AssetStatsCollector StartCollectingAssetStats() +// { +// assetStats = new AssetStatsCollector(); +// +// return assetStats; +// } +// +// /// +// /// Start collecting statistics related to users. +// /// Should only be called once. +// /// +// public static UserStatsCollector StartCollectingUserStats() +// { +// userStats = new UserStatsCollector(); +// +// return userStats; +// } /// /// Registers a statistic. diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 035b3ad180..4ab6908e90 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -86,25 +86,22 @@ namespace OpenSim.Framework.Servers /// protected virtual void StartupSpecific() { - if (m_console == null) - return; - + StatsManager.SimExtraStats = new SimExtraStatsCollector(); RegisterCommonCommands(); - - m_console.Commands.AddCommand("General", false, "quit", - "quit", - "Quit the application", HandleQuit); + RegisterCommonComponents(Config); + } - m_console.Commands.AddCommand("General", false, "shutdown", - "shutdown", - "Quit the application", HandleQuit); + protected override void ShutdownSpecific() + { + m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting..."); + + RemovePIDFile(); + + base.ShutdownSpecific(); + + Environment.Exit(0); } - /// - /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing - /// - public virtual void ShutdownSpecific() {} - /// /// Provides a list of help topics that are available. Overriding classes should append their topics to the /// information returned when the base method is called. @@ -143,25 +140,8 @@ namespace OpenSim.Framework.Servers timeTaken.Minutes, timeTaken.Seconds); } - /// - /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing - /// - public virtual void Shutdown() + public string osSecret { - ShutdownSpecific(); - - m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting..."); - RemovePIDFile(); - - Environment.Exit(0); - } - - private void HandleQuit(string module, string[] args) - { - Shutdown(); - } - - public string osSecret { // Secret uuid for the simulator get { return m_osSecret; } } diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 2c4a687237..5358444133 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers protected string m_pidFile = String.Empty; + protected ServerStatsCollector m_serverStatsCollector; + /// /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. /// @@ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers "force gc", "Manually invoke runtime garbage collection. For debugging purposes", HandleForceGc); + + m_console.Commands.AddCommand( + "General", false, "quit", + "quit", + "Quit the application", (mod, args) => Shutdown()); + + m_console.Commands.AddCommand( + "General", false, "shutdown", + "shutdown", + "Quit the application", (mod, args) => Shutdown()); + + StatsManager.RegisterConsoleCommands(m_console); + } + + public void RegisterCommonComponents(IConfigSource configSource) + { + m_serverStatsCollector = new ServerStatsCollector(); + m_serverStatsCollector.Initialise(configSource); + m_serverStatsCollector.Start(); } private void HandleForceGc(string module, string[] args) @@ -698,5 +719,16 @@ namespace OpenSim.Framework.Servers if (m_console != null) m_console.OutputFormat(format, components); } + + public virtual void Shutdown() + { + m_serverStatsCollector.Close(); + ShutdownSpecific(); + } + + /// + /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing + /// + protected virtual void ShutdownSpecific() {} } } \ No newline at end of file diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index c3e7ec2e67..e451aa8148 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -124,6 +124,7 @@ namespace OpenSim workerThreads = workerThreadsMax; m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); } + // Increase the number of IOCP threads available. // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) if (iocpThreads < iocpThreadsMin) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 11dd052a19..9325b12220 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -372,7 +372,7 @@ namespace OpenSim "Unload a module", HandleModules); } - public override void ShutdownSpecific() + protected override void ShutdownSpecific() { if (m_shutdownCommandsFile != String.Empty) { diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f9e0cf1b49..7ca87a3134 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -231,10 +231,7 @@ namespace OpenSim } if (m_console != null) - { - StatsManager.RegisterConsoleCommands(m_console); AddPluginCommands(m_console); - } } protected virtual void AddPluginCommands(ICommandConsole console) @@ -880,7 +877,7 @@ namespace OpenSim /// /// Performs any last-minute sanity checking and shuts down the region server /// - public override void ShutdownSpecific() + protected override void ShutdownSpecific() { if (proxyUrl.Length > 0) { @@ -900,6 +897,8 @@ namespace OpenSim { m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); } + + base.ShutdownSpecific(); } /// diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs deleted file mode 100644 index 6e74ce0f50..0000000000 --- a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs +++ /dev/null @@ -1,339 +0,0 @@ -/* - * 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 OpenSimulator 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 System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading; - -using log4net; -using Mono.Addins; -using Nini.Config; - -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Framework.Monitoring; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -using OpenMetaverse.StructuredData; - -namespace OpenSim.Region.OptionalModules.Framework.Monitoring -{ -[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")] -public class ServerStats : ISharedRegionModule -{ - private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private readonly string LogHeader = "[SERVER STATS]"; - - public bool Enabled = false; - private static Dictionary RegisteredStats = new Dictionary(); - - public readonly string CategoryServer = "server"; - - public readonly string ContainerProcessor = "processor"; - public readonly string ContainerMemory = "memory"; - public readonly string ContainerNetwork = "network"; - public readonly string ContainerProcess = "process"; - - public string NetworkInterfaceTypes = "Ethernet"; - - readonly int performanceCounterSampleInterval = 500; - int lastperformanceCounterSampleTime = 0; - - private class PerfCounterControl - { - public PerformanceCounter perfCounter; - public int lastFetch; - public string name; - public PerfCounterControl(PerformanceCounter pPc) - : this(pPc, String.Empty) - { - } - public PerfCounterControl(PerformanceCounter pPc, string pName) - { - perfCounter = pPc; - lastFetch = 0; - name = pName; - } - } - - PerfCounterControl processorPercentPerfCounter = null; - - #region ISharedRegionModule - // IRegionModuleBase.Name - public string Name { get { return "Server Stats"; } } - // IRegionModuleBase.ReplaceableInterface - public Type ReplaceableInterface { get { return null; } } - // IRegionModuleBase.Initialize - public void Initialise(IConfigSource source) - { - IConfig cfg = source.Configs["Monitoring"]; - - if (cfg != null) - Enabled = cfg.GetBoolean("ServerStatsEnabled", true); - - if (Enabled) - { - NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet"); - } - } - // IRegionModuleBase.Close - public void Close() - { - if (RegisteredStats.Count > 0) - { - foreach (Stat stat in RegisteredStats.Values) - { - StatsManager.DeregisterStat(stat); - stat.Dispose(); - } - RegisteredStats.Clear(); - } - } - // IRegionModuleBase.AddRegion - public void AddRegion(Scene scene) - { - } - // IRegionModuleBase.RemoveRegion - public void RemoveRegion(Scene scene) - { - } - // IRegionModuleBase.RegionLoaded - public void RegionLoaded(Scene scene) - { - } - // ISharedRegionModule.PostInitialize - public void PostInitialise() - { - if (RegisteredStats.Count == 0) - { - RegisterServerStats(); - } - } - #endregion ISharedRegionModule - - private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act) - { - string desc = pDesc; - if (desc == null) - desc = pName; - Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); - StatsManager.RegisterStat(stat); - RegisteredStats.Add(pName, stat); - } - - public void RegisterServerStats() - { - lastperformanceCounterSampleTime = Util.EnvironmentTickCount(); - PerformanceCounter tempPC; - Stat tempStat; - string tempName; - - try - { - tempName = "CPUPercent"; - tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total"); - processorPercentPerfCounter = new PerfCounterControl(tempPC); - // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy. - tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor, - StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); }, - StatVerbosity.Info); - StatsManager.RegisterStat(tempStat); - RegisteredStats.Add(tempName, tempStat); - - MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); - - MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; }); - - MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; }); - - MakeStat("Threads", null, "threads", ContainerProcessor, - (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; }); - } - catch (Exception e) - { - m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); - } - - try - { - List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); - - IEnumerable nics = NetworkInterface.GetAllNetworkInterfaces(); - foreach (NetworkInterface nic in nics) - { - if (nic.OperationalStatus != OperationalStatus.Up) - continue; - - string nicInterfaceType = nic.NetworkInterfaceType.ToString(); - if (!okInterfaceTypes.Contains(nicInterfaceType)) - { - m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.", - LogHeader, nic.Name, nicInterfaceType); - m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}", - LogHeader, NetworkInterfaceTypes); - continue; - } - - if (nic.Supports(NetworkInterfaceComponent.IPv4)) - { - IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics(); - if (nicStats != null) - { - MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork, - (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); }); - MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork, - (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); }); - MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork, - (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); }); - } - } - // TODO: add IPv6 (it may actually happen someday) - } - } - catch (Exception e) - { - m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e); - } - - MakeStat("ProcessMemory", null, "MB", ContainerMemory, - (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); - MakeStat("ObjectMemory", null, "MB", ContainerMemory, - (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); - MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, - (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); - MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, - (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); - } - - // Notes on performance counters: - // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx - // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c - // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters - private delegate double PerfCounterNextValue(); - private void GetNextValue(Stat stat, PerfCounterControl perfControl) - { - GetNextValue(stat, perfControl, 1.0); - } - private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor) - { - if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval) - { - if (perfControl != null && perfControl.perfCounter != null) - { - try - { - // Kludge for factor to run double duty. If -1, subtract the value from one - if (factor == -1) - stat.Value = 1 - perfControl.perfCounter.NextValue(); - else - stat.Value = perfControl.perfCounter.NextValue() / factor; - } - catch (Exception e) - { - m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e); - } - perfControl.lastFetch = Util.EnvironmentTickCount(); - } - } - } - - // Lookup the nic that goes with this stat and set the value by using a fetch action. - // Not sure about closure with delegates inside delegates. - private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat); - private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor) - { - // Get the one nic that has the name of this stat - IEnumerable nics = NetworkInterface.GetAllNetworkInterfaces().Where( - (network) => network.Name == stat.Description); - try - { - foreach (NetworkInterface nic in nics) - { - IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics(); - if (intrStats != null) - { - double newVal = Math.Round(getter(intrStats) / factor, 3); - stat.Value = newVal; - } - break; - } - } - catch - { - // There are times interfaces go away so we just won't update the stat for this - m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description); - } - } -} - -public class ServerStatsAggregator : Stat -{ - public ServerStatsAggregator( - string shortName, - string name, - string description, - string unitName, - string category, - string container - ) - : base( - shortName, - name, - description, - unitName, - category, - container, - StatType.Push, - MeasuresOfInterest.None, - null, - StatVerbosity.Info) - { - } - public override string ToConsoleString() - { - StringBuilder sb = new StringBuilder(); - - return sb.ToString(); - } - - public override OSDMap ToOSDMap() - { - OSDMap ret = new OSDMap(); - - return ret; - } -} - -} diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index b13c87d000..8243900da5 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -190,16 +190,7 @@ namespace OpenSim.Server.Base } RegisterCommonCommands(); - - // Register the quit command - // - MainConsole.Instance.Commands.AddCommand("General", false, "quit", - "quit", - "Quit the application", HandleQuit); - - MainConsole.Instance.Commands.AddCommand("General", false, "shutdown", - "shutdown", - "Quit the application", HandleQuit); + RegisterCommonComponents(Config); // Allow derived classes to perform initialization that // needs to be done after the console has opened @@ -231,11 +222,12 @@ namespace OpenSim.Server.Base return 0; } - protected virtual void HandleQuit(string module, string[] args) + protected override void ShutdownSpecific() { m_Running = false; m_log.Info("[CONSOLE] Quitting"); + base.ShutdownSpecific(); } protected virtual void ReadConfig() @@ -246,4 +238,4 @@ namespace OpenSim.Server.Base { } } -} +} \ No newline at end of file diff --git a/prebuild.xml b/prebuild.xml index 88db6ede06..29c54c15df 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -157,6 +157,7 @@ + From 2c9bb0f9738534732e147c090fac43f3373af1bb Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 22:55:25 +0100 Subject: [PATCH 02/29] Add server stats for available builtin threadpool and iocp workers --- .../Framework/Monitoring/ServerStatsCollector.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 80d0a89fe4..fe74ef7652 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -157,6 +157,22 @@ namespace OpenSim.Framework.Monitoring m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); } + MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerProcessor, + s => + { + int workerThreads, iocpThreads; + ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); + s.Value = workerThreads; + }); + + MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerProcessor, + s => + { + int workerThreads, iocpThreads; + ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); + s.Value = iocpThreads; + }); + try { List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); From 865d46ae1e0477f957ad674ed2a1a11ef85d885a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 22:56:39 +0100 Subject: [PATCH 03/29] Drop server level stats to debug instead of info. This was the original intention with these stats, as I didn't believe they would be useful to ordinary users if everything is working as it should. Please amend if this is an issue. Just for now, levels actually have no impact on what is displayed via the "show stats" command. --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index fe74ef7652..c601c17114 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -116,7 +116,7 @@ namespace OpenSim.Framework.Monitoring string desc = pDesc; if (desc == null) desc = pName; - Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info); + Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Debug); StatsManager.RegisterStat(stat); RegisteredStats.Add(pName, stat); } From b9dac1f8df3f58cc7b85938f7bbff1e79de371be Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 23:17:55 +0100 Subject: [PATCH 04/29] Fix test failure in BasicCircuitTests from previous commit 0d2fd0d9 --- .../Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 556df305ab..b47ff54efe 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -33,6 +33,7 @@ using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Packets; using OpenSim.Framework; +using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; using OpenSim.Tests.Common; using OpenSim.Tests.Common.Mock; @@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests { base.SetUp(); m_scene = new SceneHelpers().SetupScene(); + StatsManager.SimExtraStats = new SimExtraStatsCollector(); } /// @@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); Assert.That(spAfterAckTimeout, Is.Null); - -// TestHelpers.DisableLogging(); } // /// From 713a14a6b56188eb0ccf71e2ff78835bd258417e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 23:23:56 +0100 Subject: [PATCH 05/29] minor: remove mono compiler warnings in WebFetchInvDescModule --- .../Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index 2024018aa3..0e3cd6b283 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -34,6 +34,7 @@ using log4net; using Nini.Config; using Mono.Addins; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; @@ -44,8 +45,6 @@ using OpenSim.Framework.Capabilities; using OpenSim.Services.Interfaces; using Caps = OpenSim.Framework.Capabilities.Caps; using OpenSim.Capabilities.Handlers; -using OpenMetaverse; -using OpenMetaverse.StructuredData; namespace OpenSim.Region.ClientStack.Linden { @@ -64,7 +63,7 @@ namespace OpenSim.Region.ClientStack.Linden public List folders; } - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; From c0a00cd7fd887190db61b1c69fb0e8f104a7e438 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 23:34:09 +0100 Subject: [PATCH 06/29] Fix bug where no threadpool data would be displayed in the "show threads" command if threadpool type was QueueUserWorkItem (Unsafe worked as expected) --- OpenSim/Framework/Util.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 7f0850fba0..5e5eb7e33a 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1880,7 +1880,7 @@ namespace OpenSim.Framework } } else if ( - FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem + FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) { threadPoolUsed = "BuiltInThreadPool"; From b7c9dee033bad425870540c08832058ac86d4ab5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Mon, 17 Jun 2013 23:57:10 +0100 Subject: [PATCH 07/29] refactor: Move existing code to generate report information on the threadpool to the ServerBase rather than being in Util --- OpenSim/Framework/Servers/ServerBase.cs | 63 +++++++++++++- OpenSim/Framework/Util.cs | 104 ++++++++++-------------- 2 files changed, 103 insertions(+), 64 deletions(-) diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 5358444133..029b848946 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -667,7 +667,68 @@ namespace OpenSim.Framework.Servers sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); sb.Append("Main threadpool (excluding script engine pools)\n"); - sb.Append(Util.GetThreadPoolReport()); + sb.Append(GetThreadPoolReport()); + + return sb.ToString(); + } + + /// + /// Get a thread pool report. + /// + /// + public static string GetThreadPoolReport() + { + string threadPoolUsed = null; + int maxThreads = 0; + int minThreads = 0; + int allocatedThreads = 0; + int inUseThreads = 0; + int waitingCallbacks = 0; + int completionPortThreads = 0; + + StringBuilder sb = new StringBuilder(); + if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) + { + STPInfo stpi = Util.GetSmartThreadPoolInfo(); + + // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. + if (stpi != null) + { + threadPoolUsed = "SmartThreadPool"; + maxThreads = stpi.MaxThreads; + minThreads = stpi.MinThreads; + inUseThreads = stpi.InUseThreads; + allocatedThreads = stpi.ActiveThreads; + waitingCallbacks = stpi.WaitingCallbacks; + } + } + else if ( + Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem + || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) + { + threadPoolUsed = "BuiltInThreadPool"; + ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); + ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); + int availableThreads; + ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); + inUseThreads = maxThreads - availableThreads; + allocatedThreads = -1; + waitingCallbacks = -1; + } + + if (threadPoolUsed != null) + { + sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); + sb.AppendFormat("Max threads : {0}\n", maxThreads); + sb.AppendFormat("Min threads : {0}\n", minThreads); + sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); + sb.AppendFormat("In use threads : {0}\n", inUseThreads); + sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); + } + else + { + sb.AppendFormat("Thread pool not used\n"); + } return sb.ToString(); } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 5e5eb7e33a..ba6cc75e12 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -88,10 +88,31 @@ namespace OpenSim.Framework Thread, } + /// + /// Class for delivering SmartThreadPool statistical information + /// + /// + /// We do it this way so that we do not directly expose STP. + /// + public class STPInfo + { + public string Name { get; set; } + public STPStartInfo STPStartInfo { get; set; } + public WIGStartInfo WIGStartInfo { get; set; } + public bool IsIdle { get; set; } + public bool IsShuttingDown { get; set; } + public int MaxThreads { get; set; } + public int MinThreads { get; set; } + public int InUseThreads { get; set; } + public int ActiveThreads { get; set; } + public int WaitingCallbacks { get; set; } + public int MaxConcurrentWorkItems { get; set; } + } + /// /// Miscellaneous utility functions /// - public class Util + public static class Util { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -1852,74 +1873,31 @@ namespace OpenSim.Framework } /// - /// Get a thread pool report. + /// Get information about the current state of the smart thread pool. /// - /// - public static string GetThreadPoolReport() + /// + /// null if this isn't the pool being used for non-scriptengine threads. + /// + public static STPInfo GetSmartThreadPoolInfo() { - string threadPoolUsed = null; - int maxThreads = 0; - int minThreads = 0; - int allocatedThreads = 0; - int inUseThreads = 0; - int waitingCallbacks = 0; - int completionPortThreads = 0; + if (m_ThreadPool == null) + return null; - StringBuilder sb = new StringBuilder(); - if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) - { - // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. - if (m_ThreadPool != null) - { - threadPoolUsed = "SmartThreadPool"; - maxThreads = m_ThreadPool.MaxThreads; - minThreads = m_ThreadPool.MinThreads; - inUseThreads = m_ThreadPool.InUseThreads; - allocatedThreads = m_ThreadPool.ActiveThreads; - waitingCallbacks = m_ThreadPool.WaitingCallbacks; - } - } - else if ( - FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem - || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) - { - threadPoolUsed = "BuiltInThreadPool"; - ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); - ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); - int availableThreads; - ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); - inUseThreads = maxThreads - availableThreads; - allocatedThreads = -1; - waitingCallbacks = -1; - } + STPInfo stpi = new STPInfo(); + stpi.Name = m_ThreadPool.Name; + stpi.STPStartInfo = m_ThreadPool.STPStartInfo; + stpi.IsIdle = m_ThreadPool.IsIdle; + stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown; + stpi.MaxThreads = m_ThreadPool.MaxThreads; + stpi.MinThreads = m_ThreadPool.MinThreads; + stpi.InUseThreads = m_ThreadPool.InUseThreads; + stpi.ActiveThreads = m_ThreadPool.ActiveThreads; + stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks; + stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency; - if (threadPoolUsed != null) - { - sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); - sb.AppendFormat("Max threads : {0}\n", maxThreads); - sb.AppendFormat("Min threads : {0}\n", minThreads); - sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); - sb.AppendFormat("In use threads : {0}\n", inUseThreads); - sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); - } - else - { - sb.AppendFormat("Thread pool not used\n"); - } - - return sb.ToString(); + return stpi; } -// private static object SmartThreadPoolCallback(object o) -// { -// object[] array = (object[])o; -// WaitCallback callback = (WaitCallback)array[0]; -// object obj = array[1]; -// -// callback(obj); -// return null; -// } - #endregion FireAndForget Threading Pattern /// From a1e32b843745581f7296359427a59e988814106b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 18 Jun 2013 00:10:21 +0100 Subject: [PATCH 08/29] If SmartThreadPool is active, display statistical information about it in "show stats server" Also puts these and previous builtin threadpool stats in the "threadpool" stat container rather than "processor" --- .../Framework/Monitoring/ServerStatsCollector.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index c601c17114..0ab4b93fd8 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -49,6 +49,7 @@ namespace OpenSim.Framework.Monitoring public readonly string CategoryServer = "server"; + public readonly string ContainerThreadpool = "threadpool"; public readonly string ContainerProcessor = "processor"; public readonly string ContainerMemory = "memory"; public readonly string ContainerNetwork = "network"; @@ -157,7 +158,7 @@ namespace OpenSim.Framework.Monitoring m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); } - MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerProcessor, + MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -165,7 +166,7 @@ namespace OpenSim.Framework.Monitoring s.Value = workerThreads; }); - MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerProcessor, + MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -173,6 +174,16 @@ namespace OpenSim.Framework.Monitoring s.Value = iocpThreads; }); + if (Util.FireAndForgetMethod != null && Util.GetSmartThreadPoolInfo() != null) + { + MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads); + MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads); + MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems); + MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads); + MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads); + MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks); + } + try { List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); From 0767523834b51772cbdf61002e9c7cbae334ee72 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 18 Jun 2013 21:21:59 +0100 Subject: [PATCH 09/29] Fix other places when saving scripts or notecards in prim inventories where messages should be transient without an OK button --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6c79b13e2e..1e4d558de5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -326,7 +326,7 @@ namespace OpenSim.Region.Framework.Scenes // Update item with new asset item.AssetID = asset.FullID; if (group.UpdateInventoryItem(item)) - remoteClient.SendAgentAlertMessage("Script saved", false); + remoteClient.SendAlertMessage("Script saved"); part.SendPropertiesToClient(remoteClient); @@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - remoteClient.SendAgentAlertMessage("Script saved", false); + remoteClient.SendAlertMessage("Script saved"); } // Tell anyone managing scripts that a script has been reloaded/changed @@ -1616,11 +1616,11 @@ namespace OpenSim.Region.Framework.Scenes remoteClient, part, transactionID, currentItem); if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) - remoteClient.SendAgentAlertMessage("Notecard saved", false); + remoteClient.SendAlertMessage("Notecard saved"); else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) - remoteClient.SendAgentAlertMessage("Script saved", false); + remoteClient.SendAlertMessage("Script saved"); else - remoteClient.SendAgentAlertMessage("Item saved", false); + remoteClient.SendAlertMessage("Item saved"); } // Base ALWAYS has move From 768e8e363bfb0aedc6edc2e6c1dbf35e1e66b531 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 18 Jun 2013 22:49:49 +0100 Subject: [PATCH 10/29] Fix issue where stat samples were accidentally static, so that any additional stat with sampling would produce wrong results --- OpenSim/Framework/Monitoring/Stats/Stat.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index 2e7665f5a1..69ac0a5a1f 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs @@ -95,7 +95,7 @@ namespace OpenSim.Framework.Monitoring /// /// Will be null if no measures of interest require samples. /// - private static Queue m_samples; + private Queue m_samples; /// /// Maximum number of statistical samples. From 9501a583cbc8fd819d2b13db4f9ad76958520ce7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 18 Jun 2013 23:07:18 +0100 Subject: [PATCH 11/29] Make number of inbound http requests handled available as a httpserver..IncomingHTTPRequestsProcessed stat --- OpenSim/Framework/Monitoring/Stats/Stat.cs | 7 ++++- .../Servers/HttpServer/BaseHttpServer.cs | 30 +++++++++++++++---- OpenSim/Server/Base/ServicesServerBase.cs | 4 +++ prebuild.xml | 1 + 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index 69ac0a5a1f..ca71911abf 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs @@ -27,8 +27,9 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Text; - +using log4net; using OpenMetaverse.StructuredData; namespace OpenSim.Framework.Monitoring @@ -38,6 +39,8 @@ namespace OpenSim.Framework.Monitoring /// public class Stat : IDisposable { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// /// Category of this stat (e.g. cache, scene, etc). /// @@ -204,6 +207,8 @@ namespace OpenSim.Framework.Monitoring if (m_samples.Count >= m_maxSamples) m_samples.Dequeue(); +// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name); + m_samples.Enqueue(newValue); } } diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 96a030bba0..66874417a1 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); - /// /// This is a pending websocket request before it got an sucessful upgrade response. /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to @@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer /// public int RequestNumber { get; private set; } + /// + /// Statistic for holding number of requests processed. + /// + private Stat m_requestsProcessedStat; + private volatile int NotSocketErrors = 0; public volatile bool HTTPDRunning = false; @@ -436,9 +440,8 @@ namespace OpenSim.Framework.Servers.HttpServer } } - public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) + private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) { - OSHttpRequest req = new OSHttpRequest(context, request); WebSocketRequestDelegate dWebSocketRequestDelegate = null; lock (m_WebSocketHandlers) @@ -454,8 +457,7 @@ namespace OpenSim.Framework.Servers.HttpServer OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); resp.ReuseContext = true; - HandleRequest(req, resp); - + HandleRequest(req, resp); // !!!HACK ALERT!!! // There seems to be a bug in the underlying http code that makes subsequent requests @@ -1824,6 +1826,21 @@ namespace OpenSim.Framework.Servers.HttpServer // useful without inbound HTTP. throw e; } + + m_requestsProcessedStat + = new Stat( + "IncomingHTTPRequestsProcessed", + "Number of inbound HTTP requests processed", + "", + "requests", + "httpserver", + Port.ToString(), + StatType.Pull, + MeasuresOfInterest.AverageChangeOverTime, + stat => stat.Value = RequestNumber, + StatVerbosity.Debug); + + StatsManager.RegisterStat(m_requestsProcessedStat); } public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) @@ -1854,6 +1871,9 @@ namespace OpenSim.Framework.Servers.HttpServer public void Stop() { HTTPDRunning = false; + + StatsManager.DeregisterStat(m_requestsProcessedStat); + try { m_PollServiceManager.Stop(); diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 8243900da5..667cef80c5 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -34,6 +34,7 @@ using System.Text; using System.Xml; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers; using log4net; using log4net.Config; @@ -205,6 +206,9 @@ namespace OpenSim.Server.Base public virtual int Run() { + Watchdog.Enabled = true; + MemoryWatchdog.Enabled = true; + while (m_Running) { try diff --git a/prebuild.xml b/prebuild.xml index 29c54c15df..4cf3b8358b 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -745,6 +745,7 @@ + From dda44e31e3f649875a7fc7438c4a6880c56dbb31 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 18 Jun 2013 23:10:50 +0100 Subject: [PATCH 12/29] minor: tidy up spacing if display a unit for additional stat information --- OpenSim/Framework/Monitoring/Stats/Stat.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index ca71911abf..eb5599f3ef 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs @@ -258,7 +258,7 @@ namespace OpenSim.Framework.Monitoring int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; - sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); + sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); } } } From 3fe5e9057f4f45e39c3056742855f580a51c921f Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Mon, 10 Jun 2013 19:59:08 -0400 Subject: [PATCH 13/29] Prevent an exception if no offline messages were retrieved. --- .../CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 7d763faf10..7f3d0a2584 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -182,7 +182,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); if (msglist == null) + { m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list."); + return; + } foreach (GridInstantMessage im in msglist) { From 1a72f62d7be483cf3a0612528c2b7d7880e0ce0c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 18 Jun 2013 23:52:15 +0100 Subject: [PATCH 14/29] minor: remove mono compiler warning in OfflineIMService --- OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs index 6ba022cd93..6731923c3b 100644 --- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs +++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs @@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM { public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int MAX_IM = 25; private XmlSerializer m_serializer; From 8a86e29579d654be979bac00c2620d49eb7fb457 Mon Sep 17 00:00:00 2001 From: Talun Date: Tue, 18 Jun 2013 15:09:55 +0100 Subject: [PATCH 15/29] Mantis 6608: Math error in parcel dimensions/borders seen with land show command This patch changes the land show console command to return numbers in the range 4 to 256 for the "to" coordinates instead of 0 to 252 Also trailing spaces removed from some lines. --- .../CoreModules/World/Land/LandObject.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 84064427e0..e55c9ed87f 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -81,14 +81,14 @@ namespace OpenSim.Region.CoreModules.World.Land set { m_landData = value; } } - + public IPrimCounts PrimCounts { get; set; } public UUID RegionUUID { get { return m_scene.RegionInfo.RegionID; } } - + public Vector3 StartPoint { get @@ -101,11 +101,11 @@ namespace OpenSim.Region.CoreModules.World.Land return new Vector3(x * 4, y * 4, 0); } } - + return new Vector3(-1, -1, -1); } - } - + } + public Vector3 EndPoint { get @@ -116,15 +116,15 @@ namespace OpenSim.Region.CoreModules.World.Land { if (LandBitmap[x, y]) { - return new Vector3(x * 4, y * 4, 0); - } + return new Vector3(x * 4 + 4, y * 4 + 4, 0); + } } - } - + } + return new Vector3(-1, -1, -1); } } - + #region Constructors public LandObject(UUID owner_id, bool is_group_owned, Scene scene) From 84af1cab9ba991b2356f1025cab7f58433e2ec19 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 19 Jun 2013 20:48:12 +0100 Subject: [PATCH 16/29] Display existing statistic of how many http requests a server is making as server.network.HTTPRequestsMade in "show stats all" --- .../Monitoring/ServerStatsCollector.cs | 21 +++++++++++++++---- OpenSim/Framework/Monitoring/Stats/Stat.cs | 5 +++++ .../Servers/HttpServer/BaseHttpServer.cs | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 0ab4b93fd8..07ca14bff8 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -113,11 +113,16 @@ namespace OpenSim.Framework.Monitoring } private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act) + { + MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None); + } + + private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action act, MeasuresOfInterest moi) { string desc = pDesc; if (desc == null) desc = pName; - Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Debug); + Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug); StatsManager.RegisterStat(stat); RegisteredStats.Add(pName, stat); } @@ -141,7 +146,7 @@ namespace OpenSim.Framework.Monitoring StatsManager.RegisterStat(tempStat); RegisteredStats.Add(tempName, tempStat); - MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, + MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor, (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; }); MakeStat("UserProcessorTime", null, "sec", ContainerProcessor, @@ -158,7 +163,7 @@ namespace OpenSim.Framework.Monitoring m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e); } - MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, + MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -166,7 +171,7 @@ namespace OpenSim.Framework.Monitoring s.Value = workerThreads; }); - MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, + MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool, s => { int workerThreads, iocpThreads; @@ -184,6 +189,14 @@ namespace OpenSim.Framework.Monitoring MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks); } + MakeStat( + "HTTPRequestsMade", + "Number of outbound HTTP requests made", + "requests", + ContainerNetwork, + s => s.Value = WebUtil.RequestNumber, + MeasuresOfInterest.AverageChangeOverTime); + try { List okInterfaceTypes = new List(NetworkInterfaceTypes.Split(',')); diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index eb5599f3ef..85d1a782ab 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using log4net; @@ -247,6 +248,10 @@ namespace OpenSim.Framework.Monitoring lock (m_samples) { +// m_log.DebugFormat( +// "[STAT]: Samples for {0} are {1}", +// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray())); + foreach (double s in m_samples) { if (lastSample != null) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 66874417a1..40b8c5c1ed 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -1829,7 +1829,7 @@ namespace OpenSim.Framework.Servers.HttpServer m_requestsProcessedStat = new Stat( - "IncomingHTTPRequestsProcessed", + "HTTPRequestsServed", "Number of inbound HTTP requests processed", "", "requests", From 086fd70a5fdfd9b3a0e56201596f6d6bb20f391e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:00:39 +0100 Subject: [PATCH 17/29] Make it possible to specify display of stats in a particular 'container' by separating category and container with a period. e.g. "show stats server.network" I failed to realize this had already been implemented without the period in the show stats command (as the command help had not been updated). However, I would prefer the . approach as it will allow specifying multiple stats, easier wildcarding, etc. This commit also prevents any stat from having a period in its short name. --- OpenSim/Framework/Monitoring/Stats/Stat.cs | 8 ++++++++ OpenSim/Framework/Monitoring/StatsManager.cs | 12 +++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs index 85d1a782ab..c57ee0c3e8 100644 --- a/OpenSim/Framework/Monitoring/Stats/Stat.cs +++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs @@ -42,6 +42,8 @@ namespace OpenSim.Framework.Monitoring { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public static readonly char[] DisallowedShortNameCharacters = { '.' }; + /// /// Category of this stat (e.g. cache, scene, etc). /// @@ -166,6 +168,12 @@ namespace OpenSim.Framework.Monitoring throw new Exception( string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); + foreach (char c in DisallowedShortNameCharacters) + { + if (shortName.IndexOf(c) != -1) + throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c)); + } + ShortName = shortName; Name = name; Description = description; diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 3aee984cf8..af9f5ba182 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -68,12 +68,13 @@ namespace OpenSim.Framework.Monitoring "General", false, "show stats", - "show stats [list|all|]", + "show stats [list|all|[.]", "Show statistical information for this server", "If no final argument is specified then legacy statistics information is currently shown.\n" + "If list is specified then statistic categories are shown.\n" + "If all is specified then all registered statistics are shown.\n" + "If a category name is specified then only statistics from that category are shown.\n" + + "If a category container is also specified then only statistics from that category in that container are shown.\n" + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", HandleShowStatsCommand); } @@ -84,8 +85,11 @@ namespace OpenSim.Framework.Monitoring if (cmd.Length > 2) { - var categoryName = cmd[2]; - var containerName = cmd.Length > 3 ? cmd[3] : String.Empty; + string name = cmd[2]; + string[] components = name.Split('.'); + + string categoryName = components[0]; + string containerName = components.Length > 1 ? components[1] : null; if (categoryName == AllSubCommand) { @@ -107,7 +111,9 @@ namespace OpenSim.Framework.Monitoring else { if (String.IsNullOrEmpty(containerName)) + { OutputCategoryStatsToConsole(con, category); + } else { SortedDictionary container; From 3370e19205352a4ba75e384f8719836a0da0b1df Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:17:20 +0100 Subject: [PATCH 18/29] minor: fix mono compiler warning in FetchInventory2Handler --- .../Handlers/FetchInventory2/FetchInventory2Handler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs index c0ca1e1896..2c91328e56 100644 --- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs +++ b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs @@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers { public class FetchInventory2Handler { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IInventoryService m_inventoryService; @@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers return llsdItem; } } -} +} \ No newline at end of file From d97333255d45da686bb71d85ef492c5631c4dc31 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:20:04 +0100 Subject: [PATCH 19/29] Fix minor bug where the check whether to display SmartThreadPool stats was accidentally != null rather than == FireAndForgetMethod.SmartThreadPool Due to another check this had no practical effect --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 07ca14bff8..5d1c270ad6 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -179,7 +179,7 @@ namespace OpenSim.Framework.Monitoring s.Value = iocpThreads; }); - if (Util.FireAndForgetMethod != null && Util.GetSmartThreadPoolInfo() != null) + if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null) { MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads); MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads); From 5b1a9f84fdf4f9938180b403dd002b44e25c6efb Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:32:12 +0100 Subject: [PATCH 20/29] minor: Change "memory churn" terminology in statistics to "heap allocation rate" since this is more generally meaningful --- OpenSim/Framework/Monitoring/BaseStatsCollector.cs | 12 ++++++------ OpenSim/Framework/Monitoring/MemoryWatchdog.cs | 8 ++++---- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs index be1d02bd10..20495f6e95 100644 --- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -45,16 +45,16 @@ namespace OpenSim.Framework.Monitoring sb.Append(Environment.NewLine); sb.AppendFormat( - "Allocated to OpenSim objects: {0} MB\n", + "Heap allocated to OpenSim : {0} MB\n", Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); sb.AppendFormat( - "OpenSim last object memory churn : {0} MB/s\n", - Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); + "Last heap allocation rate : {0} MB/s\n", + Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); sb.AppendFormat( - "OpenSim average object memory churn : {0} MB/s\n", - Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); + "Average heap allocation rate: {0} MB/s\n", + Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3)); sb.AppendFormat( "Process memory : {0} MB\n", diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs index c6010cd092..c47462225b 100644 --- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs @@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring private static bool m_enabled; /// - /// Last memory churn in bytes per millisecond. + /// Average heap allocation rate in bytes per millisecond. /// - public static double AverageMemoryChurn + public static double AverageHeapAllocationRate { get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } } /// - /// Average memory churn in bytes per millisecond. + /// Last heap allocation in bytes /// - public static double LastMemoryChurn + public static double LastHeapAllocationRate { get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } } diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 5d1c270ad6..b22da1d6ba 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -242,10 +242,10 @@ namespace OpenSim.Framework.Monitoring (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); MakeStat("ObjectMemory", null, "MB", ContainerMemory, (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); - MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory, - (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); }); - MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory, - (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); }); + MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); + MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, + (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); } // Notes on performance counters: From 05790ba1cf7dd07f9f11ce248262041eb300ea49 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:45:56 +0100 Subject: [PATCH 21/29] Allow more than one stat category to be specified in "show stats" e.g. "show stats httpserver.9000 server.network" --- OpenSim/Framework/Monitoring/StatsManager.cs | 64 +++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index af9f5ba182..12d3a75d50 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace OpenSim.Framework.Monitoring @@ -68,13 +69,14 @@ namespace OpenSim.Framework.Monitoring "General", false, "show stats", - "show stats [list|all|[.]", + "show stats [list|all|([.])+", "Show statistical information for this server", "If no final argument is specified then legacy statistics information is currently shown.\n" - + "If list is specified then statistic categories are shown.\n" - + "If all is specified then all registered statistics are shown.\n" - + "If a category name is specified then only statistics from that category are shown.\n" - + "If a category container is also specified then only statistics from that category in that container are shown.\n" + + "'list' argument will show statistic categories.\n" + + "'all' will show all statistics.\n" + + "A name will show statistics from that category.\n" + + "A . name will show statistics from that category in that container.\n" + + "More than one name can be given separated by spaces.\n" + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", HandleShowStatsCommand); } @@ -85,45 +87,47 @@ namespace OpenSim.Framework.Monitoring if (cmd.Length > 2) { - string name = cmd[2]; - string[] components = name.Split('.'); + foreach (string name in cmd.Skip(2)) + { + string[] components = name.Split('.'); - string categoryName = components[0]; - string containerName = components.Length > 1 ? components[1] : null; + string categoryName = components[0]; + string containerName = components.Length > 1 ? components[1] : null; - if (categoryName == AllSubCommand) - { - OutputAllStatsToConsole(con); - } - else if (categoryName == ListSubCommand) - { - con.Output("Statistic categories available are:"); - foreach (string category in RegisteredStats.Keys) - con.OutputFormat(" {0}", category); - } - else - { - SortedDictionary> category; - if (!RegisteredStats.TryGetValue(categoryName, out category)) + if (categoryName == AllSubCommand) { - con.OutputFormat("No such category as {0}", categoryName); + OutputAllStatsToConsole(con); + } + else if (categoryName == ListSubCommand) + { + con.Output("Statistic categories available are:"); + foreach (string category in RegisteredStats.Keys) + con.OutputFormat(" {0}", category); } else { - if (String.IsNullOrEmpty(containerName)) + SortedDictionary> category; + if (!RegisteredStats.TryGetValue(categoryName, out category)) { - OutputCategoryStatsToConsole(con, category); + con.OutputFormat("No such category as {0}", categoryName); } else { - SortedDictionary container; - if (category.TryGetValue(containerName, out container)) + if (String.IsNullOrEmpty(containerName)) { - OutputContainerStatsToConsole(con, container); + OutputCategoryStatsToConsole(con, category); } else { - con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); + SortedDictionary container; + if (category.TryGetValue(containerName, out container)) + { + OutputContainerStatsToConsole(con, container); + } + else + { + con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); + } } } } From 085a87060a2ccb4910305b7c5f5374d1cc779d1a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:52:39 +0100 Subject: [PATCH 22/29] Change "ObjectMemory" stat to "HeapMemory" to align with other stat names. Also round this and ProcessMemory to three decimal places in common with other memory stats. I believe leaving out such minor info makes stats easier to read --- OpenSim/Framework/Monitoring/ServerStatsCollector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index b22da1d6ba..ac0f0bc7be 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -239,9 +239,9 @@ namespace OpenSim.Framework.Monitoring } MakeStat("ProcessMemory", null, "MB", ContainerMemory, - (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; }); - MakeStat("ObjectMemory", null, "MB", ContainerMemory, - (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; }); + (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); }); + MakeStat("HeapMemory", null, "MB", ContainerMemory, + (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); }); MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory, (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); }); MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory, From a33b6eed6d09661445a638efcbb354b0330f9093 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 20 Jun 2013 00:54:19 +0100 Subject: [PATCH 23/29] minor: remove mono compiler warnings in WebsocketServerHandler.cs --- .../HttpServer/WebsocketServerHandler.cs | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs index ee96b47c69..de89e2e638 100644 --- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs @@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer /// /// This is a regular HTTP Request... This may be removed in the future. /// - public event RegularHttpRequestDelegate OnRegularHttpRequest; +// public event RegularHttpRequestDelegate OnRegularHttpRequest; /// /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired @@ -304,15 +304,14 @@ namespace OpenSim.Framework.Servers.HttpServer if (d != null) d(this, new UpgradeCompletedEventArgs()); } - catch (IOException fail) + catch (IOException) { Close(string.Empty); } - catch (ObjectDisposedException fail) + catch (ObjectDisposedException) { Close(string.Empty); - } - + } } /// @@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer _socketState.Header = pheader; } - - if (_socketState.FrameComplete) { ProcessFrame(_socketState); @@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer _socketState.ExpectedBytes = 0; } - } } else @@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer _socketState.ReceivedBytes.Clear(); _socketState.ExpectedBytes = 0; // do some processing - } - + } } } if (offset > 0) @@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer { // We can't read the stream anymore... } - } - catch (IOException fail) + catch (IOException) { Close(string.Empty); } - catch (ObjectDisposedException fail) + catch (ObjectDisposedException) { Close(string.Empty); } From bbeff4b8ca34a4567f2215ed5e90637a00d8c81e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Thu, 20 Jun 2013 09:55:40 -0700 Subject: [PATCH 24/29] BulletSim: rework velocity updating when not colliding and not flying to prevent infinite jumps. Now jumps last only AvatarJumpFrames long (default 4) which is about as high as in SL. TODO: jumping should only depend on standing (collision with feet) rather than collision anywhere on the avatar. --- .../BulletSPlugin/BSActorAvatarMove.cs | 44 ++++++++++++++++--- .../Region/Physics/BulletSPlugin/BSParam.cs | 3 ++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs index ac8c30c9cd..928b350645 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs @@ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor // Set to true if we think we're going up stairs. // This state is remembered because collisions will turn on and off as we go up stairs. int m_walkingUpStairs; + // The amount the step up is applying. Used to smooth stair walking. float m_lastStepUp; + // Jumping happens over several frames. If use applies up force while colliding, start the + // jump and allow the jump to continue for this number of frames. + int m_jumpFrames = 0; + float m_jumpVelocity = 0f; + public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) : base(physicsScene, pObj, actorName) { @@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor if (m_controllingPrim.Friction != BSParam.AvatarFriction) { - // Probably starting up walking. Set friction to moving friction. + // Probably starting to walk. Set friction to moving friction. m_controllingPrim.Friction = BSParam.AvatarFriction; m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); } - // If falling, we keep the world's downward vector no matter what the other axis specify. - // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force). if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) { - if (m_controllingPrim.RawVelocity.Z < 0) + stepVelocity.Z = m_controllingPrim.RawVelocity.Z; + } + + + // Colliding and not flying with an upward force. The avatar must be trying to jump. + if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0) + { + // We allow the upward force to happen for this many frames. + m_jumpFrames = BSParam.AvatarJumpFrames; + m_jumpVelocity = stepVelocity.Z; + } + + // The case where the avatar is not colliding and is not flying is special. + // The avatar is either falling or jumping and the user can be applying force to the avatar + // (force in some direction or force up or down). + // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity. + // If the user is trying to apply upward force but we're not colliding, assume the avatar + // is trying to jump and don't apply the upward force if not touching the ground any more. + if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) + { + // If upward velocity is being applied, this must be a jump and only allow that to go on so long + if (m_jumpFrames > 0) + { + // Since not touching the ground, only apply upward force for so long. + m_jumpFrames--; + stepVelocity.Z = m_jumpVelocity; + } + else + { + // Since we're not affected by anything, whatever vertical motion the avatar has, continue that. stepVelocity.Z = m_controllingPrim.RawVelocity.Z; + } // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); } @@ -241,7 +275,7 @@ public class BSActorAvatarMove : BSActor m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); - // This test is done if moving forward, not flying and is colliding with something. + // Check for stairs climbing if colliding, not flying and moving forward if ( m_controllingPrim.IsColliding && !m_controllingPrim.Flying diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index aad1108cbc..6437b04896 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -134,6 +134,7 @@ public static class BSParam public static float AvatarHeightMidFudge { get; private set; } public static float AvatarHeightHighFudge { get; private set; } public static float AvatarContactProcessingThreshold { get; private set; } + public static int AvatarJumpFrames { get; private set; } public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } public static float AvatarStepHeight { get; private set; } public static float AvatarStepApproachFactor { get; private set; } @@ -567,6 +568,8 @@ public static class BSParam 0.1f ), new ParameterDefn("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 1.0f ), + new ParameterDefn("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.", + 4 ), new ParameterDefn("AvatarStepHeight", "Height of a step obstacle to consider step correction", 0.6f ) , new ParameterDefn("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", From a5de4f692bd0de5faccdcf32a923a72949bb3cca Mon Sep 17 00:00:00 2001 From: Vegaslon Date: Sat, 15 Jun 2013 17:23:43 -0400 Subject: [PATCH 25/29] BulletSim: Implementation of Linear Deflection, it is a partial help for the vehicle tuning diffrence between Opensim and Second life. Signed-off-by: Robert Adams --- .../Physics/BulletSPlugin/BSDynamics.cs | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 311cf4f220..51207f1da5 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_VhoverTimescale = Math.Max(pValue, 0.01f); break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); + m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f); break; case Vehicle.LINEAR_DEFLECTION_TIMESCALE: m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); @@ -1029,9 +1029,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); + //Compute Linear deflection. + Vector3 linearDeflectionFactorV = ComputeLinearDeflection(m_linearDeflectionEfficiency, currentVelV, pTimestep); + linearMotorCorrectionV += linearDeflectionFactorV; + // Friction reduces vehicle motion - Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); - linearMotorCorrectionV -= (currentVelV * frictionFactorW); + Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); + linearMotorCorrectionV -= (currentVelV * frictionFactorV); // Motor is vehicle coordinates. Rotate it to world coordinates Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; @@ -1048,9 +1052,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin - VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", + VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6},LinearDeflec={7}", ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, - linearMotorVelocityW, VehicleVelocity, frictionFactorW); + linearMotorVelocityW, VehicleVelocity, frictionFactorV, linearDeflectionFactorV); } public void ComputeLinearTerrainHeightCorrection(float pTimestep) @@ -1651,6 +1655,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin } return frictionFactor; } + //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis + //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity + private Vector3 ComputeLinearDeflection(float DeflectionEfficiency,Vector3 Velocity,float pTimestep) + { + Vector3 LinearDeflection = Vector3.Zero; + LinearDeflection.Y = SortedClampInRange(0, (Velocity.Y * DeflectionEfficiency) / m_linearDeflectionTimescale, Velocity.Y); + LinearDeflection.Z = SortedClampInRange(0, (Velocity.Z * DeflectionEfficiency) / m_linearDeflectionTimescale, Velocity.Z); + LinearDeflection.X += Math.Abs(LinearDeflection.Y); + LinearDeflection.X += Math.Abs(LinearDeflection.Z); + LinearDeflection *= pTimestep; + return LinearDeflection*=new Vector3(1,-1,-1); + + } + private float SortedClampInRange(float clampa, float val, float clampb) + { + if (clampa > clampb) + { + float temp = clampa; + clampa = clampb; + clampb = temp; + } + return ClampInRange(clampa, val, clampb); + + } private float ClampInRange(float low, float val, float high) { From 74539659f6f9be557dbd07fdefa1adae1c59ce87 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 21 Jun 2013 10:46:21 -0700 Subject: [PATCH 26/29] BulletSim: move new linear deflection code to own routine. Remove VehicleForwardVelocity changed storage since the value will be modified as movement is processed. --- .../Physics/BulletSPlugin/BSDynamics.cs | 66 ++++++++++--------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 51207f1da5..07e87d13eb 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin private Vector3 m_knownRotationalVelocity; private Vector3 m_knownRotationalForce; private Vector3 m_knownRotationalImpulse; - private Vector3 m_knownForwardVelocity; // vehicle relative forward speed private const int m_knownChangedPosition = 1 << 0; private const int m_knownChangedVelocity = 1 << 1; @@ -719,7 +718,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin private const int m_knownChangedRotationalImpulse = 1 << 7; private const int m_knownChangedTerrainHeight = 1 << 8; private const int m_knownChangedWaterLevel = 1 << 9; - private const int m_knownChangedForwardVelocity = 1 <<10; public void ForgetKnownVehicleProperties() { @@ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { get { - if ((m_knownHas & m_knownChangedForwardVelocity) == 0) - { - m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); - m_knownHas |= m_knownChangedForwardVelocity; - } - return m_knownForwardVelocity; + return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation)); } } private float VehicleForwardSpeed @@ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin { ComputeLinearVelocity(pTimestep); + ComputeLinearDeflection(pTimestep); + ComputeLinearTerrainHeightCorrection(pTimestep); ComputeLinearHover(pTimestep); @@ -1026,14 +1021,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // Step the motor from the current value. Get the correction needed this step. Vector3 origVelW = VehicleVelocity; // DEBUG - Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); + Vector3 currentVelV = VehicleForwardVelocity; Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); - //Compute Linear deflection. - Vector3 linearDeflectionFactorV = ComputeLinearDeflection(m_linearDeflectionEfficiency, currentVelV, pTimestep); - linearMotorCorrectionV += linearDeflectionFactorV; - - // Friction reduces vehicle motion + // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction. Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); linearMotorCorrectionV -= (currentVelV * frictionFactorV); @@ -1050,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Add this correction to the velocity to make it faster/slower. VehicleVelocity += linearMotorVelocityW; - - - VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6},LinearDeflec={7}", + VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, - linearMotorVelocityW, VehicleVelocity, frictionFactorV, linearDeflectionFactorV); + linearMotorVelocityW, VehicleVelocity, frictionFactorV); + } + + //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis + //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity + private void ComputeLinearDeflection(float pTimestep) + { + Vector3 linearDeflectionV = Vector3.Zero; + Vector3 velocityV = VehicleForwardVelocity; + + // Velocity in Y and Z dimensions is movement to the side or turning. + // Compute deflection factor from the to the side and rotational velocity + linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y); + linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z); + + // Velocity to the side and around is corrected and moved into the forward direction + linearDeflectionV.X += Math.Abs(linearDeflectionV.Y); + linearDeflectionV.X += Math.Abs(linearDeflectionV.Z); + + // Scale the deflection to the fractional simulation time + linearDeflectionV *= pTimestep; + + // Subtract the sideways and rotational velocity deflection factors while adding the correction forward + linearDeflectionV *= new Vector3(1,-1,-1); + + // Correciont is vehicle relative. Convert to world coordinates and add to the velocity + VehicleVelocity += linearDeflectionV * VehicleOrientation; + + VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}", + ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV); } public void ComputeLinearTerrainHeightCorrection(float pTimestep) @@ -1655,19 +1673,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } return frictionFactor; } - //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis - //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity - private Vector3 ComputeLinearDeflection(float DeflectionEfficiency,Vector3 Velocity,float pTimestep) - { - Vector3 LinearDeflection = Vector3.Zero; - LinearDeflection.Y = SortedClampInRange(0, (Velocity.Y * DeflectionEfficiency) / m_linearDeflectionTimescale, Velocity.Y); - LinearDeflection.Z = SortedClampInRange(0, (Velocity.Z * DeflectionEfficiency) / m_linearDeflectionTimescale, Velocity.Z); - LinearDeflection.X += Math.Abs(LinearDeflection.Y); - LinearDeflection.X += Math.Abs(LinearDeflection.Z); - LinearDeflection *= pTimestep; - return LinearDeflection*=new Vector3(1,-1,-1); - } private float SortedClampInRange(float clampa, float val, float clampb) { if (clampa > clampb) From 4778d67005c3364ee3f75bdd6640f03ff945d885 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 21 Jun 2013 20:52:46 -0700 Subject: [PATCH 27/29] Finally moved HG agent transfers to use agent fatpacks. --- .../EntityTransfer/HGEntityTransferModule.cs | 2 +- .../Handlers/Hypergrid/AgentHandlers.cs | 2 +- .../Handlers/Hypergrid/HomeAgentHandlers.cs | 208 +++++------------- .../Hypergrid/UserAgentServerConnector.cs | 2 +- .../Handlers/Simulation/AgentHandlers.cs | 76 ++++--- .../Hypergrid/GatekeeperServiceConnector.cs | 68 +----- .../Hypergrid/UserAgentServiceConnector.cs | 138 +++--------- .../Simulation/SimulationServiceConnector.cs | 29 ++- .../HypergridService/UserAgentService.cs | 12 +- .../Services/Interfaces/IHypergridServices.cs | 5 +- .../Services/LLLoginService/LLLoginService.cs | 2 +- 11 files changed, 175 insertions(+), 369 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 02ed1a08e3..0715324c49 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -273,7 +273,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); - bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); + bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason); logout = success; // flag for later logout from this grid; this is an HG TP if (success) diff --git a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs index cf1af15a37..adc2fbc081 100644 --- a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs @@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid m_Proxy = proxy; } - protected override bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) + protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) { return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason); } diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index 968c1e64c3..df875af14d 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -49,191 +49,87 @@ using log4net; namespace OpenSim.Server.Handlers.Hypergrid { - public class HomeAgentHandler + public class HomeAgentHandler : AgentPostHandler { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IUserAgentService m_UserAgentService; private string m_LoginServerIP; - private bool m_Proxy = false; - public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) + public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) : + base("/homeagent") { m_UserAgentService = userAgentService; m_LoginServerIP = loginServerIP; m_Proxy = proxy; } - public Hashtable Handler(Hashtable request) + protected override AgentDestinationData CreateAgentDestinationData() { -// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); -// -// m_log.Debug("---------------------------"); -// m_log.Debug(" >> uri=" + request["uri"]); -// m_log.Debug(" >> content-type=" + request["content-type"]); -// m_log.Debug(" >> http-method=" + request["http-method"]); -// m_log.Debug("---------------------------\n"); - - Hashtable responsedata = new Hashtable(); - responsedata["content_type"] = "text/html"; - responsedata["keepalive"] = false; - - - UUID agentID; - UUID regionID; - string action; - if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action)) - { - m_log.InfoFormat("[HOME AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]); - responsedata["int_response_code"] = 404; - responsedata["str_response_string"] = "false"; - - return responsedata; - } - - // Next, let's parse the verb - string method = (string)request["http-method"]; - if (method.Equals("POST")) - { - DoAgentPost(request, responsedata, agentID); - return responsedata; - } - else - { - m_log.InfoFormat("[HOME AGENT HANDLER]: method {0} not supported in agent message", method); - responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed; - responsedata["str_response_string"] = "Method not allowed"; - - return responsedata; - } - + return new ExtendedAgentDestinationData(); } - - protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) + protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request) { - OSDMap args = Utils.GetOSDMap((string)request["body"]); - if (args == null) - { - responsedata["int_response_code"] = HttpStatusCode.BadRequest; - responsedata["str_response_string"] = "Bad request"; - return; - } - - // retrieve the input arguments - int x = 0, y = 0; - UUID uuid = UUID.Zero; - string regionname = string.Empty; - string gatekeeper_host = string.Empty; - string gatekeeper_serveruri = string.Empty; - string destination_serveruri = string.Empty; - int gatekeeper_port = 0; - IPEndPoint client_ipaddress = null; - - if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null) - gatekeeper_host = args["gatekeeper_host"].AsString(); - if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null) - Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port); - if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null) - gatekeeper_serveruri = args["gatekeeper_serveruri"]; - if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null) - destination_serveruri = args["destination_serveruri"]; - - GridRegion gatekeeper = new GridRegion(); - gatekeeper.ServerURI = gatekeeper_serveruri; - gatekeeper.ExternalHostName = gatekeeper_host; - gatekeeper.HttpPort = (uint)gatekeeper_port; - gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); - - if (args.ContainsKey("destination_x") && args["destination_x"] != null) - Int32.TryParse(args["destination_x"].AsString(), out x); - else - m_log.WarnFormat(" -- request didn't have destination_x"); - if (args.ContainsKey("destination_y") && args["destination_y"] != null) - Int32.TryParse(args["destination_y"].AsString(), out y); - else - m_log.WarnFormat(" -- request didn't have destination_y"); - if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) - UUID.TryParse(args["destination_uuid"].AsString(), out uuid); - if (args.ContainsKey("destination_name") && args["destination_name"] != null) - regionname = args["destination_name"].ToString(); - - if (args.ContainsKey("client_ip") && args["client_ip"] != null) - { - string ip_str = args["client_ip"].ToString(); - try - { - string callerIP = GetCallerIP(request); - // Verify if this caller has authority to send the client IP - if (callerIP == m_LoginServerIP) - client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0); - else // leaving this for now, but this warning should be removed - m_log.WarnFormat("[HOME AGENT HANDLER]: Unauthorized machine {0} tried to set client ip to {1}", callerIP, ip_str); - } - catch - { - m_log.DebugFormat("[HOME AGENT HANDLER]: Exception parsing client ip address from {0}", ip_str); - } - } - - GridRegion destination = new GridRegion(); - destination.RegionID = uuid; - destination.RegionLocX = x; - destination.RegionLocY = y; - destination.RegionName = regionname; - destination.ServerURI = destination_serveruri; - - AgentCircuitData aCircuit = new AgentCircuitData(); + base.UnpackData(args, d, request); + ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d; try { - aCircuit.UnpackAgentCircuitData(args); + if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null) + data.host = args["gatekeeper_host"].AsString(); + if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null) + Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port); + if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null) + data.gatekeeperServerURI = args["gatekeeper_serveruri"]; + if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null) + data.destinationServerURI = args["destination_serveruri"]; + } - catch (Exception ex) + catch (InvalidCastException e) { - m_log.InfoFormat("[HOME AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message); - responsedata["int_response_code"] = HttpStatusCode.BadRequest; - responsedata["str_response_string"] = "Bad request"; - return; + m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData"); } - OSDMap resp = new OSDMap(2); - string reason = String.Empty; + string callerIP = GetCallerIP(request); + // Verify if this call came from the login server + if (callerIP == m_LoginServerIP) + data.fromLogin = true; - bool result = m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, client_ipaddress, out reason); - - resp["reason"] = OSD.FromString(reason); - resp["success"] = OSD.FromBoolean(result); - - // TODO: add reason if not String.Empty? - responsedata["int_response_code"] = HttpStatusCode.OK; - responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); } - private string GetCallerIP(Hashtable request) + protected override GridRegion ExtractGatekeeper(AgentDestinationData d) { - if (!m_Proxy) - return Util.GetCallerIP(request); - - // We're behind a proxy - Hashtable headers = (Hashtable)request["headers"]; - string xff = "X-Forwarded-For"; - if (headers.ContainsKey(xff.ToLower())) - xff = xff.ToLower(); - - if (!headers.ContainsKey(xff) || headers[xff] == null) + if (d is ExtendedAgentDestinationData) { - m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); - return Util.GetCallerIP(request); + ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d; + GridRegion gatekeeper = new GridRegion(); + gatekeeper.ServerURI = data.gatekeeperServerURI; + gatekeeper.ExternalHostName = data.host; + gatekeeper.HttpPort = (uint)data.port; + gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); + + return gatekeeper; } + else + m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type"); - m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); - - IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); - if (ep != null) - return ep.Address.ToString(); - - // Oops - return Util.GetCallerIP(request); + return null; } + + + protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) + { + return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason); + } + + } + + public class ExtendedAgentDestinationData : AgentDestinationData + { + public string host; + public int port; + public string gatekeeperServerURI; + public string destinationServerURI; + } } diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index b20f4672db..d9c1bd3d52 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("get_uui", GetUUI, false); server.AddXmlRPCHandler("get_uuid", GetUUID, false); - server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); + server.AddStreamHandler(new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy)); } public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index ae37ca7d23..334d3137ff 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -328,31 +328,16 @@ namespace OpenSim.Server.Handlers.Simulation return; } - // retrieve the input arguments - int x = 0, y = 0; - UUID uuid = UUID.Zero; - string regionname = string.Empty; - uint teleportFlags = 0; - if (args.ContainsKey("destination_x") && args["destination_x"] != null) - Int32.TryParse(args["destination_x"].AsString(), out x); - else - m_log.WarnFormat(" -- request didn't have destination_x"); - if (args.ContainsKey("destination_y") && args["destination_y"] != null) - Int32.TryParse(args["destination_y"].AsString(), out y); - else - m_log.WarnFormat(" -- request didn't have destination_y"); - if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) - UUID.TryParse(args["destination_uuid"].AsString(), out uuid); - if (args.ContainsKey("destination_name") && args["destination_name"] != null) - regionname = args["destination_name"].ToString(); - if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null) - teleportFlags = args["teleport_flags"].AsUInteger(); + AgentDestinationData data = CreateAgentDestinationData(); + UnpackData(args, data, request); GridRegion destination = new GridRegion(); - destination.RegionID = uuid; - destination.RegionLocX = x; - destination.RegionLocY = y; - destination.RegionName = regionname; + destination.RegionID = data.uuid; + destination.RegionLocX = data.x; + destination.RegionLocY = data.y; + destination.RegionName = data.name; + + GridRegion gatekeeper = ExtractGatekeeper(data); AgentCircuitData aCircuit = new AgentCircuitData(); try @@ -373,7 +358,7 @@ namespace OpenSim.Server.Handlers.Simulation // This is the meaning of POST agent //m_regionClient.AdjustUserInformation(aCircuit); //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); - bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); + bool result = CreateAgent(gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason); resp["reason"] = OSD.FromString(reason); resp["success"] = OSD.FromBoolean(result); @@ -385,7 +370,36 @@ namespace OpenSim.Server.Handlers.Simulation responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); } - private string GetCallerIP(Hashtable request) + protected virtual AgentDestinationData CreateAgentDestinationData() + { + return new AgentDestinationData(); + } + + protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request) + { + // retrieve the input arguments + if (args.ContainsKey("destination_x") && args["destination_x"] != null) + Int32.TryParse(args["destination_x"].AsString(), out data.x); + else + m_log.WarnFormat(" -- request didn't have destination_x"); + if (args.ContainsKey("destination_y") && args["destination_y"] != null) + Int32.TryParse(args["destination_y"].AsString(), out data.y); + else + m_log.WarnFormat(" -- request didn't have destination_y"); + if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) + UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid); + if (args.ContainsKey("destination_name") && args["destination_name"] != null) + data.name = args["destination_name"].ToString(); + if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null) + data.flags = args["teleport_flags"].AsUInteger(); + } + + protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data) + { + return null; + } + + protected string GetCallerIP(Hashtable request) { if (!m_Proxy) return Util.GetCallerIP(request); @@ -418,7 +432,7 @@ namespace OpenSim.Server.Handlers.Simulation } // subclasses can override this - protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) + protected virtual bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason) { return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); } @@ -593,4 +607,14 @@ namespace OpenSim.Server.Handlers.Simulation return m_SimulationService.UpdateAgent(destination, agent); } } + + public class AgentDestinationData + { + public int x; + public int y; + public string name; + public UUID uuid; + public uint flags; + public bool fromLogin; + } } diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 5bcff4883d..c9c6c31158 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid private IAssetService m_AssetService; - public GatekeeperServiceConnector() : base() + public GatekeeperServiceConnector() + : base() { } @@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid realHandle = Convert.ToUInt64((string)hash["handle"]); //m_log.Debug(">> HERE, realHandle: " + realHandle); } - if (hash["region_image"] != null) { + if (hash["region_image"] != null) + { imageURL = (string)hash["region_image"]; //m_log.Debug(">> HERE, imageURL: " + imageURL); } - if (hash["external_name"] != null) { + if (hash["external_name"] != null) + { externalName = (string)hash["external_name"]; //m_log.Debug(">> HERE, externalName: " + externalName); } @@ -178,7 +181,7 @@ namespace OpenSim.Services.Connectors.Hypergrid //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); imageData = OpenJPEG.EncodeFromImage(bitmap, true); } - + AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString()); // !!! for now @@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid region.RegionName = (string)hash["region_name"]; //m_log.Debug(">> HERE, region_name: " + region.RegionName); } - if (hash["hostname"] != null) { + if (hash["hostname"] != null) + { region.ExternalHostName = (string)hash["hostname"]; //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); } @@ -275,10 +279,10 @@ namespace OpenSim.Services.Connectors.Hypergrid region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); } - + if (hash["server_uri"] != null) { - region.ServerURI = (string) hash["server_uri"]; + region.ServerURI = (string)hash["server_uri"]; //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); } @@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid return null; } - - public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) - { - // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start"); - - myipaddress = String.Empty; - reason = String.Empty; - - if (destination == null) - { - m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null"); - return false; - } - - string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/"; - - try - { - OSDMap args = aCircuit.PackAgentCircuitData(); - - args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); - args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); - args["destination_name"] = OSD.FromString(destination.RegionName); - args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); - args["teleport_flags"] = OSD.FromString(flags.ToString()); - - OSDMap result = WebUtil.PostToService(uri, args, 80000); - if (result["Success"].AsBoolean()) - { - OSDMap unpacked = (OSDMap)result["_Result"]; - - if (unpacked != null) - { - reason = unpacked["reason"].AsString(); - myipaddress = unpacked["your_ip"].AsString(); - return unpacked["success"].AsBoolean(); - } - } - - reason = result["Message"] != null ? result["Message"].AsString() : "error"; - return false; - } - catch (Exception e) - { - m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString()); - reason = e.Message; - } - - return false; - } } } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 47d0cce7fd..d8a3184780 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -44,13 +44,14 @@ using Nini.Config; namespace OpenSim.Services.Connectors.Hypergrid { - public class UserAgentServiceConnector : IUserAgentService + public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - string m_ServerURL; + private string m_ServerURL; + private GridRegion m_Gatekeeper; public UserAgentServiceConnector(string url) : this(url, true) { @@ -104,9 +105,15 @@ namespace OpenSim.Services.Connectors.Hypergrid m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); } + protected override string AgentPath() + { + return "homeagent/"; + } - // The Login service calls this interface with a non-null [client] ipaddress - public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason) + // The Login service calls this interface with fromLogin=true + // Sims call it with fromLogin=false + // Either way, this is verified by the handler + public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason) { reason = String.Empty; @@ -117,119 +124,34 @@ namespace OpenSim.Services.Connectors.Hypergrid return false; } - string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/"; + GridRegion home = new GridRegion(); + home.ServerURI = m_ServerURL; + home.RegionID = destination.RegionID; + home.RegionLocX = destination.RegionLocX; + home.RegionLocY = destination.RegionLocY; - Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri); + m_Gatekeeper = gatekeeper; - HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); - AgentCreateRequest.Method = "POST"; - AgentCreateRequest.ContentType = "application/json"; - AgentCreateRequest.Timeout = 10000; - //AgentCreateRequest.KeepAlive = false; - //AgentCreateRequest.Headers.Add("Authorization", authKey); - - // Fill it in - OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress); - - string strBuffer = ""; - byte[] buffer = new byte[1]; - try - { - strBuffer = OSDParser.SerializeJsonString(args); - Encoding str = Util.UTF8; - buffer = str.GetBytes(strBuffer); - - } - catch (Exception e) - { - m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message); - // ignore. buffer will be empty, caller should check. - } - - Stream os = null; - try - { // send the Post - AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send - os = AgentCreateRequest.GetRequestStream(); - os.Write(buffer, 0, strBuffer.Length); //Send it - m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}", - uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY); - } - //catch (WebException ex) - catch - { - //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message); - reason = "cannot contact remote region"; - return false; - } - finally - { - if (os != null) - os.Close(); - } - - // Let's wait for the response - //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall"); - - try - { - using (WebResponse webResponse = AgentCreateRequest.GetResponse()) - { - if (webResponse == null) - { - m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post"); - } - else - { - using (Stream s = webResponse.GetResponseStream()) - { - using (StreamReader sr = new StreamReader(s)) - { - string response = sr.ReadToEnd().Trim(); - m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response); - - if (!String.IsNullOrEmpty(response)) - { - try - { - // we assume we got an OSDMap back - OSDMap r = Util.GetOSDMap(response); - bool success = r["success"].AsBoolean(); - reason = r["reason"].AsString(); - return success; - } - catch (NullReferenceException e) - { - m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message); - - // check for old style response - if (response.ToLower().StartsWith("true")) - return true; - - return false; - } - } - } - } - } - } - } - catch (WebException ex) - { - m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); - reason = "Destination did not reply"; - return false; - } - - return true; + Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI); + uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome; + return CreateAgent(home, aCircuit, flags, out reason); } // The simulators call this interface public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) { - return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason); + return LoginAgentToGrid(aCircuit, gatekeeper, destination, false, out reason); + } + + protected override void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags) + { + base.PackData(args, aCircuit, destination, flags); + args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI); + args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName); + args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString()); + args["destination_serveruri"] = OSD.FromString(destination.ServerURI); } protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 57f2ffa2d4..e247008b0c 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation return "agent/"; } + protected virtual void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags) + { + args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); + args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); + args["destination_name"] = OSD.FromString(destination.RegionName); + args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); + args["teleport_flags"] = OSD.FromString(flags.ToString()); + } + public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) { - // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); - + string tmp = String.Empty; + return CreateAgent(destination, aCircuit, flags, out tmp, out reason); + } + + public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason) + { + m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI); reason = String.Empty; + myipaddress = String.Empty; + if (destination == null) { m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null"); @@ -95,12 +111,7 @@ namespace OpenSim.Services.Connectors.Simulation try { OSDMap args = aCircuit.PackAgentCircuitData(); - - args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString()); - args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString()); - args["destination_name"] = OSD.FromString(destination.RegionName); - args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); - args["teleport_flags"] = OSD.FromString(flags.ToString()); + PackData(args, aCircuit, destination, flags); OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); bool success = result["success"].AsBoolean(); @@ -110,6 +121,7 @@ namespace OpenSim.Services.Connectors.Simulation reason = data["reason"].AsString(); success = data["success"].AsBoolean(); + myipaddress = data["your_ip"].AsString(); return success; } @@ -124,6 +136,7 @@ namespace OpenSim.Services.Connectors.Simulation reason = data["reason"].AsString(); success = data["success"].AsBoolean(); + myipaddress = data["your_ip"].AsString(); m_log.WarnFormat( "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); return success; diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 737e9c91af..733993fb04 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService return home; } - public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) + public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason) { m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", - agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); + agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI); string gridName = gatekeeper.ServerURI; @@ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService bool success = false; string myExternalIP = string.Empty; - m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); + m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID); if (m_GridName == gridName) success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); @@ -296,8 +296,8 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); // else set the IP addresses associated with this client - if (clientIP != null) - m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); + if (fromLogin) + m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress; m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; return true; @@ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) { reason = string.Empty; - return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason); + return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, false, out reason); } private void SetClientIP(UUID sessionID, string ip) diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 3dc877a870..f9e7f083b4 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces /// public interface IUserAgentService { - // called by login service only - bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason); - // called by simulators - bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); + bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason); void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); Dictionary GetServerURLs(UUID userID); diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 10cf90f7c1..fe43582a89 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -933,7 +933,7 @@ namespace OpenSim.Services.LLLoginService private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) { m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); - if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason)) + if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, true, out reason)) return true; return false; } From ca3ce6da7349425f117ad1f1a596e7e868fdd4c1 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 22 Jun 2013 08:26:59 -0700 Subject: [PATCH 28/29] HG: avoid call on localhost between sim and UAS for standalone. --- .../EntityTransfer/HGEntityTransferModule.cs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 0715324c49..630d1c376f 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private int m_levelHGTeleport = 0; + private string m_ThisHomeURI; private GatekeeperServiceConnector m_GatekeeperConnector; + private IUserAgentService m_UAS; protected bool m_RestrictAppearanceAbroad; protected string m_AccountName; @@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); } } + + moduleConfig = source.Configs["Hypergrid"]; + if (moduleConfig != null) + { + m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty); + if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/")) + m_ThisHomeURI += '/'; + } } public override void AddRegion(Scene scene) @@ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer base.RegionLoaded(scene); if (m_Enabled) + { m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); + m_UAS = scene.RequestModuleInterface(); + } } public override void RemoveRegion(Scene scene) @@ -272,7 +285,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) { string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); - IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); + IUserAgentService connector; + + if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null) + connector = m_UAS; + else + connector = new UserAgentServiceConnector(userAgentDriver); + bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason); logout = success; // flag for later logout from this grid; this is an HG TP From 6c7e33fe472014688837b993118fc48878f134ff Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 22 Jun 2013 08:29:06 -0700 Subject: [PATCH 29/29] Change IsLocalRegion from using region handle to using regionID. This was affecting UpdateAgent and CloseAgent in cases where the foreign region is on the same coordinates as *some* local region. --- .../Simulation/RemoteSimulationConnector.cs | 10 +++++----- OpenSim/Server/Handlers/Simulation/AgentHandlers.cs | 1 - .../Simulation/SimulationServiceConnector.cs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index b2a1b23279..d120e11c2c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; // Try local first - if (m_localBackend.IsLocalRegion(destination.RegionHandle)) + if (m_localBackend.IsLocalRegion(destination.RegionID)) return m_localBackend.UpdateAgent(destination, cAgentData); return m_remoteConnector.UpdateAgent(destination, cAgentData); @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; // Try local first - if (m_localBackend.IsLocalRegion(destination.RegionHandle)) + if (m_localBackend.IsLocalRegion(destination.RegionID)) return m_localBackend.UpdateAgent(destination, cAgentData); return m_remoteConnector.UpdateAgent(destination, cAgentData); @@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return true; // else do the remote thing - if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) + if (!m_localBackend.IsLocalRegion(destination.RegionID)) return m_remoteConnector.RetrieveAgent(destination, id, out agent); return false; @@ -273,7 +273,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return true; // else do the remote thing - if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) + if (!m_localBackend.IsLocalRegion(destination.RegionID)) return m_remoteConnector.CloseAgent(destination, id); return false; @@ -296,7 +296,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation } // else do the remote thing - if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) + if (!m_localBackend.IsLocalRegion(destination.RegionID)) return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); return false; diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 334d3137ff..71a9e6fa41 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -576,7 +576,6 @@ namespace OpenSim.Server.Handlers.Simulation //agent.Dump(); // This is one of the meanings of PUT agent result = UpdateAgent(destination, agent); - } else if ("AgentPosition".Equals(messageType)) { diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index e247008b0c..f51c809413 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -241,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation /// private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) { - // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start"); + // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI); // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";