aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers/BaseOpenSimServer.cs
diff options
context:
space:
mode:
authorMelanie Thielker2009-05-04 20:15:39 +0000
committerMelanie Thielker2009-05-04 20:15:39 +0000
commitacfb5051cd328ab21aba5bfc2878ce84d496a7f1 (patch)
treee828f8688de36d91c1917a02b651939580168125 /OpenSim/Framework/Servers/BaseOpenSimServer.cs
parent* Resolve http://opensimulator.org/mantis/view.php?id=3573 (diff)
downloadopensim-SC_OLD-acfb5051cd328ab21aba5bfc2878ce84d496a7f1.zip
opensim-SC_OLD-acfb5051cd328ab21aba5bfc2878ce84d496a7f1.tar.gz
opensim-SC_OLD-acfb5051cd328ab21aba5bfc2878ce84d496a7f1.tar.bz2
opensim-SC_OLD-acfb5051cd328ab21aba5bfc2878ce84d496a7f1.tar.xz
Intermediate commit. WILL NOT COMPILE!
Diffstat (limited to 'OpenSim/Framework/Servers/BaseOpenSimServer.cs')
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs496
1 files changed, 0 insertions, 496 deletions
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
deleted file mode 100644
index 0261146..0000000
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ /dev/null
@@ -1,496 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Text;
33using System.Threading;
34using System.Timers;
35using log4net;
36using log4net.Appender;
37using log4net.Core;
38using log4net.Repository;
39using OpenSim.Framework.Console;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Statistics;
42using Timer=System.Timers.Timer;
43
44using OpenMetaverse;
45using OpenMetaverse.StructuredData;
46
47
48namespace OpenSim.Framework.Servers
49{
50 /// <summary>
51 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc)
52 /// </summary>
53 public abstract class BaseOpenSimServer
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// This will control a periodic log printout of the current 'show stats' (if they are active) for this
59 /// server.
60 /// </summary>
61 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
62
63 protected CommandConsole m_console;
64 protected OpenSimAppender m_consoleAppender;
65
66 /// <summary>
67 /// Time at which this server was started
68 /// </summary>
69 protected DateTime m_startuptime;
70
71 /// <summary>
72 /// Record the initial startup directory for info purposes
73 /// </summary>
74 protected string m_startupDirectory = Environment.CurrentDirectory;
75
76 /// <summary>
77 /// Server version information. Usually VersionInfo + information about svn revision, operating system, etc.
78 /// </summary>
79 protected string m_version;
80
81 protected string m_pidFile = String.Empty;
82
83 /// <summary>
84 /// Random uuid for private data
85 /// </summary>
86 protected string m_osSecret = String.Empty;
87
88 protected BaseHttpServer m_httpServer;
89 public BaseHttpServer HttpServer
90 {
91 get { return m_httpServer; }
92 }
93
94 /// <summary>
95 /// Holds the non-viewer statistics collection object for this service/server
96 /// </summary>
97 protected IStatsCollector m_stats;
98
99 public BaseOpenSimServer()
100 {
101 m_startuptime = DateTime.Now;
102 m_version = VersionInfo.Version;
103
104 // Random uuid for private data
105 m_osSecret = UUID.Random().ToString();
106
107 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
108 m_periodicDiagnosticsTimer.Enabled = true;
109
110 // Add ourselves to thread monitoring. This thread will go on to become the console listening thread
111 Thread.CurrentThread.Name = "ConsoleThread";
112 ThreadTracker.Add(Thread.CurrentThread);
113 }
114
115 /// <summary>
116 /// Must be overriden by child classes for their own server specific startup behaviour.
117 /// </summary>
118 protected virtual void StartupSpecific()
119 {
120 if (m_console != null)
121 {
122 ILoggerRepository repository = LogManager.GetRepository();
123 IAppender[] appenders = repository.GetAppenders();
124
125 foreach (IAppender appender in appenders)
126 {
127 if (appender.Name == "Console")
128 {
129 m_consoleAppender = (OpenSimAppender)appender;
130 break;
131 }
132 }
133
134 if (null == m_consoleAppender)
135 {
136 Notice("No appender named Console found (see the log4net config file for this executable)!");
137 }
138 else
139 {
140 m_consoleAppender.Console = m_console;
141
142 // If there is no threshold set then the threshold is effectively everything.
143 if (null == m_consoleAppender.Threshold)
144 m_consoleAppender.Threshold = Level.All;
145
146 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
147 }
148
149 m_console.Commands.AddCommand("base", false, "quit",
150 "quit",
151 "Quit the application", HandleQuit);
152
153 m_console.Commands.AddCommand("base", false, "shutdown",
154 "shutdown",
155 "Quit the application", HandleQuit);
156
157 m_console.Commands.AddCommand("base", false, "set log level",
158 "set log level <level>",
159 "Set the console logging level", HandleLogLevel);
160
161 m_console.Commands.AddCommand("base", false, "show info",
162 "show info",
163 "Show general information", HandleShow);
164
165 m_console.Commands.AddCommand("base", false, "show stats",
166 "show stats",
167 "Show statistics", HandleShow);
168
169 m_console.Commands.AddCommand("base", false, "show threads",
170 "show threads",
171 "Show thread status", HandleShow);
172
173 m_console.Commands.AddCommand("base", false, "show uptime",
174 "show uptime",
175 "Show server uptime", HandleShow);
176
177 m_console.Commands.AddCommand("base", false, "show version",
178 "show version",
179 "Show server version", HandleShow);
180 }
181 }
182
183 /// <summary>
184 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
185 /// </summary>
186 public virtual void ShutdownSpecific() {}
187
188 /// <summary>
189 /// Provides a list of help topics that are available. Overriding classes should append their topics to the
190 /// information returned when the base method is called.
191 /// </summary>
192 ///
193 /// <returns>
194 /// A list of strings that represent different help topics on which more information is available
195 /// </returns>
196 protected virtual List<string> GetHelpTopics() { return new List<string>(); }
197
198 /// <summary>
199 /// Print statistics to the logfile, if they are active
200 /// </summary>
201 protected void LogDiagnostics(object source, ElapsedEventArgs e)
202 {
203 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n");
204 sb.Append(GetUptimeReport());
205
206 if (m_stats != null)
207 {
208 sb.Append(m_stats.Report());
209 }
210
211 sb.Append(Environment.NewLine);
212 sb.Append(GetThreadsReport());
213
214 m_log.Debug(sb);
215 }
216
217 /// <summary>
218 /// Get a report about the registered threads in this server.
219 /// </summary>
220 protected string GetThreadsReport()
221 {
222 StringBuilder sb = new StringBuilder();
223
224 List<Thread> threads = ThreadTracker.GetThreads();
225 if (threads == null)
226 {
227 sb.Append("Thread tracking is only enabled in DEBUG mode.");
228 }
229 else
230 {
231 sb.Append(threads.Count + " threads are being tracked:" + Environment.NewLine);
232 foreach (Thread t in threads)
233 {
234 if (t.IsAlive)
235 {
236 sb.Append(
237 "ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", Alive: " + t.IsAlive
238 + ", Pri: " + t.Priority + ", State: " + t.ThreadState + Environment.NewLine);
239 }
240 else
241 {
242 try
243 {
244 sb.Append("ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", DEAD" + Environment.NewLine);
245 }
246 catch
247 {
248 sb.Append("THREAD ERROR" + Environment.NewLine);
249 }
250 }
251 }
252 }
253
254 return sb.ToString();
255 }
256
257 /// <summary>
258 /// Return a report about the uptime of this server
259 /// </summary>
260 /// <returns></returns>
261 protected string GetUptimeReport()
262 {
263 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
264 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
265 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
266
267 return sb.ToString();
268 }
269
270 /// <summary>
271 /// Performs initialisation of the scene, such as loading configuration from disk.
272 /// </summary>
273 public virtual void Startup()
274 {
275 m_log.Info("[STARTUP]: Beginning startup processing");
276
277 EnhanceVersionInformation();
278
279 m_log.Info("[STARTUP]: Version: " + m_version + "\n");
280
281 StartupSpecific();
282
283 TimeSpan timeTaken = DateTime.Now - m_startuptime;
284
285 m_log.InfoFormat("[STARTUP]: Startup took {0}m {1}s", timeTaken.Minutes, timeTaken.Seconds);
286 }
287
288 /// <summary>
289 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
290 /// </summary>
291 public virtual void Shutdown()
292 {
293 ShutdownSpecific();
294
295 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
296 RemovePIDFile();
297
298 Environment.Exit(0);
299 }
300
301 private void HandleQuit(string module, string[] args)
302 {
303 Shutdown();
304 }
305
306 private void HandleLogLevel(string module, string[] cmd)
307 {
308 if (null == m_consoleAppender)
309 {
310 Notice("No appender named Console found (see the log4net config file for this executable)!");
311 return;
312 }
313
314 string rawLevel = cmd[3];
315
316 ILoggerRepository repository = LogManager.GetRepository();
317 Level consoleLevel = repository.LevelMap[rawLevel];
318
319 if (consoleLevel != null)
320 m_consoleAppender.Threshold = consoleLevel;
321 else
322 Notice(
323 String.Format(
324 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
325 rawLevel));
326
327 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
328 }
329
330 /// <summary>
331 /// Show help information
332 /// </summary>
333 /// <param name="helpArgs"></param>
334 protected virtual void ShowHelp(string[] helpArgs)
335 {
336 Notice("");
337
338 if (helpArgs.Length == 0)
339 {
340 Notice("set log level [level] - change the console logging level only. For example, off or debug.");
341 Notice("show info - show server information (e.g. startup path).");
342
343 if (m_stats != null)
344 Notice("show stats - show statistical information for this server");
345
346 Notice("show threads - list tracked threads");
347 Notice("show uptime - show server startup time and uptime.");
348 Notice("show version - show server version.");
349 Notice("");
350
351 return;
352 }
353 }
354
355 public virtual void HandleShow(string module, string[] cmd)
356 {
357 List<string> args = new List<string>(cmd);
358
359 args.RemoveAt(0);
360
361 string[] showParams = args.ToArray();
362
363 switch (showParams[0])
364 {
365 case "info":
366 Notice("Version: " + m_version);
367 Notice("Startup directory: " + m_startupDirectory);
368 break;
369
370 case "stats":
371 if (m_stats != null)
372 Notice(m_stats.Report());
373 break;
374
375 case "threads":
376 Notice(GetThreadsReport());
377 break;
378
379 case "uptime":
380 Notice(GetUptimeReport());
381 break;
382
383 case "version":
384 Notice(
385 String.Format(
386 "Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion));
387 break;
388 }
389 }
390
391 /// <summary>
392 /// Console output is only possible if a console has been established.
393 /// That is something that cannot be determined within this class. So
394 /// all attempts to use the console MUST be verified.
395 /// </summary>
396 protected void Notice(string msg)
397 {
398 if (m_console != null)
399 {
400 m_console.Notice(msg);
401 }
402 }
403
404 /// <summary>
405 /// Enhance the version string with extra information if it's available.
406 /// </summary>
407 protected void EnhanceVersionInformation()
408 {
409 string buildVersion = string.Empty;
410
411 // Add subversion revision information if available
412 // Try file "svn_revision" in the current directory first, then the .svn info.
413 // This allows to make the revision available in simulators not running from the source tree.
414 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
415 // elsewhere as well
416 string svnRevisionFileName = "svn_revision";
417 string svnFileName = ".svn/entries";
418 string inputLine;
419 int strcmp;
420
421 if (File.Exists(svnRevisionFileName))
422 {
423 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
424 buildVersion = RevisionFile.ReadLine();
425 buildVersion.Trim();
426 RevisionFile.Close();
427 }
428
429 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
430 {
431 StreamReader EntriesFile = File.OpenText(svnFileName);
432 inputLine = EntriesFile.ReadLine();
433 while (inputLine != null)
434 {
435 // using the dir svn revision at the top of entries file
436 strcmp = String.Compare(inputLine, "dir");
437 if (strcmp == 0)
438 {
439 buildVersion = EntriesFile.ReadLine();
440 break;
441 }
442 else
443 {
444 inputLine = EntriesFile.ReadLine();
445 }
446 }
447 EntriesFile.Close();
448 }
449
450 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
451 }
452
453 protected void CreatePIDFile(string path)
454 {
455 try
456 {
457 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
458 FileStream fs = File.Create(path);
459 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
460 Byte[] buf = enc.GetBytes(pidstring);
461 fs.Write(buf, 0, buf.Length);
462 fs.Close();
463 m_pidFile = path;
464 }
465 catch (Exception)
466 {
467 }
468 }
469
470 public string osSecret {
471 // Secret uuid for the simulator
472 get { return m_osSecret; }
473
474 }
475
476 public string StatReport(OSHttpRequest httpRequest)
477 {
478 return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version );
479 }
480
481 protected void RemovePIDFile()
482 {
483 if (m_pidFile != String.Empty)
484 {
485 try
486 {
487 File.Delete(m_pidFile);
488 m_pidFile = String.Empty;
489 }
490 catch (Exception)
491 {
492 }
493 }
494 }
495 }
496}