From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001
From: David Walter Seikel
Date: Thu, 3 Nov 2016 21:44:39 +1000
Subject: Initial update to OpenSim 0.8.2.1 source code.
---
OpenSim/Framework/Servers/ServerBase.cs | 381 +++++++++++++++++++++++++++++++-
1 file changed, 376 insertions(+), 5 deletions(-)
(limited to 'OpenSim/Framework/Servers/ServerBase.cs')
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 47baac8..07a09e6 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -29,6 +29,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
+using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
@@ -62,6 +63,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.
///
@@ -76,6 +79,11 @@ namespace OpenSim.Framework.Servers
protected void CreatePIDFile(string path)
{
+ if (File.Exists(path))
+ m_log.ErrorFormat(
+ "[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
+ path);
+
try
{
string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
@@ -113,6 +121,26 @@ namespace OpenSim.Framework.Servers
}
}
+ ///
+ /// Log information about the circumstances in which we're running (OpenSimulator version number, CLR details,
+ /// etc.).
+ ///
+ public void LogEnvironmentInformation()
+ {
+ // FIXME: This should be done down in ServerBase but we need to sort out and refactor the log4net
+ // XmlConfigurator calls first accross servers.
+ m_log.InfoFormat("[SERVER BASE]: Starting in {0}", m_startupDirectory);
+
+ m_log.InfoFormat("[SERVER BASE]: OpenSimulator version: {0}", m_version);
+
+ // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
+ // the clr version number doesn't match the project version number under Mono.
+ //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine);
+ m_log.InfoFormat(
+ "[SERVER BASE]: Operating system version: {0}, .NET platform {1}, {2}-bit",
+ Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32");
+ }
+
public void RegisterCommonAppenders(IConfig startupConfig)
{
ILoggerRepository repository = LogManager.GetRepository();
@@ -219,7 +247,7 @@ namespace OpenSim.Framework.Servers
"Show thread status", HandleShow);
m_console.Commands.AddCommand(
- "General", false, "threads abort",
+ "Debug", false, "threads abort",
"threads abort ",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
@@ -229,11 +257,281 @@ namespace OpenSim.Framework.Servers
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
+ m_console.Commands.AddCommand (
+ "Debug", false, "debug comms set",
+ "debug comms set serialosdreq true|false",
+ "Set comms parameters. For debug purposes.",
+ HandleDebugCommsSet);
+
+ m_console.Commands.AddCommand (
+ "Debug", false, "debug comms status",
+ "debug comms status",
+ "Show current debug comms parameters.",
+ HandleDebugCommsStatus);
+
+ m_console.Commands.AddCommand (
+ "Debug", false, "debug threadpool set",
+ "debug threadpool set worker|iocp min|max ",
+ "Set threadpool parameters. For debug purposes.",
+ HandleDebugThreadpoolSet);
+
+ m_console.Commands.AddCommand (
+ "Debug", false, "debug threadpool status",
+ "debug threadpool status",
+ "Show current debug threadpool parameters.",
+ HandleDebugThreadpoolStatus);
+
+ m_console.Commands.AddCommand(
+ "Debug", false, "debug threadpool level",
+ "debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL,
+ "Turn on logging of activity in the main thread pool.",
+ "Log levels:\n"
+ + " 0 = no logging\n"
+ + " 1 = only first line of stack trace; don't log common threads\n"
+ + " 2 = full stack trace; don't log common threads\n"
+ + " 3 = full stack trace, including common threads\n",
+ HandleDebugThreadpoolLevel);
+
+// m_console.Commands.AddCommand(
+// "Debug", false, "show threadpool calls active",
+// "show threadpool calls active",
+// "Show details about threadpool calls that are still active (currently waiting or in progress)",
+// HandleShowThreadpoolCallsActive);
+
m_console.Commands.AddCommand(
- "General", false, "force gc",
+ "Debug", false, "show threadpool calls complete",
+ "show threadpool calls complete",
+ "Show details about threadpool calls that have been completed.",
+ HandleShowThreadpoolCallsComplete);
+
+ m_console.Commands.AddCommand(
+ "Debug", false, "force gc",
"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());
+
+ ChecksManager.RegisterConsoleCommands(m_console);
+ StatsManager.RegisterConsoleCommands(m_console);
+ }
+
+ public void RegisterCommonComponents(IConfigSource configSource)
+ {
+ IConfig networkConfig = configSource.Configs["Network"];
+
+ if (networkConfig != null)
+ {
+ WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
+ }
+
+ m_serverStatsCollector = new ServerStatsCollector();
+ m_serverStatsCollector.Initialise(configSource);
+ m_serverStatsCollector.Start();
+ }
+
+ private void HandleDebugCommsStatus(string module, string[] args)
+ {
+ Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
+ }
+
+ private void HandleDebugCommsSet(string module, string[] args)
+ {
+ if (args.Length != 5)
+ {
+ Notice("Usage: debug comms set serialosdreq true|false");
+ return;
+ }
+
+ if (args[3] != "serialosdreq")
+ {
+ Notice("Usage: debug comms set serialosdreq true|false");
+ return;
+ }
+
+ bool setSerializeOsdRequests;
+
+ if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
+ return;
+
+ WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
+
+ Notice("serialosdreq is now {0}", setSerializeOsdRequests);
+ }
+
+ private void HandleShowThreadpoolCallsActive(string module, string[] args)
+ {
+ List> calls = Util.GetFireAndForgetCallsInProgress().ToList();
+ calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value));
+ int namedCalls = 0;
+
+ ConsoleDisplayList cdl = new ConsoleDisplayList();
+ foreach (KeyValuePair kvp in calls)
+ {
+ if (kvp.Value > 0)
+ {
+ cdl.AddRow(kvp.Key, kvp.Value);
+ namedCalls += kvp.Value;
+ }
+ }
+
+ cdl.AddRow("TOTAL NAMED", namedCalls);
+
+ long allQueuedCalls = Util.TotalQueuedFireAndForgetCalls;
+ long allRunningCalls = Util.TotalRunningFireAndForgetCalls;
+
+ cdl.AddRow("TOTAL QUEUED", allQueuedCalls);
+ cdl.AddRow("TOTAL RUNNING", allRunningCalls);
+ cdl.AddRow("TOTAL ANONYMOUS", allQueuedCalls + allRunningCalls - namedCalls);
+ cdl.AddRow("TOTAL ALL", allQueuedCalls + allRunningCalls);
+
+ MainConsole.Instance.Output(cdl.ToString());
+ }
+
+ private void HandleShowThreadpoolCallsComplete(string module, string[] args)
+ {
+ List> calls = Util.GetFireAndForgetCallsMade().ToList();
+ calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value));
+ int namedCallsMade = 0;
+
+ ConsoleDisplayList cdl = new ConsoleDisplayList();
+ foreach (KeyValuePair kvp in calls)
+ {
+ cdl.AddRow(kvp.Key, kvp.Value);
+ namedCallsMade += kvp.Value;
+ }
+
+ cdl.AddRow("TOTAL NAMED", namedCallsMade);
+
+ long allCallsMade = Util.TotalFireAndForgetCallsMade;
+ cdl.AddRow("TOTAL ANONYMOUS", allCallsMade - namedCallsMade);
+ cdl.AddRow("TOTAL ALL", allCallsMade);
+
+ MainConsole.Instance.Output(cdl.ToString());
+ }
+
+ private void HandleDebugThreadpoolStatus(string module, string[] args)
+ {
+ int workerThreads, iocpThreads;
+
+ ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
+ Notice("Min worker threads: {0}", workerThreads);
+ Notice("Min IOCP threads: {0}", iocpThreads);
+
+ ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
+ Notice("Max worker threads: {0}", workerThreads);
+ Notice("Max IOCP threads: {0}", iocpThreads);
+
+ ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
+ Notice("Available worker threads: {0}", workerThreads);
+ Notice("Available IOCP threads: {0}", iocpThreads);
+ }
+
+ private void HandleDebugThreadpoolSet(string module, string[] args)
+ {
+ if (args.Length != 6)
+ {
+ Notice("Usage: debug threadpool set worker|iocp min|max ");
+ return;
+ }
+
+ int newThreads;
+
+ if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads))
+ return;
+
+ string poolType = args[3];
+ string bound = args[4];
+
+ bool fail = false;
+ int workerThreads, iocpThreads;
+
+ if (poolType == "worker")
+ {
+ if (bound == "min")
+ {
+ ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
+
+ if (!ThreadPool.SetMinThreads(newThreads, iocpThreads))
+ fail = true;
+ }
+ else
+ {
+ ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
+
+ if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads))
+ fail = true;
+ }
+ }
+ else
+ {
+ if (bound == "min")
+ {
+ ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
+
+ if (!ThreadPool.SetMinThreads(workerThreads, newThreads))
+ fail = true;
+ }
+ else
+ {
+ ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
+
+ if (!ThreadPool.SetMaxThreads(workerThreads, newThreads))
+ fail = true;
+ }
+ }
+
+ if (fail)
+ {
+ Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads);
+ }
+ else
+ {
+ int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads;
+
+ ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads);
+ ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads);
+
+ Notice("Min worker threads now {0}", minWorkerThreads);
+ Notice("Min IOCP threads now {0}", minIocpThreads);
+ Notice("Max worker threads now {0}", maxWorkerThreads);
+ Notice("Max IOCP threads now {0}", maxIocpThreads);
+ }
+ }
+
+ private static void HandleDebugThreadpoolLevel(string module, string[] cmdparams)
+ {
+ if (cmdparams.Length < 4)
+ {
+ MainConsole.Instance.Output("Usage: debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL);
+ return;
+ }
+
+ string rawLevel = cmdparams[3];
+ int newLevel;
+
+ if (!int.TryParse(rawLevel, out newLevel))
+ {
+ MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawLevel);
+ return;
+ }
+
+ if (newLevel < 0 || newLevel > Util.MAX_THREADPOOL_LEVEL)
+ {
+ MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0.." + Util.MAX_THREADPOOL_LEVEL, newLevel);
+ return;
+ }
+
+ Util.LogThreadPool = newLevel;
+ MainConsole.Instance.OutputFormat("LogThreadPool set to {0}", newLevel);
}
private void HandleForceGc(string module, string[] args)
@@ -575,7 +873,8 @@ namespace OpenSim.Framework.Servers
protected string GetVersionText()
{
- return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
+ return String.Format("Version: {0} (SIMULATION/{1} - SIMULATION/{2})",
+ m_version, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax);
}
///
@@ -621,7 +920,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();
}
@@ -673,5 +1033,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
+}
--
cgit v1.1