diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Servers/ServerBase.cs | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 9eb2281..1ff8aca 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs | |||
@@ -27,16 +27,19 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Text; | 33 | using System.Text; |
33 | using System.Text.RegularExpressions; | 34 | using System.Text.RegularExpressions; |
35 | using System.Threading; | ||
34 | using log4net; | 36 | using log4net; |
35 | using log4net.Appender; | 37 | using log4net.Appender; |
36 | using log4net.Core; | 38 | using log4net.Core; |
37 | using log4net.Repository; | 39 | using log4net.Repository; |
38 | using Nini.Config; | 40 | using Nini.Config; |
39 | using OpenSim.Framework.Console; | 41 | using OpenSim.Framework.Console; |
42 | using OpenSim.Framework.Monitoring; | ||
40 | 43 | ||
41 | namespace OpenSim.Framework.Servers | 44 | namespace OpenSim.Framework.Servers |
42 | { | 45 | { |
@@ -110,6 +113,26 @@ namespace OpenSim.Framework.Servers | |||
110 | } | 113 | } |
111 | } | 114 | } |
112 | 115 | ||
116 | /// <summary> | ||
117 | /// Log information about the circumstances in which we're running (OpenSimulator version number, CLR details, | ||
118 | /// etc.). | ||
119 | /// </summary> | ||
120 | public void LogEnvironmentInformation() | ||
121 | { | ||
122 | // FIXME: This should be done down in ServerBase but we need to sort out and refactor the log4net | ||
123 | // XmlConfigurator calls first accross servers. | ||
124 | m_log.InfoFormat("[SERVER BASE]: Starting in {0}", m_startupDirectory); | ||
125 | |||
126 | m_log.InfoFormat("[SERVER BASE]: OpenSimulator version: {0}", m_version); | ||
127 | |||
128 | // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and | ||
129 | // the clr version number doesn't match the project version number under Mono. | ||
130 | //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine); | ||
131 | m_log.InfoFormat( | ||
132 | "[SERVER BASE]: Operating system version: {0}, .NET platform {1}, {2}-bit", | ||
133 | Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32"); | ||
134 | } | ||
135 | |||
113 | public void RegisterCommonAppenders(IConfig startupConfig) | 136 | public void RegisterCommonAppenders(IConfig startupConfig) |
114 | { | 137 | { |
115 | ILoggerRepository repository = LogManager.GetRepository(); | 138 | ILoggerRepository repository = LogManager.GetRepository(); |
@@ -168,6 +191,9 @@ namespace OpenSim.Framework.Servers | |||
168 | "General", false, "show info", "show info", "Show general information about the server", HandleShow); | 191 | "General", false, "show info", "show info", "Show general information about the server", HandleShow); |
169 | 192 | ||
170 | m_console.Commands.AddCommand( | 193 | m_console.Commands.AddCommand( |
194 | "General", false, "show version", "show version", "Show server version", HandleShow); | ||
195 | |||
196 | m_console.Commands.AddCommand( | ||
171 | "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow); | 197 | "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow); |
172 | 198 | ||
173 | m_console.Commands.AddCommand( | 199 | m_console.Commands.AddCommand( |
@@ -206,6 +232,34 @@ namespace OpenSim.Framework.Servers | |||
206 | "General", false, "command-script", | 232 | "General", false, "command-script", |
207 | "command-script <script>", | 233 | "command-script <script>", |
208 | "Run a command script from file", HandleScript); | 234 | "Run a command script from file", HandleScript); |
235 | |||
236 | m_console.Commands.AddCommand( | ||
237 | "General", false, "show threads", | ||
238 | "show threads", | ||
239 | "Show thread status", HandleShow); | ||
240 | |||
241 | m_console.Commands.AddCommand( | ||
242 | "General", false, "threads abort", | ||
243 | "threads abort <thread-id>", | ||
244 | "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); | ||
245 | |||
246 | m_console.Commands.AddCommand( | ||
247 | "General", false, "threads show", | ||
248 | "threads show", | ||
249 | "Show thread status. Synonym for \"show threads\"", | ||
250 | (string module, string[] args) => Notice(GetThreadsReport())); | ||
251 | |||
252 | m_console.Commands.AddCommand( | ||
253 | "General", false, "force gc", | ||
254 | "force gc", | ||
255 | "Manually invoke runtime garbage collection. For debugging purposes", | ||
256 | HandleForceGc); | ||
257 | } | ||
258 | |||
259 | private void HandleForceGc(string module, string[] args) | ||
260 | { | ||
261 | Notice("Manually invoking runtime garbage collection"); | ||
262 | GC.Collect(); | ||
209 | } | 263 | } |
210 | 264 | ||
211 | public virtual void HandleShow(string module, string[] cmd) | 265 | public virtual void HandleShow(string module, string[] cmd) |
@@ -222,9 +276,17 @@ namespace OpenSim.Framework.Servers | |||
222 | ShowInfo(); | 276 | ShowInfo(); |
223 | break; | 277 | break; |
224 | 278 | ||
279 | case "version": | ||
280 | Notice(GetVersionText()); | ||
281 | break; | ||
282 | |||
225 | case "uptime": | 283 | case "uptime": |
226 | Notice(GetUptimeReport()); | 284 | Notice(GetUptimeReport()); |
227 | break; | 285 | break; |
286 | |||
287 | case "threads": | ||
288 | Notice(GetThreadsReport()); | ||
289 | break; | ||
228 | } | 290 | } |
229 | } | 291 | } |
230 | 292 | ||
@@ -537,6 +599,75 @@ namespace OpenSim.Framework.Servers | |||
537 | } | 599 | } |
538 | 600 | ||
539 | /// <summary> | 601 | /// <summary> |
602 | /// Get a report about the registered threads in this server. | ||
603 | /// </summary> | ||
604 | protected string GetThreadsReport() | ||
605 | { | ||
606 | // This should be a constant field. | ||
607 | string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}"; | ||
608 | |||
609 | StringBuilder sb = new StringBuilder(); | ||
610 | Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo(); | ||
611 | |||
612 | sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine); | ||
613 | |||
614 | int timeNow = Environment.TickCount & Int32.MaxValue; | ||
615 | |||
616 | sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE"); | ||
617 | sb.Append(Environment.NewLine); | ||
618 | |||
619 | foreach (Watchdog.ThreadWatchdogInfo twi in threads) | ||
620 | { | ||
621 | Thread t = twi.Thread; | ||
622 | |||
623 | sb.AppendFormat( | ||
624 | reportFormat, | ||
625 | t.ManagedThreadId, | ||
626 | t.Name, | ||
627 | timeNow - twi.LastTick, | ||
628 | timeNow - twi.FirstTick, | ||
629 | t.Priority, | ||
630 | t.ThreadState); | ||
631 | |||
632 | sb.Append("\n"); | ||
633 | } | ||
634 | |||
635 | sb.Append("\n"); | ||
636 | |||
637 | // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting | ||
638 | // zero active threads. | ||
639 | int totalThreads = Process.GetCurrentProcess().Threads.Count; | ||
640 | if (totalThreads > 0) | ||
641 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); | ||
642 | |||
643 | sb.Append("Main threadpool (excluding script engine pools)\n"); | ||
644 | sb.Append(Util.GetThreadPoolReport()); | ||
645 | |||
646 | return sb.ToString(); | ||
647 | } | ||
648 | |||
649 | public virtual void HandleThreadsAbort(string module, string[] cmd) | ||
650 | { | ||
651 | if (cmd.Length != 3) | ||
652 | { | ||
653 | MainConsole.Instance.Output("Usage: threads abort <thread-id>"); | ||
654 | return; | ||
655 | } | ||
656 | |||
657 | int threadId; | ||
658 | if (!int.TryParse(cmd[2], out threadId)) | ||
659 | { | ||
660 | MainConsole.Instance.Output("ERROR: Thread id must be an integer"); | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | if (Watchdog.AbortThread(threadId)) | ||
665 | MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId); | ||
666 | else | ||
667 | MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId); | ||
668 | } | ||
669 | |||
670 | /// <summary> | ||
540 | /// Console output is only possible if a console has been established. | 671 | /// Console output is only possible if a console has been established. |
541 | /// That is something that cannot be determined within this class. So | 672 | /// That is something that cannot be determined within this class. So |
542 | /// all attempts to use the console MUST be verified. | 673 | /// all attempts to use the console MUST be verified. |