aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/BaseOpenSimServer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers/BaseOpenSimServer.cs')
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs455
1 files changed, 16 insertions, 439 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index aac9c45..c0dc907 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -27,7 +27,6 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
31using System.IO; 30using System.IO;
32using System.Reflection; 31using System.Reflection;
33using System.Text; 32using System.Text;
@@ -38,6 +37,8 @@ using log4net;
38using log4net.Appender; 37using log4net.Appender;
39using log4net.Core; 38using log4net.Core;
40using log4net.Repository; 39using log4net.Repository;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
41using OpenSim.Framework; 42using OpenSim.Framework;
42using OpenSim.Framework.Console; 43using OpenSim.Framework.Console;
43using OpenSim.Framework.Monitoring; 44using OpenSim.Framework.Monitoring;
@@ -45,16 +46,12 @@ using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer; 46using OpenSim.Framework.Servers.HttpServer;
46using Timer=System.Timers.Timer; 47using Timer=System.Timers.Timer;
47 48
48using OpenMetaverse;
49using OpenMetaverse.StructuredData;
50
51
52namespace OpenSim.Framework.Servers 49namespace OpenSim.Framework.Servers
53{ 50{
54 /// <summary> 51 /// <summary>
55 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc) 52 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc)
56 /// </summary> 53 /// </summary>
57 public abstract class BaseOpenSimServer 54 public abstract class BaseOpenSimServer : ServerBase
58 { 55 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 57
@@ -63,27 +60,6 @@ namespace OpenSim.Framework.Servers
63 /// server. 60 /// server.
64 /// </summary> 61 /// </summary>
65 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); 62 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
66
67 protected CommandConsole m_console;
68 protected OpenSimAppender m_consoleAppender;
69 protected IAppender m_logFileAppender = null;
70
71 /// <summary>
72 /// Time at which this server was started
73 /// </summary>
74 protected DateTime m_startuptime;
75
76 /// <summary>
77 /// Record the initial startup directory for info purposes
78 /// </summary>
79 protected string m_startupDirectory = Environment.CurrentDirectory;
80
81 /// <summary>
82 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
83 /// </summary>
84 protected string m_version;
85
86 protected string m_pidFile = String.Empty;
87 63
88 /// <summary> 64 /// <summary>
89 /// Random uuid for private data 65 /// Random uuid for private data
@@ -96,30 +72,13 @@ namespace OpenSim.Framework.Servers
96 get { return m_httpServer; } 72 get { return m_httpServer; }
97 } 73 }
98 74
99 public BaseOpenSimServer() 75 public BaseOpenSimServer() : base()
100 { 76 {
101 m_startuptime = DateTime.Now;
102 m_version = VersionInfo.Version;
103
104 // Random uuid for private data 77 // Random uuid for private data
105 m_osSecret = UUID.Random().ToString(); 78 m_osSecret = UUID.Random().ToString();
106 79
107 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 80 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
108 m_periodicDiagnosticsTimer.Enabled = true; 81 m_periodicDiagnosticsTimer.Enabled = true;
109
110 // This thread will go on to become the console listening thread
111 Thread.CurrentThread.Name = "ConsoleThread";
112
113 ILoggerRepository repository = LogManager.GetRepository();
114 IAppender[] appenders = repository.GetAppenders();
115
116 foreach (IAppender appender in appenders)
117 {
118 if (appender.Name == "LogFileAppender")
119 {
120 m_logFileAppender = appender;
121 }
122 }
123 } 82 }
124 83
125 /// <summary> 84 /// <summary>
@@ -127,72 +86,18 @@ namespace OpenSim.Framework.Servers
127 /// </summary> 86 /// </summary>
128 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
129 { 88 {
130 if (m_console != null) 89 if (m_console == null)
131 { 90 return;
132 ILoggerRepository repository = LogManager.GetRepository();
133 IAppender[] appenders = repository.GetAppenders();
134
135 foreach (IAppender appender in appenders)
136 {
137 if (appender.Name == "Console")
138 {
139 m_consoleAppender = (OpenSimAppender)appender;
140 break;
141 }
142 }
143
144 if (null == m_consoleAppender)
145 {
146 Notice("No appender named Console found (see the log4net config file for this executable)!");
147 }
148 else
149 {
150 m_consoleAppender.Console = m_console;
151
152 // If there is no threshold set then the threshold is effectively everything.
153 if (null == m_consoleAppender.Threshold)
154 m_consoleAppender.Threshold = Level.All;
155
156 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
157 }
158
159 m_console.Commands.AddCommand("General", false, "quit",
160 "quit",
161 "Quit the application", HandleQuit);
162
163 m_console.Commands.AddCommand("General", false, "shutdown",
164 "shutdown",
165 "Quit the application", HandleQuit);
166
167 m_console.Commands.AddCommand("General", false, "set log level",
168 "set log level <level>",
169 "Set the console logging level", HandleLogLevel);
170
171 m_console.Commands.AddCommand("General", false, "show info",
172 "show info",
173 "Show general information about the server", HandleShow);
174
175 m_console.Commands.AddCommand("General", false, "show threads",
176 "show threads",
177 "Show thread status", HandleShow);
178
179 m_console.Commands.AddCommand("General", false, "show uptime",
180 "show uptime",
181 "Show server uptime", HandleShow);
182
183 m_console.Commands.AddCommand("General", false, "show version",
184 "show version",
185 "Show server version", HandleShow);
186 91
187 m_console.Commands.AddCommand("General", false, "threads abort", 92 RegisterCommonCommands();
188 "threads abort <thread-id>", 93
189 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); 94 m_console.Commands.AddCommand("General", false, "quit",
95 "quit",
96 "Quit the application", HandleQuit);
190 97
191 m_console.Commands.AddCommand("General", false, "threads show", 98 m_console.Commands.AddCommand("General", false, "shutdown",
192 "threads show", 99 "shutdown",
193 "Show thread status. Synonym for \"show threads\"", 100 "Quit the application", HandleQuit);
194 (string module, string[] args) => Notice(GetThreadsReport()));
195 }
196 } 101 }
197 102
198 /// <summary> 103 /// <summary>
@@ -225,74 +130,11 @@ namespace OpenSim.Framework.Servers
225 } 130 }
226 131
227 /// <summary> 132 /// <summary>
228 /// Get a report about the registered threads in this server.
229 /// </summary>
230 protected string GetThreadsReport()
231 {
232 // This should be a constant field.
233 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
234
235 StringBuilder sb = new StringBuilder();
236 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
237
238 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
239
240 int timeNow = Environment.TickCount & Int32.MaxValue;
241
242 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
243 sb.Append(Environment.NewLine);
244
245 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
246 {
247 Thread t = twi.Thread;
248
249 sb.AppendFormat(
250 reportFormat,
251 t.ManagedThreadId,
252 t.Name,
253 timeNow - twi.LastTick,
254 timeNow - twi.FirstTick,
255 t.Priority,
256 t.ThreadState);
257
258 sb.Append("\n");
259 }
260
261 sb.Append("\n");
262
263 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
264 // zero active threads.
265 int totalThreads = Process.GetCurrentProcess().Threads.Count;
266 if (totalThreads > 0)
267 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
268
269 sb.Append("Main threadpool (excluding script engine pools)\n");
270 sb.Append(Util.GetThreadPoolReport());
271
272 return sb.ToString();
273 }
274
275 /// <summary>
276 /// Return a report about the uptime of this server
277 /// </summary>
278 /// <returns></returns>
279 protected string GetUptimeReport()
280 {
281 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
282 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
283 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
284
285 return sb.ToString();
286 }
287
288 /// <summary>
289 /// Performs initialisation of the scene, such as loading configuration from disk. 133 /// Performs initialisation of the scene, such as loading configuration from disk.
290 /// </summary> 134 /// </summary>
291 public virtual void Startup() 135 public virtual void Startup()
292 { 136 {
293 m_log.Info("[STARTUP]: Beginning startup processing"); 137 m_log.Info("[STARTUP]: Beginning startup processing");
294
295 EnhanceVersionInformation();
296 138
297 m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine); 139 m_log.Info("[STARTUP]: OpenSimulator version: " + m_version + Environment.NewLine);
298 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and 140 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
@@ -327,257 +169,7 @@ namespace OpenSim.Framework.Servers
327 private void HandleQuit(string module, string[] args) 169 private void HandleQuit(string module, string[] args)
328 { 170 {
329 Shutdown(); 171 Shutdown();
330 } 172 }
331
332 private void HandleLogLevel(string module, string[] cmd)
333 {
334 if (null == m_consoleAppender)
335 {
336 Notice("No appender named Console found (see the log4net config file for this executable)!");
337 return;
338 }
339
340 if (cmd.Length > 3)
341 {
342 string rawLevel = cmd[3];
343
344 ILoggerRepository repository = LogManager.GetRepository();
345 Level consoleLevel = repository.LevelMap[rawLevel];
346
347 if (consoleLevel != null)
348 m_consoleAppender.Threshold = consoleLevel;
349 else
350 Notice(
351 String.Format(
352 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
353 rawLevel));
354 }
355
356 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
357 }
358
359 /// <summary>
360 /// Show help information
361 /// </summary>
362 /// <param name="helpArgs"></param>
363 protected virtual void ShowHelp(string[] helpArgs)
364 {
365 Notice("");
366
367 if (helpArgs.Length == 0)
368 {
369 Notice("set log level [level] - change the console logging level only. For example, off or debug.");
370 Notice("show info - show server information (e.g. startup path).");
371 Notice("show threads - list tracked threads");
372 Notice("show uptime - show server startup time and uptime.");
373 Notice("show version - show server version.");
374 Notice("");
375
376 return;
377 }
378 }
379
380 public virtual void HandleShow(string module, string[] cmd)
381 {
382 List<string> args = new List<string>(cmd);
383
384 args.RemoveAt(0);
385
386 string[] showParams = args.ToArray();
387
388 switch (showParams[0])
389 {
390 case "info":
391 ShowInfo();
392 break;
393
394 case "threads":
395 Notice(GetThreadsReport());
396 break;
397
398 case "uptime":
399 Notice(GetUptimeReport());
400 break;
401
402 case "version":
403 Notice(GetVersionText());
404 break;
405 }
406 }
407
408 public virtual void HandleThreadsAbort(string module, string[] cmd)
409 {
410 if (cmd.Length != 3)
411 {
412 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
413 return;
414 }
415
416 int threadId;
417 if (!int.TryParse(cmd[2], out threadId))
418 {
419 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
420 return;
421 }
422
423 if (Watchdog.AbortThread(threadId))
424 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
425 else
426 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
427 }
428
429 protected void ShowInfo()
430 {
431 Notice(GetVersionText());
432 Notice("Startup directory: " + m_startupDirectory);
433 if (null != m_consoleAppender)
434 Notice(String.Format("Console log level: {0}", m_consoleAppender.Threshold));
435 }
436
437 protected string GetVersionText()
438 {
439 return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
440 }
441
442 /// <summary>
443 /// Console output is only possible if a console has been established.
444 /// That is something that cannot be determined within this class. So
445 /// all attempts to use the console MUST be verified.
446 /// </summary>
447 /// <param name="msg"></param>
448 protected void Notice(string msg)
449 {
450 if (m_console != null)
451 {
452 m_console.Output(msg);
453 }
454 }
455
456 /// <summary>
457 /// Console output is only possible if a console has been established.
458 /// That is something that cannot be determined within this class. So
459 /// all attempts to use the console MUST be verified.
460 /// </summary>
461 /// <param name="format"></param>
462 /// <param name="components"></param>
463 protected void Notice(string format, params string[] components)
464 {
465 if (m_console != null)
466 m_console.OutputFormat(format, components);
467 }
468
469 /// <summary>
470 /// Enhance the version string with extra information if it's available.
471 /// </summary>
472 protected void EnhanceVersionInformation()
473 {
474 string buildVersion = string.Empty;
475
476 // The subversion information is deprecated and will be removed at a later date
477 // Add subversion revision information if available
478 // Try file "svn_revision" in the current directory first, then the .svn info.
479 // This allows to make the revision available in simulators not running from the source tree.
480 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
481 // elsewhere as well
482 string gitDir = "../.git/";
483 string gitRefPointerPath = gitDir + "HEAD";
484
485 string svnRevisionFileName = "svn_revision";
486 string svnFileName = ".svn/entries";
487 string manualVersionFileName = ".version";
488 string inputLine;
489 int strcmp;
490
491 if (File.Exists(manualVersionFileName))
492 {
493 using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
494 buildVersion = CommitFile.ReadLine();
495
496 m_version += buildVersion ?? "";
497 }
498 else if (File.Exists(gitRefPointerPath))
499 {
500// m_log.DebugFormat("[OPENSIM]: Found {0}", gitRefPointerPath);
501
502 string rawPointer = "";
503
504 using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
505 rawPointer = pointerFile.ReadLine();
506
507// m_log.DebugFormat("[OPENSIM]: rawPointer [{0}]", rawPointer);
508
509 Match m = Regex.Match(rawPointer, "^ref: (.+)$");
510
511 if (m.Success)
512 {
513// m_log.DebugFormat("[OPENSIM]: Matched [{0}]", m.Groups[1].Value);
514
515 string gitRef = m.Groups[1].Value;
516 string gitRefPath = gitDir + gitRef;
517 if (File.Exists(gitRefPath))
518 {
519// m_log.DebugFormat("[OPENSIM]: Found gitRefPath [{0}]", gitRefPath);
520
521 using (StreamReader refFile = File.OpenText(gitRefPath))
522 {
523 string gitHash = refFile.ReadLine();
524 m_version += gitHash.Substring(0, 7);
525 }
526 }
527 }
528 }
529 else
530 {
531 // Remove the else logic when subversion mirror is no longer used
532 if (File.Exists(svnRevisionFileName))
533 {
534 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
535 buildVersion = RevisionFile.ReadLine();
536 buildVersion.Trim();
537 RevisionFile.Close();
538 }
539
540 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
541 {
542 StreamReader EntriesFile = File.OpenText(svnFileName);
543 inputLine = EntriesFile.ReadLine();
544 while (inputLine != null)
545 {
546 // using the dir svn revision at the top of entries file
547 strcmp = String.Compare(inputLine, "dir");
548 if (strcmp == 0)
549 {
550 buildVersion = EntriesFile.ReadLine();
551 break;
552 }
553 else
554 {
555 inputLine = EntriesFile.ReadLine();
556 }
557 }
558 EntriesFile.Close();
559 }
560
561 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
562 }
563 }
564
565 protected void CreatePIDFile(string path)
566 {
567 try
568 {
569 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
570 FileStream fs = File.Create(path);
571
572 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
573 fs.Write(buf, 0, buf.Length);
574 fs.Close();
575 m_pidFile = path;
576 }
577 catch (Exception)
578 {
579 }
580 }
581 173
582 public string osSecret { 174 public string osSecret {
583 // Secret uuid for the simulator 175 // Secret uuid for the simulator
@@ -596,20 +188,5 @@ namespace OpenSim.Framework.Servers
596 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); 188 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
597 } 189 }
598 } 190 }
599
600 protected void RemovePIDFile()
601 {
602 if (m_pidFile != String.Empty)
603 {
604 try
605 {
606 File.Delete(m_pidFile);
607 m_pidFile = String.Empty;
608 }
609 catch (Exception)
610 {
611 }
612 }
613 }
614 } 191 }
615} 192} \ No newline at end of file