aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/ServerBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/ServerBase.cs')
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs254
1 files changed, 251 insertions, 3 deletions
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 1ff8aca..7108314 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
62 62
63 protected string m_pidFile = String.Empty; 63 protected string m_pidFile = String.Empty;
64 64
65 protected ServerStatsCollector m_serverStatsCollector;
66
65 /// <summary> 67 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. 68 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary> 69 /// </summary>
@@ -76,6 +78,11 @@ namespace OpenSim.Framework.Servers
76 78
77 protected void CreatePIDFile(string path) 79 protected void CreatePIDFile(string path)
78 { 80 {
81 if (File.Exists(path))
82 m_log.ErrorFormat(
83 "[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
84 path);
85
79 try 86 try
80 { 87 {
81 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); 88 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
@@ -239,7 +246,7 @@ namespace OpenSim.Framework.Servers
239 "Show thread status", HandleShow); 246 "Show thread status", HandleShow);
240 247
241 m_console.Commands.AddCommand( 248 m_console.Commands.AddCommand(
242 "General", false, "threads abort", 249 "Debug", false, "threads abort",
243 "threads abort <thread-id>", 250 "threads abort <thread-id>",
244 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); 251 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
245 252
@@ -249,11 +256,180 @@ namespace OpenSim.Framework.Servers
249 "Show thread status. Synonym for \"show threads\"", 256 "Show thread status. Synonym for \"show threads\"",
250 (string module, string[] args) => Notice(GetThreadsReport())); 257 (string module, string[] args) => Notice(GetThreadsReport()));
251 258
259 m_console.Commands.AddCommand (
260 "Debug", false, "debug comms set",
261 "debug comms set serialosdreq true|false",
262 "Set comms parameters. For debug purposes.",
263 HandleDebugCommsSet);
264
265 m_console.Commands.AddCommand (
266 "Debug", false, "debug comms status",
267 "debug comms status",
268 "Show current debug comms parameters.",
269 HandleDebugCommsStatus);
270
271 m_console.Commands.AddCommand (
272 "Debug", false, "debug threadpool set",
273 "debug threadpool set worker|iocp min|max <n>",
274 "Set threadpool parameters. For debug purposes.",
275 HandleDebugThreadpoolSet);
276
277 m_console.Commands.AddCommand (
278 "Debug", false, "debug threadpool status",
279 "debug threadpool status",
280 "Show current debug threadpool parameters.",
281 HandleDebugThreadpoolStatus);
282
252 m_console.Commands.AddCommand( 283 m_console.Commands.AddCommand(
253 "General", false, "force gc", 284 "Debug", false, "force gc",
254 "force gc", 285 "force gc",
255 "Manually invoke runtime garbage collection. For debugging purposes", 286 "Manually invoke runtime garbage collection. For debugging purposes",
256 HandleForceGc); 287 HandleForceGc);
288
289 m_console.Commands.AddCommand(
290 "General", false, "quit",
291 "quit",
292 "Quit the application", (mod, args) => Shutdown());
293
294 m_console.Commands.AddCommand(
295 "General", false, "shutdown",
296 "shutdown",
297 "Quit the application", (mod, args) => Shutdown());
298
299 ChecksManager.RegisterConsoleCommands(m_console);
300 StatsManager.RegisterConsoleCommands(m_console);
301 }
302
303 public void RegisterCommonComponents(IConfigSource configSource)
304 {
305 IConfig networkConfig = configSource.Configs["Network"];
306
307 if (networkConfig != null)
308 {
309 WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
310 }
311
312 m_serverStatsCollector = new ServerStatsCollector();
313 m_serverStatsCollector.Initialise(configSource);
314 m_serverStatsCollector.Start();
315 }
316
317 private void HandleDebugCommsStatus(string module, string[] args)
318 {
319 Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
320 }
321
322 private void HandleDebugCommsSet(string module, string[] args)
323 {
324 if (args.Length != 5)
325 {
326 Notice("Usage: debug comms set serialosdreq true|false");
327 return;
328 }
329
330 if (args[3] != "serialosdreq")
331 {
332 Notice("Usage: debug comms set serialosdreq true|false");
333 return;
334 }
335
336 bool setSerializeOsdRequests;
337
338 if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
339 return;
340
341 WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
342
343 Notice("serialosdreq is now {0}", setSerializeOsdRequests);
344 }
345
346 private void HandleDebugThreadpoolStatus(string module, string[] args)
347 {
348 int workerThreads, iocpThreads;
349
350 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
351 Notice("Min worker threads: {0}", workerThreads);
352 Notice("Min IOCP threads: {0}", iocpThreads);
353
354 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
355 Notice("Max worker threads: {0}", workerThreads);
356 Notice("Max IOCP threads: {0}", iocpThreads);
357
358 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
359 Notice("Available worker threads: {0}", workerThreads);
360 Notice("Available IOCP threads: {0}", iocpThreads);
361 }
362
363 private void HandleDebugThreadpoolSet(string module, string[] args)
364 {
365 if (args.Length != 6)
366 {
367 Notice("Usage: debug threadpool set worker|iocp min|max <n>");
368 return;
369 }
370
371 int newThreads;
372
373 if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads))
374 return;
375
376 string poolType = args[3];
377 string bound = args[4];
378
379 bool fail = false;
380 int workerThreads, iocpThreads;
381
382 if (poolType == "worker")
383 {
384 if (bound == "min")
385 {
386 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
387
388 if (!ThreadPool.SetMinThreads(newThreads, iocpThreads))
389 fail = true;
390 }
391 else
392 {
393 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
394
395 if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads))
396 fail = true;
397 }
398 }
399 else
400 {
401 if (bound == "min")
402 {
403 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
404
405 if (!ThreadPool.SetMinThreads(workerThreads, newThreads))
406 fail = true;
407 }
408 else
409 {
410 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
411
412 if (!ThreadPool.SetMaxThreads(workerThreads, newThreads))
413 fail = true;
414 }
415 }
416
417 if (fail)
418 {
419 Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads);
420 }
421 else
422 {
423 int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads;
424
425 ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads);
426 ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads);
427
428 Notice("Min worker threads now {0}", minWorkerThreads);
429 Notice("Min IOCP threads now {0}", minIocpThreads);
430 Notice("Max worker threads now {0}", maxWorkerThreads);
431 Notice("Max IOCP threads now {0}", maxIocpThreads);
432 }
257 } 433 }
258 434
259 private void HandleForceGc(string module, string[] args) 435 private void HandleForceGc(string module, string[] args)
@@ -641,7 +817,68 @@ namespace OpenSim.Framework.Servers
641 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 817 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
642 818
643 sb.Append("Main threadpool (excluding script engine pools)\n"); 819 sb.Append("Main threadpool (excluding script engine pools)\n");
644 sb.Append(Util.GetThreadPoolReport()); 820 sb.Append(GetThreadPoolReport());
821
822 return sb.ToString();
823 }
824
825 /// <summary>
826 /// Get a thread pool report.
827 /// </summary>
828 /// <returns></returns>
829 public static string GetThreadPoolReport()
830 {
831 string threadPoolUsed = null;
832 int maxThreads = 0;
833 int minThreads = 0;
834 int allocatedThreads = 0;
835 int inUseThreads = 0;
836 int waitingCallbacks = 0;
837 int completionPortThreads = 0;
838
839 StringBuilder sb = new StringBuilder();
840 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
841 {
842 STPInfo stpi = Util.GetSmartThreadPoolInfo();
843
844 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
845 if (stpi != null)
846 {
847 threadPoolUsed = "SmartThreadPool";
848 maxThreads = stpi.MaxThreads;
849 minThreads = stpi.MinThreads;
850 inUseThreads = stpi.InUseThreads;
851 allocatedThreads = stpi.ActiveThreads;
852 waitingCallbacks = stpi.WaitingCallbacks;
853 }
854 }
855 else if (
856 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
857 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
858 {
859 threadPoolUsed = "BuiltInThreadPool";
860 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
861 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
862 int availableThreads;
863 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
864 inUseThreads = maxThreads - availableThreads;
865 allocatedThreads = -1;
866 waitingCallbacks = -1;
867 }
868
869 if (threadPoolUsed != null)
870 {
871 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
872 sb.AppendFormat("Max threads : {0}\n", maxThreads);
873 sb.AppendFormat("Min threads : {0}\n", minThreads);
874 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
875 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
876 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
877 }
878 else
879 {
880 sb.AppendFormat("Thread pool not used\n");
881 }
645 882
646 return sb.ToString(); 883 return sb.ToString();
647 } 884 }
@@ -693,5 +930,16 @@ namespace OpenSim.Framework.Servers
693 if (m_console != null) 930 if (m_console != null)
694 m_console.OutputFormat(format, components); 931 m_console.OutputFormat(format, components);
695 } 932 }
933
934 public virtual void Shutdown()
935 {
936 m_serverStatsCollector.Close();
937 ShutdownSpecific();
938 }
939
940 /// <summary>
941 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
942 /// </summary>
943 protected virtual void ShutdownSpecific() {}
696 } 944 }
697} 945}