aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs150
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/EventHistogram.cs173
-rw-r--r--OpenSim/Framework/Monitoring/Stats/PercentageStat.cs16
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs46
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs37
-rw-r--r--OpenSim/Framework/Tests/LocationTest.cs7
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs82
-rw-r--r--OpenSim/Framework/Util.cs4
-rw-r--r--OpenSim/Region/Application/Application.cs6
-rw-r--r--OpenSim/Region/Application/OpenSim.cs47
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs38
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs31
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs362
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs41
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs102
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs4
-rw-r--r--bin/OpenSimDefaults.ini7
25 files changed, 869 insertions, 362 deletions
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
index 04442c3..318cf1c 100755
--- a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
@@ -34,142 +34,6 @@ using OpenMetaverse.StructuredData;
34 34
35namespace OpenSim.Framework.Monitoring 35namespace OpenSim.Framework.Monitoring
36{ 36{
37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000)
41public class EventHistogram
42{
43 private int m_timeBase;
44 private int m_numBuckets;
45 private int m_bucketMilliseconds;
46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram;
49 private object histoLock = new object();
50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 {
53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56
57 m_histogram = new long[m_numBuckets];
58 Zero();
59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount();
61 }
62
63 public void Event()
64 {
65 this.Event(1);
66 }
67
68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt)
70 {
71 lock (histoLock)
72 {
73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75
76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds)
78 {
79 Zero();
80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount();
82 }
83 else
84 {
85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds;
87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket)
90 {
91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 {
94 m_histogram[jj] = 0;
95 }
96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets)
99 {
100 bucket -= m_numBuckets;
101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds;
104 }
105 }
106 }
107 m_histogram[m_lastBucket] += cnt;
108 }
109 }
110
111 // Get a copy of the current histogram
112 public long[] GetHistogram()
113 {
114 long[] ret = new long[m_numBuckets];
115 lock (histoLock)
116 {
117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 {
120 if (indx >= m_numBuckets)
121 indx = 0;
122 ret[ii] = m_histogram[indx];
123 }
124 }
125 return ret;
126 }
127
128 public OSDMap GetHistogramAsOSDMap()
129 {
130 OSDMap ret = new OSDMap();
131
132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135
136 // Compute a number for the first bucket in the histogram.
137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140
141 ret.Add("Values", GetHistogramAsOSDArray());
142
143 return ret;
144 }
145 // Get a copy of the current histogram
146 public OSDArray GetHistogramAsOSDArray()
147 {
148 OSDArray ret = new OSDArray(m_numBuckets);
149 lock (histoLock)
150 {
151 int indx = m_lastBucket + 1;
152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 {
154 if (indx >= m_numBuckets)
155 indx = 0;
156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157 }
158 }
159 return ret;
160 }
161
162 // Zero out the histogram
163 public void Zero()
164 {
165 lock (histoLock)
166 {
167 for (int ii = 0; ii < m_numBuckets; ii++)
168 m_histogram[ii] = 0;
169 }
170 }
171}
172
173// A statistic that wraps a counter. 37// A statistic that wraps a counter.
174// Built this way mostly so histograms and history can be created. 38// Built this way mostly so histograms and history can be created.
175public class CounterStat : Stat 39public class CounterStat : Stat
@@ -236,12 +100,18 @@ public class CounterStat : Stat
236 // If there are any histograms, add a new field that is an array of histograms as OSDMaps 100 // If there are any histograms, add a new field that is an array of histograms as OSDMaps
237 if (m_histograms.Count > 0) 101 if (m_histograms.Count > 0)
238 { 102 {
239 OSDArray histos = new OSDArray(); 103 lock (counterLock)
240 foreach (EventHistogram histo in m_histograms.Values)
241 { 104 {
242 histos.Add(histo.GetHistogramAsOSDMap()); 105 if (m_histograms.Count > 0)
106 {
107 OSDArray histos = new OSDArray();
108 foreach (EventHistogram histo in m_histograms.Values)
109 {
110 histos.Add(histo.GetHistogramAsOSDMap());
111 }
112 map.Add("Histograms", histos);
113 }
243 } 114 }
244 map.Add("Histograms", histos);
245 } 115 }
246 return map; 116 return map;
247 } 117 }
diff --git a/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs b/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
new file mode 100755
index 0000000..f51f322
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
@@ -0,0 +1,173 @@
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.Linq;
31using System.Text;
32
33using OpenMetaverse.StructuredData;
34
35namespace OpenSim.Framework.Monitoring
36{
37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000)
41public class EventHistogram
42{
43 private int m_timeBase;
44 private int m_numBuckets;
45 private int m_bucketMilliseconds;
46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram;
49 private object histoLock = new object();
50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 {
53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56
57 m_histogram = new long[m_numBuckets];
58 Zero();
59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount();
61 }
62
63 public void Event()
64 {
65 this.Event(1);
66 }
67
68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt)
70 {
71 lock (histoLock)
72 {
73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75
76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds)
78 {
79 Zero();
80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount();
82 }
83 else
84 {
85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds;
87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket)
90 {
91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 {
94 m_histogram[jj] = 0;
95 }
96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets)
99 {
100 bucket -= m_numBuckets;
101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds;
104 }
105 }
106 }
107 m_histogram[m_lastBucket] += cnt;
108 }
109 }
110
111 // Get a copy of the current histogram
112 public long[] GetHistogram()
113 {
114 long[] ret = new long[m_numBuckets];
115 lock (histoLock)
116 {
117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 {
120 if (indx >= m_numBuckets)
121 indx = 0;
122 ret[ii] = m_histogram[indx];
123 }
124 }
125 return ret;
126 }
127
128 public OSDMap GetHistogramAsOSDMap()
129 {
130 OSDMap ret = new OSDMap();
131
132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135
136 // Compute a number for the first bucket in the histogram.
137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140
141 ret.Add("Values", GetHistogramAsOSDArray());
142
143 return ret;
144 }
145 // Get a copy of the current histogram
146 public OSDArray GetHistogramAsOSDArray()
147 {
148 OSDArray ret = new OSDArray(m_numBuckets);
149 lock (histoLock)
150 {
151 int indx = m_lastBucket + 1;
152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 {
154 if (indx >= m_numBuckets)
155 indx = 0;
156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157 }
158 }
159 return ret;
160 }
161
162 // Zero out the histogram
163 public void Zero()
164 {
165 lock (histoLock)
166 {
167 for (int ii = 0; ii < m_numBuckets; ii++)
168 m_histogram[ii] = 0;
169 }
170 }
171}
172
173}
diff --git a/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
index 60bed55..55ddf06 100644
--- a/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
@@ -29,6 +29,8 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenMetaverse.StructuredData;
33
32namespace OpenSim.Framework.Monitoring 34namespace OpenSim.Framework.Monitoring
33{ 35{
34 public class PercentageStat : Stat 36 public class PercentageStat : Stat
@@ -84,5 +86,19 @@ namespace OpenSim.Framework.Monitoring
84 86
85 return sb.ToString(); 87 return sb.ToString();
86 } 88 }
89
90 // PercentageStat is a basic stat plus percent calc
91 public override OSDMap ToOSDMap()
92 {
93 // Get the foundational instance
94 OSDMap map = base.ToOSDMap();
95
96 map["StatType"] = "PercentageStat";
97
98 map.Add("Antecedent", OSD.FromLong(Antecedent));
99 map.Add("Consequent", OSD.FromLong(Consequent));
100
101 return map;
102 }
87 } 103 }
88} \ No newline at end of file 104} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index ffd5132..2b34493 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -241,6 +241,8 @@ namespace OpenSim.Framework.Monitoring
241 public virtual OSDMap ToOSDMap() 241 public virtual OSDMap ToOSDMap()
242 { 242 {
243 OSDMap ret = new OSDMap(); 243 OSDMap ret = new OSDMap();
244 ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat
245
244 ret.Add("Category", OSD.FromString(Category)); 246 ret.Add("Category", OSD.FromString(Category));
245 ret.Add("Container", OSD.FromString(Container)); 247 ret.Add("Container", OSD.FromString(Container));
246 ret.Add("ShortName", OSD.FromString(ShortName)); 248 ret.Add("ShortName", OSD.FromString(ShortName));
@@ -248,26 +250,36 @@ namespace OpenSim.Framework.Monitoring
248 ret.Add("Description", OSD.FromString(Description)); 250 ret.Add("Description", OSD.FromString(Description));
249 ret.Add("UnitName", OSD.FromString(UnitName)); 251 ret.Add("UnitName", OSD.FromString(UnitName));
250 ret.Add("Value", OSD.FromReal(Value)); 252 ret.Add("Value", OSD.FromReal(Value));
251 ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat 253
254 double lastChangeOverTime, averageChangeOverTime;
255 if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
256 {
257 ret.Add("LastChangeOverTime", OSD.FromReal(lastChangeOverTime));
258 ret.Add("AverageChangeOverTime", OSD.FromReal(averageChangeOverTime));
259 }
252 260
253 return ret; 261 return ret;
254 } 262 }
255 263
256 protected void AppendMeasuresOfInterest(StringBuilder sb) 264 // Compute the averages over time and return same.
265 // Return 'true' if averages were actually computed. 'false' if no average info.
266 public bool ComputeMeasuresOfInterest(out double lastChangeOverTime, out double averageChangeOverTime)
257 { 267 {
258 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) 268 bool ret = false;
259 == MeasuresOfInterest.AverageChangeOverTime) 269 lastChangeOverTime = 0;
270 averageChangeOverTime = 0;
271
272 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
260 { 273 {
261 double totalChange = 0; 274 double totalChange = 0;
262 double lastChangeOverTime = 0;
263 double? penultimateSample = null; 275 double? penultimateSample = null;
264 double? lastSample = null; 276 double? lastSample = null;
265 277
266 lock (m_samples) 278 lock (m_samples)
267 { 279 {
268// m_log.DebugFormat( 280 // m_log.DebugFormat(
269// "[STAT]: Samples for {0} are {1}", 281 // "[STAT]: Samples for {0} are {1}",
270// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray())); 282 // Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
271 283
272 foreach (double s in m_samples) 284 foreach (double s in m_samples)
273 { 285 {
@@ -280,13 +292,27 @@ namespace OpenSim.Framework.Monitoring
280 } 292 }
281 293
282 if (lastSample != null && penultimateSample != null) 294 if (lastSample != null && penultimateSample != null)
283 lastChangeOverTime 295 {
296 lastChangeOverTime
284 = ((double)lastSample - (double)penultimateSample) / (Watchdog.WATCHDOG_INTERVAL_MS / 1000); 297 = ((double)lastSample - (double)penultimateSample) / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
298 }
285 299
286 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; 300 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
287 301
288 double averageChangeOverTime = totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000); 302 averageChangeOverTime = totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
303 ret = true;
304 }
305
306 return ret;
307 }
289 308
309 protected void AppendMeasuresOfInterest(StringBuilder sb)
310 {
311 double lastChangeOverTime = 0;
312 double averageChangeOverTime = 0;
313
314 if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
315 {
290 sb.AppendFormat( 316 sb.AppendFormat(
291 ", {0:0.##}{1}/s, {2:0.##}{3}/s", 317 ", {0:0.##}{1}/s, {2:0.##}{3}/s",
292 lastChangeOverTime, 318 lastChangeOverTime,
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index c8e838c..7cf1fa7 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -26,10 +26,12 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Linq; 31using System.Linq;
31using System.Text; 32using System.Text;
32 33
34using OpenSim.Framework;
33using OpenMetaverse.StructuredData; 35using OpenMetaverse.StructuredData;
34 36
35namespace OpenSim.Framework.Monitoring 37namespace OpenSim.Framework.Monitoring
@@ -262,6 +264,41 @@ namespace OpenSim.Framework.Monitoring
262 return map; 264 return map;
263 } 265 }
264 266
267 public static Hashtable HandleStatsRequest(Hashtable request)
268 {
269 Hashtable responsedata = new Hashtable();
270 string regpath = request["uri"].ToString();
271 int response_code = 200;
272 string contenttype = "text/json";
273
274 string pCategoryName = StatsManager.AllSubCommand;
275 string pContainerName = StatsManager.AllSubCommand;
276 string pStatName = StatsManager.AllSubCommand;
277
278 if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
279 if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
280 if (request.ContainsKey("stat")) pStatName = request["cat"].ToString();
281
282 string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
283
284 // If requestor wants it as a callback function, build response as a function rather than just the JSON string.
285 if (request.ContainsKey("callback"))
286 {
287 strOut = request["callback"].ToString() + "(" + strOut + ");";
288 }
289
290 // m_log.DebugFormat("{0} StatFetch: uri={1}, cat={2}, cont={3}, stat={4}, resp={5}",
291 // LogHeader, regpath, pCategoryName, pContainerName, pStatName, strOut);
292
293 responsedata["int_response_code"] = response_code;
294 responsedata["content_type"] = contenttype;
295 responsedata["keepalive"] = false;
296 responsedata["str_response_string"] = strOut;
297 responsedata["access_control_allow_origin"] = "*";
298
299 return responsedata;
300 }
301
265// /// <summary> 302// /// <summary>
266// /// Start collecting statistics related to assets. 303// /// Start collecting statistics related to assets.
267// /// Should only be called once. 304// /// Should only be called once.
diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs
index af5f164..3d5d1d2 100644
--- a/OpenSim/Framework/Tests/LocationTest.cs
+++ b/OpenSim/Framework/Tests/LocationTest.cs
@@ -55,11 +55,18 @@ namespace OpenSim.Framework.Tests
55 Location TestLocation2 = new Location(1095216660736000); 55 Location TestLocation2 = new Location(1095216660736000);
56 Assert.That(TestLocation1 == TestLocation2); 56 Assert.That(TestLocation1 == TestLocation2);
57 57
58 Assert.That(TestLocation1.X == 255000 && TestLocation1.Y == 256000, "Test xy location doesn't match position in the constructor");
58 Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); 59 Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided");
59 60
60 Assert.That(TestLocation2.RegionHandle == 1095216660736000, 61 Assert.That(TestLocation2.RegionHandle == 1095216660736000,
61 "Location RegionHandle Property didn't match regionhandle provided in constructor"); 62 "Location RegionHandle Property didn't match regionhandle provided in constructor");
62 63
64 ulong RegionHandle = TestLocation1.RegionHandle;
65 Assert.That(RegionHandle.Equals(1095216660736000), "Equals(regionhandle) failed to match the position in the constructor");
66
67 TestLocation2 = new Location(RegionHandle);
68 Assert.That(TestLocation2.Equals(255000, 256000), "Decoded regionhandle failed to match the original position in the constructor");
69
63 70
64 TestLocation1 = new Location(255001, 256001); 71 TestLocation1 = new Location(255001, 256001);
65 TestLocation2 = new Location(1095216660736000); 72 TestLocation2 = new Location(1095216660736000);
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index 11ca068..3b7f252 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -282,5 +282,87 @@ namespace OpenSim.Framework.Tests
282 String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i])); 282 String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i]));
283 } 283 }
284 } 284 }
285
286 [Test]
287 public void FakeParcelIDTests()
288 {
289 byte[] hexBytes8 = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
290 byte[] hexBytes16 = {
291 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
292 0x77, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f };
293 UInt64 var64Bit = (UInt64)0xfedcba9876543210;
294
295 //Region handle is for location 255000,256000.
296 ulong regionHandle1 = 1095216660736000;
297 uint x1 = 100;
298 uint y1 = 200;
299 uint z1 = 22;
300 ulong regionHandle2;
301 uint x2, y2, z2;
302 UUID fakeParcelID1, fakeParcelID2, uuid;
303
304 ulong bigInt64 = Util.BytesToUInt64Big(hexBytes8);
305 Assert.AreEqual(var64Bit, bigInt64,
306 "BytesToUint64Bit conversion of 8 bytes to UInt64 failed.");
307
308 //Test building and decoding using some typical input values
309 fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1);
310 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2);
311 Assert.AreEqual(regionHandle1, regionHandle2,
312 "region handle decoded from FakeParcelID wth X/Y failed.");
313 Assert.AreEqual(x1, x2,
314 "X coordinate decoded from FakeParcelID wth X/Y failed.");
315 Assert.AreEqual(y1, y2,
316 "Y coordinate decoded from FakeParcelID wth X/Y failed.");
317
318 fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1, z1);
319 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2, out z2);
320 Assert.AreEqual(regionHandle1, regionHandle2,
321 "region handle decoded from FakeParcelID with X/Y/Z failed.");
322 Assert.AreEqual(x1, x2,
323 "X coordinate decoded from FakeParcelID with X/Y/Z failed.");
324 Assert.AreEqual(y1, y2,
325 "Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
326 Assert.AreEqual(z1, z2,
327 "Z coordinate decoded from FakeParcelID with X/Y/Z failed.");
328
329 //Do some more extreme tests to check the encoding and decoding
330 x1 = 0x55aa;
331 y1 = 0x9966;
332 z1 = 0x5a96;
333
334 fakeParcelID1 = Util.BuildFakeParcelID(var64Bit, x1, y1);
335 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2);
336 Assert.AreEqual(var64Bit, regionHandle2,
337 "region handle decoded from FakeParcelID with X/Y/Z failed.");
338 Assert.AreEqual(x1, x2,
339 "X coordinate decoded from FakeParcelID with X/Y/Z failed.");
340 Assert.AreEqual(y1, y2,
341 "Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
342
343 fakeParcelID1 = Util.BuildFakeParcelID(var64Bit, x1, y1, z1);
344 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2, out z2);
345 Assert.AreEqual(var64Bit, regionHandle2,
346 "region handle decoded from FakeParcelID with X/Y/Z failed.");
347 Assert.AreEqual(x1, x2,
348 "X coordinate decoded from FakeParcelID with X/Y/Z failed.");
349 Assert.AreEqual(y1, y2,
350 "Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
351 Assert.AreEqual(z1, z2,
352 "Z coordinate decoded from FakeParcelID with X/Y/Z failed.");
353
354
355 x1 = 64;
356 y1 = 192;
357 fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1);
358 Util.FakeParcelIDToGlobalPosition(fakeParcelID1, out x2, out y2);
359 Assert.AreEqual(255000+x1, x2,
360 "Global X coordinate decoded from regionHandle failed.");
361 Assert.AreEqual(256000+y1, y2,
362 "Global Y coordinate decoded from regionHandle failed.");
363
364 uuid = new UUID("00dd0700-00d1-0700-3800-000032000000");
365 Util.FakeParcelIDToGlobalPosition(uuid, out x2, out y2);
366 }
285 } 367 }
286} 368}
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 19d40db..7398b37 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1259,7 +1259,7 @@ namespace OpenSim.Framework
1259 byte[] bytes = 1259 byte[] bytes =
1260 { 1260 {
1261 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1261 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1262 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1262 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1263 (byte)x, (byte)(x >> 8), 0, 0, 1263 (byte)x, (byte)(x >> 8), 0, 0,
1264 (byte)y, (byte)(y >> 8), 0, 0 }; 1264 (byte)y, (byte)(y >> 8), 0, 0 };
1265 return new UUID(bytes, 0); 1265 return new UUID(bytes, 0);
@@ -1270,7 +1270,7 @@ namespace OpenSim.Framework
1270 byte[] bytes = 1270 byte[] bytes =
1271 { 1271 {
1272 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1272 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1273 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1273 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1274 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), 1274 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
1275 (byte)y, (byte)(y >> 8), 0, 0 }; 1275 (byte)y, (byte)(y >> 8), 0, 0 };
1276 return new UUID(bytes, 0); 1276 return new UUID(bytes, 0);
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index 2e155ec..3a4e5df 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -142,19 +142,19 @@ namespace OpenSim
142 if (iocpThreads < iocpThreadsMin) 142 if (iocpThreads < iocpThreadsMin)
143 { 143 {
144 iocpThreads = iocpThreadsMin; 144 iocpThreads = iocpThreadsMin;
145 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IO completion threads to {0}",iocpThreads); 145 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IOCP threads to {0}",iocpThreads);
146 } 146 }
147 // Make sure we don't overallocate IOCP threads and thrash system resources 147 // Make sure we don't overallocate IOCP threads and thrash system resources
148 if ( iocpThreads > iocpThreadsMax ) 148 if ( iocpThreads > iocpThreadsMax )
149 { 149 {
150 iocpThreads = iocpThreadsMax; 150 iocpThreads = iocpThreadsMax;
151 m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IO completion threads to {0}",iocpThreads); 151 m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IOCP completion threads to {0}",iocpThreads);
152 } 152 }
153 // set the resulting worker and IO completion thread counts back to ThreadPool 153 // set the resulting worker and IO completion thread counts back to ThreadPool
154 if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) ) 154 if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) )
155 { 155 {
156 m_log.InfoFormat( 156 m_log.InfoFormat(
157 "[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IO completion threads", 157 "[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IOCP threads",
158 workerThreads, iocpThreads); 158 workerThreads, iocpThreads);
159 } 159 }
160 else 160 else
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 6dd1f5b..a18a6fe 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -172,6 +172,13 @@ namespace OpenSim
172 if (userStatsURI != String.Empty) 172 if (userStatsURI != String.Empty)
173 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this)); 173 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
174 174
175 if (managedStatsURI != String.Empty)
176 {
177 string urlBase = String.Format("/{0}/", managedStatsURI);
178 MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest);
179 m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase);
180 }
181
175 if (m_console is RemoteConsole) 182 if (m_console is RemoteConsole)
176 { 183 {
177 if (m_consolePort == 0) 184 if (m_consolePort == 0)
@@ -348,18 +355,6 @@ namespace OpenSim
348 m_console.Commands.AddCommand("Regions", false, "delete-region", 355 m_console.Commands.AddCommand("Regions", false, "delete-region",
349 "delete-region <name>", 356 "delete-region <name>",
350 "Delete a region from disk", RunCommand); 357 "Delete a region from disk", RunCommand);
351
352 m_console.Commands.AddCommand("General", false, "modules list",
353 "modules list",
354 "List modules", HandleModules);
355
356 m_console.Commands.AddCommand("General", false, "modules load",
357 "modules load <name>",
358 "Load a module", HandleModules);
359
360 m_console.Commands.AddCommand("General", false, "modules unload",
361 "modules unload <name>",
362 "Unload a module", HandleModules);
363 } 358 }
364 359
365 protected override void ShutdownSpecific() 360 protected override void ShutdownSpecific()
@@ -557,34 +552,6 @@ namespace OpenSim
557 } 552 }
558 553
559 /// <summary> 554 /// <summary>
560 /// Load, Unload, and list Region modules in use
561 /// </summary>
562 /// <param name="module"></param>
563 /// <param name="cmd"></param>
564 private void HandleModules(string module, string[] cmd)
565 {
566 List<string> args = new List<string>(cmd);
567 args.RemoveAt(0);
568 string[] cmdparams = args.ToArray();
569
570 if (cmdparams.Length > 0)
571 {
572 switch (cmdparams[0].ToLower())
573 {
574 case "list":
575 //TODO: Convert to new region modules
576 break;
577 case "unload":
578 //TODO: Convert to new region modules
579 break;
580 case "load":
581 //TODO: Convert to new region modules
582 break;
583 }
584 }
585 }
586
587 /// <summary>
588 /// Runs commands issued by the server console from the operator 555 /// Runs commands issued by the server console from the operator
589 /// </summary> 556 /// </summary>
590 /// <param name="command">The first argument of the parameter (the command)</param> 557 /// <param name="command">The first argument of the parameter (the command)</param>
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index db76529..0f3bac4 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -75,6 +75,7 @@ namespace OpenSim
75 protected int proxyOffset = 0; 75 protected int proxyOffset = 0;
76 76
77 public string userStatsURI = String.Empty; 77 public string userStatsURI = String.Empty;
78 public string managedStatsURI = String.Empty;
78 79
79 protected bool m_autoCreateClientStack = true; 80 protected bool m_autoCreateClientStack = true;
80 81
@@ -197,6 +198,8 @@ namespace OpenSim
197 198
198 string permissionModules = startupConfig.GetString("permissionmodules", "DefaultPermissionsModule"); 199 string permissionModules = startupConfig.GetString("permissionmodules", "DefaultPermissionsModule");
199 m_permsModules = new List<string>(permissionModules.Split(',')); 200 m_permsModules = new List<string>(permissionModules.Split(','));
201
202 managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty);
200 } 203 }
201 204
202 // Load the simulation data service 205 // Load the simulation data service
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index 141af8a..626932f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
91 public void RemoveForClient() 91 public void RemoveForClient()
92 { 92 {
93 TestHelpers.InMethod(); 93 TestHelpers.InMethod();
94// log4net.Config.XmlConfigurator.Configure(); 94// TestHelpers.EnableLogging();
95 95
96 UUID spId = TestHelpers.ParseTail(0x1); 96 UUID spId = TestHelpers.ParseTail(0x1);
97 97
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 0e20e38..8cbbfd9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -337,6 +337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 private bool m_VelocityInterpolate = false; 337 private bool m_VelocityInterpolate = false;
338 private const uint MaxTransferBytesPerPacket = 600; 338 private const uint MaxTransferBytesPerPacket = 600;
339 339
340 private volatile bool m_justEditedTerrain = false;
340 341
341 /// <value> 342 /// <value>
342 /// List used in construction of data blocks for an object update packet. This is to stop us having to 343 /// List used in construction of data blocks for an object update packet. This is to stop us having to
@@ -536,7 +537,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
536 // We still perform a force close inside the sync lock since this is intended to attempt close where 537 // We still perform a force close inside the sync lock since this is intended to attempt close where
537 // there is some unidentified connection problem, not where we have issues due to deadlock 538 // there is some unidentified connection problem, not where we have issues due to deadlock
538 if (!IsActive && !force) 539 if (!IsActive && !force)
540 {
541 m_log.DebugFormat(
542 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set",
543 Name, m_scene.Name);
544
539 return; 545 return;
546 }
540 547
541 IsActive = false; 548 IsActive = false;
542 CloseWithoutChecks(sendStop); 549 CloseWithoutChecks(sendStop);
@@ -1231,9 +1238,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1231 LLHeightFieldMoronize(map); 1238 LLHeightFieldMoronize(map);
1232 1239
1233 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1240 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1234 layerpack.Header.Reliable = true; 1241
1242 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1243 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
1244 // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
1245 // invalidating previous packets for that area.
1246
1247 // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
1248 // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
1249
1250 // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
1251 // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
1252 // patches.
1235 1253
1236 OutPacket(layerpack, ThrottleOutPacketType.Task); 1254 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
1255 if (m_justEditedTerrain)
1256 {
1257 layerpack.Header.Reliable = false;
1258 OutPacket(layerpack,
1259 ThrottleOutPacketType.Unknown );
1260 }
1261 else
1262 {
1263 layerpack.Header.Reliable = true;
1264 OutPacket(layerpack,
1265 ThrottleOutPacketType.Task);
1266 }
1237 } 1267 }
1238 catch (Exception e) 1268 catch (Exception e)
1239 { 1269 {
@@ -6367,6 +6397,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6367 //m_log.Info("[LAND]: LAND:" + modify.ToString()); 6397 //m_log.Info("[LAND]: LAND:" + modify.ToString());
6368 if (modify.ParcelData.Length > 0) 6398 if (modify.ParcelData.Length > 0)
6369 { 6399 {
6400 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6401 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6402 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6370 if (OnModifyTerrain != null) 6403 if (OnModifyTerrain != null)
6371 { 6404 {
6372 for (int i = 0; i < modify.ParcelData.Length; i++) 6405 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6382,6 +6415,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6382 } 6415 }
6383 } 6416 }
6384 } 6417 }
6418 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6385 } 6419 }
6386 6420
6387 return true; 6421 return true;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 71b464b..0431b53 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1871,9 +1871,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1871 1871
1872 if (!client.SceneAgent.IsChildAgent) 1872 if (!client.SceneAgent.IsChildAgent)
1873 client.Kick("Simulator logged you out due to connection timeout."); 1873 client.Kick("Simulator logged you out due to connection timeout.");
1874
1875 client.CloseWithoutChecks(true);
1876 } 1874 }
1875
1876 m_scene.IncomingCloseAgent(client.AgentId, true);
1877 } 1877 }
1878 1878
1879 private void IncomingPacketHandler() 1879 private void IncomingPacketHandler()
@@ -2216,7 +2216,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2216 if (!client.IsLoggingOut) 2216 if (!client.IsLoggingOut)
2217 { 2217 {
2218 client.IsLoggingOut = true; 2218 client.IsLoggingOut = true;
2219 client.Close(false, false); 2219 m_scene.IncomingCloseAgent(client.AgentId, false);
2220 } 2220 }
2221 } 2221 }
2222 } 2222 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index b47ff54..9700224 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
200 public void TestLogoutClientDueToAck() 200 public void TestLogoutClientDueToAck()
201 { 201 {
202 TestHelpers.InMethod(); 202 TestHelpers.InMethod();
203// TestHelpers.EnableLogging(); 203 TestHelpers.EnableLogging();
204 204
205 IniConfigSource ics = new IniConfigSource(); 205 IniConfigSource ics = new IniConfigSource();
206 IConfig config = ics.AddConfig("ClientStack.LindenUDP"); 206 IConfig config = ics.AddConfig("ClientStack.LindenUDP");
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 4286eef..711167f 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -1069,8 +1069,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1069 // Now let's make it officially a child agent 1069 // Now let's make it officially a child agent
1070 sp.MakeChildAgent(); 1070 sp.MakeChildAgent();
1071 1071
1072 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1072 // May still need to signal neighbours whether child agents may need closing irrespective of whether this
1073 // one needed closing. Neighbour regions also contain logic to prevent a close if a subsequent move or
1074 // teleport re-established the child connection.
1075 //
1076 // It may be possible to also close child agents after a pause but one needs to be very careful about
1077 // race conditions between different regions on rapid teleporting (e.g. from A1 to a non-neighbour B, back
1078 // to a neighbour A2 then off to a non-neighbour C. Also, closing child agents early may be more compatible
1079 // with complicated scenarios where there a mixture of V1 and V2 teleports, though this is conjecture. It's
1080 // easier to close immediately and greatly reduce the scope of race conditions if possible.
1081 sp.CloseChildAgents(newRegionX, newRegionY);
1073 1082
1083 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1074 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1084 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1075 { 1085 {
1076 sp.DoNotCloseAfterTeleport = false; 1086 sp.DoNotCloseAfterTeleport = false;
@@ -1086,14 +1096,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1086 if (!sp.DoNotCloseAfterTeleport) 1096 if (!sp.DoNotCloseAfterTeleport)
1087 { 1097 {
1088 // OK, it got this agent. Let's close everything 1098 // OK, it got this agent. Let's close everything
1089 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.Name); 1099 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing agent {0} in {1}", sp.Name, Scene.Name);
1090 sp.CloseChildAgents(newRegionX, newRegionY);
1091 sp.Scene.IncomingCloseAgent(sp.UUID, false); 1100 sp.Scene.IncomingCloseAgent(sp.UUID, false);
1092
1093 } 1101 }
1094 else 1102 else
1095 { 1103 {
1096 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.Name); 1104 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {1}", sp.Name, Scene.Name);
1097 sp.DoNotCloseAfterTeleport = false; 1105 sp.DoNotCloseAfterTeleport = false;
1098 } 1106 }
1099 } 1107 }
@@ -1836,10 +1844,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1836 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 1844 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1837 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles); 1845 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1838 1846
1839 //Dump("Current Neighbors", neighbourHandles); 1847// Dump("Current Neighbors", neighbourHandles);
1840 //Dump("Previous Neighbours", previousRegionNeighbourHandles); 1848// Dump("Previous Neighbours", previousRegionNeighbourHandles);
1841 //Dump("New Neighbours", newRegions); 1849// Dump("New Neighbours", newRegions);
1842 //Dump("Old Neighbours", oldRegions); 1850// Dump("Old Neighbours", oldRegions);
1843 1851
1844 /// Update the scene presence's known regions here on this region 1852 /// Update the scene presence's known regions here on this region
1845 sp.DropOldNeighbours(oldRegions); 1853 sp.DropOldNeighbours(oldRegions);
@@ -1847,8 +1855,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1847 /// Collect as many seeds as possible 1855 /// Collect as many seeds as possible
1848 Dictionary<ulong, string> seeds; 1856 Dictionary<ulong, string> seeds;
1849 if (sp.Scene.CapsModule != null) 1857 if (sp.Scene.CapsModule != null)
1850 seeds 1858 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1851 = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1852 else 1859 else
1853 seeds = new Dictionary<ulong, string>(); 1860 seeds = new Dictionary<ulong, string>();
1854 1861
@@ -1918,6 +1925,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1918 newAgent = true; 1925 newAgent = true;
1919 else 1926 else
1920 newAgent = false; 1927 newAgent = false;
1928// continue;
1921 1929
1922 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 1930 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
1923 { 1931 {
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index bb304df..ad33f23 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -45,6 +45,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static string LogHeader = "[MODULE COMMS]";
48 49
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>(); 50 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50 51
@@ -148,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); 149 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
149 if (mi == null) 150 if (mi == null)
150 { 151 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); 152 m_log.WarnFormat("{0} Failed to register method {1}", LogHeader, meth);
152 return; 153 return;
153 } 154 }
154 155
@@ -165,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
165 { 166 {
166// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); 167// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
167 168
168 Type delegateType; 169 Type delegateType = typeof(void);
169 List<Type> typeArgs = mi.GetParameters() 170 List<Type> typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType) 171 .Select(p => p.ParameterType)
171 .ToList(); 172 .ToList();
@@ -176,8 +177,16 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
176 } 177 }
177 else 178 else
178 { 179 {
179 typeArgs.Add(mi.ReturnType); 180 try
180 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 181 {
182 typeArgs.Add(mi.ReturnType);
183 delegateType = Expression.GetFuncType(typeArgs.ToArray());
184 }
185 catch (Exception e)
186 {
187 m_log.ErrorFormat("{0} Failed to create function signature. Most likely more than 5 parameters. Method={1}. Error={2}",
188 LogHeader, mi.Name, e);
189 }
181 } 190 }
182 191
183 Delegate fcall; 192 Delegate fcall;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 4d49794..173b603 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -76,6 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.", 76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
77 consoleSetTerrainHeights); 77 consoleSetTerrainHeights);
78 78
79 m_module.Scene.AddCommand("Regions", m_module, "set water height",
80 "set water height <height> [<x>] [<y>]",
81 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
82 "Specify -1 in <x> or <y> to wildcard that coordinate.",
83 consoleSetWaterHeight);
84
85
79 m_module.Scene.AddCommand( 86 m_module.Scene.AddCommand(
80 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand); 87 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
81 } 88 }
@@ -121,7 +128,29 @@ namespace OpenSim.Region.CoreModules.World.Estate
121 } 128 }
122 } 129 }
123 } 130 }
124 131 protected void consoleSetWaterHeight(string module, string[] args)
132 {
133 string heightstring = args[3];
134
135 int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
136 int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
137
138 if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
139 {
140 if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
141 {
142 double selectedheight = double.Parse(heightstring);
143
144 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
145 string.Format(" {0}", selectedheight));
146 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
147
148 m_module.Scene.RegionInfo.RegionSettings.Save();
149 m_module.TriggerRegionInfoChange();
150 m_module.sendRegionHandshakeToAll();
151 }
152 }
153 }
125 protected void consoleSetTerrainHeights(string module, string[] args) 154 protected void consoleSetTerrainHeights(string module, string[] args)
126 { 155 {
127 string num = args[3]; 156 string num = args[3];
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index a5f5749..1808fdd 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -572,7 +572,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
572 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 572 if (!Scene.TeleportClientHome(user, s.ControllingClient))
573 { 573 {
574 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 574 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
575 s.ControllingClient.Close(); 575 Scene.IncomingCloseAgent(s.UUID, false);
576 } 576 }
577 } 577 }
578 } 578 }
@@ -807,7 +807,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
807 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 807 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
808 { 808 {
809 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 809 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
810 s.ControllingClient.Close(); 810 Scene.IncomingCloseAgent(s.UUID, false);
811 } 811 }
812 } 812 }
813 } 813 }
@@ -830,7 +830,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
830 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) 830 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
831 { 831 {
832 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 832 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
833 p.ControllingClient.Close(); 833 Scene.IncomingCloseAgent(p.UUID, false);
834 } 834 }
835 } 835 }
836 } 836 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index aa09092..6323a88 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes
151 public SynchronizeSceneHandler SynchronizeScene; 151 public SynchronizeSceneHandler SynchronizeScene;
152 152
153 /// <summary> 153 /// <summary>
154 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. 154 /// Used to prevent simultaneous calls to code that adds and removes agents.
155 /// </summary> 155 /// </summary>
156 private object m_removeClientLock = new object(); 156 private object m_removeClientLock = new object();
157 157
@@ -1338,7 +1338,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 Thread.Sleep(500); 1338 Thread.Sleep(500);
1339 1339
1340 // Stop all client threads. 1340 // Stop all client threads.
1341 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1341 ForEachScenePresence(delegate(ScenePresence avatar) { IncomingCloseAgent(avatar.UUID, false); });
1342 1342
1343 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1343 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1344 EventManager.TriggerSceneShuttingDown(this); 1344 EventManager.TriggerSceneShuttingDown(this);
@@ -3127,7 +3127,8 @@ namespace OpenSim.Region.Framework.Scenes
3127 if (sp != null) 3127 if (sp != null)
3128 { 3128 {
3129 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3129 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3130 sp.ControllingClient.Close(); 3130
3131 IncomingCloseAgent(sp.UUID, false);
3131 } 3132 }
3132 3133
3133 // BANG! SLASH! 3134 // BANG! SLASH!
@@ -3541,47 +3542,48 @@ namespace OpenSim.Region.Framework.Scenes
3541 3542
3542 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3543 public override void RemoveClient(UUID agentID, bool closeChildAgents)
3543 { 3544 {
3544// CheckHeartbeat(); 3545 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3545 bool isChildAgent = false;
3546 AgentCircuitData acd;
3547 3546
3548 lock (m_removeClientLock) 3547 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3548 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3549 // However, will keep for now just in case.
3550 if (acd == null)
3549 { 3551 {
3550 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3552 m_log.ErrorFormat(
3553 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3551 3554
3552 if (acd == null) 3555 return;
3553 { 3556 }
3554 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); 3557 else
3555 return; 3558 {
3556 } 3559 m_authenticateHandler.RemoveCircuit(agentID);
3557 else
3558 {
3559 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3560 // simultaneously.
3561 // We also need to remove by agent ID since NPCs will have no circuit code.
3562 m_authenticateHandler.RemoveCircuit(agentID);
3563 }
3564 } 3560 }
3565 3561
3562 // TODO: Can we now remove this lock?
3566 lock (acd) 3563 lock (acd)
3567 { 3564 {
3565 bool isChildAgent = false;
3566
3568 ScenePresence avatar = GetScenePresence(agentID); 3567 ScenePresence avatar = GetScenePresence(agentID);
3569 3568
3569 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3570 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3571 // However, will keep for now just in case.
3570 if (avatar == null) 3572 if (avatar == null)
3571 { 3573 {
3572 m_log.WarnFormat( 3574 m_log.ErrorFormat(
3573 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3575 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3574 3576
3575 return; 3577 return;
3576 } 3578 }
3577 3579
3578 try 3580 try
3579 { 3581 {
3580 isChildAgent = avatar.IsChildAgent; 3582 isChildAgent = avatar.IsChildAgent;
3581 3583
3582 m_log.DebugFormat( 3584 m_log.DebugFormat(
3583 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3585 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3584 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3586 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3585 3587
3586 // Don't do this to root agents, it's not nice for the viewer 3588 // Don't do this to root agents, it's not nice for the viewer
3587 if (closeChildAgents && isChildAgent) 3589 if (closeChildAgents && isChildAgent)
@@ -3745,13 +3747,13 @@ namespace OpenSim.Region.Framework.Scenes
3745 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3747 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3746 /// the LLUDP stack). 3748 /// the LLUDP stack).
3747 /// </remarks> 3749 /// </remarks>
3748 /// <param name="agent">CircuitData of the agent who is connecting</param> 3750 /// <param name="acd">CircuitData of the agent who is connecting</param>
3749 /// <param name="reason">Outputs the reason for the false response on this string</param> 3751 /// <param name="reason">Outputs the reason for the false response on this string</param>
3750 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3752 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3751 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3753 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3752 /// <returns>True if the region accepts this agent. False if it does not. False will 3754 /// <returns>True if the region accepts this agent. False if it does not. False will
3753 /// also return a reason.</returns> 3755 /// also return a reason.</returns>
3754 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3756 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3755 { 3757 {
3756 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3758 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3757 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3759 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3771,15 +3773,15 @@ namespace OpenSim.Region.Framework.Scenes
3771 m_log.DebugFormat( 3773 m_log.DebugFormat(
3772 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3774 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})",
3773 RegionInfo.RegionName, 3775 RegionInfo.RegionName,
3774 (agent.child ? "child" : "root"), 3776 (acd.child ? "child" : "root"),
3775 agent.firstname, 3777 acd.firstname,
3776 agent.lastname, 3778 acd.lastname,
3777 agent.AgentID, 3779 acd.AgentID,
3778 agent.circuitcode, 3780 acd.circuitcode,
3779 agent.IPAddress, 3781 acd.IPAddress,
3780 agent.Viewer, 3782 acd.Viewer,
3781 ((TPFlags)teleportFlags).ToString(), 3783 ((TPFlags)teleportFlags).ToString(),
3782 agent.startpos 3784 acd.startpos
3783 ); 3785 );
3784 3786
3785 if (!LoginsEnabled) 3787 if (!LoginsEnabled)
@@ -3797,7 +3799,7 @@ namespace OpenSim.Region.Framework.Scenes
3797 { 3799 {
3798 foreach (string viewer in m_AllowedViewers) 3800 foreach (string viewer in m_AllowedViewers)
3799 { 3801 {
3800 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3802 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3801 { 3803 {
3802 ViewerDenied = false; 3804 ViewerDenied = false;
3803 break; 3805 break;
@@ -3814,7 +3816,7 @@ namespace OpenSim.Region.Framework.Scenes
3814 { 3816 {
3815 foreach (string viewer in m_BannedViewers) 3817 foreach (string viewer in m_BannedViewers)
3816 { 3818 {
3817 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3819 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3818 { 3820 {
3819 ViewerDenied = true; 3821 ViewerDenied = true;
3820 break; 3822 break;
@@ -3826,61 +3828,115 @@ namespace OpenSim.Region.Framework.Scenes
3826 { 3828 {
3827 m_log.DebugFormat( 3829 m_log.DebugFormat(
3828 "[SCENE]: Access denied for {0} {1} using {2}", 3830 "[SCENE]: Access denied for {0} {1} using {2}",
3829 agent.firstname, agent.lastname, agent.Viewer); 3831 acd.firstname, acd.lastname, acd.Viewer);
3830 reason = "Access denied, your viewer is banned by the region owner"; 3832 reason = "Access denied, your viewer is banned by the region owner";
3831 return false; 3833 return false;
3832 } 3834 }
3835
3836 ILandObject land;
3837 ScenePresence sp;
3833 3838
3834 lock (agent) 3839 lock (m_removeClientLock)
3835 { 3840 {
3836 ScenePresence sp = GetScenePresence(agent.AgentID); 3841 sp = GetScenePresence(acd.AgentID);
3837 3842
3838 if (sp != null) 3843 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3844 // closed.
3845 if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running)
3839 { 3846 {
3840 if (!sp.IsChildAgent) 3847 m_log.DebugFormat(
3841 { 3848 "[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name);
3842 // We have a root agent. Is it in transit?
3843 if (!EntityTransferModule.IsInTransit(sp.UUID))
3844 {
3845 // We have a zombie from a crashed session.
3846 // Or the same user is trying to be root twice here, won't work.
3847 // Kill it.
3848 m_log.WarnFormat(
3849 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3850 sp.Name, sp.UUID, RegionInfo.RegionName);
3851 3849
3852 if (sp.ControllingClient != null) 3850 // In the case where, for example, an A B C D region layout, an avatar may
3853 sp.ControllingClient.Close(true, true); 3851 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3852 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3853 if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3854 {
3855 m_log.DebugFormat(
3856 "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3857 sp.Name, Name);
3854 3858
3855 sp = null; 3859 sp.DoNotCloseAfterTeleport = true;
3856 }
3857 //else
3858 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3859 } 3860 }
3860 else 3861 else if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3862 {
3862 // We have a child agent here 3863 m_log.DebugFormat(
3864 "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt previous end-of-teleport close.",
3865 sp.Name, Name);
3866
3863 sp.DoNotCloseAfterTeleport = true; 3867 sp.DoNotCloseAfterTeleport = true;
3864 //m_log.WarnFormat("[SCENE]: Existing child scene presence for {0} {1} in {2}", sp.Name, sp.UUID, RegionInfo.RegionName);
3865 } 3868 }
3866 } 3869 }
3870 }
3871
3872 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3873 // allow unpredictable things to happen.
3874 if (sp != null)
3875 {
3876 const int polls = 10;
3877 const int pollInterval = 1000;
3878 int pollsLeft = polls;
3879
3880 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3881 Thread.Sleep(pollInterval);
3882
3883 if (sp.LifecycleState == ScenePresenceState.Removing)
3884 {
3885 m_log.WarnFormat(
3886 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3887 sp.Name, Name, polls * pollInterval / 1000);
3888
3889 return false;
3890 }
3891 else if (polls != pollsLeft)
3892 {
3893 m_log.DebugFormat(
3894 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3895 sp.Name, Name, polls * pollInterval / 1000);
3896 }
3897 }
3898
3899 // TODO: can we remove this lock?
3900 lock (acd)
3901 {
3902 if (sp != null && !sp.IsChildAgent)
3903 {
3904 // We have a root agent. Is it in transit?
3905 if (!EntityTransferModule.IsInTransit(sp.UUID))
3906 {
3907 // We have a zombie from a crashed session.
3908 // Or the same user is trying to be root twice here, won't work.
3909 // Kill it.
3910 m_log.WarnFormat(
3911 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3912 sp.Name, sp.UUID, RegionInfo.RegionName);
3913
3914 if (sp.ControllingClient != null)
3915 IncomingCloseAgent(sp.UUID, true);
3916
3917 sp = null;
3918 }
3919 //else
3920 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3921 }
3867 3922
3868 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags. 3923 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3869 // We need the circuit data here for some of the subsequent checks. (groups, for example) 3924 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3870 // If the checks fail, we remove the circuit. 3925 // If the checks fail, we remove the circuit.
3871 agent.teleportFlags = teleportFlags; 3926 acd.teleportFlags = teleportFlags;
3872 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 3927 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3873 3928
3929 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3930
3874 // On login test land permisions 3931 // On login test land permisions
3875 if (vialogin) 3932 if (vialogin)
3876 { 3933 {
3877 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3934 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3878 if (cache != null) 3935 if (cache != null)
3879 cache.Remove(agent.firstname + " " + agent.lastname); 3936 cache.Remove(acd.firstname + " " + acd.lastname);
3880 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3937 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3881 { 3938 {
3882 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3939 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3883 m_authenticateHandler.RemoveCircuit(agent.circuitcode);
3884 return false; 3940 return false;
3885 } 3941 }
3886 } 3942 }
@@ -3891,9 +3947,9 @@ namespace OpenSim.Region.Framework.Scenes
3891 { 3947 {
3892 try 3948 try
3893 { 3949 {
3894 if (!VerifyUserPresence(agent, out reason)) 3950 if (!VerifyUserPresence(acd, out reason))
3895 { 3951 {
3896 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3952 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3897 return false; 3953 return false;
3898 } 3954 }
3899 } 3955 }
@@ -3902,16 +3958,16 @@ namespace OpenSim.Region.Framework.Scenes
3902 m_log.ErrorFormat( 3958 m_log.ErrorFormat(
3903 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3959 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3904 3960
3905 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3961 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 3962 return false;
3907 } 3963 }
3908 } 3964 }
3909 3965
3910 try 3966 try
3911 { 3967 {
3912 if (!AuthorizeUser(agent, SeeIntoRegion, out reason)) 3968 if (!AuthorizeUser(acd, SeeIntoRegion, out reason))
3913 { 3969 {
3914 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3970 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3915 return false; 3971 return false;
3916 } 3972 }
3917 } 3973 }
@@ -3920,15 +3976,20 @@ namespace OpenSim.Region.Framework.Scenes
3920 m_log.ErrorFormat( 3976 m_log.ErrorFormat(
3921 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3977 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3922 3978
3923 m_authenticateHandler.RemoveCircuit(agent.circuitcode); 3979 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3924 return false; 3980 return false;
3925 } 3981 }
3926 3982
3927 m_log.InfoFormat( 3983 m_log.InfoFormat(
3928 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 3984 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3929 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 3985 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3930 agent.AgentID, agent.circuitcode); 3986 acd.AgentID, acd.circuitcode);
3931 3987
3988 if (CapsModule != null)
3989 {
3990 CapsModule.SetAgentCapsSeeds(acd);
3991 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
3992 }
3932 } 3993 }
3933 else 3994 else
3934 { 3995 {
@@ -3940,14 +4001,14 @@ namespace OpenSim.Region.Framework.Scenes
3940 { 4001 {
3941 m_log.DebugFormat( 4002 m_log.DebugFormat(
3942 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4003 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3943 agent.AgentID, RegionInfo.RegionName); 4004 acd.AgentID, RegionInfo.RegionName);
3944 4005
3945 sp.AdjustKnownSeeds(); 4006 sp.AdjustKnownSeeds();
3946 4007
3947 if (CapsModule != null) 4008 if (CapsModule != null)
3948 { 4009 {
3949 CapsModule.SetAgentCapsSeeds(agent); 4010 CapsModule.SetAgentCapsSeeds(acd);
3950 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 4011 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
3951 } 4012 }
3952 } 4013 }
3953 } 4014 }
@@ -3955,28 +4016,28 @@ namespace OpenSim.Region.Framework.Scenes
3955 // Try caching an incoming user name much earlier on to see if this helps with an issue 4016 // Try caching an incoming user name much earlier on to see if this helps with an issue
3956 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName 4017 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3957 // request for the HG avatar appears to trigger before the user name is cached. 4018 // request for the HG avatar appears to trigger before the user name is cached.
3958 CacheUserName(null, agent); 4019 CacheUserName(null, acd);
3959 } 4020 }
3960 4021
3961 if (CapsModule != null) 4022 if (CapsModule != null)
3962 { 4023 {
3963 CapsModule.ActivateCaps(agent.circuitcode); 4024 CapsModule.ActivateCaps(acd.circuitcode);
3964 } 4025 }
3965 4026
3966 if (vialogin) 4027 if (vialogin)
3967 { 4028 {
3968// CleanDroppedAttachments(); 4029// CleanDroppedAttachments();
3969 4030
3970 if (TestBorderCross(agent.startpos, Cardinals.E)) 4031 if (TestBorderCross(acd.startpos, Cardinals.E))
3971 { 4032 {
3972 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4033 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3973 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4034 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3974 } 4035 }
3975 4036
3976 if (TestBorderCross(agent.startpos, Cardinals.N)) 4037 if (TestBorderCross(acd.startpos, Cardinals.N))
3977 { 4038 {
3978 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4039 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3979 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4040 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3980 } 4041 }
3981 4042
3982 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4043 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3986,39 +4047,39 @@ namespace OpenSim.Region.Framework.Scenes
3986 { 4047 {
3987 lock (EastBorders) 4048 lock (EastBorders)
3988 { 4049 {
3989 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4050 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3990 { 4051 {
3991 m_log.Warn("FIX AGENT POSITION"); 4052 m_log.Warn("FIX AGENT POSITION");
3992 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4053 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3993 if (agent.startpos.Z > 720) 4054 if (acd.startpos.Z > 720)
3994 agent.startpos.Z = 720; 4055 acd.startpos.Z = 720;
3995 } 4056 }
3996 } 4057 }
3997 lock (NorthBorders) 4058 lock (NorthBorders)
3998 { 4059 {
3999 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4060 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4000 { 4061 {
4001 m_log.Warn("FIX Agent POSITION"); 4062 m_log.Warn("FIX Agent POSITION");
4002 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4063 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4003 if (agent.startpos.Z > 720) 4064 if (acd.startpos.Z > 720)
4004 agent.startpos.Z = 720; 4065 acd.startpos.Z = 720;
4005 } 4066 }
4006 } 4067 }
4007 } else 4068 } else
4008 { 4069 {
4009 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4070 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4010 { 4071 {
4011 m_log.Warn("FIX AGENT POSITION"); 4072 m_log.Warn("FIX AGENT POSITION");
4012 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4073 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4013 if (agent.startpos.Z > 720) 4074 if (acd.startpos.Z > 720)
4014 agent.startpos.Z = 720; 4075 acd.startpos.Z = 720;
4015 } 4076 }
4016 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4077 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4017 { 4078 {
4018 m_log.Warn("FIX Agent POSITION"); 4079 m_log.Warn("FIX Agent POSITION");
4019 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4080 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4020 if (agent.startpos.Z > 720) 4081 if (acd.startpos.Z > 720)
4021 agent.startpos.Z = 720; 4082 acd.startpos.Z = 720;
4022 } 4083 }
4023 } 4084 }
4024 4085
@@ -4034,12 +4095,12 @@ namespace OpenSim.Region.Framework.Scenes
4034 { 4095 {
4035 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4096 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4036 if (SpawnPointRouting == "random") 4097 if (SpawnPointRouting == "random")
4037 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4098 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4038 telehub.AbsolutePosition, 4099 telehub.AbsolutePosition,
4039 telehub.GroupRotation 4100 telehub.GroupRotation
4040 ); 4101 );
4041 else 4102 else
4042 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4103 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4043 telehub.AbsolutePosition, 4104 telehub.AbsolutePosition,
4044 telehub.GroupRotation 4105 telehub.GroupRotation
4045 ); 4106 );
@@ -4047,7 +4108,7 @@ namespace OpenSim.Region.Framework.Scenes
4047 else 4108 else
4048 { 4109 {
4049 // We have a single SpawnPoint and will route the agent to it 4110 // We have a single SpawnPoint and will route the agent to it
4050 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4111 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4051 } 4112 }
4052 4113
4053 return true; 4114 return true;
@@ -4060,7 +4121,7 @@ namespace OpenSim.Region.Framework.Scenes
4060 { 4121 {
4061 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4122 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4062 { 4123 {
4063 agent.startpos = land.LandData.UserLocation; 4124 acd.startpos = land.LandData.UserLocation;
4064 } 4125 }
4065 } 4126 }
4066 */// This is now handled properly in ScenePresence.MakeRootAgent 4127 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4444,24 +4505,25 @@ namespace OpenSim.Region.Framework.Scenes
4444 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4505 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4445 if (childAgentUpdate != null) 4506 if (childAgentUpdate != null)
4446 { 4507 {
4447 if (childAgentUpdate.ControllingClient.SessionId == cAgentData.SessionID) 4508 if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4509 // Only warn for now
4510 m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4511 childAgentUpdate.UUID, cAgentData.SessionID);
4512
4513 // I can't imagine *yet* why we would get an update if the agent is a root agent..
4514 // however to avoid a race condition crossing borders..
4515 if (childAgentUpdate.IsChildAgent)
4448 { 4516 {
4449 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4517 uint rRegionX = (uint)(cAgentData.RegionHandle >> 40);
4450 // however to avoid a race condition crossing borders.. 4518 uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8);
4451 if (childAgentUpdate.IsChildAgent) 4519 uint tRegionX = RegionInfo.RegionLocX;
4452 { 4520 uint tRegionY = RegionInfo.RegionLocY;
4453 uint rRegionX = (uint)(cAgentData.RegionHandle >> 40); 4521 //Send Data to ScenePresence
4454 uint rRegionY = (((uint)(cAgentData.RegionHandle)) >> 8); 4522 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4455 uint tRegionX = RegionInfo.RegionLocX; 4523 // Not Implemented:
4456 uint tRegionY = RegionInfo.RegionLocY; 4524 //TODO: Do we need to pass the message on to one of our neighbors?
4457 //Send Data to ScenePresence
4458 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4459 // Not Implemented:
4460 //TODO: Do we need to pass the message on to one of our neighbors?
4461 }
4462 } 4525 }
4463 else 4526
4464 m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}", childAgentUpdate.UUID, cAgentData.SessionID);
4465 return true; 4527 return true;
4466 } 4528 }
4467 4529
@@ -4540,11 +4602,51 @@ namespace OpenSim.Region.Framework.Scenes
4540 /// </param> 4602 /// </param>
4541 public bool IncomingCloseAgent(UUID agentID, bool force) 4603 public bool IncomingCloseAgent(UUID agentID, bool force)
4542 { 4604 {
4543 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4605 ScenePresence sp;
4544 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4606
4545 if (presence != null) 4607 lock (m_removeClientLock)
4608 {
4609 sp = GetScenePresence(agentID);
4610
4611 if (sp == null)
4612 {
4613 m_log.DebugFormat(
4614 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}",
4615 agentID, Name);
4616
4617 return false;
4618 }
4619
4620 if (sp.LifecycleState != ScenePresenceState.Running)
4621 {
4622 m_log.DebugFormat(
4623 "[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}",
4624 sp.Name, Name, sp.LifecycleState);
4625
4626 return false;
4627 }
4628
4629 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4630 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4631 // want to obey this close since C may have renewed the child agent lease on B.
4632 if (sp.DoNotCloseAfterTeleport)
4633 {
4634 m_log.DebugFormat(
4635 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4636 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4637
4638 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4639 sp.DoNotCloseAfterTeleport = false;
4640
4641 return false;
4642 }
4643
4644 sp.LifecycleState = ScenePresenceState.Removing;
4645 }
4646
4647 if (sp != null)
4546 { 4648 {
4547 presence.ControllingClient.Close(force, force); 4649 sp.ControllingClient.Close(force, force);
4548 return true; 4650 return true;
4549 } 4651 }
4550 4652
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 48bf6f3..5301a82 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -75,6 +75,8 @@ namespace OpenSim.Region.Framework.Scenes
75 75
76 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
77 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
78// ~ScenePresence() 80// ~ScenePresence()
79// { 81// {
80// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
@@ -86,10 +88,27 @@ namespace OpenSim.Region.Framework.Scenes
86 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
87 } 89 }
88 90
89 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
90
91 public PresenceType PresenceType { get; private set; } 91 public PresenceType PresenceType { get; private set; }
92 92
93 private ScenePresenceStateMachine m_stateMachine;
94
95 /// <summary>
96 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
97 /// for more details.
98 /// </summary>
99 public ScenePresenceState LifecycleState
100 {
101 get
102 {
103 return m_stateMachine.GetState();
104 }
105
106 set
107 {
108 m_stateMachine.SetState(value);
109 }
110 }
111
93// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 112// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
94 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 113 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
95 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 114 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -299,9 +318,9 @@ namespace OpenSim.Region.Framework.Scenes
299 /// <summary> 318 /// <summary>
300 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address. 319 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
301 /// </summary> 320 /// </summary>
302 string m_callbackURI; 321 private string m_callbackURI;
303 322
304 UUID m_originRegionID; 323 public UUID m_originRegionID;
305 324
306 /// <summary> 325 /// <summary>
307 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent 326 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
@@ -813,7 +832,7 @@ namespace OpenSim.Region.Framework.Scenes
813 832
814 public ScenePresence( 833 public ScenePresence(
815 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 834 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
816 { 835 {
817 AttachmentsSyncLock = new Object(); 836 AttachmentsSyncLock = new Object();
818 AllowMovement = true; 837 AllowMovement = true;
819 IsChildAgent = true; 838 IsChildAgent = true;
@@ -859,6 +878,8 @@ namespace OpenSim.Region.Framework.Scenes
859 SetDirectionVectors(); 878 SetDirectionVectors();
860 879
861 Appearance = appearance; 880 Appearance = appearance;
881
882 m_stateMachine = new ScenePresenceStateMachine(this);
862 } 883 }
863 884
864 private void RegionHeartbeatEnd(Scene scene) 885 private void RegionHeartbeatEnd(Scene scene)
@@ -956,7 +977,7 @@ namespace OpenSim.Region.Framework.Scenes
956 /// </summary> 977 /// </summary>
957 public void MakeRootAgent(Vector3 pos, bool isFlying) 978 public void MakeRootAgent(Vector3 pos, bool isFlying)
958 { 979 {
959 m_log.DebugFormat( 980 m_log.InfoFormat(
960 "[SCENE]: Upgrading child to root agent for {0} in {1}", 981 "[SCENE]: Upgrading child to root agent for {0} in {1}",
961 Name, m_scene.RegionInfo.RegionName); 982 Name, m_scene.RegionInfo.RegionName);
962 983
@@ -996,6 +1017,11 @@ namespace OpenSim.Region.Framework.Scenes
996 1017
997 IsChildAgent = false; 1018 IsChildAgent = false;
998 1019
1020 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1021 // set and prevent the close of the connection on a subsequent re-teleport.
1022 // Should not be needed if we are not trying to tell this region to close
1023// DoNotCloseAfterTeleport = false;
1024
999 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1025 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1000 if (gm != null) 1026 if (gm != null)
1001 Grouptitle = gm.GetGroupTitle(m_uuid); 1027 Grouptitle = gm.GetGroupTitle(m_uuid);
@@ -1520,7 +1546,7 @@ namespace OpenSim.Region.Framework.Scenes
1520 private bool WaitForUpdateAgent(IClientAPI client) 1546 private bool WaitForUpdateAgent(IClientAPI client)
1521 { 1547 {
1522 // Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero 1548 // Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero
1523 int count = 20; 1549 int count = 50;
1524 while (m_originRegionID.Equals(UUID.Zero) && count-- > 0) 1550 while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
1525 { 1551 {
1526 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name); 1552 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
@@ -3994,6 +4020,7 @@ namespace OpenSim.Region.Framework.Scenes
3994// Animator.Close(); 4020// Animator.Close();
3995 Animator = null; 4021 Animator = null;
3996 4022
4023 LifecycleState = ScenePresenceState.Removed;
3997 } 4024 }
3998 4025
3999 public void AddAttachment(SceneObjectGroup gobj) 4026 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
new file mode 100644
index 0000000..dc3a212
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -0,0 +1,102 @@
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;
29
30namespace OpenSim.Region.Framework.Scenes
31{
32 /// <summary>
33 /// The possible states that a scene presence can be in. This is currently orthagonal to whether a scene presence
34 /// is root or child.
35 /// </summary>
36 /// <remarks>
37 /// This is a state machine.
38 ///
39 /// [Entry] => Running
40 /// Running => Removing
41 /// Removing => Removed
42 ///
43 /// All other methods should only see the scene presence in running state - this is the normal operational state
44 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
45 /// </remarks>
46 public enum ScenePresenceState
47 {
48 Running, // Normal operation state. The scene presence is available.
49 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
50 Removed, // The presence has been removed from the scene and is effectively dead.
51 // There is no exit from this state.
52 }
53
54 internal class ScenePresenceStateMachine
55 {
56 private ScenePresence m_sp;
57 private ScenePresenceState m_state;
58
59 internal ScenePresenceStateMachine(ScenePresence sp)
60 {
61 m_sp = sp;
62 m_state = ScenePresenceState.Running;
63 }
64
65 internal ScenePresenceState GetState()
66 {
67 return m_state;
68 }
69
70 /// <summary>
71 /// Updates the state of an agent that is already in transit.
72 /// </summary>
73 /// <param name='id'></param>
74 /// <param name='newState'></param>
75 /// <returns></returns>
76 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
77 internal void SetState(ScenePresenceState newState)
78 {
79 bool transitionOkay = false;
80
81 lock (this)
82 {
83 if (newState == ScenePresenceState.Removing && m_state == ScenePresenceState.Running)
84 transitionOkay = true;
85 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
86 transitionOkay = true;
87 }
88
89 if (!transitionOkay)
90 {
91 throw new Exception(
92 string.Format(
93 "Scene presence {0} is not allowed to move from state {1} to new state {2} in {3}",
94 m_sp.Name, m_state, newState, m_sp.Scene.Name));
95 }
96 else
97 {
98 m_state = newState;
99 }
100 }
101 }
102} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 58a417e..9af3dce 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -96,8 +96,8 @@ public sealed class BSCharacter : BSPhysObject
96 m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName); 96 m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
97 PhysicalActors.Add(AvatarMoveActorName, m_moveActor); 97 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
98 98
99 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 99 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6}",
100 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 100 LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos);
101 101
102 // do actual creation in taint time 102 // do actual creation in taint time
103 PhysScene.TaintedObject("BSCharacter.create", delegate() 103 PhysScene.TaintedObject("BSCharacter.create", delegate()
@@ -190,6 +190,10 @@ public sealed class BSCharacter : BSPhysObject
190 } 190 }
191 191
192 set { 192 set {
193 // This is how much the avatar size is changing. Positive means getting bigger.
194 // The avatar altitude must be adjusted for this change.
195 float heightChange = value.Z - _size.Z;
196
193 _size = value; 197 _size = value;
194 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 198 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
195 // replace with the default values. 199 // replace with the default values.
@@ -207,6 +211,10 @@ public sealed class BSCharacter : BSPhysObject
207 { 211 {
208 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale); 212 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
209 UpdatePhysicalMassProperties(RawMass, true); 213 UpdatePhysicalMassProperties(RawMass, true);
214
215 // Adjust the avatar's position to account for the increase/decrease in size
216 ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
217
210 // Make sure this change appears as a property update event 218 // Make sure this change appears as a property update event
211 PhysScene.PE.PushUpdate(PhysBody); 219 PhysScene.PE.PushUpdate(PhysBody);
212 } 220 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 4520171..fcb892a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -570,9 +570,9 @@ public static class BSParam
570 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground", 570 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
571 -0.2f ), 571 -0.2f ),
572 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground", 572 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
573 0.1f ), 573 0.2f ),
574 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground", 574 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
575 0.1f ), 575 0.2f ),
576 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 576 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
577 0.1f ), 577 0.1f ),
578 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 578 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index f8e2829..67963a5 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -264,8 +264,15 @@
264 264
265 ; Simulator Stats URI 265 ; Simulator Stats URI
266 ; Enable JSON simulator data by setting a URI name (case sensitive) 266 ; Enable JSON simulator data by setting a URI name (case sensitive)
267 ; Returns regular sim stats (SimFPS, ...)
267 ; Stats_URI = "jsonSimStats" 268 ; Stats_URI = "jsonSimStats"
268 269
270 ; Simulator StatsManager URI
271 ; Enable fetch of StatsManager registered stats. Fetch is query which can optionally
272 ; specify category, container and stat to fetch. If not selected, returns all of that type.
273 ; http://simulatorHTTPport/ManagedStats/?cat=Category&cont=Container&stat=Statistic
274 ; ManagedStatsRemoteFetchURI = "ManagedStats"
275
269 ; Make OpenSim start all regions woth logins disabled. They will need 276 ; Make OpenSim start all regions woth logins disabled. They will need
270 ; to be enabled from the console if this is set 277 ; to be enabled from the console if this is set
271 ; StartDisabled = false 278 ; StartDisabled = false