diff options
author | Melanie Thielker | 2009-05-04 20:15:39 +0000 |
---|---|---|
committer | Melanie Thielker | 2009-05-04 20:15:39 +0000 |
commit | acfb5051cd328ab21aba5bfc2878ce84d496a7f1 (patch) | |
tree | e828f8688de36d91c1917a02b651939580168125 /OpenSim/Framework/Servers/BaseOpenSimServer.cs | |
parent | * Resolve http://opensimulator.org/mantis/view.php?id=3573 (diff) | |
download | opensim-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.cs | 496 |
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.IO; | ||
31 | using System.Reflection; | ||
32 | using System.Text; | ||
33 | using System.Threading; | ||
34 | using System.Timers; | ||
35 | using log4net; | ||
36 | using log4net.Appender; | ||
37 | using log4net.Core; | ||
38 | using log4net.Repository; | ||
39 | using OpenSim.Framework.Console; | ||
40 | using OpenSim.Framework.Servers; | ||
41 | using OpenSim.Framework.Statistics; | ||
42 | using Timer=System.Timers.Timer; | ||
43 | |||
44 | using OpenMetaverse; | ||
45 | using OpenMetaverse.StructuredData; | ||
46 | |||
47 | |||
48 | namespace 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 | } | ||