aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
authorDan Lake2012-03-27 12:51:58 -0700
committerDan Lake2012-03-27 12:51:58 -0700
commit971d32fda3cf8384987a6709cd2242afecce13ab (patch)
tree2607c27fad429ff0036fe7b7d275ddf717397282 /OpenSim/Framework
parentWhen loading objects from DB, first add to scene, then call TriggerOnSceneObj... (diff)
parentHG: beginning of a more restrictive inventory access procedure (optional). Ex... (diff)
downloadopensim-SC-971d32fda3cf8384987a6709cd2242afecce13ab.zip
opensim-SC-971d32fda3cf8384987a6709cd2242afecce13ab.tar.gz
opensim-SC-971d32fda3cf8384987a6709cd2242afecce13ab.tar.bz2
opensim-SC-971d32fda3cf8384987a6709cd2242afecce13ab.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs122
-rw-r--r--OpenSim/Framework/GcNotify.cs62
-rw-r--r--OpenSim/Framework/IClientAPI.cs3
-rw-r--r--OpenSim/Framework/ICommandConsole.cs2
-rw-r--r--OpenSim/Framework/ILandObject.cs1
-rw-r--r--OpenSim/Framework/MultipartForm.cs2
-rw-r--r--OpenSim/Framework/RegionInfo.cs6
-rw-r--r--OpenSim/Framework/SLUtil.cs4
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs36
-rw-r--r--OpenSim/Framework/Statistics/BaseStatsCollector.cs8
-rw-r--r--OpenSim/Framework/Util.cs230
-rw-r--r--OpenSim/Framework/WebUtil.cs48
12 files changed, 412 insertions, 112 deletions
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index 0d6288b..c5d6b78 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -29,6 +29,7 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; 31using System.Diagnostics;
32using System.Linq;
32using System.Reflection; 33using System.Reflection;
33using System.Text; 34using System.Text;
34using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
@@ -40,6 +41,8 @@ namespace OpenSim.Framework.Console
40{ 41{
41 public class Commands : ICommands 42 public class Commands : ICommands
42 { 43 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
43 /// <summary> 46 /// <summary>
44 /// Encapsulates a command that can be invoked from the console 47 /// Encapsulates a command that can be invoked from the console
45 /// </summary> 48 /// </summary>
@@ -76,6 +79,8 @@ namespace OpenSim.Framework.Console
76 public List<CommandDelegate> fn; 79 public List<CommandDelegate> fn;
77 } 80 }
78 81
82 public const string GeneralHelpText = "For more information, type 'help <item>' where <item> is one of the following categories:";
83
79 /// <value> 84 /// <value>
80 /// Commands organized by keyword in a tree 85 /// Commands organized by keyword in a tree
81 /// </value> 86 /// </value>
@@ -83,6 +88,11 @@ namespace OpenSim.Framework.Console
83 new Dictionary<string, object>(); 88 new Dictionary<string, object>();
84 89
85 /// <summary> 90 /// <summary>
91 /// Commands organized by module
92 /// </summary>
93 private Dictionary<string, List<CommandInfo>> m_modulesCommands = new Dictionary<string, List<CommandInfo>>();
94
95 /// <summary>
86 /// Get help for the given help string 96 /// Get help for the given help string
87 /// </summary> 97 /// </summary>
88 /// <param name="helpParts">Parsed parts of the help string. If empty then general help is returned.</param> 98 /// <param name="helpParts">Parsed parts of the help string. If empty then general help is returned.</param>
@@ -98,8 +108,8 @@ namespace OpenSim.Framework.Console
98 // General help 108 // General help
99 if (helpParts.Count == 0) 109 if (helpParts.Count == 0)
100 { 110 {
101 help.AddRange(CollectHelp(tree)); 111 help.Add(GeneralHelpText);
102 help.Sort(); 112 help.AddRange(CollectModulesHelp(tree));
103 } 113 }
104 else 114 else
105 { 115 {
@@ -118,6 +128,13 @@ namespace OpenSim.Framework.Console
118 { 128 {
119 string originalHelpRequest = string.Join(" ", helpParts.ToArray()); 129 string originalHelpRequest = string.Join(" ", helpParts.ToArray());
120 List<string> help = new List<string>(); 130 List<string> help = new List<string>();
131
132 // Check modules first to see if we just need to display a list of those commands
133 if (TryCollectModuleHelp(originalHelpRequest, help))
134 {
135 help.Insert(0, GeneralHelpText);
136 return help;
137 }
121 138
122 Dictionary<string, object> dict = tree; 139 Dictionary<string, object> dict = tree;
123 while (helpParts.Count > 0) 140 while (helpParts.Count > 0)
@@ -161,25 +178,63 @@ namespace OpenSim.Framework.Console
161 return help; 178 return help;
162 } 179 }
163 180
164 private List<string> CollectHelp(Dictionary<string, object> dict) 181 /// <summary>
182 /// Try to collect help for the given module if that module exists.
183 /// </summary>
184 /// <param name="moduleName"></param>
185 /// <param name="helpText">/param>
186 /// <returns>true if there was the module existed, false otherwise.</returns>
187 private bool TryCollectModuleHelp(string moduleName, List<string> helpText)
165 { 188 {
166 List<string> result = new List<string>(); 189 lock (m_modulesCommands)
167
168 foreach (KeyValuePair<string, object> kvp in dict)
169 { 190 {
170 if (kvp.Value is Dictionary<string, Object>) 191 foreach (string key in m_modulesCommands.Keys)
171 { 192 {
172 result.AddRange(CollectHelp((Dictionary<string, Object>)kvp.Value)); 193 // Allow topic help requests to succeed whether they are upper or lowercase.
173 } 194 if (moduleName.ToLower() == key.ToLower())
174 else 195 {
175 { 196 List<CommandInfo> commands = m_modulesCommands[key];
176 if (((CommandInfo)kvp.Value).long_help != String.Empty) 197 var ourHelpText = commands.ConvertAll(c => string.Format("{0} - {1}", c.help_text, c.long_help));
177 result.Add(((CommandInfo)kvp.Value).help_text+" - "+ 198 ourHelpText.Sort();
178 ((CommandInfo)kvp.Value).long_help); 199 helpText.AddRange(ourHelpText);
200
201 return true;
202 }
179 } 203 }
204
205 return false;
206 }
207 }
208
209 private List<string> CollectModulesHelp(Dictionary<string, object> dict)
210 {
211 lock (m_modulesCommands)
212 {
213 List<string> helpText = new List<string>(m_modulesCommands.Keys);
214 helpText.Sort();
215 return helpText;
180 } 216 }
181 return result;
182 } 217 }
218
219// private List<string> CollectHelp(Dictionary<string, object> dict)
220// {
221// List<string> result = new List<string>();
222//
223// foreach (KeyValuePair<string, object> kvp in dict)
224// {
225// if (kvp.Value is Dictionary<string, Object>)
226// {
227// result.AddRange(CollectHelp((Dictionary<string, Object>)kvp.Value));
228// }
229// else
230// {
231// if (((CommandInfo)kvp.Value).long_help != String.Empty)
232// result.Add(((CommandInfo)kvp.Value).help_text+" - "+
233// ((CommandInfo)kvp.Value).long_help);
234// }
235// }
236// return result;
237// }
183 238
184 /// <summary> 239 /// <summary>
185 /// Add a command to those which can be invoked from the console. 240 /// Add a command to those which can be invoked from the console.
@@ -212,21 +267,19 @@ namespace OpenSim.Framework.Console
212 267
213 Dictionary<string, Object> current = tree; 268 Dictionary<string, Object> current = tree;
214 269
215 foreach (string s in parts) 270 foreach (string part in parts)
216 { 271 {
217 if (current.ContainsKey(s)) 272 if (current.ContainsKey(part))
218 { 273 {
219 if (current[s] is Dictionary<string, Object>) 274 if (current[part] is Dictionary<string, Object>)
220 { 275 current = (Dictionary<string, Object>)current[part];
221 current = (Dictionary<string, Object>)current[s];
222 }
223 else 276 else
224 return; 277 return;
225 } 278 }
226 else 279 else
227 { 280 {
228 current[s] = new Dictionary<string, Object>(); 281 current[part] = new Dictionary<string, Object>();
229 current = (Dictionary<string, Object>)current[s]; 282 current = (Dictionary<string, Object>)current[part];
230 } 283 }
231 } 284 }
232 285
@@ -250,6 +303,24 @@ namespace OpenSim.Framework.Console
250 info.fn = new List<CommandDelegate>(); 303 info.fn = new List<CommandDelegate>();
251 info.fn.Add(fn); 304 info.fn.Add(fn);
252 current[String.Empty] = info; 305 current[String.Empty] = info;
306
307 // Now add command to modules dictionary
308 lock (m_modulesCommands)
309 {
310 List<CommandInfo> commands;
311 if (m_modulesCommands.ContainsKey(module))
312 {
313 commands = m_modulesCommands[module];
314 }
315 else
316 {
317 commands = new List<CommandInfo>();
318 m_modulesCommands[module] = commands;
319 }
320
321// m_log.DebugFormat("[COMMAND CONSOLE]: Adding to category {0} command {1}", module, command);
322 commands.Add(info);
323 }
253 } 324 }
254 325
255 public string[] FindNextOption(string[] cmd, bool term) 326 public string[] FindNextOption(string[] cmd, bool term)
@@ -607,8 +678,9 @@ namespace OpenSim.Framework.Console
607 { 678 {
608 Commands = new Commands(); 679 Commands = new Commands();
609 680
610 Commands.AddCommand("console", false, "help", "help [<command>]", 681 Commands.AddCommand(
611 "Get general command list or more detailed help on a specific command", Help); 682 "Help", false, "help", "help [<item>]",
683 "Display help on a particular command or on a list of commands in a category", Help);
612 } 684 }
613 685
614 private void Help(string module, string[] cmd) 686 private void Help(string module, string[] cmd)
diff --git a/OpenSim/Framework/GcNotify.cs b/OpenSim/Framework/GcNotify.cs
new file mode 100644
index 0000000..14a22a6
--- /dev/null
+++ b/OpenSim/Framework/GcNotify.cs
@@ -0,0 +1,62 @@
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.Reflection;
30using log4net;
31
32public class GcNotify
33{
34 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
35
36 public static bool Enabled
37 {
38 get { return s_initialized; }
39 set
40 {
41 if (!s_initialized && value)
42 new GcNotify();
43
44 s_initialized = value;
45 }
46 }
47
48 private static bool s_initialized = false;
49
50 private GcNotify() {}
51
52 ~GcNotify()
53 {
54 if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload())
55 {
56 m_log.DebugFormat("[GC NOTIFY]: Garbage collection triggered.");
57
58 if (Enabled)
59 new GcNotify();
60 }
61 }
62} \ No newline at end of file
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index c85e599..3f560d0 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1215,10 +1215,9 @@ namespace OpenSim.Framework
1215 /// <param name="OrbitalPosition">The orbital position is given in radians, and must be "adjusted" for the linden client, see LLClientView</param> 1215 /// <param name="OrbitalPosition">The orbital position is given in radians, and must be "adjusted" for the linden client, see LLClientView</param>
1216 void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, 1216 void SendSunPos(Vector3 sunPos, Vector3 sunVel, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear,
1217 float OrbitalPosition); 1217 float OrbitalPosition);
1218 1218
1219 void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks); 1219 void SendViewerEffect(ViewerEffectPacket.EffectBlock[] effectBlocks);
1220 void SendViewerTime(int phase); 1220 void SendViewerTime(int phase);
1221 UUID GetDefaultAnimation(string name);
1222 1221
1223 void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, string flAbout, 1222 void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, string flAbout,
1224 uint flags, UUID flImageID, UUID imageID, string profileURL, UUID partnerID); 1223 uint flags, UUID flImageID, UUID imageID, string profileURL, UUID partnerID);
diff --git a/OpenSim/Framework/ICommandConsole.cs b/OpenSim/Framework/ICommandConsole.cs
index d33b9b5..ca0ff93 100644
--- a/OpenSim/Framework/ICommandConsole.cs
+++ b/OpenSim/Framework/ICommandConsole.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Framework
40 /// <summary> 40 /// <summary>
41 /// Get help for the given help string 41 /// Get help for the given help string
42 /// </summary> 42 /// </summary>
43 /// <param name="helpParts">Parsed parts of the help string. If empty then general help is returned.</param> 43 /// <param name="cmd">Parsed parts of the help string. If empty then general help is returned.</param>
44 /// <returns></returns> 44 /// <returns></returns>
45 List<string> GetHelp(string[] cmd); 45 List<string> GetHelp(string[] cmd);
46 46
diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs
index dd73b3f..4f98d7b 100644
--- a/OpenSim/Framework/ILandObject.cs
+++ b/OpenSim/Framework/ILandObject.cs
@@ -71,6 +71,7 @@ namespace OpenSim.Framework
71 bool IsEitherBannedOrRestricted(UUID avatar); 71 bool IsEitherBannedOrRestricted(UUID avatar);
72 bool IsBannedFromLand(UUID avatar); 72 bool IsBannedFromLand(UUID avatar);
73 bool IsRestrictedFromLand(UUID avatar); 73 bool IsRestrictedFromLand(UUID avatar);
74 bool IsInLandAccessList(UUID avatar);
74 void SendLandUpdateToClient(IClientAPI remote_client); 75 void SendLandUpdateToClient(IClientAPI remote_client);
75 void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client); 76 void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client);
76 List<LandAccessEntry> CreateAccessListArrayByFlag(AccessList flag); 77 List<LandAccessEntry> CreateAccessListArrayByFlag(AccessList flag);
diff --git a/OpenSim/Framework/MultipartForm.cs b/OpenSim/Framework/MultipartForm.cs
index 90c4007..7a13e8b 100644
--- a/OpenSim/Framework/MultipartForm.cs
+++ b/OpenSim/Framework/MultipartForm.cs
@@ -119,7 +119,7 @@ namespace OpenSim.Framework
119 // Copy the temporary stream to the network stream 119 // Copy the temporary stream to the network stream
120 formDataStream.Seek(0, SeekOrigin.Begin); 120 formDataStream.Seek(0, SeekOrigin.Begin);
121 using (Stream requestStream = request.GetRequestStream()) 121 using (Stream requestStream = request.GetRequestStream())
122 formDataStream.CopyTo(requestStream, (int)formDataStream.Length); 122 formDataStream.CopyStream(requestStream, (int)formDataStream.Length);
123 } 123 }
124 124
125 #endregion Stream Writing 125 #endregion Stream Writing
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 5ba3863..a505524 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -421,12 +421,18 @@ namespace OpenSim.Framework
421 set { m_internalEndPoint = value; } 421 set { m_internalEndPoint = value; }
422 } 422 }
423 423
424 /// <summary>
425 /// The x co-ordinate of this region in map tiles (e.g. 1000).
426 /// </summary>
424 public uint RegionLocX 427 public uint RegionLocX
425 { 428 {
426 get { return m_regionLocX.Value; } 429 get { return m_regionLocX.Value; }
427 set { m_regionLocX = value; } 430 set { m_regionLocX = value; }
428 } 431 }
429 432
433 /// <summary>
434 /// The y co-ordinate of this region in map tiles (e.g. 1000).
435 /// </summary>
430 public uint RegionLocY 436 public uint RegionLocY
431 { 437 {
432 get { return m_regionLocY.Value; } 438 get { return m_regionLocY.Value; }
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index b337e03..db4541e 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -27,7 +27,9 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
30using System.Reflection; 31using System.Reflection;
32using System.Xml;
31using log4net; 33using log4net;
32using OpenMetaverse; 34using OpenMetaverse;
33 35
@@ -375,4 +377,4 @@ namespace OpenSim.Framework
375 return output; 377 return output;
376 } 378 }
377 } 379 }
378} 380} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 6a3135e..06a8021 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -161,43 +161,43 @@ namespace OpenSim.Framework.Servers
161 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold)); 161 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
162 } 162 }
163 163
164 m_console.Commands.AddCommand("base", false, "quit", 164 m_console.Commands.AddCommand("General", false, "quit",
165 "quit", 165 "quit",
166 "Quit the application", HandleQuit); 166 "Quit the application", HandleQuit);
167 167
168 m_console.Commands.AddCommand("base", false, "shutdown", 168 m_console.Commands.AddCommand("General", false, "shutdown",
169 "shutdown", 169 "shutdown",
170 "Quit the application", HandleQuit); 170 "Quit the application", HandleQuit);
171 171
172 m_console.Commands.AddCommand("base", false, "set log level", 172 m_console.Commands.AddCommand("General", false, "set log level",
173 "set log level <level>", 173 "set log level <level>",
174 "Set the console logging level", HandleLogLevel); 174 "Set the console logging level", HandleLogLevel);
175 175
176 m_console.Commands.AddCommand("base", false, "show info", 176 m_console.Commands.AddCommand("General", false, "show info",
177 "show info", 177 "show info",
178 "Show general information about the server", HandleShow); 178 "Show general information about the server", HandleShow);
179 179
180 m_console.Commands.AddCommand("base", false, "show stats", 180 m_console.Commands.AddCommand("General", false, "show stats",
181 "show stats", 181 "show stats",
182 "Show statistics", HandleShow); 182 "Show statistics", HandleShow);
183 183
184 m_console.Commands.AddCommand("base", false, "show threads", 184 m_console.Commands.AddCommand("General", false, "show threads",
185 "show threads", 185 "show threads",
186 "Show thread status", HandleShow); 186 "Show thread status", HandleShow);
187 187
188 m_console.Commands.AddCommand("base", false, "show uptime", 188 m_console.Commands.AddCommand("General", false, "show uptime",
189 "show uptime", 189 "show uptime",
190 "Show server uptime", HandleShow); 190 "Show server uptime", HandleShow);
191 191
192 m_console.Commands.AddCommand("base", false, "show version", 192 m_console.Commands.AddCommand("General", false, "show version",
193 "show version", 193 "show version",
194 "Show server version", HandleShow); 194 "Show server version", HandleShow);
195 195
196 m_console.Commands.AddCommand("base", false, "threads abort", 196 m_console.Commands.AddCommand("General", false, "threads abort",
197 "threads abort <thread-id>", 197 "threads abort <thread-id>",
198 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); 198 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
199 199
200 m_console.Commands.AddCommand("base", false, "threads show", 200 m_console.Commands.AddCommand("General", false, "threads show",
201 "threads show", 201 "threads show",
202 "Show thread status. Synonym for \"show threads\"", 202 "Show thread status. Synonym for \"show threads\"",
203 (string module, string[] args) => Notice(GetThreadsReport())); 203 (string module, string[] args) => Notice(GetThreadsReport()));
@@ -269,15 +269,19 @@ namespace OpenSim.Framework.Servers
269 t.Priority, 269 t.Priority,
270 t.ThreadState); 270 t.ThreadState);
271 271
272 sb.Append(Environment.NewLine); 272 sb.Append("\n");
273 } 273 }
274 274
275 int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0; 275 sb.Append("\n");
276 ThreadPool.GetAvailableThreads(out workers, out ports);
277 ThreadPool.GetMaxThreads(out maxWorkers, out maxPorts);
278 276
279 sb.Append(Environment.NewLine + "*** ThreadPool threads ***" + Environment.NewLine); 277 // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
280 sb.Append("workers: " + (maxWorkers - workers) + " (" + maxWorkers + "); ports: " + (maxPorts - ports) + " (" + maxPorts + ")" + Environment.NewLine); 278 // zero active threads.
279 int totalThreads = Process.GetCurrentProcess().Threads.Count;
280 if (totalThreads > 0)
281 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
282
283 sb.Append("Main threadpool (excluding script engine pools)\n");
284 sb.Append(Util.GetThreadPoolReport());
281 285
282 return sb.ToString(); 286 return sb.ToString();
283 } 287 }
diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs
index a1841c5..c9e57ce 100644
--- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs
@@ -26,8 +26,8 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Diagnostics;
29using System.Text; 30using System.Text;
30
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33 33
@@ -46,8 +46,12 @@ namespace OpenSim.Framework.Statistics
46 sb.Append(Environment.NewLine); 46 sb.Append(Environment.NewLine);
47 sb.Append( 47 sb.Append(
48 string.Format( 48 string.Format(
49 "Allocated to OpenSim : {0} MB" + Environment.NewLine, 49 "Allocated to OpenSim objects: {0} MB\n",
50 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); 50 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
51 sb.Append(
52 string.Format(
53 "Process memory : {0} MB\n",
54 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0)));
51 55
52 return sb.ToString(); 56 return sb.ToString();
53 } 57 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index efa4a7b..e03bb74 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -35,7 +35,7 @@ using System.IO;
35using System.IO.Compression; 35using System.IO.Compression;
36using System.Net; 36using System.Net;
37using System.Net.Sockets; 37using System.Net.Sockets;
38using System.Reflection; 38using System.Reflection;
39using System.Runtime.InteropServices; 39using System.Runtime.InteropServices;
40using System.Runtime.Serialization; 40using System.Runtime.Serialization;
41using System.Runtime.Serialization.Formatters.Binary; 41using System.Runtime.Serialization.Formatters.Binary;
@@ -81,12 +81,15 @@ namespace OpenSim.Framework
81 81
82 private static uint nextXferID = 5000; 82 private static uint nextXferID = 5000;
83 private static Random randomClass = new Random(); 83 private static Random randomClass = new Random();
84
84 // Get a list of invalid file characters (OS dependent) 85 // Get a list of invalid file characters (OS dependent)
85 private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]"; 86 private static string regexInvalidFileChars = "[" + new String(Path.GetInvalidFileNameChars()) + "]";
86 private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]"; 87 private static string regexInvalidPathChars = "[" + new String(Path.GetInvalidPathChars()) + "]";
87 private static object XferLock = new object(); 88 private static object XferLock = new object();
88 /// <summary>Thread pool used for Util.FireAndForget if 89
89 /// FireAndForgetMethod.SmartThreadPool is used</summary> 90 /// <summary>
91 /// Thread pool used for Util.FireAndForget if FireAndForgetMethod.SmartThreadPool is used
92 /// </summary>
90 private static SmartThreadPool m_ThreadPool; 93 private static SmartThreadPool m_ThreadPool;
91 94
92 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. 95 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
@@ -144,7 +147,6 @@ namespace OpenSim.Framework
144 return lerp(y, lerp(x, a, b), lerp(x, c, d)); 147 return lerp(y, lerp(x, a, b), lerp(x, c, d));
145 } 148 }
146 149
147
148 public static Encoding UTF8 = Encoding.UTF8; 150 public static Encoding UTF8 = Encoding.UTF8;
149 151
150 /// <value> 152 /// <value>
@@ -376,20 +378,20 @@ namespace OpenSim.Framework
376 } 378 }
377 379
378 return sb.ToString(); 380 return sb.ToString();
379 } 381 }
380 382
381 /// <summary> 383 /// <summary>
382 /// Is the platform Windows? 384 /// Is the platform Windows?
383 /// </summary> 385 /// </summary>
384 /// <returns>true if so, false otherwise</returns> 386 /// <returns>true if so, false otherwise</returns>
385 public static bool IsWindows() 387 public static bool IsWindows()
386 { 388 {
387 PlatformID platformId = Environment.OSVersion.Platform; 389 PlatformID platformId = Environment.OSVersion.Platform;
388 390
389 return (platformId == PlatformID.Win32NT 391 return (platformId == PlatformID.Win32NT
390 || platformId == PlatformID.Win32S 392 || platformId == PlatformID.Win32S
391 || platformId == PlatformID.Win32Windows 393 || platformId == PlatformID.Win32Windows
392 || platformId == PlatformID.WinCE); 394 || platformId == PlatformID.WinCE);
393 } 395 }
394 396
395 public static bool LoadArchSpecificWindowsDll(string libraryName) 397 public static bool LoadArchSpecificWindowsDll(string libraryName)
@@ -1502,27 +1504,27 @@ namespace OpenSim.Framework
1502 } 1504 }
1503 1505
1504 return data; 1506 return data;
1505 } 1507 }
1506 1508
1507 /// <summary> 1509 /// <summary>
1508 /// Used to trigger an early library load on Windows systems. 1510 /// Used to trigger an early library load on Windows systems.
1509 /// </summary> 1511 /// </summary>
1510 /// <remarks> 1512 /// <remarks>
1511 /// Required to get 32-bit and 64-bit processes to automatically use the 1513 /// Required to get 32-bit and 64-bit processes to automatically use the
1512 /// appropriate native library. 1514 /// appropriate native library.
1513 /// </remarks> 1515 /// </remarks>
1514 /// <param name="dllToLoad"></param> 1516 /// <param name="dllToLoad"></param>
1515 /// <returns></returns> 1517 /// <returns></returns>
1516 [DllImport("kernel32.dll")] 1518 [DllImport("kernel32.dll")]
1517 public static extern IntPtr LoadLibrary(string dllToLoad); 1519 public static extern IntPtr LoadLibrary(string dllToLoad);
1518 1520
1519 /// <summary> 1521 /// <summary>
1520 /// Determine whether the current process is 64 bit 1522 /// Determine whether the current process is 64 bit
1521 /// </summary> 1523 /// </summary>
1522 /// <returns>true if so, false if not</returns> 1524 /// <returns>true if so, false if not</returns>
1523 public static bool Is64BitProcess() 1525 public static bool Is64BitProcess()
1524 { 1526 {
1525 return IntPtr.Size == 8; 1527 return IntPtr.Size == 8;
1526 } 1528 }
1527 1529
1528 #region FireAndForget Threading Pattern 1530 #region FireAndForget Threading Pattern
@@ -1671,6 +1673,61 @@ namespace OpenSim.Framework
1671 } 1673 }
1672 } 1674 }
1673 1675
1676 /// <summary>
1677 /// Get a thread pool report.
1678 /// </summary>
1679 /// <returns></returns>
1680 public static string GetThreadPoolReport()
1681 {
1682 string threadPoolUsed = null;
1683 int maxThreads = 0;
1684 int minThreads = 0;
1685 int allocatedThreads = 0;
1686 int inUseThreads = 0;
1687 int waitingCallbacks = 0;
1688 int completionPortThreads = 0;
1689
1690 StringBuilder sb = new StringBuilder();
1691 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1692 {
1693 threadPoolUsed = "SmartThreadPool";
1694 maxThreads = m_ThreadPool.MaxThreads;
1695 minThreads = m_ThreadPool.MinThreads;
1696 inUseThreads = m_ThreadPool.InUseThreads;
1697 allocatedThreads = m_ThreadPool.ActiveThreads;
1698 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1699 }
1700 else if (
1701 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1702 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1703 {
1704 threadPoolUsed = "BuiltInThreadPool";
1705 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1706 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1707 int availableThreads;
1708 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1709 inUseThreads = maxThreads - availableThreads;
1710 allocatedThreads = -1;
1711 waitingCallbacks = -1;
1712 }
1713
1714 if (threadPoolUsed != null)
1715 {
1716 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
1717 sb.AppendFormat("Max threads : {0}\n", maxThreads);
1718 sb.AppendFormat("Min threads : {0}\n", minThreads);
1719 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
1720 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
1721 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
1722 }
1723 else
1724 {
1725 sb.AppendFormat("Thread pool not used\n");
1726 }
1727
1728 return sb.ToString();
1729 }
1730
1674 private static object SmartThreadPoolCallback(object o) 1731 private static object SmartThreadPoolCallback(object o)
1675 { 1732 {
1676 object[] array = (object[])o; 1733 object[] array = (object[])o;
@@ -1701,13 +1758,26 @@ namespace OpenSim.Framework
1701 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by 1758 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by
1702 /// 'EnvironmentTickCount()') and accounts for any wrapping. 1759 /// 'EnvironmentTickCount()') and accounts for any wrapping.
1703 /// </summary> 1760 /// </summary>
1761 /// <param name="newValue"></param>
1762 /// <param name="prevValue"></param>
1704 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns> 1763 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
1705 public static Int32 EnvironmentTickCountSubtract(Int32 prevValue) 1764 public static Int32 EnvironmentTickCountSubtract(Int32 newValue, Int32 prevValue)
1706 { 1765 {
1707 Int32 diff = EnvironmentTickCount() - prevValue; 1766 Int32 diff = newValue - prevValue;
1708 return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); 1767 return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1);
1709 } 1768 }
1710 1769
1770 /// <summary>
1771 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive
1772 /// and negative every 24.9 days. Subtracts the passed value (previously fetched by
1773 /// 'EnvironmentTickCount()') and accounts for any wrapping.
1774 /// </summary>
1775 /// <returns>subtraction of passed prevValue from current Environment.TickCount</returns>
1776 public static Int32 EnvironmentTickCountSubtract(Int32 prevValue)
1777 {
1778 return EnvironmentTickCountSubtract(EnvironmentTickCount(), prevValue);
1779 }
1780
1711 // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount 1781 // Returns value of Tick Count A - TickCount B accounting for wrapping of TickCount
1712 // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount(). 1782 // Assumes both tcA and tcB came from previous calls to Util.EnvironmentTickCount().
1713 // A positive return value indicates A occured later than B 1783 // A positive return value indicates A occured later than B
@@ -1870,11 +1940,12 @@ namespace OpenSim.Framework
1870 #region Universal User Identifiers 1940 #region Universal User Identifiers
1871 /// <summary> 1941 /// <summary>
1872 /// </summary> 1942 /// </summary>
1873 /// <param name="value">uuid[;endpoint[;name]]</param> 1943 /// <param name="value">uuid[;endpoint[;first last[;secret]]]</param>
1874 /// <param name="uuid"></param> 1944 /// <param name="uuid">the uuid part</param>
1875 /// <param name="url"></param> 1945 /// <param name="url">the endpoint part (e.g. http://foo.com)</param>
1876 /// <param name="firstname"></param> 1946 /// <param name="firstname">the first name part (e.g. Test)</param>
1877 /// <param name="lastname"></param> 1947 /// <param name="lastname">the last name part (e.g User)</param>
1948 /// <param name="secret">the secret part</param>
1878 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) 1949 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
1879 { 1950 {
1880 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 1951 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty;
@@ -1903,31 +1974,64 @@ namespace OpenSim.Framework
1903 } 1974 }
1904 1975
1905 /// <summary> 1976 /// <summary>
1906 /// 1977 /// Produces a universal (HG) system-facing identifier given the information
1907 /// </summary> 1978 /// </summary>
1908 /// <param name="acircuit"></param> 1979 /// <param name="acircuit"></param>
1909 /// <returns>uuid[;endpoint[;name]]</returns> 1980 /// <returns>uuid[;homeURI[;first last]]</returns>
1910 public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit) 1981 public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit)
1911 { 1982 {
1912 if (acircuit.ServiceURLs.ContainsKey("HomeURI")) 1983 if (acircuit.ServiceURLs.ContainsKey("HomeURI"))
1984 return UniversalIdentifier(acircuit.AgentID, acircuit.firstname, acircuit.lastname, acircuit.ServiceURLs["HomeURI"].ToString());
1985 else
1986 return acircuit.AgentID.ToString();
1987 }
1988
1989 /// <summary>
1990 /// Produces a universal (HG) system-facing identifier given the information
1991 /// </summary>
1992 /// <param name="id">UUID of the user</param>
1993 /// <param name="firstName">first name (e.g Test)</param>
1994 /// <param name="lastName">last name (e.g. User)</param>
1995 /// <param name="homeURI">homeURI (e.g. http://foo.com)</param>
1996 /// <returns>a string of the form uuid[;homeURI[;first last]]</returns>
1997 public static string UniversalIdentifier(UUID id, String firstName, String lastName, String homeURI)
1998 {
1999 string agentsURI = homeURI;
2000 if (!agentsURI.EndsWith("/"))
2001 agentsURI += "/";
2002
2003 // This is ugly, but there's no other way, given that the name is changed
2004 // in the agent circuit data for foreigners
2005 if (lastName.Contains("@"))
1913 { 2006 {
1914 string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString(); 2007 string[] parts = firstName.Split(new char[] { '.' });
1915 if (!agentsURI.EndsWith("/")) 2008 if (parts.Length == 2)
1916 agentsURI += "/"; 2009 return id.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
2010 }
2011 return id.ToString() + ";" + agentsURI + ";" + firstName + " " + lastName;
1917 2012
1918 // This is ugly, but there's no other way, given that the name is changed 2013 }
1919 // in the agent circuit data for foreigners 2014
1920 if (acircuit.lastname.Contains("@")) 2015 /// <summary>
1921 { 2016 /// Produces a universal (HG) user-facing name given the information
1922 string[] parts = acircuit.firstname.Split(new char[] { '.' }); 2017 /// </summary>
1923 if (parts.Length == 2) 2018 /// <param name="firstName"></param>
1924 return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1]; 2019 /// <param name="lastName"></param>
1925 } 2020 /// <param name="homeURI"></param>
1926 return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname; 2021 /// <returns>string of the form first.last @foo.com or first last</returns>
2022 public static string UniversalName(String firstName, String lastName, String homeURI)
2023 {
2024 Uri uri = null;
2025 try
2026 {
2027 uri = new Uri(homeURI);
1927 } 2028 }
1928 else 2029 catch (UriFormatException)
1929 return acircuit.AgentID.ToString(); 2030 {
1930 } 2031 return firstName + " " + lastName;
2032 }
2033 return firstName + "." + lastName + " " + "@" + uri.Authority;
2034 }
1931 #endregion 2035 #endregion
1932 } 2036 }
1933} 2037}
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index af25da9..ead8f46 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -63,6 +63,31 @@ namespace OpenSim.Framework
63 // a "long" call for warning & debugging purposes 63 // a "long" call for warning & debugging purposes
64 public const int LongCallTime = 500; 64 public const int LongCallTime = 500;
65 65
66 // dictionary of end points
67 private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
68
69
70 private static object EndPointLock(string url)
71 {
72 System.Uri uri = new System.Uri(url);
73 string endpoint = string.Format("{0}:{1}",uri.Host,uri.Port);
74
75 lock (m_endpointSerializer)
76 {
77 object eplock = null;
78
79 if (! m_endpointSerializer.TryGetValue(endpoint,out eplock))
80 {
81 eplock = new object();
82 m_endpointSerializer.Add(endpoint,eplock);
83 // m_log.WarnFormat("[WEB UTIL] add a new host to end point serializer {0}",endpoint);
84 }
85
86 return eplock;
87 }
88 }
89
90
66 #region JSONRequest 91 #region JSONRequest
67 92
68 /// <summary> 93 /// <summary>
@@ -96,6 +121,14 @@ namespace OpenSim.Framework
96 121
97 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed) 122 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
98 { 123 {
124 lock (EndPointLock(url))
125 {
126 return ServiceOSDRequestWorker(url,data,method,timeout,compressed);
127 }
128 }
129
130 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
131 {
99 int reqnum = m_requestNumber++; 132 int reqnum = m_requestNumber++;
100 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 133 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
101 134
@@ -248,6 +281,14 @@ namespace OpenSim.Framework
248 281
249 public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout) 282 public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout)
250 { 283 {
284 lock (EndPointLock(url))
285 {
286 return ServiceFormRequestWorker(url,data,timeout);
287 }
288 }
289
290 private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
291 {
251 int reqnum = m_requestNumber++; 292 int reqnum = m_requestNumber++;
252 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 293 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
253 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method); 294 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
@@ -469,8 +510,13 @@ namespace OpenSim.Framework
469 /// <remarks> 510 /// <remarks>
470 /// Copying begins at the streams' current positions. The positions are 511 /// Copying begins at the streams' current positions. The positions are
471 /// NOT reset after copying is complete. 512 /// NOT reset after copying is complete.
513 /// NOTE!! .NET 4.0 adds the method 'Stream.CopyTo(stream, bufferSize)'.
514 /// This function could be replaced with that method once we move
515 /// totally to .NET 4.0. For versions before, this routine exists.
516 /// This routine used to be named 'CopyTo' but the int parameter has
517 /// a different meaning so this method was renamed to avoid any confusion.
472 /// </remarks> 518 /// </remarks>
473 public static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) 519 public static int CopyStream(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy)
474 { 520 {
475 byte[] buffer = new byte[4096]; 521 byte[] buffer = new byte[4096];
476 int readBytes; 522 int readBytes;