aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2013-06-23 01:59:57 +0100
committerMelanie2013-06-23 01:59:57 +0100
commitf70357eaa355b8c152f3d793d0fceafa14df5fd4 (patch)
treeffda32c340bd7f6d69652e9d9a959c7396f42a2f /OpenSim
parentMerge branch 'avination-current' into careminster (diff)
parentMerge branch 'master' of melanie@opensimulator.org:/var/git/opensim (diff)
downloadopensim-SC-f70357eaa355b8c152f3d793d0fceafa14df5fd4.zip
opensim-SC-f70357eaa355b8c152f3d793d0fceafa14df5fd4.tar.gz
opensim-SC-f70357eaa355b8c152f3d793d0fceafa14df5fd4.tar.bz2
opensim-SC-f70357eaa355b8c152f3d793d0fceafa14df5fd4.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Framework/Monitoring/BaseStatsCollector.cs OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs4
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs14
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs8
-rw-r--r--OpenSim/Framework/Monitoring/ServerStatsCollector.cs349
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs24
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs130
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs46
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs30
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs20
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs95
-rw-r--r--OpenSim/Framework/Util.cs104
-rw-r--r--OpenSim/Region/Application/Application.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs2
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs20
-rw-r--r--OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs339
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs44
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs66
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs3
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs20
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs2
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs200
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs2
-rw-r--r--OpenSim/Server/Handlers/Simulation/AgentHandlers.cs77
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs68
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs138
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs31
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs12
-rw-r--r--OpenSim/Services/Interfaces/IHypergridServices.cs5
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs2
34 files changed, 952 insertions, 950 deletions
diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
index 6ba022c..6731923 100644
--- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
+++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
@@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
46{ 46{
47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService 47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private const int MAX_IM = 25; 50 private const int MAX_IM = 25;
51 51
52 private XmlSerializer m_serializer; 52 private XmlSerializer m_serializer;
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
index c305797..d1503ee 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
46{ 46{
47 public class FetchInventory2Handler 47 public class FetchInventory2Handler
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private IInventoryService m_inventoryService; 51 private IInventoryService m_inventoryService;
52 52
@@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
121 return llsdItem; 121 return llsdItem;
122 } 122 }
123 } 123 }
124} 124} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 23dba09..96536e8 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -44,16 +44,16 @@ namespace OpenSim.Framework.Monitoring
44 sb.Append("MEMORY STATISTICS"); 44 sb.Append("MEMORY STATISTICS");
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46 sb.AppendFormat( 46 sb.AppendFormat(
47 "Allocated to OpenSim objects: {0} MB\n", 47 "Heap allocated to OpenSim : {0} MB\n",
48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
49 49
50 sb.AppendFormat( 50 sb.AppendFormat(
51 "OpenSim last object memory churn : {0} MB/s\n", 51 "Last heap allocation rate : {0} MB/s\n",
52 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); 52 Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
53 53
54 sb.AppendFormat( 54 sb.AppendFormat(
55 "OpenSim average object memory churn : {0} MB/s\n", 55 "Average heap allocation rate: {0} MB/s\n",
56 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); 56 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
57 57
58 Process myprocess = Process.GetCurrentProcess(); 58 Process myprocess = Process.GetCurrentProcess();
59 if (!myprocess.HasExited) 59 if (!myprocess.HasExited)
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index c6010cd..c474622 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Last memory churn in bytes per millisecond. 63 /// Average heap allocation rate in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageHeapAllocationRate
66 { 66 {
67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } 67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond. 71 /// Last heap allocation in bytes
72 /// </summary> 72 /// </summary>
73 public static double LastMemoryChurn 73 public static double LastHeapAllocationRate
74 { 74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } 75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 } 76 }
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
new file mode 100644
index 0000000..ac0f0bc
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
@@ -0,0 +1,349 @@
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.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35using log4net;
36using Nini.Config;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39
40namespace OpenSim.Framework.Monitoring
41{
42 public class ServerStatsCollector
43 {
44 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45 private readonly string LogHeader = "[SERVER STATS]";
46
47 public bool Enabled = false;
48 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
49
50 public readonly string CategoryServer = "server";
51
52 public readonly string ContainerThreadpool = "threadpool";
53 public readonly string ContainerProcessor = "processor";
54 public readonly string ContainerMemory = "memory";
55 public readonly string ContainerNetwork = "network";
56 public readonly string ContainerProcess = "process";
57
58 public string NetworkInterfaceTypes = "Ethernet";
59
60 readonly int performanceCounterSampleInterval = 500;
61// int lastperformanceCounterSampleTime = 0;
62
63 private class PerfCounterControl
64 {
65 public PerformanceCounter perfCounter;
66 public int lastFetch;
67 public string name;
68 public PerfCounterControl(PerformanceCounter pPc)
69 : this(pPc, String.Empty)
70 {
71 }
72 public PerfCounterControl(PerformanceCounter pPc, string pName)
73 {
74 perfCounter = pPc;
75 lastFetch = 0;
76 name = pName;
77 }
78 }
79
80 PerfCounterControl processorPercentPerfCounter = null;
81
82 // IRegionModuleBase.Initialize
83 public void Initialise(IConfigSource source)
84 {
85 IConfig cfg = source.Configs["Monitoring"];
86
87 if (cfg != null)
88 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
89
90 if (Enabled)
91 {
92 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
93 }
94 }
95
96 public void Start()
97 {
98 if (RegisteredStats.Count == 0)
99 RegisterServerStats();
100 }
101
102 public void Close()
103 {
104 if (RegisteredStats.Count > 0)
105 {
106 foreach (Stat stat in RegisteredStats.Values)
107 {
108 StatsManager.DeregisterStat(stat);
109 stat.Dispose();
110 }
111 RegisteredStats.Clear();
112 }
113 }
114
115 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
116 {
117 MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
118 }
119
120 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
121 {
122 string desc = pDesc;
123 if (desc == null)
124 desc = pName;
125 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
126 StatsManager.RegisterStat(stat);
127 RegisteredStats.Add(pName, stat);
128 }
129
130 public void RegisterServerStats()
131 {
132// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
133 PerformanceCounter tempPC;
134 Stat tempStat;
135 string tempName;
136
137 try
138 {
139 tempName = "CPUPercent";
140 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
141 processorPercentPerfCounter = new PerfCounterControl(tempPC);
142 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
143 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
144 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
145 StatVerbosity.Info);
146 StatsManager.RegisterStat(tempStat);
147 RegisteredStats.Add(tempName, tempStat);
148
149 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
150 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
151
152 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
153 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
154
155 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
156 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
157
158 MakeStat("Threads", null, "threads", ContainerProcessor,
159 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
160 }
161 catch (Exception e)
162 {
163 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
164 }
165
166 MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
167 s =>
168 {
169 int workerThreads, iocpThreads;
170 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
171 s.Value = workerThreads;
172 });
173
174 MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
175 s =>
176 {
177 int workerThreads, iocpThreads;
178 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
179 s.Value = iocpThreads;
180 });
181
182 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
183 {
184 MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
185 MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
186 MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
187 MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
188 MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
189 MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
190 }
191
192 MakeStat(
193 "HTTPRequestsMade",
194 "Number of outbound HTTP requests made",
195 "requests",
196 ContainerNetwork,
197 s => s.Value = WebUtil.RequestNumber,
198 MeasuresOfInterest.AverageChangeOverTime);
199
200 try
201 {
202 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
203
204 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
205 foreach (NetworkInterface nic in nics)
206 {
207 if (nic.OperationalStatus != OperationalStatus.Up)
208 continue;
209
210 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
211 if (!okInterfaceTypes.Contains(nicInterfaceType))
212 {
213 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
214 LogHeader, nic.Name, nicInterfaceType);
215 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
216 LogHeader, NetworkInterfaceTypes);
217 continue;
218 }
219
220 if (nic.Supports(NetworkInterfaceComponent.IPv4))
221 {
222 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
223 if (nicStats != null)
224 {
225 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
226 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
227 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
228 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
229 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
230 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
231 }
232 }
233 // TODO: add IPv6 (it may actually happen someday)
234 }
235 }
236 catch (Exception e)
237 {
238 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
239 }
240
241 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
242 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
243 MakeStat("HeapMemory", null, "MB", ContainerMemory,
244 (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
245 MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
246 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
247 MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
248 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
249 }
250
251 // Notes on performance counters:
252 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
253 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
254 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
255 private delegate double PerfCounterNextValue();
256 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
257 {
258 GetNextValue(stat, perfControl, 1.0);
259 }
260 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
261 {
262 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
263 {
264 if (perfControl != null && perfControl.perfCounter != null)
265 {
266 try
267 {
268 // Kludge for factor to run double duty. If -1, subtract the value from one
269 if (factor == -1)
270 stat.Value = 1 - perfControl.perfCounter.NextValue();
271 else
272 stat.Value = perfControl.perfCounter.NextValue() / factor;
273 }
274 catch (Exception e)
275 {
276 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
277 }
278 perfControl.lastFetch = Util.EnvironmentTickCount();
279 }
280 }
281 }
282
283 // Lookup the nic that goes with this stat and set the value by using a fetch action.
284 // Not sure about closure with delegates inside delegates.
285 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
286 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
287 {
288 // Get the one nic that has the name of this stat
289 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
290 (network) => network.Name == stat.Description);
291 try
292 {
293 foreach (NetworkInterface nic in nics)
294 {
295 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
296 if (intrStats != null)
297 {
298 double newVal = Math.Round(getter(intrStats) / factor, 3);
299 stat.Value = newVal;
300 }
301 break;
302 }
303 }
304 catch
305 {
306 // There are times interfaces go away so we just won't update the stat for this
307 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
308 }
309 }
310 }
311
312 public class ServerStatsAggregator : Stat
313 {
314 public ServerStatsAggregator(
315 string shortName,
316 string name,
317 string description,
318 string unitName,
319 string category,
320 string container
321 )
322 : base(
323 shortName,
324 name,
325 description,
326 unitName,
327 category,
328 container,
329 StatType.Push,
330 MeasuresOfInterest.None,
331 null,
332 StatVerbosity.Info)
333 {
334 }
335 public override string ToConsoleString()
336 {
337 StringBuilder sb = new StringBuilder();
338
339 return sb.ToString();
340 }
341
342 public override OSDMap ToOSDMap()
343 {
344 OSDMap ret = new OSDMap();
345
346 return ret;
347 }
348 }
349}
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index 2e7665f..c57ee0c 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -27,8 +27,10 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
30using System.Text; 32using System.Text;
31 33using log4net;
32using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
33 35
34namespace OpenSim.Framework.Monitoring 36namespace OpenSim.Framework.Monitoring
@@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
38 /// </summary> 40 /// </summary>
39 public class Stat : IDisposable 41 public class Stat : IDisposable
40 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 public static readonly char[] DisallowedShortNameCharacters = { '.' };
46
41 /// <summary> 47 /// <summary>
42 /// Category of this stat (e.g. cache, scene, etc). 48 /// Category of this stat (e.g. cache, scene, etc).
43 /// </summary> 49 /// </summary>
@@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
95 /// <remarks> 101 /// <remarks>
96 /// Will be null if no measures of interest require samples. 102 /// Will be null if no measures of interest require samples.
97 /// </remarks> 103 /// </remarks>
98 private static Queue<double> m_samples; 104 private Queue<double> m_samples;
99 105
100 /// <summary> 106 /// <summary>
101 /// Maximum number of statistical samples. 107 /// Maximum number of statistical samples.
@@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
162 throw new Exception( 168 throw new Exception(
163 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); 169 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
164 170
171 foreach (char c in DisallowedShortNameCharacters)
172 {
173 if (shortName.IndexOf(c) != -1)
174 throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
175 }
176
165 ShortName = shortName; 177 ShortName = shortName;
166 Name = name; 178 Name = name;
167 Description = description; 179 Description = description;
@@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
204 if (m_samples.Count >= m_maxSamples) 216 if (m_samples.Count >= m_maxSamples)
205 m_samples.Dequeue(); 217 m_samples.Dequeue();
206 218
219// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
220
207 m_samples.Enqueue(newValue); 221 m_samples.Enqueue(newValue);
208 } 222 }
209 } 223 }
@@ -242,6 +256,10 @@ namespace OpenSim.Framework.Monitoring
242 256
243 lock (m_samples) 257 lock (m_samples)
244 { 258 {
259// m_log.DebugFormat(
260// "[STAT]: Samples for {0} are {1}",
261// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
262
245 foreach (double s in m_samples) 263 foreach (double s in m_samples)
246 { 264 {
247 if (lastSample != null) 265 if (lastSample != null)
@@ -253,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
253 271
254 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; 272 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
255 273
256 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); 274 sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
257 } 275 }
258 } 276 }
259 } 277 }
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 24db6d4..12d3a75 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Text; 31using System.Text;
31 32
32namespace OpenSim.Framework.Monitoring 33namespace OpenSim.Framework.Monitoring
@@ -54,13 +55,13 @@ namespace OpenSim.Framework.Monitoring
54 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats 55 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); 56 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
56 57
57 private static AssetStatsCollector assetStats; 58// private static AssetStatsCollector assetStats;
58 private static UserStatsCollector userStats; 59// private static UserStatsCollector userStats;
59 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 60// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
60 61
61 public static AssetStatsCollector AssetStats { get { return assetStats; } } 62// public static AssetStatsCollector AssetStats { get { return assetStats; } }
62 public static UserStatsCollector UserStats { get { return userStats; } } 63// public static UserStatsCollector UserStats { get { return userStats; } }
63 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 64 public static SimExtraStatsCollector SimExtraStats { get; set; }
64 65
65 public static void RegisterConsoleCommands(ICommandConsole console) 66 public static void RegisterConsoleCommands(ICommandConsole console)
66 { 67 {
@@ -68,12 +69,14 @@ namespace OpenSim.Framework.Monitoring
68 "General", 69 "General",
69 false, 70 false,
70 "show stats", 71 "show stats",
71 "show stats [list|all|<category>]", 72 "show stats [list|all|(<category>[.<container>])+",
72 "Show statistical information for this server", 73 "Show statistical information for this server",
73 "If no final argument is specified then legacy statistics information is currently shown.\n" 74 "If no final argument is specified then legacy statistics information is currently shown.\n"
74 + "If list is specified then statistic categories are shown.\n" 75 + "'list' argument will show statistic categories.\n"
75 + "If all is specified then all registered statistics are shown.\n" 76 + "'all' will show all statistics.\n"
76 + "If a category name is specified then only statistics from that category are shown.\n" 77 + "A <category> name will show statistics from that category.\n"
78 + "A <category>.<container> name will show statistics from that category in that container.\n"
79 + "More than one name can be given separated by spaces.\n"
77 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", 80 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
78 HandleShowStatsCommand); 81 HandleShowStatsCommand);
79 } 82 }
@@ -84,43 +87,47 @@ namespace OpenSim.Framework.Monitoring
84 87
85 if (cmd.Length > 2) 88 if (cmd.Length > 2)
86 { 89 {
87 var categoryName = cmd[2]; 90 foreach (string name in cmd.Skip(2))
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
89
90 if (categoryName == AllSubCommand)
91 { 91 {
92 foreach (var category in RegisteredStats.Values) 92 string[] components = name.Split('.');
93
94 string categoryName = components[0];
95 string containerName = components.Length > 1 ? components[1] : null;
96
97 if (categoryName == AllSubCommand)
93 { 98 {
94 OutputCategoryStatsToConsole(con, category); 99 OutputAllStatsToConsole(con);
95 } 100 }
96 } 101 else if (categoryName == ListSubCommand)
97 else if (categoryName == ListSubCommand)
98 {
99 con.Output("Statistic categories available are:");
100 foreach (string category in RegisteredStats.Keys)
101 con.OutputFormat(" {0}", category);
102 }
103 else
104 {
105 SortedDictionary<string, SortedDictionary<string, Stat>> category;
106 if (!RegisteredStats.TryGetValue(categoryName, out category))
107 { 102 {
108 con.OutputFormat("No such category as {0}", categoryName); 103 con.Output("Statistic categories available are:");
104 foreach (string category in RegisteredStats.Keys)
105 con.OutputFormat(" {0}", category);
109 } 106 }
110 else 107 else
111 { 108 {
112 if (String.IsNullOrEmpty(containerName)) 109 SortedDictionary<string, SortedDictionary<string, Stat>> category;
113 OutputCategoryStatsToConsole(con, category); 110 if (!RegisteredStats.TryGetValue(categoryName, out category))
111 {
112 con.OutputFormat("No such category as {0}", categoryName);
113 }
114 else 114 else
115 { 115 {
116 SortedDictionary<string, Stat> container; 116 if (String.IsNullOrEmpty(containerName))
117 if (category.TryGetValue(containerName, out container))
118 { 117 {
119 OutputContainerStatsToConsole(con, container); 118 OutputCategoryStatsToConsole(con, category);
120 } 119 }
121 else 120 else
122 { 121 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); 122 SortedDictionary<string, Stat> container;
123 if (category.TryGetValue(containerName, out container))
124 {
125 OutputContainerStatsToConsole(con, container);
126 }
127 else
128 {
129 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
130 }
124 } 131 }
125 } 132 }
126 } 133 }
@@ -129,7 +136,18 @@ namespace OpenSim.Framework.Monitoring
129 else 136 else
130 { 137 {
131 // Legacy 138 // Legacy
132 con.Output(SimExtraStats.Report()); 139 if (SimExtraStats != null)
140 con.Output(SimExtraStats.Report());
141 else
142 OutputAllStatsToConsole(con);
143 }
144 }
145
146 private static void OutputAllStatsToConsole(ICommandConsole con)
147 {
148 foreach (var category in RegisteredStats.Values)
149 {
150 OutputCategoryStatsToConsole(con, category);
133 } 151 }
134 } 152 }
135 153
@@ -150,27 +168,27 @@ namespace OpenSim.Framework.Monitoring
150 } 168 }
151 } 169 }
152 170
153 /// <summary> 171// /// <summary>
154 /// Start collecting statistics related to assets. 172// /// Start collecting statistics related to assets.
155 /// Should only be called once. 173// /// Should only be called once.
156 /// </summary> 174// /// </summary>
157 public static AssetStatsCollector StartCollectingAssetStats() 175// public static AssetStatsCollector StartCollectingAssetStats()
158 { 176// {
159 assetStats = new AssetStatsCollector(); 177// assetStats = new AssetStatsCollector();
160 178//
161 return assetStats; 179// return assetStats;
162 } 180// }
163 181//
164 /// <summary> 182// /// <summary>
165 /// Start collecting statistics related to users. 183// /// Start collecting statistics related to users.
166 /// Should only be called once. 184// /// Should only be called once.
167 /// </summary> 185// /// </summary>
168 public static UserStatsCollector StartCollectingUserStats() 186// public static UserStatsCollector StartCollectingUserStats()
169 { 187// {
170 userStats = new UserStatsCollector(); 188// userStats = new UserStatsCollector();
171 189//
172 return userStats; 190// return userStats;
173 } 191// }
174 192
175 /// <summary> 193 /// <summary>
176 /// Registers a statistic. 194 /// Registers a statistic.
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 6c04c69..bfd67c7 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -86,26 +86,23 @@ namespace OpenSim.Framework.Servers
86 /// </summary> 86 /// </summary>
87 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
88 { 88 {
89 if (m_console == null) 89 StatsManager.SimExtraStats = new SimExtraStatsCollector();
90 return;
91
92 RegisterCommonCommands(); 90 RegisterCommonCommands();
93 91 RegisterCommonComponents(Config);
94 m_console.Commands.AddCommand("General", false, "quit", 92 }
95 "quit", 93
96 "Quit the application", HandleQuit); 94 protected override void ShutdownSpecific()
95 {
96 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
97
98 RemovePIDFile();
97 99
98 m_console.Commands.AddCommand("General", false, "shutdown", 100 base.ShutdownSpecific();
99 "shutdown", 101
100 "Quit the application", HandleQuit); 102 Environment.Exit(0);
101 } 103 }
102 104
103 /// <summary> 105 /// <summary>
104 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
105 /// </summary>
106 public virtual void ShutdownSpecific() {}
107
108 /// <summary>
109 /// Provides a list of help topics that are available. Overriding classes should append their topics to the 106 /// Provides a list of help topics that are available. Overriding classes should append their topics to the
110 /// information returned when the base method is called. 107 /// information returned when the base method is called.
111 /// </summary> 108 /// </summary>
@@ -153,25 +150,8 @@ namespace OpenSim.Framework.Servers
153 timeTaken.Minutes, timeTaken.Seconds); 150 timeTaken.Minutes, timeTaken.Seconds);
154 } 151 }
155 152
156 /// <summary> 153 public string osSecret
157 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
158 /// </summary>
159 public virtual void Shutdown()
160 { 154 {
161 ShutdownSpecific();
162
163 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
164 RemovePIDFile();
165
166 Environment.Exit(0);
167 }
168
169 private void HandleQuit(string module, string[] args)
170 {
171 Shutdown();
172 }
173
174 public string osSecret {
175 // Secret uuid for the simulator 155 // Secret uuid for the simulator
176 get { return m_osSecret; } 156 get { return m_osSecret; }
177 } 157 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index d29cc61..80d1080 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57
58 /// <summary> 57 /// <summary>
59 /// This is a pending websocket request before it got an sucessful upgrade response. 58 /// This is a pending websocket request before it got an sucessful upgrade response.
60 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to 59 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
81 /// </remarks> 80 /// </remarks>
82 public int RequestNumber { get; private set; } 81 public int RequestNumber { get; private set; }
83 82
83 /// <summary>
84 /// Statistic for holding number of requests processed.
85 /// </summary>
86 private Stat m_requestsProcessedStat;
87
84 private volatile int NotSocketErrors = 0; 88 private volatile int NotSocketErrors = 0;
85 public volatile bool HTTPDRunning = false; 89 public volatile bool HTTPDRunning = false;
86 90
@@ -437,9 +441,8 @@ namespace OpenSim.Framework.Servers.HttpServer
437 } 441 }
438 } 442 }
439 443
440 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 444 private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
441 { 445 {
442
443 OSHttpRequest req = new OSHttpRequest(context, request); 446 OSHttpRequest req = new OSHttpRequest(context, request);
444 WebSocketRequestDelegate dWebSocketRequestDelegate = null; 447 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
445 lock (m_WebSocketHandlers) 448 lock (m_WebSocketHandlers)
@@ -455,8 +458,7 @@ namespace OpenSim.Framework.Servers.HttpServer
455 458
456 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 459 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
457 resp.ReuseContext = true; 460 resp.ReuseContext = true;
458 HandleRequest(req, resp); 461 HandleRequest(req, resp);
459
460 462
461 // !!!HACK ALERT!!! 463 // !!!HACK ALERT!!!
462 // There seems to be a bug in the underlying http code that makes subsequent requests 464 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -1870,6 +1872,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1870 // useful without inbound HTTP. 1872 // useful without inbound HTTP.
1871 throw e; 1873 throw e;
1872 } 1874 }
1875
1876 m_requestsProcessedStat
1877 = new Stat(
1878 "HTTPRequestsServed",
1879 "Number of inbound HTTP requests processed",
1880 "",
1881 "requests",
1882 "httpserver",
1883 Port.ToString(),
1884 StatType.Pull,
1885 MeasuresOfInterest.AverageChangeOverTime,
1886 stat => stat.Value = RequestNumber,
1887 StatVerbosity.Debug);
1888
1889 StatsManager.RegisterStat(m_requestsProcessedStat);
1873 } 1890 }
1874 1891
1875 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) 1892 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1902,6 +1919,9 @@ namespace OpenSim.Framework.Servers.HttpServer
1902 public void Stop() 1919 public void Stop()
1903 { 1920 {
1904 HTTPDRunning = false; 1921 HTTPDRunning = false;
1922
1923 StatsManager.DeregisterStat(m_requestsProcessedStat);
1924
1905 try 1925 try
1906 { 1926 {
1907 m_PollServiceManager.Stop(); 1927 m_PollServiceManager.Stop();
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index ee96b47..de89e2e 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
75 /// <summary> 75 /// <summary>
76 /// This is a regular HTTP Request... This may be removed in the future. 76 /// This is a regular HTTP Request... This may be removed in the future.
77 /// </summary> 77 /// </summary>
78 public event RegularHttpRequestDelegate OnRegularHttpRequest; 78// public event RegularHttpRequestDelegate OnRegularHttpRequest;
79 79
80 /// <summary> 80 /// <summary>
81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired 81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@@ -304,15 +304,14 @@ namespace OpenSim.Framework.Servers.HttpServer
304 if (d != null) 304 if (d != null)
305 d(this, new UpgradeCompletedEventArgs()); 305 d(this, new UpgradeCompletedEventArgs());
306 } 306 }
307 catch (IOException fail) 307 catch (IOException)
308 { 308 {
309 Close(string.Empty); 309 Close(string.Empty);
310 } 310 }
311 catch (ObjectDisposedException fail) 311 catch (ObjectDisposedException)
312 { 312 {
313 Close(string.Empty); 313 Close(string.Empty);
314 } 314 }
315
316 } 315 }
317 316
318 /// <summary> 317 /// <summary>
@@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
414 _socketState.Header = pheader; 413 _socketState.Header = pheader;
415 } 414 }
416 415
417
418
419 if (_socketState.FrameComplete) 416 if (_socketState.FrameComplete)
420 { 417 {
421 ProcessFrame(_socketState); 418 ProcessFrame(_socketState);
@@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
424 _socketState.ExpectedBytes = 0; 421 _socketState.ExpectedBytes = 0;
425 422
426 } 423 }
427
428 } 424 }
429 } 425 }
430 else 426 else
@@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
457 _socketState.ReceivedBytes.Clear(); 453 _socketState.ReceivedBytes.Clear();
458 _socketState.ExpectedBytes = 0; 454 _socketState.ExpectedBytes = 0;
459 // do some processing 455 // do some processing
460 } 456 }
461
462 } 457 }
463 } 458 }
464 if (offset > 0) 459 if (offset > 0)
@@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
477 { 472 {
478 // We can't read the stream anymore... 473 // We can't read the stream anymore...
479 } 474 }
480
481 } 475 }
482 catch (IOException fail) 476 catch (IOException)
483 { 477 {
484 Close(string.Empty); 478 Close(string.Empty);
485 } 479 }
486 catch (ObjectDisposedException fail) 480 catch (ObjectDisposedException)
487 { 481 {
488 Close(string.Empty); 482 Close(string.Empty);
489 } 483 }
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index b9e3c18..eb8c9f8 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
62 62
63 protected string m_pidFile = String.Empty; 63 protected string m_pidFile = String.Empty;
64 64
65 protected ServerStatsCollector m_serverStatsCollector;
66
65 /// <summary> 67 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. 68 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary> 69 /// </summary>
@@ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers
259 "force gc", 261 "force gc",
260 "Manually invoke runtime garbage collection. For debugging purposes", 262 "Manually invoke runtime garbage collection. For debugging purposes",
261 HandleForceGc); 263 HandleForceGc);
264
265 m_console.Commands.AddCommand(
266 "General", false, "quit",
267 "quit",
268 "Quit the application", (mod, args) => Shutdown());
269
270 m_console.Commands.AddCommand(
271 "General", false, "shutdown",
272 "shutdown",
273 "Quit the application", (mod, args) => Shutdown());
274
275 StatsManager.RegisterConsoleCommands(m_console);
276 }
277
278 public void RegisterCommonComponents(IConfigSource configSource)
279 {
280 m_serverStatsCollector = new ServerStatsCollector();
281 m_serverStatsCollector.Initialise(configSource);
282 m_serverStatsCollector.Start();
262 } 283 }
263 284
264 private void HandleForceGc(string module, string[] args) 285 private void HandleForceGc(string module, string[] args)
@@ -646,7 +667,68 @@ namespace OpenSim.Framework.Servers
646 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 667 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
647 668
648 sb.Append("Main threadpool (excluding script engine pools)\n"); 669 sb.Append("Main threadpool (excluding script engine pools)\n");
649 sb.Append(Util.GetThreadPoolReport()); 670 sb.Append(GetThreadPoolReport());
671
672 return sb.ToString();
673 }
674
675 /// <summary>
676 /// Get a thread pool report.
677 /// </summary>
678 /// <returns></returns>
679 public static string GetThreadPoolReport()
680 {
681 string threadPoolUsed = null;
682 int maxThreads = 0;
683 int minThreads = 0;
684 int allocatedThreads = 0;
685 int inUseThreads = 0;
686 int waitingCallbacks = 0;
687 int completionPortThreads = 0;
688
689 StringBuilder sb = new StringBuilder();
690 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
691 {
692 STPInfo stpi = Util.GetSmartThreadPoolInfo();
693
694 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
695 if (stpi != null)
696 {
697 threadPoolUsed = "SmartThreadPool";
698 maxThreads = stpi.MaxThreads;
699 minThreads = stpi.MinThreads;
700 inUseThreads = stpi.InUseThreads;
701 allocatedThreads = stpi.ActiveThreads;
702 waitingCallbacks = stpi.WaitingCallbacks;
703 }
704 }
705 else if (
706 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
707 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
708 {
709 threadPoolUsed = "BuiltInThreadPool";
710 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
711 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
712 int availableThreads;
713 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
714 inUseThreads = maxThreads - availableThreads;
715 allocatedThreads = -1;
716 waitingCallbacks = -1;
717 }
718
719 if (threadPoolUsed != null)
720 {
721 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
722 sb.AppendFormat("Max threads : {0}\n", maxThreads);
723 sb.AppendFormat("Min threads : {0}\n", minThreads);
724 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
725 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
726 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
727 }
728 else
729 {
730 sb.AppendFormat("Thread pool not used\n");
731 }
650 732
651 return sb.ToString(); 733 return sb.ToString();
652 } 734 }
@@ -698,5 +780,16 @@ namespace OpenSim.Framework.Servers
698 if (m_console != null) 780 if (m_console != null)
699 m_console.OutputFormat(format, components); 781 m_console.OutputFormat(format, components);
700 } 782 }
783
784 public virtual void Shutdown()
785 {
786 m_serverStatsCollector.Close();
787 ShutdownSpecific();
788 }
789
790 /// <summary>
791 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
792 /// </summary>
793 protected virtual void ShutdownSpecific() {}
701 } 794 }
702} 795}
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 0852b49..7675be8 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -89,9 +89,30 @@ namespace OpenSim.Framework
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// Class for delivering SmartThreadPool statistical information
93 /// </summary>
94 /// <remarks>
95 /// We do it this way so that we do not directly expose STP.
96 /// </remarks>
97 public class STPInfo
98 {
99 public string Name { get; set; }
100 public STPStartInfo STPStartInfo { get; set; }
101 public WIGStartInfo WIGStartInfo { get; set; }
102 public bool IsIdle { get; set; }
103 public bool IsShuttingDown { get; set; }
104 public int MaxThreads { get; set; }
105 public int MinThreads { get; set; }
106 public int InUseThreads { get; set; }
107 public int ActiveThreads { get; set; }
108 public int WaitingCallbacks { get; set; }
109 public int MaxConcurrentWorkItems { get; set; }
110 }
111
112 /// <summary>
92 /// Miscellaneous utility functions 113 /// Miscellaneous utility functions
93 /// </summary> 114 /// </summary>
94 public class Util 115 public static class Util
95 { 116 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 117 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 118
@@ -1864,74 +1885,31 @@ namespace OpenSim.Framework
1864 } 1885 }
1865 1886
1866 /// <summary> 1887 /// <summary>
1867 /// Get a thread pool report. 1888 /// Get information about the current state of the smart thread pool.
1868 /// </summary> 1889 /// </summary>
1869 /// <returns></returns> 1890 /// <returns>
1870 public static string GetThreadPoolReport() 1891 /// null if this isn't the pool being used for non-scriptengine threads.
1892 /// </returns>
1893 public static STPInfo GetSmartThreadPoolInfo()
1871 { 1894 {
1872 string threadPoolUsed = null; 1895 if (m_ThreadPool == null)
1873 int maxThreads = 0; 1896 return null;
1874 int minThreads = 0;
1875 int allocatedThreads = 0;
1876 int inUseThreads = 0;
1877 int waitingCallbacks = 0;
1878 int completionPortThreads = 0;
1879
1880 StringBuilder sb = new StringBuilder();
1881 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1882 {
1883 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1884 if (m_ThreadPool != null)
1885 {
1886 threadPoolUsed = "SmartThreadPool";
1887 maxThreads = m_ThreadPool.MaxThreads;
1888 minThreads = m_ThreadPool.MinThreads;
1889 inUseThreads = m_ThreadPool.InUseThreads;
1890 allocatedThreads = m_ThreadPool.ActiveThreads;
1891 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1892 }
1893 }
1894 else if (
1895 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1896 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1897 {
1898 threadPoolUsed = "BuiltInThreadPool";
1899 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1900 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1901 int availableThreads;
1902 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1903 inUseThreads = maxThreads - availableThreads;
1904 allocatedThreads = -1;
1905 waitingCallbacks = -1;
1906 }
1907 1897
1908 if (threadPoolUsed != null) 1898 STPInfo stpi = new STPInfo();
1909 { 1899 stpi.Name = m_ThreadPool.Name;
1910 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); 1900 stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
1911 sb.AppendFormat("Max threads : {0}\n", maxThreads); 1901 stpi.IsIdle = m_ThreadPool.IsIdle;
1912 sb.AppendFormat("Min threads : {0}\n", minThreads); 1902 stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
1913 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); 1903 stpi.MaxThreads = m_ThreadPool.MaxThreads;
1914 sb.AppendFormat("In use threads : {0}\n", inUseThreads); 1904 stpi.MinThreads = m_ThreadPool.MinThreads;
1915 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); 1905 stpi.InUseThreads = m_ThreadPool.InUseThreads;
1916 } 1906 stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
1917 else 1907 stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
1918 { 1908 stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
1919 sb.AppendFormat("Thread pool not used\n");
1920 }
1921 1909
1922 return sb.ToString(); 1910 return stpi;
1923 } 1911 }
1924 1912
1925// private static object SmartThreadPoolCallback(object o)
1926// {
1927// object[] array = (object[])o;
1928// WaitCallback callback = (WaitCallback)array[0];
1929// object obj = array[1];
1930//
1931// callback(obj);
1932// return null;
1933// }
1934
1935 #endregion FireAndForget Threading Pattern 1913 #endregion FireAndForget Threading Pattern
1936 1914
1937 /// <summary> 1915 /// <summary>
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index c3e7ec2..e451aa8 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -124,6 +124,7 @@ namespace OpenSim
124 workerThreads = workerThreadsMax; 124 workerThreads = workerThreadsMax;
125 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); 125 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
126 } 126 }
127
127 // Increase the number of IOCP threads available. 128 // Increase the number of IOCP threads available.
128 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) 129 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
129 if (iocpThreads < iocpThreadsMin) 130 if (iocpThreads < iocpThreadsMin)
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index a7e7d03..6c22414 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -372,7 +372,7 @@ namespace OpenSim
372 "Unload a module", HandleModules); 372 "Unload a module", HandleModules);
373 } 373 }
374 374
375 public override void ShutdownSpecific() 375 protected override void ShutdownSpecific()
376 { 376 {
377 if (m_shutdownCommandsFile != String.Empty) 377 if (m_shutdownCommandsFile != String.Empty)
378 { 378 {
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 0ed85b8..11cacac 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -246,10 +246,7 @@ namespace OpenSim
246 } 246 }
247 247
248 if (m_console != null) 248 if (m_console != null)
249 {
250 StatsManager.RegisterConsoleCommands(m_console);
251 AddPluginCommands(m_console); 249 AddPluginCommands(m_console);
252 }
253 } 250 }
254 251
255 protected virtual void AddPluginCommands(ICommandConsole console) 252 protected virtual void AddPluginCommands(ICommandConsole console)
@@ -964,7 +961,7 @@ namespace OpenSim
964 /// <summary> 961 /// <summary>
965 /// Performs any last-minute sanity checking and shuts down the region server 962 /// Performs any last-minute sanity checking and shuts down the region server
966 /// </summary> 963 /// </summary>
967 public override void ShutdownSpecific() 964 protected override void ShutdownSpecific()
968 { 965 {
969 if (proxyUrl.Length > 0) 966 if (proxyUrl.Length > 0)
970 { 967 {
@@ -984,6 +981,8 @@ namespace OpenSim
984 { 981 {
985 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); 982 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
986 } 983 }
984
985 base.ShutdownSpecific();
987 } 986 }
988 987
989 /// <summary> 988 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 556df30..b47ff54 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -33,6 +33,7 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
38using OpenSim.Tests.Common.Mock; 39using OpenSim.Tests.Common.Mock;
@@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
69 { 70 {
70 base.SetUp(); 71 base.SetUp();
71 m_scene = new SceneHelpers().SetupScene(); 72 m_scene = new SceneHelpers().SetupScene();
73 StatsManager.SimExtraStats = new SimExtraStatsCollector();
72 } 74 }
73 75
74 /// <summary> 76 /// <summary>
@@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
210 212
211 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); 213 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
212 Assert.That(spAfterAckTimeout, Is.Null); 214 Assert.That(spAfterAckTimeout, Is.Null);
213
214// TestHelpers.DisableLogging();
215 } 215 }
216 216
217// /// <summary> 217// /// <summary>
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index d372c0e..73b3678f 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 54
55 private int m_levelHGTeleport = 0; 55 private int m_levelHGTeleport = 0;
56 private string m_ThisHomeURI;
56 57
57 private GatekeeperServiceConnector m_GatekeeperConnector; 58 private GatekeeperServiceConnector m_GatekeeperConnector;
59 private IUserAgentService m_UAS;
58 60
59 protected bool m_RestrictAppearanceAbroad; 61 protected bool m_RestrictAppearanceAbroad;
60 protected string m_AccountName; 62 protected string m_AccountName;
@@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
143 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 145 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
144 } 146 }
145 } 147 }
148
149 moduleConfig = source.Configs["Hypergrid"];
150 if (moduleConfig != null)
151 {
152 m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty);
153 if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/"))
154 m_ThisHomeURI += '/';
155 }
146 } 156 }
147 157
148 public override void AddRegion(Scene scene) 158 public override void AddRegion(Scene scene)
@@ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
194 base.RegionLoaded(scene); 204 base.RegionLoaded(scene);
195 205
196 if (m_Enabled) 206 if (m_Enabled)
207 {
197 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); 208 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
209 m_UAS = scene.RequestModuleInterface<IUserAgentService>();
210 }
198 } 211 }
199 212
200 public override void RemoveRegion(Scene scene) 213 public override void RemoveRegion(Scene scene)
@@ -272,8 +285,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
272 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) 285 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
273 { 286 {
274 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); 287 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
275 IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); 288 IUserAgentService connector;
276 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); 289
290 if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null)
291 connector = m_UAS;
292 else
293 connector = new UserAgentServiceConnector(userAgentDriver);
294
295 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason);
277 logout = success; // flag for later logout from this grid; this is an HG TP 296 logout = success; // flag for later logout from this grid; this is an HG TP
278 297
279 if (success) 298 if (success)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index c8698ca..f7dae59 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
194 return false; 194 return false;
195 195
196 // Try local first 196 // Try local first
197 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 197 if (m_localBackend.IsLocalRegion(destination.RegionID))
198 return m_localBackend.UpdateAgent(destination, cAgentData); 198 return m_localBackend.UpdateAgent(destination, cAgentData);
199 199
200 return m_remoteConnector.UpdateAgent(destination, cAgentData); 200 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
206 return false; 206 return false;
207 207
208 // Try local first 208 // Try local first
209 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 209 if (m_localBackend.IsLocalRegion(destination.RegionID))
210 return m_localBackend.UpdateAgent(destination, cAgentData); 210 return m_localBackend.UpdateAgent(destination, cAgentData);
211 211
212 return m_remoteConnector.UpdateAgent(destination, cAgentData); 212 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
224 return true; 224 return true;
225 225
226 // else do the remote thing 226 // else do the remote thing
227 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 227 if (!m_localBackend.IsLocalRegion(destination.RegionID))
228 return m_remoteConnector.RetrieveAgent(destination, id, out agent); 228 return m_remoteConnector.RetrieveAgent(destination, id, out agent);
229 229
230 return false; 230 return false;
@@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
288 return true; 288 return true;
289 289
290 // else do the remote thing 290 // else do the remote thing
291 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 291 if (!m_localBackend.IsLocalRegion(destination.RegionID))
292 return m_remoteConnector.CloseAgent(destination, id); 292 return m_remoteConnector.CloseAgent(destination, id);
293 293
294 return false; 294 return false;
@@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
311 } 311 }
312 312
313 // else do the remote thing 313 // else do the remote thing
314 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 314 if (!m_localBackend.IsLocalRegion(destination.RegionID))
315 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); 315 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
316 316
317 return false; 317 return false;
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 31f8a3f..ce4bd0f 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -82,14 +82,14 @@ namespace OpenSim.Region.CoreModules.World.Land
82 82
83 set { m_landData = value; } 83 set { m_landData = value; }
84 } 84 }
85 85
86 public IPrimCounts PrimCounts { get; set; } 86 public IPrimCounts PrimCounts { get; set; }
87 87
88 public UUID RegionUUID 88 public UUID RegionUUID
89 { 89 {
90 get { return m_scene.RegionInfo.RegionID; } 90 get { return m_scene.RegionInfo.RegionID; }
91 } 91 }
92 92
93 public Vector3 StartPoint 93 public Vector3 StartPoint
94 { 94 {
95 get 95 get
@@ -102,11 +102,11 @@ namespace OpenSim.Region.CoreModules.World.Land
102 return new Vector3(x * 4, y * 4, 0); 102 return new Vector3(x * 4, y * 4, 0);
103 } 103 }
104 } 104 }
105 105
106 return new Vector3(-1, -1, -1); 106 return new Vector3(-1, -1, -1);
107 } 107 }
108 } 108 }
109 109
110 public Vector3 EndPoint 110 public Vector3 EndPoint
111 { 111 {
112 get 112 get
@@ -117,15 +117,15 @@ namespace OpenSim.Region.CoreModules.World.Land
117 { 117 {
118 if (LandBitmap[x, y]) 118 if (LandBitmap[x, y])
119 { 119 {
120 return new Vector3(x * 4, y * 4, 0); 120 return new Vector3(x * 4 + 4, y * 4 + 4, 0);
121 } 121 }
122 } 122 }
123 } 123 }
124 124
125 return new Vector3(-1, -1, -1); 125 return new Vector3(-1, -1, -1);
126 } 126 }
127 } 127 }
128 128
129 #region Constructors 129 #region Constructors
130 130
131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
deleted file mode 100644
index 6e74ce0..0000000
--- a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
+++ /dev/null
@@ -1,339 +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 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.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.OptionalModules.Framework.Monitoring
49{
50[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")]
51public class ServerStats : ISharedRegionModule
52{
53 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
54 private readonly string LogHeader = "[SERVER STATS]";
55
56 public bool Enabled = false;
57 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
58
59 public readonly string CategoryServer = "server";
60
61 public readonly string ContainerProcessor = "processor";
62 public readonly string ContainerMemory = "memory";
63 public readonly string ContainerNetwork = "network";
64 public readonly string ContainerProcess = "process";
65
66 public string NetworkInterfaceTypes = "Ethernet";
67
68 readonly int performanceCounterSampleInterval = 500;
69 int lastperformanceCounterSampleTime = 0;
70
71 private class PerfCounterControl
72 {
73 public PerformanceCounter perfCounter;
74 public int lastFetch;
75 public string name;
76 public PerfCounterControl(PerformanceCounter pPc)
77 : this(pPc, String.Empty)
78 {
79 }
80 public PerfCounterControl(PerformanceCounter pPc, string pName)
81 {
82 perfCounter = pPc;
83 lastFetch = 0;
84 name = pName;
85 }
86 }
87
88 PerfCounterControl processorPercentPerfCounter = null;
89
90 #region ISharedRegionModule
91 // IRegionModuleBase.Name
92 public string Name { get { return "Server Stats"; } }
93 // IRegionModuleBase.ReplaceableInterface
94 public Type ReplaceableInterface { get { return null; } }
95 // IRegionModuleBase.Initialize
96 public void Initialise(IConfigSource source)
97 {
98 IConfig cfg = source.Configs["Monitoring"];
99
100 if (cfg != null)
101 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
102
103 if (Enabled)
104 {
105 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
106 }
107 }
108 // IRegionModuleBase.Close
109 public void Close()
110 {
111 if (RegisteredStats.Count > 0)
112 {
113 foreach (Stat stat in RegisteredStats.Values)
114 {
115 StatsManager.DeregisterStat(stat);
116 stat.Dispose();
117 }
118 RegisteredStats.Clear();
119 }
120 }
121 // IRegionModuleBase.AddRegion
122 public void AddRegion(Scene scene)
123 {
124 }
125 // IRegionModuleBase.RemoveRegion
126 public void RemoveRegion(Scene scene)
127 {
128 }
129 // IRegionModuleBase.RegionLoaded
130 public void RegionLoaded(Scene scene)
131 {
132 }
133 // ISharedRegionModule.PostInitialize
134 public void PostInitialise()
135 {
136 if (RegisteredStats.Count == 0)
137 {
138 RegisterServerStats();
139 }
140 }
141 #endregion ISharedRegionModule
142
143 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
144 {
145 string desc = pDesc;
146 if (desc == null)
147 desc = pName;
148 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
149 StatsManager.RegisterStat(stat);
150 RegisteredStats.Add(pName, stat);
151 }
152
153 public void RegisterServerStats()
154 {
155 lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
156 PerformanceCounter tempPC;
157 Stat tempStat;
158 string tempName;
159
160 try
161 {
162 tempName = "CPUPercent";
163 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
164 processorPercentPerfCounter = new PerfCounterControl(tempPC);
165 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
166 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
167 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
168 StatVerbosity.Info);
169 StatsManager.RegisterStat(tempStat);
170 RegisteredStats.Add(tempName, tempStat);
171
172 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
173 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
174
175 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
176 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
177
178 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
179 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
180
181 MakeStat("Threads", null, "threads", ContainerProcessor,
182 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
183 }
184 catch (Exception e)
185 {
186 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
187 }
188
189 try
190 {
191 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
192
193 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
194 foreach (NetworkInterface nic in nics)
195 {
196 if (nic.OperationalStatus != OperationalStatus.Up)
197 continue;
198
199 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
200 if (!okInterfaceTypes.Contains(nicInterfaceType))
201 {
202 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
203 LogHeader, nic.Name, nicInterfaceType);
204 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
205 LogHeader, NetworkInterfaceTypes);
206 continue;
207 }
208
209 if (nic.Supports(NetworkInterfaceComponent.IPv4))
210 {
211 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
212 if (nicStats != null)
213 {
214 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
215 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
216 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
217 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
218 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
219 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
220 }
221 }
222 // TODO: add IPv6 (it may actually happen someday)
223 }
224 }
225 catch (Exception e)
226 {
227 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
228 }
229
230 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
231 (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
232 MakeStat("ObjectMemory", null, "MB", ContainerMemory,
233 (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
234 MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory,
235 (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
236 MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory,
237 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
238 }
239
240 // Notes on performance counters:
241 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
242 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
243 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
244 private delegate double PerfCounterNextValue();
245 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
246 {
247 GetNextValue(stat, perfControl, 1.0);
248 }
249 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
250 {
251 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
252 {
253 if (perfControl != null && perfControl.perfCounter != null)
254 {
255 try
256 {
257 // Kludge for factor to run double duty. If -1, subtract the value from one
258 if (factor == -1)
259 stat.Value = 1 - perfControl.perfCounter.NextValue();
260 else
261 stat.Value = perfControl.perfCounter.NextValue() / factor;
262 }
263 catch (Exception e)
264 {
265 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
266 }
267 perfControl.lastFetch = Util.EnvironmentTickCount();
268 }
269 }
270 }
271
272 // Lookup the nic that goes with this stat and set the value by using a fetch action.
273 // Not sure about closure with delegates inside delegates.
274 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
275 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
276 {
277 // Get the one nic that has the name of this stat
278 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
279 (network) => network.Name == stat.Description);
280 try
281 {
282 foreach (NetworkInterface nic in nics)
283 {
284 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
285 if (intrStats != null)
286 {
287 double newVal = Math.Round(getter(intrStats) / factor, 3);
288 stat.Value = newVal;
289 }
290 break;
291 }
292 }
293 catch
294 {
295 // There are times interfaces go away so we just won't update the stat for this
296 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
297 }
298 }
299}
300
301public class ServerStatsAggregator : Stat
302{
303 public ServerStatsAggregator(
304 string shortName,
305 string name,
306 string description,
307 string unitName,
308 string category,
309 string container
310 )
311 : base(
312 shortName,
313 name,
314 description,
315 unitName,
316 category,
317 container,
318 StatType.Push,
319 MeasuresOfInterest.None,
320 null,
321 StatVerbosity.Info)
322 {
323 }
324 public override string ToConsoleString()
325 {
326 StringBuilder sb = new StringBuilder();
327
328 return sb.ToString();
329 }
330
331 public override OSDMap ToOSDMap()
332 {
333 OSDMap ret = new OSDMap();
334
335 return ret;
336 }
337}
338
339}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index ac8c30c..928b350 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor
43 // Set to true if we think we're going up stairs. 43 // Set to true if we think we're going up stairs.
44 // This state is remembered because collisions will turn on and off as we go up stairs. 44 // This state is remembered because collisions will turn on and off as we go up stairs.
45 int m_walkingUpStairs; 45 int m_walkingUpStairs;
46 // The amount the step up is applying. Used to smooth stair walking.
46 float m_lastStepUp; 47 float m_lastStepUp;
47 48
49 // Jumping happens over several frames. If use applies up force while colliding, start the
50 // jump and allow the jump to continue for this number of frames.
51 int m_jumpFrames = 0;
52 float m_jumpVelocity = 0f;
53
48 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName) 54 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
49 : base(physicsScene, pObj, actorName) 55 : base(physicsScene, pObj, actorName)
50 { 56 {
@@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor
206 212
207 if (m_controllingPrim.Friction != BSParam.AvatarFriction) 213 if (m_controllingPrim.Friction != BSParam.AvatarFriction)
208 { 214 {
209 // Probably starting up walking. Set friction to moving friction. 215 // Probably starting to walk. Set friction to moving friction.
210 m_controllingPrim.Friction = BSParam.AvatarFriction; 216 m_controllingPrim.Friction = BSParam.AvatarFriction;
211 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction); 217 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
212 } 218 }
213 219
214 // If falling, we keep the world's downward vector no matter what the other axis specify.
215 // The check for RawVelocity.Z < 0 makes jumping work (temporary upward force).
216 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding) 220 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
217 { 221 {
218 if (m_controllingPrim.RawVelocity.Z < 0) 222 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
223 }
224
225
226 // Colliding and not flying with an upward force. The avatar must be trying to jump.
227 if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0)
228 {
229 // We allow the upward force to happen for this many frames.
230 m_jumpFrames = BSParam.AvatarJumpFrames;
231 m_jumpVelocity = stepVelocity.Z;
232 }
233
234 // The case where the avatar is not colliding and is not flying is special.
235 // The avatar is either falling or jumping and the user can be applying force to the avatar
236 // (force in some direction or force up or down).
237 // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity.
238 // If the user is trying to apply upward force but we're not colliding, assume the avatar
239 // is trying to jump and don't apply the upward force if not touching the ground any more.
240 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
241 {
242 // If upward velocity is being applied, this must be a jump and only allow that to go on so long
243 if (m_jumpFrames > 0)
244 {
245 // Since not touching the ground, only apply upward force for so long.
246 m_jumpFrames--;
247 stepVelocity.Z = m_jumpVelocity;
248 }
249 else
250 {
251 // Since we're not affected by anything, whatever vertical motion the avatar has, continue that.
219 stepVelocity.Z = m_controllingPrim.RawVelocity.Z; 252 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
253 }
220 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity); 254 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
221 } 255 }
222 256
@@ -241,7 +275,7 @@ public class BSActorAvatarMove : BSActor
241 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}", 275 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
242 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying, 276 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
243 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z); 277 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
244 // This test is done if moving forward, not flying and is colliding with something. 278
245 // Check for stairs climbing if colliding, not flying and moving forward 279 // Check for stairs climbing if colliding, not flying and moving forward
246 if ( m_controllingPrim.IsColliding 280 if ( m_controllingPrim.IsColliding
247 && !m_controllingPrim.Flying 281 && !m_controllingPrim.Flying
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 311cf4f..07e87d1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
209 m_VhoverTimescale = Math.Max(pValue, 0.01f); 209 m_VhoverTimescale = Math.Max(pValue, 0.01f);
210 break; 210 break;
211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
212 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 212 m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
213 break; 213 break;
214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
707 private Vector3 m_knownRotationalVelocity; 707 private Vector3 m_knownRotationalVelocity;
708 private Vector3 m_knownRotationalForce; 708 private Vector3 m_knownRotationalForce;
709 private Vector3 m_knownRotationalImpulse; 709 private Vector3 m_knownRotationalImpulse;
710 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
711 710
712 private const int m_knownChangedPosition = 1 << 0; 711 private const int m_knownChangedPosition = 1 << 0;
713 private const int m_knownChangedVelocity = 1 << 1; 712 private const int m_knownChangedVelocity = 1 << 1;
@@ -719,7 +718,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
719 private const int m_knownChangedRotationalImpulse = 1 << 7; 718 private const int m_knownChangedRotationalImpulse = 1 << 7;
720 private const int m_knownChangedTerrainHeight = 1 << 8; 719 private const int m_knownChangedTerrainHeight = 1 << 8;
721 private const int m_knownChangedWaterLevel = 1 << 9; 720 private const int m_knownChangedWaterLevel = 1 << 9;
722 private const int m_knownChangedForwardVelocity = 1 <<10;
723 721
724 public void ForgetKnownVehicleProperties() 722 public void ForgetKnownVehicleProperties()
725 { 723 {
@@ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
923 { 921 {
924 get 922 get
925 { 923 {
926 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) 924 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
927 {
928 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
929 m_knownHas |= m_knownChangedForwardVelocity;
930 }
931 return m_knownForwardVelocity;
932 } 925 }
933 } 926 }
934 private float VehicleForwardSpeed 927 private float VehicleForwardSpeed
@@ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
981 { 974 {
982 ComputeLinearVelocity(pTimestep); 975 ComputeLinearVelocity(pTimestep);
983 976
977 ComputeLinearDeflection(pTimestep);
978
984 ComputeLinearTerrainHeightCorrection(pTimestep); 979 ComputeLinearTerrainHeightCorrection(pTimestep);
985 980
986 ComputeLinearHover(pTimestep); 981 ComputeLinearHover(pTimestep);
@@ -1026,12 +1021,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1026 { 1021 {
1027 // Step the motor from the current value. Get the correction needed this step. 1022 // Step the motor from the current value. Get the correction needed this step.
1028 Vector3 origVelW = VehicleVelocity; // DEBUG 1023 Vector3 origVelW = VehicleVelocity; // DEBUG
1029 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); 1024 Vector3 currentVelV = VehicleForwardVelocity;
1030 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); 1025 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
1031 1026
1032 // Friction reduces vehicle motion 1027 // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
1033 Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); 1028 Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
1034 linearMotorCorrectionV -= (currentVelV * frictionFactorW); 1029 linearMotorCorrectionV -= (currentVelV * frictionFactorV);
1035 1030
1036 // Motor is vehicle coordinates. Rotate it to world coordinates 1031 // Motor is vehicle coordinates. Rotate it to world coordinates
1037 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; 1032 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
@@ -1046,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1046 // Add this correction to the velocity to make it faster/slower. 1041 // Add this correction to the velocity to make it faster/slower.
1047 VehicleVelocity += linearMotorVelocityW; 1042 VehicleVelocity += linearMotorVelocityW;
1048 1043
1049
1050
1051 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", 1044 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
1052 ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, 1045 ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV,
1053 linearMotorVelocityW, VehicleVelocity, frictionFactorW); 1046 linearMotorVelocityW, VehicleVelocity, frictionFactorV);
1047 }
1048
1049 //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis
1050 //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity
1051 private void ComputeLinearDeflection(float pTimestep)
1052 {
1053 Vector3 linearDeflectionV = Vector3.Zero;
1054 Vector3 velocityV = VehicleForwardVelocity;
1055
1056 // Velocity in Y and Z dimensions is movement to the side or turning.
1057 // Compute deflection factor from the to the side and rotational velocity
1058 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
1059 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
1060
1061 // Velocity to the side and around is corrected and moved into the forward direction
1062 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
1063 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
1064
1065 // Scale the deflection to the fractional simulation time
1066 linearDeflectionV *= pTimestep;
1067
1068 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward
1069 linearDeflectionV *= new Vector3(1,-1,-1);
1070
1071 // Correciont is vehicle relative. Convert to world coordinates and add to the velocity
1072 VehicleVelocity += linearDeflectionV * VehicleOrientation;
1073
1074 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
1075 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
1054 } 1076 }
1055 1077
1056 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1078 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1652,6 +1674,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1652 return frictionFactor; 1674 return frictionFactor;
1653 } 1675 }
1654 1676
1677 private float SortedClampInRange(float clampa, float val, float clampb)
1678 {
1679 if (clampa > clampb)
1680 {
1681 float temp = clampa;
1682 clampa = clampb;
1683 clampb = temp;
1684 }
1685 return ClampInRange(clampa, val, clampb);
1686
1687 }
1688
1655 private float ClampInRange(float low, float val, float high) 1689 private float ClampInRange(float low, float val, float high)
1656 { 1690 {
1657 return Math.Max(low, Math.Min(val, high)); 1691 return Math.Max(low, Math.Min(val, high));
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index aad1108..6437b04 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -134,6 +134,7 @@ public static class BSParam
134 public static float AvatarHeightMidFudge { get; private set; } 134 public static float AvatarHeightMidFudge { get; private set; }
135 public static float AvatarHeightHighFudge { get; private set; } 135 public static float AvatarHeightHighFudge { get; private set; }
136 public static float AvatarContactProcessingThreshold { get; private set; } 136 public static float AvatarContactProcessingThreshold { get; private set; }
137 public static int AvatarJumpFrames { get; private set; }
137 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } 138 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
138 public static float AvatarStepHeight { get; private set; } 139 public static float AvatarStepHeight { get; private set; }
139 public static float AvatarStepApproachFactor { get; private set; } 140 public static float AvatarStepApproachFactor { get; private set; }
@@ -567,6 +568,8 @@ public static class BSParam
567 0.1f ), 568 0.1f ),
568 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 569 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
569 1.0f ), 570 1.0f ),
571 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
572 4 ),
570 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", 573 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
571 0.6f ) , 574 0.6f ) ,
572 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", 575 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index b13c87d..667cef8 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -34,6 +34,7 @@ using System.Text;
34using System.Xml; 34using System.Xml;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37using OpenSim.Framework.Monitoring;
37using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
38using log4net; 39using log4net;
39using log4net.Config; 40using log4net.Config;
@@ -190,16 +191,7 @@ namespace OpenSim.Server.Base
190 } 191 }
191 192
192 RegisterCommonCommands(); 193 RegisterCommonCommands();
193 194 RegisterCommonComponents(Config);
194 // Register the quit command
195 //
196 MainConsole.Instance.Commands.AddCommand("General", false, "quit",
197 "quit",
198 "Quit the application", HandleQuit);
199
200 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown",
201 "shutdown",
202 "Quit the application", HandleQuit);
203 195
204 // Allow derived classes to perform initialization that 196 // Allow derived classes to perform initialization that
205 // needs to be done after the console has opened 197 // needs to be done after the console has opened
@@ -214,6 +206,9 @@ namespace OpenSim.Server.Base
214 206
215 public virtual int Run() 207 public virtual int Run()
216 { 208 {
209 Watchdog.Enabled = true;
210 MemoryWatchdog.Enabled = true;
211
217 while (m_Running) 212 while (m_Running)
218 { 213 {
219 try 214 try
@@ -231,11 +226,12 @@ namespace OpenSim.Server.Base
231 return 0; 226 return 0;
232 } 227 }
233 228
234 protected virtual void HandleQuit(string module, string[] args) 229 protected override void ShutdownSpecific()
235 { 230 {
236 m_Running = false; 231 m_Running = false;
237 m_log.Info("[CONSOLE] Quitting"); 232 m_log.Info("[CONSOLE] Quitting");
238 233
234 base.ShutdownSpecific();
239 } 235 }
240 236
241 protected virtual void ReadConfig() 237 protected virtual void ReadConfig()
@@ -246,4 +242,4 @@ namespace OpenSim.Server.Base
246 { 242 {
247 } 243 }
248 } 244 }
249} 245} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
index cf1af15..adc2fbc 100644
--- a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
61 m_Proxy = proxy; 61 m_Proxy = proxy;
62 } 62 }
63 63
64 protected override bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 64 protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
65 { 65 {
66 return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason); 66 return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason);
67 } 67 }
diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
index 968c1e6..df875af 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
@@ -49,191 +49,87 @@ using log4net;
49 49
50namespace OpenSim.Server.Handlers.Hypergrid 50namespace OpenSim.Server.Handlers.Hypergrid
51{ 51{
52 public class HomeAgentHandler 52 public class HomeAgentHandler : AgentPostHandler
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private IUserAgentService m_UserAgentService; 55 private IUserAgentService m_UserAgentService;
56 56
57 private string m_LoginServerIP; 57 private string m_LoginServerIP;
58 private bool m_Proxy = false;
59 58
60 public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) 59 public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) :
60 base("/homeagent")
61 { 61 {
62 m_UserAgentService = userAgentService; 62 m_UserAgentService = userAgentService;
63 m_LoginServerIP = loginServerIP; 63 m_LoginServerIP = loginServerIP;
64 m_Proxy = proxy; 64 m_Proxy = proxy;
65 } 65 }
66 66
67 public Hashtable Handler(Hashtable request) 67 protected override AgentDestinationData CreateAgentDestinationData()
68 { 68 {
69// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); 69 return new ExtendedAgentDestinationData();
70// 70 }
71// m_log.Debug("---------------------------"); 71 protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request)
72// m_log.Debug(" >> uri=" + request["uri"]); 72 {
73// m_log.Debug(" >> content-type=" + request["content-type"]); 73 base.UnpackData(args, d, request);
74// m_log.Debug(" >> http-method=" + request["http-method"]); 74 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
75// m_log.Debug("---------------------------\n"); 75 try
76
77 Hashtable responsedata = new Hashtable();
78 responsedata["content_type"] = "text/html";
79 responsedata["keepalive"] = false;
80
81
82 UUID agentID;
83 UUID regionID;
84 string action;
85 if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action))
86 { 76 {
87 m_log.InfoFormat("[HOME AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]); 77 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
88 responsedata["int_response_code"] = 404; 78 data.host = args["gatekeeper_host"].AsString();
89 responsedata["str_response_string"] = "false"; 79 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
80 Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port);
81 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null)
82 data.gatekeeperServerURI = args["gatekeeper_serveruri"];
83 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null)
84 data.destinationServerURI = args["destination_serveruri"];
90 85
91 return responsedata;
92 } 86 }
93 87 catch (InvalidCastException e)
94 // Next, let's parse the verb
95 string method = (string)request["http-method"];
96 if (method.Equals("POST"))
97 { 88 {
98 DoAgentPost(request, responsedata, agentID); 89 m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData");
99 return responsedata;
100 } 90 }
101 else
102 {
103 m_log.InfoFormat("[HOME AGENT HANDLER]: method {0} not supported in agent message", method);
104 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
105 responsedata["str_response_string"] = "Method not allowed";
106 91
107 return responsedata; 92 string callerIP = GetCallerIP(request);
108 } 93 // Verify if this call came from the login server
94 if (callerIP == m_LoginServerIP)
95 data.fromLogin = true;
109 96
110 } 97 }
111 98
112 protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) 99 protected override GridRegion ExtractGatekeeper(AgentDestinationData d)
113 { 100 {
114 OSDMap args = Utils.GetOSDMap((string)request["body"]); 101 if (d is ExtendedAgentDestinationData)
115 if (args == null)
116 { 102 {
117 responsedata["int_response_code"] = HttpStatusCode.BadRequest; 103 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
118 responsedata["str_response_string"] = "Bad request"; 104 GridRegion gatekeeper = new GridRegion();
119 return; 105 gatekeeper.ServerURI = data.gatekeeperServerURI;
106 gatekeeper.ExternalHostName = data.host;
107 gatekeeper.HttpPort = (uint)data.port;
108 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
109
110 return gatekeeper;
120 } 111 }
121
122 // retrieve the input arguments
123 int x = 0, y = 0;
124 UUID uuid = UUID.Zero;
125 string regionname = string.Empty;
126 string gatekeeper_host = string.Empty;
127 string gatekeeper_serveruri = string.Empty;
128 string destination_serveruri = string.Empty;
129 int gatekeeper_port = 0;
130 IPEndPoint client_ipaddress = null;
131
132 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
133 gatekeeper_host = args["gatekeeper_host"].AsString();
134 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
135 Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port);
136 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null)
137 gatekeeper_serveruri = args["gatekeeper_serveruri"];
138 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null)
139 destination_serveruri = args["destination_serveruri"];
140
141 GridRegion gatekeeper = new GridRegion();
142 gatekeeper.ServerURI = gatekeeper_serveruri;
143 gatekeeper.ExternalHostName = gatekeeper_host;
144 gatekeeper.HttpPort = (uint)gatekeeper_port;
145 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
146
147 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
148 Int32.TryParse(args["destination_x"].AsString(), out x);
149 else 112 else
150 m_log.WarnFormat(" -- request didn't have destination_x"); 113 m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type");
151 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
152 Int32.TryParse(args["destination_y"].AsString(), out y);
153 else
154 m_log.WarnFormat(" -- request didn't have destination_y");
155 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
156 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
157 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
158 regionname = args["destination_name"].ToString();
159
160 if (args.ContainsKey("client_ip") && args["client_ip"] != null)
161 {
162 string ip_str = args["client_ip"].ToString();
163 try
164 {
165 string callerIP = GetCallerIP(request);
166 // Verify if this caller has authority to send the client IP
167 if (callerIP == m_LoginServerIP)
168 client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0);
169 else // leaving this for now, but this warning should be removed
170 m_log.WarnFormat("[HOME AGENT HANDLER]: Unauthorized machine {0} tried to set client ip to {1}", callerIP, ip_str);
171 }
172 catch
173 {
174 m_log.DebugFormat("[HOME AGENT HANDLER]: Exception parsing client ip address from {0}", ip_str);
175 }
176 }
177
178 GridRegion destination = new GridRegion();
179 destination.RegionID = uuid;
180 destination.RegionLocX = x;
181 destination.RegionLocY = y;
182 destination.RegionName = regionname;
183 destination.ServerURI = destination_serveruri;
184
185 AgentCircuitData aCircuit = new AgentCircuitData();
186 try
187 {
188 aCircuit.UnpackAgentCircuitData(args);
189 }
190 catch (Exception ex)
191 {
192 m_log.InfoFormat("[HOME AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message);
193 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
194 responsedata["str_response_string"] = "Bad request";
195 return;
196 }
197
198 OSDMap resp = new OSDMap(2);
199 string reason = String.Empty;
200 114
201 bool result = m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, client_ipaddress, out reason); 115 return null;
202
203 resp["reason"] = OSD.FromString(reason);
204 resp["success"] = OSD.FromBoolean(result);
205
206 // TODO: add reason if not String.Empty?
207 responsedata["int_response_code"] = HttpStatusCode.OK;
208 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
209 } 116 }
210 117
211 private string GetCallerIP(Hashtable request)
212 {
213 if (!m_Proxy)
214 return Util.GetCallerIP(request);
215
216 // We're behind a proxy
217 Hashtable headers = (Hashtable)request["headers"];
218 string xff = "X-Forwarded-For";
219 if (headers.ContainsKey(xff.ToLower()))
220 xff = xff.ToLower();
221 118
222 if (!headers.ContainsKey(xff) || headers[xff] == null) 119 protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
223 { 120 {
224 m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); 121 return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason);
225 return Util.GetCallerIP(request); 122 }
226 }
227 123
228 m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); 124 }
229 125
230 IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); 126 public class ExtendedAgentDestinationData : AgentDestinationData
231 if (ep != null) 127 {
232 return ep.Address.ToString(); 128 public string host;
129 public int port;
130 public string gatekeeperServerURI;
131 public string destinationServerURI;
233 132
234 // Oops
235 return Util.GetCallerIP(request);
236 }
237 } 133 }
238 134
239} 135}
diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
index b20f467..d9c1bd3 100644
--- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
@@ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
108 server.AddXmlRPCHandler("get_uui", GetUUI, false); 108 server.AddXmlRPCHandler("get_uui", GetUUI, false);
109 server.AddXmlRPCHandler("get_uuid", GetUUID, false); 109 server.AddXmlRPCHandler("get_uuid", GetUUID, false);
110 110
111 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); 111 server.AddStreamHandler(new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy));
112 } 112 }
113 113
114 public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) 114 public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient)
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index 9b34298..c62f256 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -351,31 +351,16 @@ namespace OpenSim.Server.Handlers.Simulation
351 return; 351 return;
352 } 352 }
353 353
354 // retrieve the input arguments 354 AgentDestinationData data = CreateAgentDestinationData();
355 int x = 0, y = 0; 355 UnpackData(args, data, request);
356 UUID uuid = UUID.Zero;
357 string regionname = string.Empty;
358 uint teleportFlags = 0;
359 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
360 Int32.TryParse(args["destination_x"].AsString(), out x);
361 else
362 m_log.WarnFormat(" -- request didn't have destination_x");
363 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
364 Int32.TryParse(args["destination_y"].AsString(), out y);
365 else
366 m_log.WarnFormat(" -- request didn't have destination_y");
367 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
368 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
369 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
370 regionname = args["destination_name"].ToString();
371 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
372 teleportFlags = args["teleport_flags"].AsUInteger();
373 356
374 GridRegion destination = new GridRegion(); 357 GridRegion destination = new GridRegion();
375 destination.RegionID = uuid; 358 destination.RegionID = data.uuid;
376 destination.RegionLocX = x; 359 destination.RegionLocX = data.x;
377 destination.RegionLocY = y; 360 destination.RegionLocY = data.y;
378 destination.RegionName = regionname; 361 destination.RegionName = data.name;
362
363 GridRegion gatekeeper = ExtractGatekeeper(data);
379 364
380 AgentCircuitData aCircuit = new AgentCircuitData(); 365 AgentCircuitData aCircuit = new AgentCircuitData();
381 try 366 try
@@ -396,7 +381,7 @@ namespace OpenSim.Server.Handlers.Simulation
396 // This is the meaning of POST agent 381 // This is the meaning of POST agent
397 //m_regionClient.AdjustUserInformation(aCircuit); 382 //m_regionClient.AdjustUserInformation(aCircuit);
398 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); 383 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
399 bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); 384 bool result = CreateAgent(gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason);
400 385
401 resp["reason"] = OSD.FromString(reason); 386 resp["reason"] = OSD.FromString(reason);
402 resp["success"] = OSD.FromBoolean(result); 387 resp["success"] = OSD.FromBoolean(result);
@@ -408,7 +393,36 @@ namespace OpenSim.Server.Handlers.Simulation
408 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); 393 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
409 } 394 }
410 395
411 private string GetCallerIP(Hashtable request) 396 protected virtual AgentDestinationData CreateAgentDestinationData()
397 {
398 return new AgentDestinationData();
399 }
400
401 protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
402 {
403 // retrieve the input arguments
404 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
405 Int32.TryParse(args["destination_x"].AsString(), out data.x);
406 else
407 m_log.WarnFormat(" -- request didn't have destination_x");
408 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
409 Int32.TryParse(args["destination_y"].AsString(), out data.y);
410 else
411 m_log.WarnFormat(" -- request didn't have destination_y");
412 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
413 UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid);
414 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
415 data.name = args["destination_name"].ToString();
416 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
417 data.flags = args["teleport_flags"].AsUInteger();
418 }
419
420 protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data)
421 {
422 return null;
423 }
424
425 protected string GetCallerIP(Hashtable request)
412 { 426 {
413 if (!m_Proxy) 427 if (!m_Proxy)
414 return Util.GetCallerIP(request); 428 return Util.GetCallerIP(request);
@@ -441,7 +455,7 @@ namespace OpenSim.Server.Handlers.Simulation
441 } 455 }
442 456
443 // subclasses can override this 457 // subclasses can override this
444 protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 458 protected virtual bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
445 { 459 {
446 reason = String.Empty; 460 reason = String.Empty;
447 461
@@ -593,7 +607,6 @@ namespace OpenSim.Server.Handlers.Simulation
593 //agent.Dump(); 607 //agent.Dump();
594 // This is one of the meanings of PUT agent 608 // This is one of the meanings of PUT agent
595 result = UpdateAgent(destination, agent); 609 result = UpdateAgent(destination, agent);
596
597 } 610 }
598 else if ("AgentPosition".Equals(messageType)) 611 else if ("AgentPosition".Equals(messageType))
599 { 612 {
@@ -624,4 +637,14 @@ namespace OpenSim.Server.Handlers.Simulation
624 return m_SimulationService.UpdateAgent(destination, agent); 637 return m_SimulationService.UpdateAgent(destination, agent);
625 } 638 }
626 } 639 }
640
641 public class AgentDestinationData
642 {
643 public int x;
644 public int y;
645 public string name;
646 public UUID uuid;
647 public uint flags;
648 public bool fromLogin;
649 }
627} 650}
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index d840527..803cd1b 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
53 53
54 private IAssetService m_AssetService; 54 private IAssetService m_AssetService;
55 55
56 public GatekeeperServiceConnector() : base() 56 public GatekeeperServiceConnector()
57 : base()
57 { 58 {
58 } 59 }
59 60
@@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid
123 realHandle = Convert.ToUInt64((string)hash["handle"]); 124 realHandle = Convert.ToUInt64((string)hash["handle"]);
124 //m_log.Debug(">> HERE, realHandle: " + realHandle); 125 //m_log.Debug(">> HERE, realHandle: " + realHandle);
125 } 126 }
126 if (hash["region_image"] != null) { 127 if (hash["region_image"] != null)
128 {
127 imageURL = (string)hash["region_image"]; 129 imageURL = (string)hash["region_image"];
128 //m_log.Debug(">> HERE, imageURL: " + imageURL); 130 //m_log.Debug(">> HERE, imageURL: " + imageURL);
129 } 131 }
130 if (hash["external_name"] != null) { 132 if (hash["external_name"] != null)
133 {
131 externalName = (string)hash["external_name"]; 134 externalName = (string)hash["external_name"];
132 //m_log.Debug(">> HERE, externalName: " + externalName); 135 //m_log.Debug(">> HERE, externalName: " + externalName);
133 } 136 }
@@ -179,7 +182,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
179 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); 182 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
180 imageData = OpenJPEG.EncodeFromImage(bitmap, true); 183 imageData = OpenJPEG.EncodeFromImage(bitmap, true);
181 } 184 }
182 185
183 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString()); 186 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
184 187
185 // !!! for now 188 // !!! for now
@@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
257 region.RegionName = (string)hash["region_name"]; 260 region.RegionName = (string)hash["region_name"];
258 //m_log.Debug(">> HERE, region_name: " + region.RegionName); 261 //m_log.Debug(">> HERE, region_name: " + region.RegionName);
259 } 262 }
260 if (hash["hostname"] != null) { 263 if (hash["hostname"] != null)
264 {
261 region.ExternalHostName = (string)hash["hostname"]; 265 region.ExternalHostName = (string)hash["hostname"];
262 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); 266 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
263 } 267 }
@@ -275,10 +279,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
275 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); 279 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
276 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); 280 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
277 } 281 }
278 282
279 if (hash["server_uri"] != null) 283 if (hash["server_uri"] != null)
280 { 284 {
281 region.ServerURI = (string) hash["server_uri"]; 285 region.ServerURI = (string)hash["server_uri"];
282 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); 286 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
283 } 287 }
284 288
@@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid
295 299
296 return null; 300 return null;
297 } 301 }
298
299 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
300 {
301 // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start");
302
303 myipaddress = String.Empty;
304 reason = String.Empty;
305
306 if (destination == null)
307 {
308 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null");
309 return false;
310 }
311
312 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
313
314 try
315 {
316 OSDMap args = aCircuit.PackAgentCircuitData();
317
318 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
319 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
320 args["destination_name"] = OSD.FromString(destination.RegionName);
321 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
322 args["teleport_flags"] = OSD.FromString(flags.ToString());
323
324 OSDMap result = WebUtil.PostToService(uri, args, 80000);
325 if (result["Success"].AsBoolean())
326 {
327 OSDMap unpacked = (OSDMap)result["_Result"];
328
329 if (unpacked != null)
330 {
331 reason = unpacked["reason"].AsString();
332 myipaddress = unpacked["your_ip"].AsString();
333 return unpacked["success"].AsBoolean();
334 }
335 }
336
337 reason = result["Message"] != null ? result["Message"].AsString() : "error";
338 return false;
339 }
340 catch (Exception e)
341 {
342 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
343 reason = e.Message;
344 }
345
346 return false;
347 }
348 } 302 }
349} 303}
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index d7e38f1..5f5b7a7 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -44,13 +44,14 @@ using Nini.Config;
44 44
45namespace OpenSim.Services.Connectors.Hypergrid 45namespace OpenSim.Services.Connectors.Hypergrid
46{ 46{
47 public class UserAgentServiceConnector : IUserAgentService 47 public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
48 { 48 {
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
50 LogManager.GetLogger( 50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 string m_ServerURL; 53 private string m_ServerURL;
54 private GridRegion m_Gatekeeper;
54 55
55 public UserAgentServiceConnector(string url) : this(url, true) 56 public UserAgentServiceConnector(string url) : this(url, true)
56 { 57 {
@@ -102,9 +103,15 @@ namespace OpenSim.Services.Connectors.Hypergrid
102 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); 103 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
103 } 104 }
104 105
106 protected override string AgentPath()
107 {
108 return "homeagent/";
109 }
105 110
106 // The Login service calls this interface with a non-null [client] ipaddress 111 // The Login service calls this interface with fromLogin=true
107 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason) 112 // Sims call it with fromLogin=false
113 // Either way, this is verified by the handler
114 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)
108 { 115 {
109 reason = String.Empty; 116 reason = String.Empty;
110 117
@@ -115,119 +122,34 @@ namespace OpenSim.Services.Connectors.Hypergrid
115 return false; 122 return false;
116 } 123 }
117 124
118 string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/"; 125 GridRegion home = new GridRegion();
119 126 home.ServerURI = m_ServerURL;
120 Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri); 127 home.RegionID = destination.RegionID;
121 128 home.RegionLocX = destination.RegionLocX;
122 HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); 129 home.RegionLocY = destination.RegionLocY;
123 AgentCreateRequest.Method = "POST";
124 AgentCreateRequest.ContentType = "application/json";
125 AgentCreateRequest.Timeout = 10000;
126 //AgentCreateRequest.KeepAlive = false;
127 //AgentCreateRequest.Headers.Add("Authorization", authKey);
128
129 // Fill it in
130 OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress);
131
132 string strBuffer = "";
133 byte[] buffer = new byte[1];
134 try
135 {
136 strBuffer = OSDParser.SerializeJsonString(args);
137 Encoding str = Util.UTF8;
138 buffer = str.GetBytes(strBuffer);
139
140 }
141 catch (Exception e)
142 {
143 m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
144 // ignore. buffer will be empty, caller should check.
145 }
146
147 Stream os = null;
148 try
149 { // send the Post
150 AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
151 os = AgentCreateRequest.GetRequestStream();
152 os.Write(buffer, 0, strBuffer.Length); //Send it
153 m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}",
154 uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY);
155 }
156 //catch (WebException ex)
157 catch
158 {
159 //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message);
160 reason = "cannot contact remote region";
161 return false;
162 }
163 finally
164 {
165 if (os != null)
166 os.Close();
167 }
168
169 // Let's wait for the response
170 //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall");
171 130
172 try 131 m_Gatekeeper = gatekeeper;
173 {
174 using (WebResponse webResponse = AgentCreateRequest.GetResponse())
175 {
176 if (webResponse == null)
177 {
178 m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post");
179 }
180 else
181 {
182 using (Stream s = webResponse.GetResponseStream())
183 {
184 using (StreamReader sr = new StreamReader(s))
185 {
186 string response = sr.ReadToEnd().Trim();
187 m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response);
188
189 if (!String.IsNullOrEmpty(response))
190 {
191 try
192 {
193 // we assume we got an OSDMap back
194 OSDMap r = Util.GetOSDMap(response);
195 bool success = r["success"].AsBoolean();
196 reason = r["reason"].AsString();
197 return success;
198 }
199 catch (NullReferenceException e)
200 {
201 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
202
203 // check for old style response
204 if (response.ToLower().StartsWith("true"))
205 return true;
206
207 return false;
208 }
209 }
210 }
211 }
212 }
213 }
214 }
215 catch (WebException ex)
216 {
217 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
218 reason = "Destination did not reply";
219 return false;
220 }
221 132
222 return true; 133 Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
223 134
135 uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
136 return CreateAgent(home, aCircuit, flags, out reason);
224 } 137 }
225 138
226 139
227 // The simulators call this interface 140 // The simulators call this interface
228 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) 141 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
229 { 142 {
230 return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason); 143 return LoginAgentToGrid(aCircuit, gatekeeper, destination, false, out reason);
144 }
145
146 protected override void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
147 {
148 base.PackData(args, aCircuit, destination, flags);
149 args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI);
150 args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName);
151 args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString());
152 args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
231 } 153 }
232 154
233 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) 155 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress)
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index ef2494a..da77719 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation
79 return "agent/"; 79 return "agent/";
80 } 80 }
81 81
82 protected virtual void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
83 {
84 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
85 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
86 args["destination_name"] = OSD.FromString(destination.RegionName);
87 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
88 args["teleport_flags"] = OSD.FromString(flags.ToString());
89 }
90
82 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) 91 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason)
83 { 92 {
84 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); 93 string tmp = String.Empty;
85 94 return CreateAgent(destination, aCircuit, flags, out tmp, out reason);
95 }
96
97 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
98 {
99 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
86 reason = String.Empty; 100 reason = String.Empty;
101 myipaddress = String.Empty;
102
87 if (destination == null) 103 if (destination == null)
88 { 104 {
89 reason = "Destination not found"; 105 reason = "Destination not found";
@@ -96,12 +112,7 @@ namespace OpenSim.Services.Connectors.Simulation
96 try 112 try
97 { 113 {
98 OSDMap args = aCircuit.PackAgentCircuitData(); 114 OSDMap args = aCircuit.PackAgentCircuitData();
99 115 PackData(args, aCircuit, destination, flags);
100 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
101 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
102 args["destination_name"] = OSD.FromString(destination.RegionName);
103 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
104 args["teleport_flags"] = OSD.FromString(flags.ToString());
105 116
106 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); 117 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
107 bool success = result["success"].AsBoolean(); 118 bool success = result["success"].AsBoolean();
@@ -111,6 +122,7 @@ namespace OpenSim.Services.Connectors.Simulation
111 122
112 reason = data["reason"].AsString(); 123 reason = data["reason"].AsString();
113 success = data["success"].AsBoolean(); 124 success = data["success"].AsBoolean();
125 myipaddress = data["your_ip"].AsString();
114 return success; 126 return success;
115 } 127 }
116 128
@@ -125,6 +137,7 @@ namespace OpenSim.Services.Connectors.Simulation
125 137
126 reason = data["reason"].AsString(); 138 reason = data["reason"].AsString();
127 success = data["success"].AsBoolean(); 139 success = data["success"].AsBoolean();
140 myipaddress = data["your_ip"].AsString();
128 m_log.WarnFormat( 141 m_log.WarnFormat(
129 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); 142 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
130 return success; 143 return success;
@@ -229,7 +242,7 @@ namespace OpenSim.Services.Connectors.Simulation
229 /// </summary> 242 /// </summary>
230 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) 243 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
231 { 244 {
232 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start"); 245 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI);
233 246
234 // Eventually, we want to use a caps url instead of the agentID 247 // Eventually, we want to use a caps url instead of the agentID
235 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; 248 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index ec76508..a6b5fc2 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService
210 return home; 210 return home;
211 } 211 }
212 212
213 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) 213 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason)
214 { 214 {
215 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", 215 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
216 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); 216 agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI);
217 217
218 string gridName = gatekeeper.ServerURI; 218 string gridName = gatekeeper.ServerURI;
219 219
@@ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService
265 bool success = false; 265 bool success = false;
266 string myExternalIP = string.Empty; 266 string myExternalIP = string.Empty;
267 267
268 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 268 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID);
269 269
270 if (m_GridName == gridName) 270 if (m_GridName == gridName)
271 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); 271 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
@@ -296,8 +296,8 @@ namespace OpenSim.Services.HypergridService
296 296
297 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); 297 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP);
298 // else set the IP addresses associated with this client 298 // else set the IP addresses associated with this client
299 if (clientIP != null) 299 if (fromLogin)
300 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); 300 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress;
301 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; 301 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
302 302
303 return true; 303 return true;
@@ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService
306 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) 306 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
307 { 307 {
308 reason = string.Empty; 308 reason = string.Empty;
309 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason); 309 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, false, out reason);
310 } 310 }
311 311
312 private void SetClientIP(UUID sessionID, string ip) 312 private void SetClientIP(UUID sessionID, string ip)
diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs
index 3dc877a..f9e7f08 100644
--- a/OpenSim/Services/Interfaces/IHypergridServices.cs
+++ b/OpenSim/Services/Interfaces/IHypergridServices.cs
@@ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces
48 /// </summary> 48 /// </summary>
49 public interface IUserAgentService 49 public interface IUserAgentService
50 { 50 {
51 // called by login service only 51 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason);
52 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason);
53 // called by simulators
54 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason);
55 void LogoutAgent(UUID userID, UUID sessionID); 52 void LogoutAgent(UUID userID, UUID sessionID);
56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); 53 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
57 Dictionary<string, object> GetServerURLs(UUID userID); 54 Dictionary<string, object> GetServerURLs(UUID userID);
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 81712f6..faf7f71 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -941,7 +941,7 @@ namespace OpenSim.Services.LLLoginService
941 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) 941 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
942 { 942 {
943 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); 943 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName);
944 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason)) 944 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, true, out reason))
945 return true; 945 return true;
946 return false; 946 return false;
947 } 947 }