diff options
Diffstat (limited to 'OpenSim/Framework/Servers/ServerBase.cs')
-rw-r--r-- | OpenSim/Framework/Servers/ServerBase.cs | 254 |
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 | } |