diff options
author | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
commit | 134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch) | |
tree | 216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Framework/Servers/ServerBase.cs | |
parent | More changing to production grid. Double oops. (diff) | |
download | opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2 opensim-SC-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz |
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Servers/ServerBase.cs | 381 |
1 files changed, 376 insertions, 5 deletions
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; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | 30 | using System.Diagnostics; |
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Linq; | ||
32 | using System.Reflection; | 33 | using System.Reflection; |
33 | using System.Text; | 34 | using System.Text; |
34 | using System.Text.RegularExpressions; | 35 | using System.Text.RegularExpressions; |
@@ -62,6 +63,8 @@ namespace OpenSim.Framework.Servers | |||
62 | 63 | ||
63 | protected string m_pidFile = String.Empty; | 64 | protected string m_pidFile = String.Empty; |
64 | 65 | ||
66 | protected ServerStatsCollector m_serverStatsCollector; | ||
67 | |||
65 | /// <summary> | 68 | /// <summary> |
66 | /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. | 69 | /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. |
67 | /// </summary> | 70 | /// </summary> |
@@ -76,6 +79,11 @@ namespace OpenSim.Framework.Servers | |||
76 | 79 | ||
77 | protected void CreatePIDFile(string path) | 80 | protected void CreatePIDFile(string path) |
78 | { | 81 | { |
82 | if (File.Exists(path)) | ||
83 | m_log.ErrorFormat( | ||
84 | "[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.", | ||
85 | path); | ||
86 | |||
79 | try | 87 | try |
80 | { | 88 | { |
81 | string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); | 89 | string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); |
@@ -113,6 +121,26 @@ namespace OpenSim.Framework.Servers | |||
113 | } | 121 | } |
114 | } | 122 | } |
115 | 123 | ||
124 | /// <summary> | ||
125 | /// Log information about the circumstances in which we're running (OpenSimulator version number, CLR details, | ||
126 | /// etc.). | ||
127 | /// </summary> | ||
128 | public void LogEnvironmentInformation() | ||
129 | { | ||
130 | // FIXME: This should be done down in ServerBase but we need to sort out and refactor the log4net | ||
131 | // XmlConfigurator calls first accross servers. | ||
132 | m_log.InfoFormat("[SERVER BASE]: Starting in {0}", m_startupDirectory); | ||
133 | |||
134 | m_log.InfoFormat("[SERVER BASE]: OpenSimulator version: {0}", m_version); | ||
135 | |||
136 | // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and | ||
137 | // the clr version number doesn't match the project version number under Mono. | ||
138 | //m_log.Info("[STARTUP]: Virtual machine runtime version: " + Environment.Version + Environment.NewLine); | ||
139 | m_log.InfoFormat( | ||
140 | "[SERVER BASE]: Operating system version: {0}, .NET platform {1}, {2}-bit", | ||
141 | Environment.OSVersion, Environment.OSVersion.Platform, Util.Is64BitProcess() ? "64" : "32"); | ||
142 | } | ||
143 | |||
116 | public void RegisterCommonAppenders(IConfig startupConfig) | 144 | public void RegisterCommonAppenders(IConfig startupConfig) |
117 | { | 145 | { |
118 | ILoggerRepository repository = LogManager.GetRepository(); | 146 | ILoggerRepository repository = LogManager.GetRepository(); |
@@ -219,7 +247,7 @@ namespace OpenSim.Framework.Servers | |||
219 | "Show thread status", HandleShow); | 247 | "Show thread status", HandleShow); |
220 | 248 | ||
221 | m_console.Commands.AddCommand( | 249 | m_console.Commands.AddCommand( |
222 | "General", false, "threads abort", | 250 | "Debug", false, "threads abort", |
223 | "threads abort <thread-id>", | 251 | "threads abort <thread-id>", |
224 | "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); | 252 | "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); |
225 | 253 | ||
@@ -229,11 +257,281 @@ namespace OpenSim.Framework.Servers | |||
229 | "Show thread status. Synonym for \"show threads\"", | 257 | "Show thread status. Synonym for \"show threads\"", |
230 | (string module, string[] args) => Notice(GetThreadsReport())); | 258 | (string module, string[] args) => Notice(GetThreadsReport())); |
231 | 259 | ||
260 | m_console.Commands.AddCommand ( | ||
261 | "Debug", false, "debug comms set", | ||
262 | "debug comms set serialosdreq true|false", | ||
263 | "Set comms parameters. For debug purposes.", | ||
264 | HandleDebugCommsSet); | ||
265 | |||
266 | m_console.Commands.AddCommand ( | ||
267 | "Debug", false, "debug comms status", | ||
268 | "debug comms status", | ||
269 | "Show current debug comms parameters.", | ||
270 | HandleDebugCommsStatus); | ||
271 | |||
272 | m_console.Commands.AddCommand ( | ||
273 | "Debug", false, "debug threadpool set", | ||
274 | "debug threadpool set worker|iocp min|max <n>", | ||
275 | "Set threadpool parameters. For debug purposes.", | ||
276 | HandleDebugThreadpoolSet); | ||
277 | |||
278 | m_console.Commands.AddCommand ( | ||
279 | "Debug", false, "debug threadpool status", | ||
280 | "debug threadpool status", | ||
281 | "Show current debug threadpool parameters.", | ||
282 | HandleDebugThreadpoolStatus); | ||
283 | |||
284 | m_console.Commands.AddCommand( | ||
285 | "Debug", false, "debug threadpool level", | ||
286 | "debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL, | ||
287 | "Turn on logging of activity in the main thread pool.", | ||
288 | "Log levels:\n" | ||
289 | + " 0 = no logging\n" | ||
290 | + " 1 = only first line of stack trace; don't log common threads\n" | ||
291 | + " 2 = full stack trace; don't log common threads\n" | ||
292 | + " 3 = full stack trace, including common threads\n", | ||
293 | HandleDebugThreadpoolLevel); | ||
294 | |||
295 | // m_console.Commands.AddCommand( | ||
296 | // "Debug", false, "show threadpool calls active", | ||
297 | // "show threadpool calls active", | ||
298 | // "Show details about threadpool calls that are still active (currently waiting or in progress)", | ||
299 | // HandleShowThreadpoolCallsActive); | ||
300 | |||
232 | m_console.Commands.AddCommand( | 301 | m_console.Commands.AddCommand( |
233 | "General", false, "force gc", | 302 | "Debug", false, "show threadpool calls complete", |
303 | "show threadpool calls complete", | ||
304 | "Show details about threadpool calls that have been completed.", | ||
305 | HandleShowThreadpoolCallsComplete); | ||
306 | |||
307 | m_console.Commands.AddCommand( | ||
308 | "Debug", false, "force gc", | ||
234 | "force gc", | 309 | "force gc", |
235 | "Manually invoke runtime garbage collection. For debugging purposes", | 310 | "Manually invoke runtime garbage collection. For debugging purposes", |
236 | HandleForceGc); | 311 | HandleForceGc); |
312 | |||
313 | m_console.Commands.AddCommand( | ||
314 | "General", false, "quit", | ||
315 | "quit", | ||
316 | "Quit the application", (mod, args) => Shutdown()); | ||
317 | |||
318 | m_console.Commands.AddCommand( | ||
319 | "General", false, "shutdown", | ||
320 | "shutdown", | ||
321 | "Quit the application", (mod, args) => Shutdown()); | ||
322 | |||
323 | ChecksManager.RegisterConsoleCommands(m_console); | ||
324 | StatsManager.RegisterConsoleCommands(m_console); | ||
325 | } | ||
326 | |||
327 | public void RegisterCommonComponents(IConfigSource configSource) | ||
328 | { | ||
329 | IConfig networkConfig = configSource.Configs["Network"]; | ||
330 | |||
331 | if (networkConfig != null) | ||
332 | { | ||
333 | WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false); | ||
334 | } | ||
335 | |||
336 | m_serverStatsCollector = new ServerStatsCollector(); | ||
337 | m_serverStatsCollector.Initialise(configSource); | ||
338 | m_serverStatsCollector.Start(); | ||
339 | } | ||
340 | |||
341 | private void HandleDebugCommsStatus(string module, string[] args) | ||
342 | { | ||
343 | Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint); | ||
344 | } | ||
345 | |||
346 | private void HandleDebugCommsSet(string module, string[] args) | ||
347 | { | ||
348 | if (args.Length != 5) | ||
349 | { | ||
350 | Notice("Usage: debug comms set serialosdreq true|false"); | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | if (args[3] != "serialosdreq") | ||
355 | { | ||
356 | Notice("Usage: debug comms set serialosdreq true|false"); | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | bool setSerializeOsdRequests; | ||
361 | |||
362 | if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests)) | ||
363 | return; | ||
364 | |||
365 | WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests; | ||
366 | |||
367 | Notice("serialosdreq is now {0}", setSerializeOsdRequests); | ||
368 | } | ||
369 | |||
370 | private void HandleShowThreadpoolCallsActive(string module, string[] args) | ||
371 | { | ||
372 | List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsInProgress().ToList(); | ||
373 | calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value)); | ||
374 | int namedCalls = 0; | ||
375 | |||
376 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
377 | foreach (KeyValuePair<string, int> kvp in calls) | ||
378 | { | ||
379 | if (kvp.Value > 0) | ||
380 | { | ||
381 | cdl.AddRow(kvp.Key, kvp.Value); | ||
382 | namedCalls += kvp.Value; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | cdl.AddRow("TOTAL NAMED", namedCalls); | ||
387 | |||
388 | long allQueuedCalls = Util.TotalQueuedFireAndForgetCalls; | ||
389 | long allRunningCalls = Util.TotalRunningFireAndForgetCalls; | ||
390 | |||
391 | cdl.AddRow("TOTAL QUEUED", allQueuedCalls); | ||
392 | cdl.AddRow("TOTAL RUNNING", allRunningCalls); | ||
393 | cdl.AddRow("TOTAL ANONYMOUS", allQueuedCalls + allRunningCalls - namedCalls); | ||
394 | cdl.AddRow("TOTAL ALL", allQueuedCalls + allRunningCalls); | ||
395 | |||
396 | MainConsole.Instance.Output(cdl.ToString()); | ||
397 | } | ||
398 | |||
399 | private void HandleShowThreadpoolCallsComplete(string module, string[] args) | ||
400 | { | ||
401 | List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsMade().ToList(); | ||
402 | calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value)); | ||
403 | int namedCallsMade = 0; | ||
404 | |||
405 | ConsoleDisplayList cdl = new ConsoleDisplayList(); | ||
406 | foreach (KeyValuePair<string, int> kvp in calls) | ||
407 | { | ||
408 | cdl.AddRow(kvp.Key, kvp.Value); | ||
409 | namedCallsMade += kvp.Value; | ||
410 | } | ||
411 | |||
412 | cdl.AddRow("TOTAL NAMED", namedCallsMade); | ||
413 | |||
414 | long allCallsMade = Util.TotalFireAndForgetCallsMade; | ||
415 | cdl.AddRow("TOTAL ANONYMOUS", allCallsMade - namedCallsMade); | ||
416 | cdl.AddRow("TOTAL ALL", allCallsMade); | ||
417 | |||
418 | MainConsole.Instance.Output(cdl.ToString()); | ||
419 | } | ||
420 | |||
421 | private void HandleDebugThreadpoolStatus(string module, string[] args) | ||
422 | { | ||
423 | int workerThreads, iocpThreads; | ||
424 | |||
425 | ThreadPool.GetMinThreads(out workerThreads, out iocpThreads); | ||
426 | Notice("Min worker threads: {0}", workerThreads); | ||
427 | Notice("Min IOCP threads: {0}", iocpThreads); | ||
428 | |||
429 | ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); | ||
430 | Notice("Max worker threads: {0}", workerThreads); | ||
431 | Notice("Max IOCP threads: {0}", iocpThreads); | ||
432 | |||
433 | ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads); | ||
434 | Notice("Available worker threads: {0}", workerThreads); | ||
435 | Notice("Available IOCP threads: {0}", iocpThreads); | ||
436 | } | ||
437 | |||
438 | private void HandleDebugThreadpoolSet(string module, string[] args) | ||
439 | { | ||
440 | if (args.Length != 6) | ||
441 | { | ||
442 | Notice("Usage: debug threadpool set worker|iocp min|max <n>"); | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | int newThreads; | ||
447 | |||
448 | if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads)) | ||
449 | return; | ||
450 | |||
451 | string poolType = args[3]; | ||
452 | string bound = args[4]; | ||
453 | |||
454 | bool fail = false; | ||
455 | int workerThreads, iocpThreads; | ||
456 | |||
457 | if (poolType == "worker") | ||
458 | { | ||
459 | if (bound == "min") | ||
460 | { | ||
461 | ThreadPool.GetMinThreads(out workerThreads, out iocpThreads); | ||
462 | |||
463 | if (!ThreadPool.SetMinThreads(newThreads, iocpThreads)) | ||
464 | fail = true; | ||
465 | } | ||
466 | else | ||
467 | { | ||
468 | ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); | ||
469 | |||
470 | if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads)) | ||
471 | fail = true; | ||
472 | } | ||
473 | } | ||
474 | else | ||
475 | { | ||
476 | if (bound == "min") | ||
477 | { | ||
478 | ThreadPool.GetMinThreads(out workerThreads, out iocpThreads); | ||
479 | |||
480 | if (!ThreadPool.SetMinThreads(workerThreads, newThreads)) | ||
481 | fail = true; | ||
482 | } | ||
483 | else | ||
484 | { | ||
485 | ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); | ||
486 | |||
487 | if (!ThreadPool.SetMaxThreads(workerThreads, newThreads)) | ||
488 | fail = true; | ||
489 | } | ||
490 | } | ||
491 | |||
492 | if (fail) | ||
493 | { | ||
494 | Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads); | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads; | ||
499 | |||
500 | ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads); | ||
501 | ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads); | ||
502 | |||
503 | Notice("Min worker threads now {0}", minWorkerThreads); | ||
504 | Notice("Min IOCP threads now {0}", minIocpThreads); | ||
505 | Notice("Max worker threads now {0}", maxWorkerThreads); | ||
506 | Notice("Max IOCP threads now {0}", maxIocpThreads); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | private static void HandleDebugThreadpoolLevel(string module, string[] cmdparams) | ||
511 | { | ||
512 | if (cmdparams.Length < 4) | ||
513 | { | ||
514 | MainConsole.Instance.Output("Usage: debug threadpool level 0.." + Util.MAX_THREADPOOL_LEVEL); | ||
515 | return; | ||
516 | } | ||
517 | |||
518 | string rawLevel = cmdparams[3]; | ||
519 | int newLevel; | ||
520 | |||
521 | if (!int.TryParse(rawLevel, out newLevel)) | ||
522 | { | ||
523 | MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawLevel); | ||
524 | return; | ||
525 | } | ||
526 | |||
527 | if (newLevel < 0 || newLevel > Util.MAX_THREADPOOL_LEVEL) | ||
528 | { | ||
529 | MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0.." + Util.MAX_THREADPOOL_LEVEL, newLevel); | ||
530 | return; | ||
531 | } | ||
532 | |||
533 | Util.LogThreadPool = newLevel; | ||
534 | MainConsole.Instance.OutputFormat("LogThreadPool set to {0}", newLevel); | ||
237 | } | 535 | } |
238 | 536 | ||
239 | private void HandleForceGc(string module, string[] args) | 537 | private void HandleForceGc(string module, string[] args) |
@@ -575,7 +873,8 @@ namespace OpenSim.Framework.Servers | |||
575 | 873 | ||
576 | protected string GetVersionText() | 874 | protected string GetVersionText() |
577 | { | 875 | { |
578 | return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion); | 876 | return String.Format("Version: {0} (SIMULATION/{1} - SIMULATION/{2})", |
877 | m_version, VersionInfo.SimulationServiceVersionSupportedMin, VersionInfo.SimulationServiceVersionSupportedMax); | ||
579 | } | 878 | } |
580 | 879 | ||
581 | /// <summary> | 880 | /// <summary> |
@@ -621,7 +920,68 @@ namespace OpenSim.Framework.Servers | |||
621 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); | 920 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); |
622 | 921 | ||
623 | sb.Append("Main threadpool (excluding script engine pools)\n"); | 922 | sb.Append("Main threadpool (excluding script engine pools)\n"); |
624 | sb.Append(Util.GetThreadPoolReport()); | 923 | sb.Append(GetThreadPoolReport()); |
924 | |||
925 | return sb.ToString(); | ||
926 | } | ||
927 | |||
928 | /// <summary> | ||
929 | /// Get a thread pool report. | ||
930 | /// </summary> | ||
931 | /// <returns></returns> | ||
932 | public static string GetThreadPoolReport() | ||
933 | { | ||
934 | string threadPoolUsed = null; | ||
935 | int maxThreads = 0; | ||
936 | int minThreads = 0; | ||
937 | int allocatedThreads = 0; | ||
938 | int inUseThreads = 0; | ||
939 | int waitingCallbacks = 0; | ||
940 | int completionPortThreads = 0; | ||
941 | |||
942 | StringBuilder sb = new StringBuilder(); | ||
943 | if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) | ||
944 | { | ||
945 | STPInfo stpi = Util.GetSmartThreadPoolInfo(); | ||
946 | |||
947 | // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. | ||
948 | if (stpi != null) | ||
949 | { | ||
950 | threadPoolUsed = "SmartThreadPool"; | ||
951 | maxThreads = stpi.MaxThreads; | ||
952 | minThreads = stpi.MinThreads; | ||
953 | inUseThreads = stpi.InUseThreads; | ||
954 | allocatedThreads = stpi.ActiveThreads; | ||
955 | waitingCallbacks = stpi.WaitingCallbacks; | ||
956 | } | ||
957 | } | ||
958 | else if ( | ||
959 | Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem | ||
960 | || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) | ||
961 | { | ||
962 | threadPoolUsed = "BuiltInThreadPool"; | ||
963 | ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); | ||
964 | ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); | ||
965 | int availableThreads; | ||
966 | ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); | ||
967 | inUseThreads = maxThreads - availableThreads; | ||
968 | allocatedThreads = -1; | ||
969 | waitingCallbacks = -1; | ||
970 | } | ||
971 | |||
972 | if (threadPoolUsed != null) | ||
973 | { | ||
974 | sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); | ||
975 | sb.AppendFormat("Max threads : {0}\n", maxThreads); | ||
976 | sb.AppendFormat("Min threads : {0}\n", minThreads); | ||
977 | sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); | ||
978 | sb.AppendFormat("In use threads : {0}\n", inUseThreads); | ||
979 | sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); | ||
980 | } | ||
981 | else | ||
982 | { | ||
983 | sb.AppendFormat("Thread pool not used\n"); | ||
984 | } | ||
625 | 985 | ||
626 | return sb.ToString(); | 986 | return sb.ToString(); |
627 | } | 987 | } |
@@ -673,5 +1033,16 @@ namespace OpenSim.Framework.Servers | |||
673 | if (m_console != null) | 1033 | if (m_console != null) |
674 | m_console.OutputFormat(format, components); | 1034 | m_console.OutputFormat(format, components); |
675 | } | 1035 | } |
1036 | |||
1037 | public virtual void Shutdown() | ||
1038 | { | ||
1039 | m_serverStatsCollector.Close(); | ||
1040 | ShutdownSpecific(); | ||
1041 | } | ||
1042 | |||
1043 | /// <summary> | ||
1044 | /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing | ||
1045 | /// </summary> | ||
1046 | protected virtual void ShutdownSpecific() {} | ||
676 | } | 1047 | } |
677 | } \ No newline at end of file | 1048 | } |