aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Servers
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Servers')
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs455
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs72
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Servers/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs677
-rw-r--r--OpenSim/Framework/Servers/Tests/OSHttpTests.cs3
-rw-r--r--OpenSim/Framework/Servers/Tests/VersionInfoTests.cs3
7 files changed, 771 insertions, 505 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
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index b018e57..2cd626f 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -542,11 +542,8 @@ namespace OpenSim.Framework.Servers.HttpServer
542 { 542 {
543 case null: 543 case null:
544 case "text/html": 544 case "text/html":
545
546 if (DebugLevel >= 3) 545 if (DebugLevel >= 3)
547 m_log.DebugFormat( 546 LogIncomingToContentTypeHandler(request);
548 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
549 RequestNumber, Port, request.ContentType, request.HttpMethod, request.Url.PathAndQuery, request.RemoteIPEndPoint);
550 547
551 buffer = HandleHTTPRequest(request, response); 548 buffer = HandleHTTPRequest(request, response);
552 break; 549 break;
@@ -554,11 +551,8 @@ namespace OpenSim.Framework.Servers.HttpServer
554 case "application/llsd+xml": 551 case "application/llsd+xml":
555 case "application/xml+llsd": 552 case "application/xml+llsd":
556 case "application/llsd+json": 553 case "application/llsd+json":
557
558 if (DebugLevel >= 3) 554 if (DebugLevel >= 3)
559 m_log.DebugFormat( 555 LogIncomingToContentTypeHandler(request);
560 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
561 RequestNumber, Port, request.ContentType, request.HttpMethod, request.Url.PathAndQuery, request.RemoteIPEndPoint);
562 556
563 buffer = HandleLLSDRequests(request, response); 557 buffer = HandleLLSDRequests(request, response);
564 break; 558 break;
@@ -693,7 +687,7 @@ namespace OpenSim.Framework.Servers.HttpServer
693 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", 687 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
694 RequestNumber, 688 RequestNumber,
695 Port, 689 Port,
696 request.ContentType, 690 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType,
697 request.HttpMethod, 691 request.HttpMethod,
698 request.Url.PathAndQuery, 692 request.Url.PathAndQuery,
699 request.RemoteIPEndPoint); 693 request.RemoteIPEndPoint);
@@ -725,8 +719,11 @@ namespace OpenSim.Framework.Servers.HttpServer
725 if (DebugLevel == 5) 719 if (DebugLevel == 5)
726 { 720 {
727 const int sampleLength = 80; 721 const int sampleLength = 80;
728 char[] sampleChars = new char[sampleLength]; 722 char[] sampleChars = new char[sampleLength + 3];
729 reader.Read(sampleChars, 0, sampleLength); 723 reader.Read(sampleChars, 0, sampleLength);
724 sampleChars[80] = '.';
725 sampleChars[81] = '.';
726 sampleChars[82] = '.';
730 output = new string(sampleChars); 727 output = new string(sampleChars);
731 } 728 }
732 else 729 else
@@ -734,7 +731,7 @@ namespace OpenSim.Framework.Servers.HttpServer
734 output = reader.ReadToEnd(); 731 output = reader.ReadToEnd();
735 } 732 }
736 733
737 m_log.DebugFormat("[BASE HTTP SERVER]: {0}...", output.Replace("\n", @"\n")); 734 m_log.DebugFormat("[BASE HTTP SERVER]: {0}", output.Replace("\n", @"\n"));
738 } 735 }
739 } 736 }
740 737
@@ -1285,59 +1282,6 @@ namespace OpenSim.Framework.Servers.HttpServer
1285 map["login"] = OSD.FromString("false"); 1282 map["login"] = OSD.FromString("false");
1286 return map; 1283 return map;
1287 } 1284 }
1288 /// <summary>
1289 /// A specific agent handler was provided. Such a handler is expecetd to have an
1290 /// intimate, and highly specific relationship with the client. Consequently,
1291 /// nothing is done here.
1292 /// </summary>
1293 /// <param name="handler"></param>
1294 /// <param name="request"></param>
1295 /// <param name="response"></param>
1296
1297 private bool HandleAgentRequest(IHttpAgentHandler handler, OSHttpRequest request, OSHttpResponse response)
1298 {
1299 // In the case of REST, then handler is responsible for ALL aspects of
1300 // the request/response handling. Nothing is done here, not even encoding.
1301
1302 try
1303 {
1304 return handler.Handle(request, response);
1305 }
1306 catch (Exception e)
1307 {
1308 // If the handler did in fact close the stream, then this will blow
1309 // chunks. So that that doesn't disturb anybody we throw away any
1310 // and all exceptions raised. We've done our best to release the
1311 // client.
1312 try
1313 {
1314 m_log.Warn("[HTTP-AGENT]: Error - " + e.Message);
1315 response.SendChunked = false;
1316 response.KeepAlive = true;
1317 response.StatusCode = (int)OSHttpStatusCode.ServerErrorInternalError;
1318 //response.OutputStream.Close();
1319 try
1320 {
1321 response.Send();
1322 //response.FreeContext();
1323 }
1324 catch (SocketException f)
1325 {
1326 // This has to be here to prevent a Linux/Mono crash
1327 m_log.Warn(
1328 String.Format("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux. ", f.Message), f);
1329 }
1330 }
1331 catch(Exception)
1332 {
1333 }
1334 }
1335
1336 // Indicate that the request has been "handled"
1337
1338 return true;
1339
1340 }
1341 1285
1342 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response) 1286 public byte[] HandleHTTPRequest(OSHttpRequest request, OSHttpResponse response)
1343 { 1287 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..02ecc25
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Servers.HttpServer")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("c4ea5baa-81c4-4867-a645-1ec360c1f164")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..021f63c
--- /dev/null
+++ b/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Servers")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("b48e8b3e-5c5c-4673-b31f-21e13b8e568b")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
new file mode 100644
index 0000000..47baac8
--- /dev/null
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -0,0 +1,677 @@
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 OpenSimulator 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.Diagnostics;
31using System.IO;
32using System.Reflection;
33using System.Text;
34using System.Text.RegularExpressions;
35using System.Threading;
36using log4net;
37using log4net.Appender;
38using log4net.Core;
39using log4net.Repository;
40using Nini.Config;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43
44namespace OpenSim.Framework.Servers
45{
46 public class ServerBase
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 public IConfigSource Config { get; protected set; }
51
52 /// <summary>
53 /// Console to be used for any command line output. Can be null, in which case there should be no output.
54 /// </summary>
55 protected ICommandConsole m_console;
56
57 protected OpenSimAppender m_consoleAppender;
58 protected FileAppender m_logFileAppender;
59
60 protected DateTime m_startuptime;
61 protected string m_startupDirectory = Environment.CurrentDirectory;
62
63 protected string m_pidFile = String.Empty;
64
65 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary>
68 protected string m_version;
69
70 public ServerBase()
71 {
72 m_startuptime = DateTime.Now;
73 m_version = VersionInfo.Version;
74 EnhanceVersionInformation();
75 }
76
77 protected void CreatePIDFile(string path)
78 {
79 try
80 {
81 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
82
83 using (FileStream fs = File.Create(path))
84 {
85 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
86 fs.Write(buf, 0, buf.Length);
87 }
88
89 m_pidFile = path;
90
91 m_log.InfoFormat("[SERVER BASE]: Created pid file {0}", m_pidFile);
92 }
93 catch (Exception e)
94 {
95 m_log.Warn(string.Format("[SERVER BASE]: Could not create PID file at {0} ", path), e);
96 }
97 }
98
99 protected void RemovePIDFile()
100 {
101 if (m_pidFile != String.Empty)
102 {
103 try
104 {
105 File.Delete(m_pidFile);
106 }
107 catch (Exception e)
108 {
109 m_log.Error(string.Format("[SERVER BASE]: Error whilst removing {0} ", m_pidFile), e);
110 }
111
112 m_pidFile = String.Empty;
113 }
114 }
115
116 public void RegisterCommonAppenders(IConfig startupConfig)
117 {
118 ILoggerRepository repository = LogManager.GetRepository();
119 IAppender[] appenders = repository.GetAppenders();
120
121 foreach (IAppender appender in appenders)
122 {
123 if (appender.Name == "Console")
124 {
125 m_consoleAppender = (OpenSimAppender)appender;
126 }
127 else if (appender.Name == "LogFileAppender")
128 {
129 m_logFileAppender = (FileAppender)appender;
130 }
131 }
132
133 if (null == m_consoleAppender)
134 {
135 Notice("No appender named Console found (see the log4net config file for this executable)!");
136 }
137 else
138 {
139 // FIXME: This should be done through an interface rather than casting.
140 m_consoleAppender.Console = (ConsoleBase)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 if (m_logFileAppender != null && startupConfig != null)
150 {
151 string cfgFileName = startupConfig.GetString("LogFile", null);
152 if (cfgFileName != null)
153 {
154 m_logFileAppender.File = cfgFileName;
155 m_logFileAppender.ActivateOptions();
156 }
157
158 m_log.InfoFormat("[SERVER BASE]: Logging started to file {0}", m_logFileAppender.File);
159 }
160 }
161
162 /// <summary>
163 /// Register common commands once m_console has been set if it is going to be set
164 /// </summary>
165 public void RegisterCommonCommands()
166 {
167 if (m_console == null)
168 return;
169
170 m_console.Commands.AddCommand(
171 "General", false, "show info", "show info", "Show general information about the server", HandleShow);
172
173 m_console.Commands.AddCommand(
174 "General", false, "show version", "show version", "Show server version", HandleShow);
175
176 m_console.Commands.AddCommand(
177 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow);
178
179 m_console.Commands.AddCommand(
180 "General", false, "get log level", "get log level", "Get the current console logging level",
181 (mod, cmd) => ShowLogLevel());
182
183 m_console.Commands.AddCommand(
184 "General", false, "set log level", "set log level <level>",
185 "Set the console logging level for this session.", HandleSetLogLevel);
186
187 m_console.Commands.AddCommand(
188 "General", false, "config set",
189 "config set <section> <key> <value>",
190 "Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
191
192 m_console.Commands.AddCommand(
193 "General", false, "config get",
194 "config get [<section>] [<key>]",
195 "Synonym for config show",
196 HandleConfig);
197
198 m_console.Commands.AddCommand(
199 "General", false, "config show",
200 "config show [<section>] [<key>]",
201 "Show config information",
202 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
203 + "If a section is given but not a field, then all fields in that section are printed.",
204 HandleConfig);
205
206 m_console.Commands.AddCommand(
207 "General", false, "config save",
208 "config save <path>",
209 "Save current configuration to a file at the given path", HandleConfig);
210
211 m_console.Commands.AddCommand(
212 "General", false, "command-script",
213 "command-script <script>",
214 "Run a command script from file", HandleScript);
215
216 m_console.Commands.AddCommand(
217 "General", false, "show threads",
218 "show threads",
219 "Show thread status", HandleShow);
220
221 m_console.Commands.AddCommand(
222 "General", false, "threads abort",
223 "threads abort <thread-id>",
224 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
225
226 m_console.Commands.AddCommand(
227 "General", false, "threads show",
228 "threads show",
229 "Show thread status. Synonym for \"show threads\"",
230 (string module, string[] args) => Notice(GetThreadsReport()));
231
232 m_console.Commands.AddCommand(
233 "General", false, "force gc",
234 "force gc",
235 "Manually invoke runtime garbage collection. For debugging purposes",
236 HandleForceGc);
237 }
238
239 private void HandleForceGc(string module, string[] args)
240 {
241 Notice("Manually invoking runtime garbage collection");
242 GC.Collect();
243 }
244
245 public virtual void HandleShow(string module, string[] cmd)
246 {
247 List<string> args = new List<string>(cmd);
248
249 args.RemoveAt(0);
250
251 string[] showParams = args.ToArray();
252
253 switch (showParams[0])
254 {
255 case "info":
256 ShowInfo();
257 break;
258
259 case "version":
260 Notice(GetVersionText());
261 break;
262
263 case "uptime":
264 Notice(GetUptimeReport());
265 break;
266
267 case "threads":
268 Notice(GetThreadsReport());
269 break;
270 }
271 }
272
273 /// <summary>
274 /// Change and load configuration file data.
275 /// </summary>
276 /// <param name="module"></param>
277 /// <param name="cmd"></param>
278 private void HandleConfig(string module, string[] cmd)
279 {
280 List<string> args = new List<string>(cmd);
281 args.RemoveAt(0);
282 string[] cmdparams = args.ToArray();
283
284 if (cmdparams.Length > 0)
285 {
286 string firstParam = cmdparams[0].ToLower();
287
288 switch (firstParam)
289 {
290 case "set":
291 if (cmdparams.Length < 4)
292 {
293 Notice("Syntax: config set <section> <key> <value>");
294 Notice("Example: config set ScriptEngine.DotNetEngine NumberOfScriptThreads 5");
295 }
296 else
297 {
298 IConfig c;
299 IConfigSource source = new IniConfigSource();
300 c = source.AddConfig(cmdparams[1]);
301 if (c != null)
302 {
303 string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3);
304 c.Set(cmdparams[2], _value);
305 Config.Merge(source);
306
307 Notice("In section [{0}], set {1} = {2}", c.Name, cmdparams[2], _value);
308 }
309 }
310 break;
311
312 case "get":
313 case "show":
314 if (cmdparams.Length == 1)
315 {
316 foreach (IConfig config in Config.Configs)
317 {
318 Notice("[{0}]", config.Name);
319 string[] keys = config.GetKeys();
320 foreach (string key in keys)
321 Notice(" {0} = {1}", key, config.GetString(key));
322 }
323 }
324 else if (cmdparams.Length == 2 || cmdparams.Length == 3)
325 {
326 IConfig config = Config.Configs[cmdparams[1]];
327 if (config == null)
328 {
329 Notice("Section \"{0}\" does not exist.",cmdparams[1]);
330 break;
331 }
332 else
333 {
334 if (cmdparams.Length == 2)
335 {
336 Notice("[{0}]", config.Name);
337 foreach (string key in config.GetKeys())
338 Notice(" {0} = {1}", key, config.GetString(key));
339 }
340 else
341 {
342 Notice(
343 "config get {0} {1} : {2}",
344 cmdparams[1], cmdparams[2], config.GetString(cmdparams[2]));
345 }
346 }
347 }
348 else
349 {
350 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
351 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
352 }
353
354 break;
355
356 case "save":
357 if (cmdparams.Length < 2)
358 {
359 Notice("Syntax: config save <path>");
360 return;
361 }
362
363 string path = cmdparams[1];
364 Notice("Saving configuration file: {0}", path);
365
366 if (Config is IniConfigSource)
367 {
368 IniConfigSource iniCon = (IniConfigSource)Config;
369 iniCon.Save(path);
370 }
371 else if (Config is XmlConfigSource)
372 {
373 XmlConfigSource xmlCon = (XmlConfigSource)Config;
374 xmlCon.Save(path);
375 }
376
377 break;
378 }
379 }
380 }
381
382 private void HandleSetLogLevel(string module, string[] cmd)
383 {
384 if (cmd.Length != 4)
385 {
386 Notice("Usage: set log level <level>");
387 return;
388 }
389
390 if (null == m_consoleAppender)
391 {
392 Notice("No appender named Console found (see the log4net config file for this executable)!");
393 return;
394 }
395
396 string rawLevel = cmd[3];
397
398 ILoggerRepository repository = LogManager.GetRepository();
399 Level consoleLevel = repository.LevelMap[rawLevel];
400
401 if (consoleLevel != null)
402 m_consoleAppender.Threshold = consoleLevel;
403 else
404 Notice(
405 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
406 rawLevel);
407
408 ShowLogLevel();
409 }
410
411 private void ShowLogLevel()
412 {
413 Notice("Console log level is {0}", m_consoleAppender.Threshold);
414 }
415
416 protected virtual void HandleScript(string module, string[] parms)
417 {
418 if (parms.Length != 2)
419 {
420 Notice("Usage: command-script <path-to-script");
421 return;
422 }
423
424 RunCommandScript(parms[1]);
425 }
426
427 /// <summary>
428 /// Run an optional startup list of commands
429 /// </summary>
430 /// <param name="fileName"></param>
431 protected void RunCommandScript(string fileName)
432 {
433 if (m_console == null)
434 return;
435
436 if (File.Exists(fileName))
437 {
438 m_log.Info("[SERVER BASE]: Running " + fileName);
439
440 using (StreamReader readFile = File.OpenText(fileName))
441 {
442 string currentCommand;
443 while ((currentCommand = readFile.ReadLine()) != null)
444 {
445 currentCommand = currentCommand.Trim();
446 if (!(currentCommand == ""
447 || currentCommand.StartsWith(";")
448 || currentCommand.StartsWith("//")
449 || currentCommand.StartsWith("#")))
450 {
451 m_log.Info("[SERVER BASE]: Running '" + currentCommand + "'");
452 m_console.RunCommand(currentCommand);
453 }
454 }
455 }
456 }
457 }
458
459 /// <summary>
460 /// Return a report about the uptime of this server
461 /// </summary>
462 /// <returns></returns>
463 protected string GetUptimeReport()
464 {
465 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
466 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
467 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
468
469 return sb.ToString();
470 }
471
472 protected void ShowInfo()
473 {
474 Notice(GetVersionText());
475 Notice("Startup directory: " + m_startupDirectory);
476 if (null != m_consoleAppender)
477 Notice(String.Format("Console log level: {0}", m_consoleAppender.Threshold));
478 }
479
480 /// <summary>
481 /// Enhance the version string with extra information if it's available.
482 /// </summary>
483 protected void EnhanceVersionInformation()
484 {
485 string buildVersion = string.Empty;
486
487 // The subversion information is deprecated and will be removed at a later date
488 // Add subversion revision information if available
489 // Try file "svn_revision" in the current directory first, then the .svn info.
490 // This allows to make the revision available in simulators not running from the source tree.
491 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
492 // elsewhere as well
493 string gitDir = "../.git/";
494 string gitRefPointerPath = gitDir + "HEAD";
495
496 string svnRevisionFileName = "svn_revision";
497 string svnFileName = ".svn/entries";
498 string manualVersionFileName = ".version";
499 string inputLine;
500 int strcmp;
501
502 if (File.Exists(manualVersionFileName))
503 {
504 using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
505 buildVersion = CommitFile.ReadLine();
506
507 m_version += buildVersion ?? "";
508 }
509 else if (File.Exists(gitRefPointerPath))
510 {
511// m_log.DebugFormat("[SERVER BASE]: Found {0}", gitRefPointerPath);
512
513 string rawPointer = "";
514
515 using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
516 rawPointer = pointerFile.ReadLine();
517
518// m_log.DebugFormat("[SERVER BASE]: rawPointer [{0}]", rawPointer);
519
520 Match m = Regex.Match(rawPointer, "^ref: (.+)$");
521
522 if (m.Success)
523 {
524// m_log.DebugFormat("[SERVER BASE]: Matched [{0}]", m.Groups[1].Value);
525
526 string gitRef = m.Groups[1].Value;
527 string gitRefPath = gitDir + gitRef;
528 if (File.Exists(gitRefPath))
529 {
530// m_log.DebugFormat("[SERVER BASE]: Found gitRefPath [{0}]", gitRefPath);
531
532 using (StreamReader refFile = File.OpenText(gitRefPath))
533 {
534 string gitHash = refFile.ReadLine();
535 m_version += gitHash.Substring(0, 7);
536 }
537 }
538 }
539 }
540 else
541 {
542 // Remove the else logic when subversion mirror is no longer used
543 if (File.Exists(svnRevisionFileName))
544 {
545 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
546 buildVersion = RevisionFile.ReadLine();
547 buildVersion.Trim();
548 RevisionFile.Close();
549 }
550
551 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
552 {
553 StreamReader EntriesFile = File.OpenText(svnFileName);
554 inputLine = EntriesFile.ReadLine();
555 while (inputLine != null)
556 {
557 // using the dir svn revision at the top of entries file
558 strcmp = String.Compare(inputLine, "dir");
559 if (strcmp == 0)
560 {
561 buildVersion = EntriesFile.ReadLine();
562 break;
563 }
564 else
565 {
566 inputLine = EntriesFile.ReadLine();
567 }
568 }
569 EntriesFile.Close();
570 }
571
572 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
573 }
574 }
575
576 protected string GetVersionText()
577 {
578 return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
579 }
580
581 /// <summary>
582 /// Get a report about the registered threads in this server.
583 /// </summary>
584 protected string GetThreadsReport()
585 {
586 // This should be a constant field.
587 string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
588
589 StringBuilder sb = new StringBuilder();
590 Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
591
592 sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
593
594 int timeNow = Environment.TickCount & Int32.MaxValue;
595
596 sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
597 sb.Append(Environment.NewLine);
598
599 foreach (Watchdog.ThreadWatchdogInfo twi in threads)
600 {
601 Thread t = twi.Thread;
602
603 sb.AppendFormat(
604 reportFormat,
605 t.ManagedThreadId,
606 t.Name,
607 timeNow - twi.LastTick,
608 timeNow - twi.FirstTick,
609 t.Priority,
610 t.ThreadState);
611
612 sb.Append("\n");
613 }
614
615 sb.Append("\n");
616
617 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
618 // zero active threads.
619 int totalThreads = Process.GetCurrentProcess().Threads.Count;
620 if (totalThreads > 0)
621 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
622
623 sb.Append("Main threadpool (excluding script engine pools)\n");
624 sb.Append(Util.GetThreadPoolReport());
625
626 return sb.ToString();
627 }
628
629 public virtual void HandleThreadsAbort(string module, string[] cmd)
630 {
631 if (cmd.Length != 3)
632 {
633 MainConsole.Instance.Output("Usage: threads abort <thread-id>");
634 return;
635 }
636
637 int threadId;
638 if (!int.TryParse(cmd[2], out threadId))
639 {
640 MainConsole.Instance.Output("ERROR: Thread id must be an integer");
641 return;
642 }
643
644 if (Watchdog.AbortThread(threadId))
645 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
646 else
647 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
648 }
649
650 /// <summary>
651 /// Console output is only possible if a console has been established.
652 /// That is something that cannot be determined within this class. So
653 /// all attempts to use the console MUST be verified.
654 /// </summary>
655 /// <param name="msg"></param>
656 protected void Notice(string msg)
657 {
658 if (m_console != null)
659 {
660 m_console.Output(msg);
661 }
662 }
663
664 /// <summary>
665 /// Console output is only possible if a console has been established.
666 /// That is something that cannot be determined within this class. So
667 /// all attempts to use the console MUST be verified.
668 /// </summary>
669 /// <param name="format"></param>
670 /// <param name="components"></param>
671 protected void Notice(string format, params object[] components)
672 {
673 if (m_console != null)
674 m_console.OutputFormat(format, components);
675 }
676 }
677} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
index dc4eb8f..3412e0f 100644
--- a/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
+++ b/OpenSim/Framework/Servers/Tests/OSHttpTests.cs
@@ -35,11 +35,12 @@ using HttpServer;
35using HttpServer.FormDecoders; 35using HttpServer.FormDecoders;
36using NUnit.Framework; 36using NUnit.Framework;
37using OpenSim.Framework.Servers.HttpServer; 37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Tests.Common;
38 39
39namespace OpenSim.Framework.Servers.Tests 40namespace OpenSim.Framework.Servers.Tests
40{ 41{
41 [TestFixture] 42 [TestFixture]
42 public class OSHttpTests 43 public class OSHttpTests : OpenSimTestCase
43 { 44 {
44 // we need an IHttpClientContext for our tests 45 // we need an IHttpClientContext for our tests
45 public class TestHttpClientContext: IHttpClientContext 46 public class TestHttpClientContext: IHttpClientContext
diff --git a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
index 49e5061..480f2bb 100644
--- a/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
+++ b/OpenSim/Framework/Servers/Tests/VersionInfoTests.cs
@@ -29,11 +29,12 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using NUnit.Framework; 31using NUnit.Framework;
32using OpenSim.Tests.Common;
32 33
33namespace OpenSim.Framework.Servers.Tests 34namespace OpenSim.Framework.Servers.Tests
34{ 35{
35 [TestFixture] 36 [TestFixture]
36 public class VersionInfoTests 37 public class VersionInfoTests : OpenSimTestCase
37 { 38 {
38 [Test] 39 [Test]
39 public void TestVersionLength() 40 public void TestVersionLength()